home *** CD-ROM | disk | FTP | other *** search
- program calendar;
- {*************************************************************************
- Program: CALENDAR
- Author: Richard Conn
- Date: 4 Feb 82
-
- Description:
- CALENDAR is used to display a Calendar to the user. The
- Calendar may be that of a particular Month in a particular Year
- or that of all Months in a Particular Year.
- The calendar displayed is the Gregorian Calendar.
- The Calendar display may be sent to the user's Console
- (by default) or optionally to the user's LST: device or a disk file.
-
- Usage:
- calendar [month] year [/o]
- where
- month may be one of january, february, ..., december
- (optional and only first three letters are req'd)
- year may be any year after byear
- o may be one of the following --
- p - send output to Printer
- d - send output to Disk
- (o is optional and defaults to Console if omitted)
-
- Examples:
- CALENDAR JANUARY 1982 -- Calendar of Month of January of 1982
- CALENDAR JAN 1982 -- Same as Above
- CALENDAR 1982 -- Calendar of all months of 1982
- CALENDAR 1982 /P -- Same as Above but Output to Printer
- CALENDAR 1982 /D -- Same as Above but Output to Disk
- CALENDAR 1982 /P/D -- Same as Above but Output to Disk
- (Disk has priority)
- *****************************************************************************}
-
- {***************************************************************************
-
- 'version' is the Version Number of CALENDAR.
- 'byear1' is the Base Year of CALENDAR. This year MUST be a Leap
- Year. Since CALENDAR uses integer arithmetic to do its calculations,
- the range of years that may be addressed by CALENDAR is from byear to
- byear + 30,000 (approx).
- 'bday1' is the Base Day of CALENDAR. This is the number (1 to 7)
- of the First Sunday in January of the Base Year.
-
- ****************************************************************************}
- const
- version = 13;
- byear1 = 1804; { Base Year for this program }
- bday1 = 1; { Base Day for the Base Year }
-
- {***********************************************
- Global Types and Variables
- ************************************************}
- type
- strptr = ^string;
- var
- ofile : text;
- filename : string[14];
- month1, year1, dow : integer;
- mposfnd, mpos, ypos : integer;
- mdays : array [1..12] of integer;
- month : array [1..12] of string[10];
- year : string;
- command : strptr;
- cmdline, yline : string;
- lyear : boolean;
- icount : integer;
- match, conout, diskout : boolean;
- byear, bday, bdow : integer;
-
- {****************************************************
- External PASCAL/MT+ System Functions
- *****************************************************}
- external function @cmd : strptr;
-
- {**************************************************************************
- Function: day_count
- Computes the number of days since the beginning of the year.
- (Jan 1 = Day 0)
- Input Parameters:
- day: integer in range 1-31
- month: integer in range 1-12
- year: integer
- mdays[i, 1<=i<=12 ]: number of days in month i, i=1=January
- (Global Parameter)
- Output Parameters:
- day_count: Number of days since 1st day of year (0=1st day)
- ***************************************************************************}
- function day_count (day, month, year : integer) : integer;
- var
- ndays, i : integer;
- begin
- ndays := day - 1; { Adjust for first day being day 0}
- if month <> 1 then for i:=1 to month-1 do ndays := ndays + mdays[i];
- { Compute Number of Days since Year Start }
- day_count := ndays;
- lyear := false; { Assume NOT Leap Year }
- if (year mod 4) <> 0 then exit; { If not Leap Year, Done }
- if ((year mod 100) = 0) and ((year mod 400) <> 0) then exit;
- { 2000, 2400, etc are Leap, other centurys not }
- lyear := true; { Leap Year }
- if month < 3 then exit; { If in Feb or Jan, Done }
- day_count := ndays + 1; { Adjust for Leap Year }
- end;
-
- {*********************************************************************
- Function: day_of_week
- Computes day of the week that a given date falls on.
- Input Parameters:
- day : integer in range 1-31
- month : integer in range 1-12
- year : integer
- Output Parameters:
- day_of_week : integer in range 1-7 (bday = Sunday)
- **********************************************************************}
- function day_of_week (day, month, year : integer) : integer;
- var
- ndays, tyear : integer;
- begin
- ndays := day_count (day, month, year); { Compute Number of Days }
- ndays := ndays + 365*(year - byear) + ((year - byear + 3) div 4);
- tyear := (year div 100) * 100; { Century below given year }
- if ((tyear mod 400) <> 0) and (byear < tyear) and (tyear < year) then
- ndays := ndays - 1; { Adjust for NO Leap Year century }
- day_of_week := (ndays mod 7) + 1;
- end;
-
- {************************************************************************
- Function: CLINE
- Print syntax of Command Line for Calendar Program.
- Input/Output Parameters: None
- *************************************************************************}
- procedure cline; { Print Syntax of Command Line }
- begin
- writeln(' Calendar Command Line should be:');
- writeln(' calendar month year /o');
- writeln(' ', byear1, ' <= YEAR <= 30,000 (approx)');
- writeln(' Only first three characters of MONTH are meaningful');
- writeln(' /O may be one of --');
- writeln(' /P to send output to Printer');
- writeln(' /D to send output to Disk File');
- writeln;
- writeln(' Examples:');
- writeln(' CALENDAR JAN 1982');
- writeln(' CALENDAR DECEMBER 2000');
- writeln(' CALENDAR 1982 /D');
- writeln(' CALENDAR 1984 /P');
- end;
-
- {*************************************************************************
- Function: NUMBER
- Converts the input string of digits to an integer.
- Input Parameter:
- value: string of digits
- Output Parameter:
- number: value of digit string; evaluation stops at
- first non-digit character
- **************************************************************************}
- function number (valstr : string) : integer;
- var
- idx, numb : integer;
- cont : boolean;
- digit : char;
- idigit : integer;
- val1 : string;
- begin
- val1 := valstr; { Temp Variable }
- numb := 0; { Initialize result }
-
- { Test for Empty Input String; if empty, return zero value }
- if length(val1) = 0 then begin
- number := numb; { Pass out value }
- exit;
- end;
-
- { Extract each digit from string and convert into result }
- cont := true;
- idx := 1;
- while cont do begin
- digit := val1[idx]; { Get next digit }
- if (digit < '0') or (digit > '9') then idigit := 10 else
- idigit := ord(digit) - ord('0'); { Convert to bin }
- if idigit = 10 then cont := false;
- if cont then numb := numb * 10 + idigit; { Update Value }
- idx := idx + 1; { Increment Char Pointer }
- if length (val1) < idx then cont := false;
- end;
- number := numb; { Final Value }
- end;
-
- {************************************************************************
- Function: CAL
- Prints one line of the calendar.
- Input Parameters:
- dow: Day of the Week to Start On
- day: Number of Day in Month
- month: Month of Year
- lyear: Leap Year (T/F)
- Output Parameter:
- cal: Number of next Day in Month (0=done)
- ************************************************************************}
- function cal (dow, day, month : integer) : integer;
- var
- i : integer;
- monlen, nday, ndays : integer;
- begin
- { If day is zero, print blank entry }
- if day=0 then begin
- for i:=1 to 7 do write(ofile, ' ');
- write(ofile, ' ');
- cal := 0;
- exit;
- end;
-
- { Determine number of days in month }
- monlen := mdays[month];
- { If month is Feb and it is a leap year, then add 1 }
- if (month=2) and lyear then monlen := monlen + 1;
-
- { If number < Sunday, set dow to 7+ }
- if dow < bday then dow := dow + 7;
-
- { If not Sunday, space over to proper starting column of month cal }
- if dow <> bday then for i:=1 to dow-bday do write(ofile, ' ');
-
- { Compute number of days in current line }
- ndays := 7 - (dow-bday);
- { If we exceed number of days in month, adjust to limit }
- if day+ndays > monlen then ndays := monlen-day+1;
-
- { We are in proper position, to print day entries in Calendar line }
- if ndays<>0 then for i:=1 to ndays do begin
- nday := day + i - 1;
- write(ofile, nday:2, ' ');
- end;
- { Fill out rest of line if end of calendar }
- if (day<>1) and (ndays<>7) then
- for i:=ndays+1 to 7 do write(ofile, ' ');
-
- { Write ending spaces }
- write(ofile, ' ');
-
- { Set return value to be day of month to start on or zero if done }
- if monlen < (ndays+day) then cal := 0 else cal := day + ndays;
-
- end; { CAL }
-
- {**********************************************************************
- Function: DOMONTH
- Prints Calendar for Month 'month1' of Year 'year1'.
- Input Parameters:
- month1: month number (1 to 12)
- year1: year number (byear to 30,000)
- Output Parameters:
- - None -
- ***********************************************************************}
- procedure domonth;
- var
- day1 : integer;
- begin
- { Determine what day of the week the first day of month falls on }
- day1 := day_of_week (1,month1,year1); { Day of 1st Day of Month }
-
- { Write header for Calendar Month }
- writeln(ofile); writeln(ofile, 'Calendar for ',month[month1],' ',
- year1);
- writeln(ofile, 'Su Mo Tu We Th Fr Sa');
-
- { Print first line of Calendar }
- day1 := cal (day1, 1, month1); writeln(ofile);
-
- { Print rest of Calendar }
- while day1 <> 0 do begin
- day1 := cal (bday, day1, month1);
- writeln(ofile);
- end;
-
- end; { DOMONTH }
-
- {**************************************************************
- Function: DOYEAR
- Prints Calendar for Year 'year1'.
- Input Parameters:
- year1: year number
- Output Parameters:
- - None -
- **************************************************************}
- procedure doyear;
- var
- dayx : array [1..3] of integer;
- idx, mbase, group3, group4 : integer;
-
- begin
- { Write Header for Calendar }
- writeln(ofile, ' Calendar of Year ', year1);
- writeln(ofile);
-
- { Loop over Calendar as 4 rows of three months each }
- for group3 := 1 to 4 do begin
- { Compute Base Month Number }
- mbase := (group3-1) * 3 + 1;
-
- { Page if output to CON: and beginning 3rd group of months }
- if (group3 = 3) and conout then begin
- write('Strike RETURN Key to Continue - ');
- readln; writeln;
- end;
-
- { Print Heading of Each Month }
- writeln(ofile);
- for group4 := mbase to mbase+2 do
- write(ofile, 'Calendar for ',month[group4], ' ');
- if ((group3 = 1) or (group3 = 3)) and conout then
- writeln(ofile, year1) else writeln(ofile);
- for group4 := mbase to mbase+2 do begin
- write(ofile, 'Su Mo Tu We Th Fr Sa ');
- idx := group4 mod 3; if idx=0 then idx := 3;
- dayx[idx] := day_of_week(1,group4,year1);
- end;
- writeln(ofile);
-
- { Print first line of Calendar }
- dayx[1] := cal (dayx[1], 1, mbase);
- dayx[2] := cal (dayx[2], 1, mbase+1);
- dayx[3] := cal (dayx[3], 1, mbase+2);
- writeln(ofile);
-
- { Print rest of Calendar }
- repeat
- dayx[1] := cal (bday, dayx[1], mbase);
- dayx[2] := cal (bday, dayx[2], mbase+1);
- dayx[3] := cal (bday, dayx[3], mbase+2);
- writeln(ofile);
- until dayx[1]+dayx[2]+dayx[3] = 0;
- writeln(ofile);
- end;
-
- end; { DOYEAR }
-
- {*************************************************************************
- Function: Initialize
- Initialize the command line pointer, the number of days
- in each month, and the names of the months.
- Input/Output Parameters: None
- **************************************************************************}
- procedure initialize;
- begin
- { Point to Command Line }
- command := @cmd;
- cmdline := command^;
-
- { Number of days in each month }
- mdays[1] := 31; mdays[2] := 28; mdays[3] := 31;
- mdays[4] := 30; mdays[5] := 31; mdays[6] := 30;
- mdays[7] := 31; mdays[8] := 31; mdays[9] := 30;
- mdays[10] := 31; mdays[11] := 30; mdays[12] := 31;
-
- { Names of each month }
- month[1] := 'JANUARY '; month[2] := 'FEBRUARY ';
- month[3] := 'MARCH '; month[4] := 'APRIL ';
- month[5] := 'MAY '; month[6] := 'JUNE ';
- month[7] := 'JULY '; month[8] := 'AUGUST ';
- month[9] := 'SEPTEMBER'; month[10] := 'OCTOBER ';
- month[11] := 'NOVEMBER '; month[12] := 'DECEMBER ';
-
- end; { Initialize }
-
- {Mainline}
- begin
- { Initialize Month Data and Command Line Pointer }
- initialize;
-
- { Print Banner }
- writeln('Calendar, Version ',(version div 10),'.',(version mod 10));
-
- { Determine Output Direction }
- diskout := false; { Assume no disk output }
- conout := false; { Assume no console output }
- if pos ('/D',cmdline) <> 0 then begin
- diskout := true;
- write('Name of Disk Output File? '); readln(filename); end
- else if pos ('/P',cmdline) <> 0 then filename := 'LST:'
- else begin
- filename := 'CON:'; conout := true; end;
-
- { Open Output File or Device }
- assign (ofile, filename);
- rewrite(ofile);
- if ioresult = 255 then begin
- writeln ('Fatal Error: Cannot Open ', filename, ' for Output');
- exit;
- end;
- writeln('Calendar Output File/Device is ',filename);
-
- { Determine which month was specified in command line }
- month1 := 0; { Assume none for all months }
- match := false; { No match found }
- for icount:=1 to 12 do begin
- mpos := pos (copy (month[icount],1,3), cmdline);
- if mpos <> 0 then begin
- if match then begin
- writeln('Error -- More than one month given');
- exit;
- end;
- match := true; { We have a match }
- month1 := icount;
- mposfnd := mpos;
- end;
- end;
-
- { Extract Year from command line }
- yline := copy (cmdline, mposfnd, length(cmdline)-mposfnd+1);
- ypos := pos (' ', yline);
- year := copy (yline, ypos, length(yline)-ypos+1);
- while (length(year) <> 0) and (year[1] = ' ') do
- year := copy (year, 2, length(year)-1);
- year1 := number(year); { Convert Year String into Number }
-
- { If no year specified, give syntax of command }
- if year1 = 0 then begin
- cline; { Print syntax of command line }
- exit;
- end;
- { If year specified is out of range, say so }
- if year1 < byear1 then begin
- write('Invalid Year Specification');
- writeln(' -- Year Specified was ',year1);
- writeln('Year MUST be such that ', byear1, ' <= Year');
- cline; { Print syntax of command line }
- exit;
- end;
-
- { Determine Base Year from byear1 and Base Day from bday1 }
- byear := byear1; bday := bday1;
- while year1 > byear+44 do begin
- bdow := day_of_week (1,1,byear+44); { First day of leap year }
- byear := byear + 44; { Set byear to next 11th leap year }
- if bdow <= bday then bday := bday - bdow + 1
- else bday := 7 - (bdow - bday) + 1;
- { bday = 1st Sunday of Leap Year }
- end;
-
- { Do Calendar }
- if ?match then doyear else domonth;
- if diskout then close (ofile, icount);
-
- end. {Mainline}
-