allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (03/22/89)
Posting-number: Volume 6, Issue 74 Submitted-by: THE MASTER <evh@vax1.acs.udel.edu> Archive-name: pcal #! /bin/sh # To extract, remove mail header lines and type "sh filename" echo x - README sed -e 's/^X//' > README << '!FaR!OuT!' XTo compile: X----------- X X cc -o pcal pcal.c X X X X X XInfo on usage etc: X------------------ X XI wrote this because I was interested in writing a routine to figure Xout the day of the week for a specific date(as it ended up, I couldn't Xget my hands on any algorithm so I got ripped some code from some one's Xprogram in the archives). Any how I ended up writing this calendar program. X X XI call this program 'pcal' because it it prints out one month per page. XEach month is separated by control-L type form feed character. XFor testing, I picked random years and verified them. XEach month is made up of a grid of 7(width) by 5(height) squares. Any Xmonth that requires over 5 squares high wil have the the appropriate Xdays split in half. X X XA typical month looks like. X X X 1989 X X April X X | SUN | MON | TUE | WED | THU | FRI | SAT | X ----------------------------------------------------------------------- X | | | | | | | 1| | X | | | | | | |--- | X | | | | | | | | X | | | | | | | | X | | | | | | | | X ----------------------------------------------------------------------- X | 2| | 3| | 4| | 5| | 6| | 7| | 8| | X |--- |--- |--- |--- |--- |--- |--- | X | | | | | | | | X | | | | | | | | X | | | | | | | | X ----------------------------------------------------------------------- X | 9| |10| |11| |12| |13| |14| |15| | X |--- |--- |--- |--- |--- |--- |--- | X | | | | | | | | X | | | | | | | | X | | | | | | | | X ----------------------------------------------------------------------- X |16| |17| |18| |19| |20| |21| |22| | X |--- |--- |--- |--- |--- |--- |--- | X | | | | | | | | X | | | | | | | | X | | | | | | | | X ----------------------------------------------------------------------- X |23| _/|24| |25| |26| |27| |28| |29| | X |--- _/ |--- |--- |--- |--- |--- |--- | X | _/ | | | | | | | X | _/ ---| | | | | | | X |/ |30| | | | | | | X ----------------------------------------------------------------------- X X X X XUsage: pcal [-l] [-m startmonth] X [-n nummonths] [-u] [-y startyear] X startmonth:day of month to start on(1=jan...12=dec) X startyear :year to start on(1989=1989, 89=0089) X default startday=1, startmonth=1, X startyear=current year X nummonths :#of months to print out(default is 12) X -l :suppress printing of ^L's after each month X default is to print them X -u :print this synopsis X X X XExamples: X Say todays date is March 17, 1989. X X X pcal -> print out a 12 month calendar for the year 1989. X Each month is printed on a separate page. X X pcal -n 3 ->print out Jan,Feb,March of 1989, each on a separate X page. X X pcal -n 3 -l ->print out Jan,Feb,March of 1989. Each month is printed X one after another. X X pcal -m 4 -n 1 -> prints out the month of April, 1989 and a form feed. X X pcal -m 4 -y 1992 -n 24 ->prints out months from April, 1992 to X April, 1994. Each month separated by a control-L. X X XFeel free to make any changes to the code, but leave my name at the top Xof the code file(s). X !FaR!OuT! echo x - pcal.c sed -e 's/^X//' > pcal.c << '!FaR!OuT!' X/*pcal.c Sun Feb 26 23:08:25 EST 1989*/ X X X X/* X *Contents: One page per month calendar program. X * X *Author : Troy Saville(evh@vax1.acs.udel.edu) X * X *Compiling: cc -o pcal pcal.c X * X *byebye - make a clean exit from the program X *getmmddyy - get month,day,year of todays date(from the system) X *isleapyear - determine if year is a leap year X *jan1 - get day of week for 1st day of a year X *dayofweek - get day of week for any day of any year X *genweek - driver to print out one week of a month X *genmonth - driver to print out a complete month X *main - the pcal program X * X */ X X X X X X X/*generate a calender, 1 month per page*/ X X X#include <stdio.h> X#include <strings.h> X#include <time.h> X X X X/*width of calendar, not including margin*/ X#define NUMWIDTH 71 X/*#of spaces to indent calendar*/ X#define NUMINDENT 4 X X#define INDENT() printf("%-*.*s",NUMINDENT,NUMINDENT,spaces) X X/*check for split sqaure on calendar*/ X#define THESPLIT (weeknum == 5) && (endday < numdays) && (week[i]+7 <= numdays) X X Xstatic char *spaces = " "; Xstatic char *dashes = "-------------------------------------------------------------------------------"; X Xstatic int daysinmonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; X Xchar *monthnames[] = {"January", "February", "March", "April", "May", "June", X "July", "August", "September", "October", "November", X "December"}; X Xchar *daynames[] = {"Sun" ,"Mon" ,"Tue" ,"Wed" ,"Thu" ,"Fri" ,"Sat" }; X X X/*day of week that first day starts on*/ X#define DAYSTART 0 X X/*first month to print out*/ X#define MONSTART 0 X X X/*exit the program cleanly - display error message*/ Xvoid byebye(fmt,a1,a2,a3,a4,a5,a6,a7) X char *fmt; X int a1,a2,a3,a4,a5,a6,a7; X { X if (fmt != NULL) X { X char tmp[80]; X sprintf(tmp,fmt,a1,a2,a3,a4,a5,a6,a7); X printf(tmp); X } X X printf("\n"); X printf("Usage: pcal [-l] [-m startmonth]\n"); X printf(" [-n nummonths] [-u] [-y startyear]\n"); X printf(" startmonth:day of month to start on(1=jan...12=dec)\n"); X printf(" startyear :year to start on(1989=1989, 89=0089)\n"); X printf(" default startday=1, startmonth=1,\n"); X printf(" startyear=current year\n"); X printf(" nummonths :#of months to print out(default is 12)\n"); X printf(" -l :suppress printing of ^L's after each month\n"); X printf(" default is to print them\n"); X printf(" -u :print this synopsis\n"); X X exit(0); X } X X X X/*get month,day,year of today date, year=89(mean actual year is 1989*/ Xvoid getmmddyy(month,day,year) X int *month, *day, *year; X { X long clockval,time(); X struct tm *dateinfo,*localtime(); X X clockval = time((long *) 0); X X dateinfo = localtime(&clockval); X if (month) X *month = dateinfo->tm_mon+1; X if (day) X *day = dateinfo->tm_mday; X if (year) X *year = dateinfo->tm_year; X } X X X X X/****************************************************************************** X *isleapyear Tue Oct 25, 1988 -> 21:42:56 X * X *returns 1 if 'year' is a leap year else returns 0. X *1988 should be passed as 1988 and not 88. X */ Xint isleapyear(year) X int year; X { X return((!(year % 4)) && (year % 100) ? 1 : 0); X } X X X/*Return day of the week for Jan 1 of the specified year.*/ X/*0=sunday....6=saturday*/ X/*I ripped this out of someone elses program*/ X/*author unknown*/ Xint jan1(year) X int year; X { X int day; X X day = year + 4 + ((year + 3) / 4); /* Julian Calendar */ X if (year > 1800) /* If it's recent, do */ X { X day -= ((year - 1701) / 100); /* Clavian correction */ X day += ((year - 1601) / 400); /* Gregorian correction */ X } X if (year > 1752) /* Adjust for Gregorian */ X day += 3; /* calendar */ X X return (day % 7); X } X X X X X/*return day of the week for the date passed in*/ X/*month = 0-11, day is 1 based, year is assumed to be 4 digits*/ X/*RETURN:0= sunday.....6=saturday*/ Xint dayofweek(month,day,year) X int month,day,year; X { X int i; X int dow = (-1); X X dow += day + jan1(year); X X for(i=0;i < month;i++) X dow += daysinmonth[i] + ((i == 1) * isleapyear(year)); X X return(dow % 7); X } X X X/************************************************************************ X *genweek Mon Feb 27 00:46:16 EST 1989 X * - generate calander for 1 week X */ Xvoid genweek(week,weeknum,startday,daysinweek,numdays) X int week[]; /*#of each day of week to be generated*/ X int weeknum; /*week # for current month*/ X int startday; /*starting day X int daysinweek; /*last day to be generated*/ X int numdays; /*#days in month*/ X { X int i; X int row; X int endday; X X if (weeknum > 5) X return; X X endday = startday + daysinweek - 1; X X X for(row=0;row < 5;row++) X { X INDENT(); X printf("|"); X X for(i=0;i< 7;i++) X { X /*see if day of the week contains a day for this month*/ X if (week[i]) X switch(row) X { X case 0: X printf("%2d| %s",week[i], X (THESPLIT) ? "_/" : " "); X break; X X case 1: X printf("--- %s ",(THESPLIT) ? "_/" : " "); X break; X X case 2: X printf(" %s ",(THESPLIT) ? "_/" : " "); X break; X X case 3: X printf(" %s",(THESPLIT) ? "_/ ---" : " "); X break; X X case 4: X if (THESPLIT) X printf("/ |%2d",week[i]+7); X else X printf(" "); X break; X } X else /*this day of the week is in last month or next month*/ X printf("%-9.9s",spaces); X printf("|"); X } X X printf("\n"); X } X X INDENT(); X printf("%-*.*s\n", NUMWIDTH, NUMWIDTH,dashes); X } X X X X/************************************************************************ X *genmonth Sun Feb 26 23:21:30 EST 1989 X * - generate calander for 1 month X */ Xvoid genmonth(month,year) X int month; X int year; X { X int i,j,k; X int startday; /*day of week 1st day starts on*/ X int numdays; /*#days in month*/ X int dow; /*dat of week*/ X int weeknum = 1; /*# of the current week to print*/ X int week[7]; X X i = (80 - strlen(monthnames[month])) / 2; X X printf("%-*.*s%-s\n\n",i,i,spaces,monthnames[month]); X X numdays = daysinmonth[month] + ((month==1) * isleapyear(year)); X X startday = dayofweek(month,1,year); X X INDENT(); X printf("| SUN | MON | TUE | WED | THU | FRI | SAT |\n"); X INDENT(); X printf("%-*.*s\n", NUMWIDTH, NUMWIDTH,dashes); X X /*figure out first row*/ X /*first row of calander*/ X for(i=0,j=0;i < 7;i++) X if (i >= startday) X week[i] = ++j; X else X week[i] = 0; X X /*generate row for one week of calendar*/ X i = 7 - startday; X genweek(week,weeknum,1,i,numdays); X X /*rest of calendar*/ X for(k=0; i < numdays;i += k,k=0) X { X for(j=0;j < 7;j++) X if ((i+k) < numdays) X week[j] = ++k + i; X else X week[j] = 0; X if (k) X genweek(week,++weeknum,i+1,k,numdays); X } X } X X X X/************************************************************************** X *main X * - main program X * X */ Xmain(argc,argv) X int argc; X char *argv[]; X { X int i,j; X int curmonth = 1; /*current month of year*/ X int curyear; /*current year*/ X int numday; /*#of the day of the week*/ X int nummonths = 12; /*#of months to print out*/ X int controll = 0; /*suppress printing of control L's 0=no, 1=yes*/ X X X /*set defaults*/ X getmmddyy(0,0,&curyear); X curyear += 1900; X X /*parse command line args*/ X for(i=1;i<argc;i++) X { X if (argv[i][0] == '-') X switch(argv[i][1]) X { X case 'm': /*day # of the week to start calander on*/ X if (++i == argc) X byebye("-m requires integer arguement"); X else if ( (sscanf(argv[i],"%d", &curmonth) != 1) || X (curmonth < 1) || (curmonth > 12) ) X byebye("Bad arg '%s' for -m flag\n", argv[i]); X break; X X case 'n': /*#of months to print*/ X if (++i == argc) X byebye("-n requires integer arguement"); X else if ( (sscanf(argv[i],"%d", &nummonths) != 1) || X (nummonths < 1) ) X byebye("Bad arg '%s' for -n flag\n", argv[i]); X break; X X case 'y': /*day # of the week to start calander on*/ X if (++i == argc) X byebye("-y requires integer arguement"); X else if (sscanf(argv[i],"%d", &curyear) != 1) X byebye("Bad arg '%s' for -y flag\n", argv[i]); X break; X X case 'l': /*suppress ^L's*/ X controll = 1; X break; X X case 'u': /*usage*/ X byebye(0); X break; X X default: X byebye("Bad command line arguement: %s",argv[i]); X break; X } X else X byebye("Bad command line arguement: %s",argv[i]); X } X X curmonth--; X X X /*loop through months*/ X for(;nummonths > 0;nummonths--, curmonth++) X { X if (curmonth == 12) X { X curmonth = 0; X curyear++; X } X X printf("\n\n\n%-*.*s%-4d\n\n",38,38,spaces,curyear); X X genmonth(curmonth,curyear); X X if (!controll) X printf(" \n"); /*form feed to next page*/ X } X X X } X X X X X X X !FaR!OuT! exit