home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
OS2MNX1.ZIP
/
CAL.C
next >
Wrap
C/C++ Source or Header
|
1989-12-28
|
9KB
|
347 lines
/* $Header: D:/RCS/RCS/cal.c 1.1 89/12/26 22:57:46 RCA Exp $
* $Log: cal.c $
* Revision 1.1 89/12/26 22:57:46 RCA
* Initial revision
*
*/
/* cal - print a calendar Author: Martin Minow */
#include <stdio.h>
#define do3months domonth
#define IO_SUCCESS 0
#define IO_ERROR 1
#define EOS 0
#define ENTRY_SIZE 3
#define DAYS_PER_WEEK 7
#define WEEKS_PER_MONTH 6
#define MONTHS_PER_LINE 3
#define MONTH_SPACE 3
char *badarg = {"Bad argument\n"};
char *how = {"Usage: cal [month] year (4 digits)\n"};
/*
* calendar() stuffs data into layout[], output() copies from
* layout[] to outline[], (then trims blanks).
*/
char layout[MONTHS_PER_LINE][WEEKS_PER_MONTH][DAYS_PER_WEEK][ENTRY_SIZE];
char outline[(MONTHS_PER_LINE * DAYS_PER_WEEK * ENTRY_SIZE)
+ (MONTHS_PER_LINE * MONTH_SPACE)
+ 1];
char *weekday = " S M Tu W Th F S";
char *monthname[] = {
"???", /* No month 0 */
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
main(argc, argv)
int argc;
char *argv[];
{
register int month;
register int year;
register int arg1val;
int arg1len;
int arg2val;
if (argc <= 1)
{
usage(how);
} else
{
arg1val = atoi(argv[1]);
arg1len = strlen(argv[1]);
if (argc == 2)
{
/*
* Only one argument, if small, it's a month. If large,
* it's a year. Note: cal 0082 Year 0082 cal 82
* Year 0082
*/
if (arg1len <= 2 && arg1val <= 12)
do3months(year, arg1val);
else
doyear(arg1val);
} else
{
/*
* Two arguments, allow 1980 12 or 12 1980
*/
arg2val = atoi(argv[2]);
if (arg1len > 2)
do3months(arg1val, arg2val);
else
do3months(arg2val, arg1val);
}
}
exit(IO_SUCCESS);
}
doyear(year)
int year;
/*
* Print the calendar for an entire year.
*/
{
register int month;
if (year < 1 || year > 9999)
usage(badarg);
if (year < 100)
printf("\n\n\n 00%2d\n\n", year);
else
printf("\n\n\n%35d\n\n", year);
for (month = 1; month <= 12; month += MONTHS_PER_LINE)
{
printf("%12s%23s%23s\n",
monthname[month],
monthname[month + 1],
monthname[month + 2]);
printf("%s %s %s\n", weekday, weekday, weekday);
calendar(year, month + 0, 0);
calendar(year, month + 1, 1);
calendar(year, month + 2, 2);
output(3);
#if MONTHS_PER_LINE != 3
<<error, the above won 't work >>
#endif
}
printf("\n\n\n");
}
domonth(year, month)
int year;
int month;
/*
* Do one specific month -- note: no longer used
*/
{
if (year < 1 || year > 9999)
usage(badarg);
if (month <= 0 || month > 12)
usage(badarg);
printf("%9s%5d\n\n%s\n", monthname[month], year, weekday);
calendar(year, month, 0);
output(1);
printf("\n\n");
}
output(nmonths)
int nmonths; /* Number of months to do */
/*
* Clean up and output the text.
*/
{
register int week;
register int month;
register char *outp;
int i;
char tmpbuf[21], *p;
for (week = 0; week < WEEKS_PER_MONTH; week++)
{
outp = outline;
for (month = 0; month < nmonths; month++)
{
/*
* The -1 in the following removes the unwanted leading
* blank from the entry for Sunday.
*/
p = &layout[month][week][0][1];
for (i = 0; i < 20; i++)
tmpbuf[i] = *p++;
tmpbuf[20] = 0;
sprintf(outp, "%s ", tmpbuf);
outp += (DAYS_PER_WEEK * ENTRY_SIZE) + MONTH_SPACE - 1;
}
while (outp > outline && outp[-1] == ' ')
outp--;
*outp = EOS;
puts(outline);
}
}
calendar(year, month, index)
int year;
int month;
int index; /* Which of the three months */
/*
* Actually build the calendar for this month.
*/
{
register char *tp;
int week;
register int wday;
register int today;
setmonth(year, month);
for (week = 0; week < WEEKS_PER_MONTH; week++)
{
for (wday = 0; wday < DAYS_PER_WEEK; wday++)
{
tp = &layout[index][week][wday][0];
*tp++ = ' ';
today = getdate(week, wday);
if (today <= 0)
{
*tp++ = ' ';
*tp++ = ' ';
} else
if (today < 10)
{
*tp++ = ' ';
*tp = (today + '0');
} else
{
*tp++ = (today / 10) + '0';
*tp = (today % 10) + '0';
}
}
}
}
usage(s)
char *s;
{
/* Fatal parameter error. */
fprintf(stderr, "%s", s);
exit(IO_ERROR);
}
/*
* Calendar routines, intended for eventual porting to TeX
*
* date(year, month, week, wday) Returns the date on this week (0 is
* first, 5 last possible) and day of the week (Sunday == 0)
* Note: January is month 1.
*
* setmonth(year, month) Parameters are as above, sets getdate() for
* this month.
*
* int getdate(week, wday) Parameters are as above, uses the data
* set by setmonth()
*/
/*
* This structure is used to pass data between setmonth() and
* getdate(). It needs considerable expansion if the
* Julian->Gregorian change is to be extended to other countries.
*/
static struct
{
int this_month; /* month number used in 1752 checking */
int feb; /* Days in February for this month */
int sept; /* Days in September for this month */
int days_in_month; /* Number of days in this month */
int dow_first; /* Day of week of the 1st day in month */
} info;
static int day_month[] = { /* 30 days hath September... */
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int
date(year, month, week, wday)
int year; /* Calendar date being computed */
int month; /* January == 1 */
int week; /* Week in the month 0..5 inclusive */
int wday; /* Weekday, Sunday == 0 */
/*
* Return the date of the month that fell on this week and
* weekday. Return zero if it's out of range.
*/
{
setmonth(year, month);
return (getdate(week, wday));
}
setmonth(year, month)
int year; /* Year to compute */
int month; /* Month, January is month 1 */
/*
* Setup the parameters needed to compute this month (stored in
* the info structure).
*/
{
register int i;
if (month < 1 || month > 12)
{ /* Verify caller's parameters */
info.days_in_month = 0; /* Garbage flag */
return;
}
info.this_month = month; /* used in 1752 checking */
info.dow_first = Jan1(year); /* Day of January 1st for now */
info.feb = 29; /* Assume leap year */
info.sept = 30; /* Assume normal year */
/*
* Determine whether it's an ordinary year, a leap year or the
* magical calendar switch year of 1752.
*/
switch ((Jan1(year + 1) + 7 - info.dow_first) % 7)
{
case 1: /* Not a leap year */
info.feb = 28;
case 2: /* Ordinary leap year */
break;
default: /* The magical moment arrives */
info.sept = 19; /* 19 days hath September */
break;
}
info.days_in_month =
(month == 2) ? info.feb
: (month == 9) ? info.sept
: day_month[month];
for (i = 1; i < month; i++)
{
switch (i)
{ /* Special months? */
case 2: /* February */
info.dow_first += info.feb;
break;
case 9:
info.dow_first += info.sept;
break;
default:
info.dow_first += day_month[i];
break;
}
}
info.dow_first %= 7; /* Now it's Sunday to Saturday */
}
int
getdate(week, wday)
int week;
int wday;
{
register int today;
/*
* Get a first guess at today's date and make sure it's in range.
*/
today = (week * 7) + wday - info.dow_first + 1;
if (today <= 0 || today > info.days_in_month)
return (0);
else
if (info.sept == 19 && info.this_month == 9
&& today >= 3) /* The magical month? */
return (today + 11); /* If so, some dates changed */
else /* Otherwise, */
return (today); /* Return the date */
}
static int
Jan1(year)
int year;
/*
* Return day of the week for Jan 1 of the specified year.
*/
{
register int day;
day = year + 4 + ((year + 3) / 4); /* Julian Calendar */
if (year > 1800)
{ /* If it's recent, do */
day -= ((year - 1701) / 100); /* Clavian correction */
day += ((year - 1601) / 400); /* Gregorian correction */
}
if (year > 1752) /* Adjust for Gregorian */
day += 3; /* calendar */
return (day % 7);
}