home *** CD-ROM | disk | FTP | other *** search
- /*
- * pcal.c - generate PostScript file to print calendar for any month and year
- *
- * The original PostScript code to generate the calendars was written by
- * Patrick Wood (Copywrite (c) 1987 by Patrick Wood of Pipeline Associates,
- * Inc.), and authorized for modification and redistribution. The calendar
- * file inclusion code was originally written in "bs(1)" by Bill Vogel of
- * AT&T. Patrick's original PostScript was modified and enhanced several
- * times by others whose names have regrettably been lost. This C version
- * was originally created by Ken Keirnan of Pacific Bell; additional
- * enhancements by Joseph P. Larson, Ed Hand, and Andrew Rogers (who also
- * did the VMS port).
- *
- * Revision history:
- *
- * 2.00 AWR 08/08/90 included revision history; replaced -r
- * flag with -l and -p; replaced -s and -S
- * flags with -b and -g; recognize flags
- * set in date file; translate ( and ) in
- * text to octal escape sequence; usage()
- * message condensed to fit 24x80 screen
- *
- * Parameters:
- *
- * pcal [opts] generate calendar for current month/year
- *
- * pcal [opts] yy generate calendar for entire year yy
- *
- * pcal [opts] mm yy generate calendar for month mm
- * (Jan = 1), year yy (19yy if yy < 100)
- *
- * pcal [opts] mm yy n as above, for n consecutive months
- *
- * Output:
- *
- * PostScript file to print calendars for all selected months.
- *
- * Options:
- *
- * -b <DAY> print specified weekday in black
- * -g <DAY> print specified weekday in gray
- * (default: print Saturdays and Sundays in gray)
- *
- * -d <FONT> specify alternate font for day names
- * (default: Times-Bold)
- *
- * -e generate empty calendar (ignore date file)
- *
- * -f <FILE> specify alternate date file (default:
- * ~/calendar on Un*x, SYS$LOGIN:CALENDAR.DAT
- * on VMS)
- *
- * -o <FILE> specify alternate output file (default:
- * stdout on Un*x, CALENDAR.PS on VMS)
- *
- * -l generate landscape-mode calendars
- * -p generate portrait-mode calendars
- * (default: landscape-mode)
- *
- * -t <FONT> specify alternate font for titles
- * (default: Times-Bold)
- *
- * Parameters and flags may be mixed on the command line.
- *
- * All but the -e and -f options may be specified in the date file by
- * the inclusion of one or more lines of the form "opt <options>". Any
- * such options override the defaults, but are themselves overridden
- * by options specified explicitly on the command line. (The -b, -d,
- * -g, -o, and -t flags may be specified without arguments to reset
- * the corresponding options to the defaults.)
- */
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include <time.h>
- #include <string.h>
-
- #ifdef VMS /* VMS oddities isolated here */
-
- #define DATEFILE "calendar.dat"
- #define OUTFILE "calendar.ps"
- #define END_PATH ']'
- #define EXIT_SUCCESS 1
- #define EXIT_FAILURE 3
-
- #else /* non-VMS - assume Un*x of some sort */
-
- #define DATEFILE "calendar"
- #define OUTFILE ""
- #define END_PATH '/'
- #define EXIT_SUCCESS 0
- #define EXIT_FAILURE 1
- extern char *getenv(); /* to translate "HOME" to path name */
-
- #endif
-
- #define IS_LEAP(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
- #define INIT_COLORS memcpy(color, default_color, sizeof(color))
-
- #define PRT (void)printf
- #define FPR (void)fprintf
-
- #define FALSE 0
- #define TRUE 1
-
- #define DATEFILE_FLAGS "ef" /* flags relating to date file name */
- #define OTHER_FLAGS "bdglopt" /* all other flags */
-
- #define DAYFONT "Times-Bold" /* default font names */
- #define TITLEFONT "Times-Bold"
-
- #define LANDSCAPE 90 /* degrees to rotate for landscape/portrait */
- #define PORTRAIT 0
- #define ROTATE LANDSCAPE /* default */
-
- #define BLACK 0 /* colors for dates */
- #define GRAY 1
-
- #define NO_DATEFILE 0 /* date file (if any) to use */
- #define USER_DATEFILE 1
- #define SYS_DATEFILE 2
-
- #define MIN_YR 1900 /* significant years (calendar limits) */
- #define MAX_YR 9999
-
- #define JAN 1 /* significant months */
- #define FEB 2
- #define DEC 12
-
- #define STRSIZ 100 /* size of misc. strings */
-
- #define MAXARGS 3 /* numeric command-line args */
-
- #define HOLIDAY (1 << 6) /* bit set to flag day as holiday */
-
- #define WHITESPACE " \t" /* token delimiters in date file */
-
- /*
- * Global variables:
- */
-
- FILE *dfp = NULL; /* date file pointer */
- int init_month; /* initial month, year, number of months */
- int init_year;
- int nmonths;
- int curr_year; /* current default year for date file entries */
- char *words[100]; /* maximum number of words per date file line */
- char lbuf[512]; /* maximum date file line size */
- char progname[STRSIZ]; /* program name (for error messages) */
- char color[7]; /* colors of weekdays - cf. default_color[] */
-
- /*
- * Default values for command-line options:
- */
-
- char default_color[7] = { /* -b, -g */
- GRAY, BLACK, BLACK, BLACK, BLACK, BLACK, GRAY /* cf. COLOR_MSG */
- };
-
- int datefile_type = SYS_DATEFILE; /* -e, -f */
- char datefile[STRSIZ] = "";
-
- int rotate = ROTATE; /* -l, -p */
-
- char dayfont[STRSIZ] = DAYFONT; /* -d, -t */
- char titlefont[STRSIZ] = TITLEFONT;
-
- char outfile[STRSIZ] = OUTFILE; /* -o */
-
- /*
- * Language-dependent strings (month and day names, option file keywords):
- */
-
- static char *months[12] = {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"
- };
-
- static char *days[7] = {
- "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
- "Saturday"
- };
-
- #define MIN_DAY_LEN 2 /* minimum size of day/month abbreviations */
- #define MIN_MONTH_LEN 3
-
- #define ALL "All" /* command-line or date file keywords */
- #define OPT "Opt"
- #define YEAR "Year"
-
- #define COLOR_MSG "Sat/Sun in gray, others in black" /* cf. usage() */
-
- /*
- * PostScript boilerplate
- */
-
- #include "pcalinit.h"
-
-
- /*
- * Main program - parse and validate command-line arguments, open files,
- * generate PostScript boilerplate and code to generate calendars.
- *
- * Program structure:
- *
- * main() calls get_args() once just to get the date file name and any numeric
- * arguments (month, year, number of months), and calls find_options() to make
- * a preliminary pass through the date file looking for "opt" lines (which
- * override the defaults for the command-line flags). It then calls get_args()
- * again to process the other command-line flags, which in turn override any
- * specified in the date file.
- *
- * main() then generates the common PostScript code and then calls pmonth() to
- * print the calendars.
- *
- * find_options() calls getline() to read the date file. Upon encountering
- * an "opt" line, it calls loadwords() to tokenize the line and get_args()
- * to parse it.
- *
- * pmonth() calls find_holidays() to make a first pass through the date file
- * to generate the list of holidays to be printed in gray; it then calls
- * find_daytext() to make a second pass to generate the text to be printed
- * inside the calendar boxes.
- *
- * find_holidays() and find_daytext() both call getday() to retrieve the next
- * day of interest from the date file.
- *
- * getday() calls getline() to read successive lines from the date file and
- * calls parse() to interpret them, stopping when parse() determines that the
- * line contains a usable date or when EOF is reached.
- *
- * getline() reads one or more lines from the date file, stripping comments
- * (# through end-of-line) and ignoring blank lines.
- *
- * parse() parses a line from the date file, determining whether or not it
- * contains a date in the current month and year. It calls utility routines
- * is_valid() to validate the date found and loadwords() to split any
- * accompanying text into individual tokens for PostScript to print.
- *
- */
- main(argc, argv)
- int argc;
- char **argv;
- {
- char *p, **ap;
- int i, month, year, ngray;
-
- #define DO_HEADER(phdr) for (ap = phdr; *ap; ap++) PRT("%s\n", *ap)
-
- INIT_COLORS; /* set up default colors */
-
- /* isolate root program name (for use in error messages) */
-
- strcpy(progname, **argv ? *argv : "pcal");
-
- if ((p = strrchr(progname, END_PATH)) != NULL)
- strcpy(progname, ++p);
- if ((p = strchr(progname, '.')) != NULL)
- *p = '\0';
-
- /*
- * Get the arguments from a) "opt" lines in the date file, and b)
- * the command line, in that order
- */
-
- /* parse command-line arguments once to find name of date file */
-
- if (!get_args(argv, DATEFILE_FLAGS, TRUE)) {
- usage();
- exit(EXIT_FAILURE);
- }
-
- /* Attempt to open the date file as specified by the [-e | -f] flags */
-
- switch (datefile_type) {
- case NO_DATEFILE:
- dfp = NULL;
- break;
-
- case USER_DATEFILE:
- /* Attempt to open user-specified calendar file */
- if ((dfp = fopen(datefile, "r")) == NULL) {
- FPR(stderr, "%s: can't open file %s\n", progname,
- datefile);
- exit(EXIT_FAILURE);
- }
- break;
-
- case SYS_DATEFILE:
- /* Look for the system (default) calendar file */
- #ifdef VMS
- strcpy(datefile, "SYS$LOGIN:"); /* get home directory (VMS) */
- #else
- *datefile = '\0'; /* translate "HOME" to path (Un*x) */
- if ((p = getenv("HOME")) != NULL) {
- strcat(datefile, p);
- strcat(datefile, "/");
- }
- #endif
- strcat(datefile, DATEFILE);
- dfp = fopen(datefile, "r"); /* no error if nonexistent */
- break;
- }
-
- find_options(); /* read date file looking for option lines */
-
- /* reparse command line - flags there supersede those in date file */
-
- get_args(argv, OTHER_FLAGS, FALSE);
-
- /* done with the arguments and flags - try to open the output file */
-
- if (*outfile && freopen(outfile, "w", stdout) == (FILE *) NULL) {
- FPR(stderr, "%s: can't open file %s\n", progname, outfile);
- exit(EXIT_FAILURE);
- }
-
- /*
- * Write out PostScript prolog
- */
-
- /* font names */
-
- PRT("%%!\n");
- PRT("/titlefont /%s def\n/dayfont /%s def\n", titlefont, dayfont);
-
- /* month names */
-
- PRT("/month_names [");
- for (i = 0; i < 12; i++)
- PRT("%s(%s) ", i % 6 == 0 ? "\n\t" : "", months[i]);
- PRT("] def\n");
-
- /* day names */
-
- PRT("/day_names [");
- for (i = 0; i < 7; i++)
- PRT("%s(%s) ", i % 6 == 0 ? "\n\t" : "", days[i]);
- PRT("] def\n");
-
- /* colors (black/gray) to print weekdays and holidays */
-
- PRT("/day_gray [");
- for (ngray = i = 0; i < 7; ngray += color[i++] == GRAY)
- PRT(" %s", color[i] == GRAY ? "true" : "false");
- PRT(" ] def\n");
- PRT("/holiday_gray %s def\n", ngray <= 3 ? "true" : "false");
-
- /* PostScript boilerplate (part 1) */
-
- DO_HEADER(header_1);
-
- /* landscape or portrait mode */
-
- PRT("\t%d rotate\n", rotate);
- if (rotate == LANDSCAPE)
- PRT("\t50 -120 translate\n");
- else
- PRT("\t0.75 0.75 scale\n\t50 460 translate\n");
-
- /* PostScript boilerplate (part 2) */
-
- DO_HEADER(header_2);
-
- /*
- * Write out PostScript code to print calendars
- */
-
- month = init_month;
- year = init_year;
-
- while (nmonths--) {
- pmonth(month, year);
- if (++month > DEC) {
- month = JAN;
- year++;
- }
- }
-
- if (dfp) /* close date file */
- fclose(dfp);
-
- #ifdef VMS
- FPR(stderr, "Output is in file %s\n", outfile);
- #endif
- exit(EXIT_SUCCESS);
- }
-
- /*
- * get_args - walk the argument list, parsing all arguments but processing only
- * those specified in "flags". If "do_numargs" is TRUE, processes numeric
- * arguments (month, year, number of months) as well.
- */
- int get_args(argv, flags, do_numargs)
- char **argv; /* argument list */
- char *flags; /* which flags to process */
- int do_numargs; /* process numeric arguments? */
- {
- char *p, *opt;
- int i, do_flag;
- long tmp; /* for getting current month/year */
- struct tm *p_tm;
- int badopt = FALSE; /* flag set if bad param */
- int nargs = 0; /* count of non-flag args */
- int numargs[MAXARGS]; /* non-flag (numeric) args */
-
- /* Look for the argument following flag - may be separated by spaces or
- * not (bumps argv in former case). If no non-flag argument appears, set
- * "arg" to NULL (-b, -d, -g, -o, and -t without an argument reset the
- * corresponding option to its default value).
- */
- #define GETARG(arg) arg = *(*argv + 2) ? *argv + 2 : \
- (*(argv+1) && **(argv+1) != '-' ? *++argv : NULL)
-
- /* Walk argument list, ignoring first element (program name) */
-
- while (*++argv) {
-
- /* Assume that any non-flag argument is a numeric argument */
- if (**argv != '-') {
- if (do_numargs && nargs < MAXARGS)
- numargs[nargs++] = atoi(*argv);
- continue;
- }
-
- /* Is this flag among those to be processed beyond parsing? */
-
- do_flag = strchr(flags, *(opt = *argv + 1)) != NULL;
-
- switch (*opt) {
-
- case 'b': /* print day in black or gray */
- case 'g':
- GETARG(p);
- if (do_flag)
- if (p)
- set_color(p, *opt == 'b' ? BLACK : GRAY);
- else
- INIT_COLORS; /* reset to defaults */
- break;
-
- case 'd': /* specify alternate day font */
- GETARG(p);
- if (do_flag)
- strcpy(dayfont, p ? p : DAYFONT);
- break;
-
- case 'e': /* generate empty calendar */
- if (do_flag) {
- datefile_type = NO_DATEFILE;
- datefile[0] = '\0';
- }
- break;
-
- case 'f': /* specify alternate date file */
- GETARG(p);
- if (p && do_flag) {
- datefile_type = USER_DATEFILE;
- strcpy(datefile, p);
- }
- break;
-
- case 'l': /* generate landscape calendar */
- if (do_flag)
- rotate = LANDSCAPE;
- break;
-
- case 'o': /* specify alternate output file */
- GETARG(p);
- if (do_flag)
- strcpy(outfile, p ? p : OUTFILE);
- break;
-
- case 'p': /* generate portrait calendar */
- if (do_flag)
- rotate = PORTRAIT;
- break;
-
- case 't': /* specify alternate title font */
- GETARG(p);
- if (do_flag)
- strcpy(titlefont, p ? p : TITLEFONT);
- break;
-
- default: /* unrecognized flag */
- FPR(stderr, "%s: illegal option -%s\n", progname, opt);
- badopt = TRUE;
- break;
- }
- }
-
- if (!do_numargs)
- return (!badopt); /* return TRUE if OK, FALSE if error */
-
- /* Validate non-flag (numeric) parameters */
-
- switch (nargs) {
- case 0: /* no arguments - print current month/year */
- time(&tmp);
- p_tm = localtime(&tmp);
- init_month = p_tm->tm_mon + 1;
- init_year = p_tm->tm_year;
- nmonths = 1;
- break;
- case 1: /* one argument - print entire year */
- init_month = JAN;
- init_year = numargs[0];
- nmonths = 12;
- break;
- default: /* two or three arguments - print one or more months */
- init_month = numargs[0];
- init_year = numargs[1];
- nmonths = nargs > 2 ? numargs[2] : 1;
- break;
- }
-
- if (nmonths < 1) /* ensure at least one month */
- nmonths = 1;
-
- /* check range of month and year */
-
- if (init_month < JAN || init_month > DEC) {
- FPR(stderr, "%s: month %d not in range 1 .. 12\n", progname,
- init_month);
- badopt = TRUE;
- }
-
- if (init_year > 0 && init_year < 100) /* treat nn as 19nn */
- init_year += 1900;
-
- if (init_year < MIN_YR || init_year > MAX_YR) {
- FPR(stderr, "%s year %d not in range %d .. %d\n", progname,
- init_year, MIN_YR, MAX_YR);
- badopt = TRUE;
- }
-
- return (!badopt); /* return TRUE if OK, FALSE if error */
- }
-
-
-
- /*
- * usage - print message explaining correct usage of the command-line
- * arguments and flags
- */
- usage()
- {
- FPR(stderr, "\nUsage:\t%s [-b DAY]* [-d FONT] [-e | -f FILE] [-g DAY]* [-o FILE]\n", progname);
- FPR(stderr, "\t\t[-l|-p] [-t FONT] [ [ [mm] yy ] | [mm yy n] ]\n");
- FPR(stderr, "\n");
- FPR(stderr, "\t-b DAY\t\tprint weekday DAY in black\n");
- FPR(stderr, "\t-g DAY\t\tprint weekday DAY in gray\n");
- FPR(stderr, "\t\t\t(default: %s)\n", COLOR_MSG);
- FPR(stderr, "\n");
- FPR(stderr, "\t-d FONT\t\tspecify alternate day name font (default: %s)\n",
- DAYFONT);
- FPR(stderr, "\t-t FONT\t\tspecify alternate title font (default: %s)\n",
- TITLEFONT);
- FPR(stderr, "\n");
- FPR(stderr, "\t-e\t\tgenerate empty calendar (ignore date file)\n");
- FPR(stderr, "\t-f FILE\t\tspecify alternate date file (default: %s)\n",
- DATEFILE);
- FPR(stderr, "\t-o FILE\t\tspecify alternate output file (default: %s)\n",
- OUTFILE[0] ? OUTFILE : "stdout");
- FPR(stderr, "\n");
- FPR(stderr, "\t-l\t\tgenerate landscape-style calendars");
- #if (ROTATE == LANDSCAPE)
- FPR(stderr, " (default)");
- #endif
- FPR(stderr, "\n\t-p\t\tgenerate portrait-style calendars");
- #if (ROTATE == PORTRAIT)
- FPR(stderr, " (default)");
- #endif
- FPR(stderr, "\n\n");
- FPR(stderr, "\tyy\t\tgenerate calendar for year yy (19yy if yy < 100)\n");
- FPR(stderr, "\tmm yy\t\tgenerate calendar for month mm (Jan = 1), year yy\n");
- FPR(stderr, "\tmm yy n\t\tgenerate calendars for n months, starting at mm/yy\n");
- FPR(stderr, "\t(default)\tgenerate calendar for current month/year\n");
- }
-
-
- /*
- * is_valid - return TRUE if d is a valid date in m/y (assumed valid)
- */
- int is_valid(m, d, y)
- register int m, d, y;
- {
- static char len[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
- return (d >= 1 && d <= (len[m] + (m == FEB && IS_LEAP(y))) );
- }
-
-
- /*
- * loadwords - tokenize line buffer into word array, return word count
- * (assumes strtok() has already been called with non-null first arg)
- */
- int loadwords()
- {
- register char **ap = words;
- register i;
-
- for (i = 0; *ap = strtok(NULL, WHITESPACE) ; ap++, i++) ;
- return(i);
- }
-
-
- /*
- * strcap - convert first character of string to uppercase, rest to lowercase
- */
- char *strcap(s)
- char *s;
- {
- char *p = s;
-
- if (*p) {
- if (islower(*p))
- *p = toupper(*p);
- while (*++p)
- if (isupper(*p))
- *p = tolower(*p);
- }
- return(s);
- }
-
-
- /*
- * set_color - set one or all weekdays to print in black or gray
- */
- set_color(day, col)
- char *day; /* weekday name (or "all") */
- int col; /* select black or gray */
- {
- int i, do_all;
-
- do_all = strncmp(strcap(day), ALL, strlen(ALL)) == 0; /* set all days? */
-
- for (i = 0; i < 7; i++)
- if (do_all || strncmp(day, days[i], MIN_DAY_LEN) == 0)
- color[i] = col;
- }
-
-
- /*
- * prt_word - print word as PostScript string, converting '(' and ')' to octal
- */
- prt_word(p)
- char *p;
- {
- PRT("(");
- for ( ; *p ; p++)
- if (*p == '(' || *p == ')')
- PRT("\\%03o", *p);
- else
- PRT("%c", *p);
- PRT(")\n");
- }
-
- /*
- * parse - check date file entry for (in lbuf[]) for desired month/year
- *
- * Looks for an entry of one of the following forms:
- *
- * year <year>
- * <month_name> <day>{*} {<text>}
- * <month><sep><day>{<sep><year>}{*} {<text>}
- *
- * where
- * <month_name> := first 3+ characters of name of month (in English)
- * <sep> := one or more non-numeric, non-space, non-'*' characters
- *
- * Returns day (with holiday flag set if specified) if date file entry
- * is applicable to current month/year; 0 if not. If applicable, parses
- * any following text into global array words[].
- *
- * Also see find_options(), which is used during an initial pass to identify
- * and parse only lines of the form
- *
- * opt <options>
- *
- * which override defaults for command-line options.
- */
- int parse(month, year)
- register int month, year;
- {
- register char *cp;
- int mm, dd, yy;
- int is_holiday;
-
- /* macro to skip numeric field */
-
- #define SKIP_FIELD(p) \
- if (1) {while (isdigit(*p)) p++; while (*p && !isdigit(*p)) p++;} else
-
- /*
- * Get first field - can be either "year", "opt" (ignored), a month
- * name, or a (complete) numeric date spec
- */
-
- cp = strtok(lbuf, WHITESPACE); /* set up strtok() to parse line */
-
- /*
- * If field begins with alpha, look for "year" or month name
- */
- if (isalpha(*cp)) {
- strcap(cp);
-
- /* Check for "year" line */
-
- if (strcmp(cp, YEAR) == 0) {
- cp = strtok(NULL, WHITESPACE);
- if ((yy = atoi(cp)) > 0) {
- if (yy < 100)
- yy += 1900;
- curr_year = yy;
- }
- return(0);
- }
-
- /* Check month and year. "opt" falls out here */
-
- if (year != curr_year ||
- strncmp(cp, months[month-1], MIN_MONTH_LEN) != 0)
- return(0);
-
- /* month found, get and validate day */
-
- if ((cp = strtok(NULL, WHITESPACE)) == NULL ||
- !is_valid(month, dd = atoi(cp), year))
- return(0);
-
- is_holiday = cp[strlen(cp) - 1] == '*'; /* look for holiday flag */
-
- if (loadwords() || is_holiday)
- return(dd | is_holiday * HOLIDAY);
- return(0);
- }
-
- /*
- * Not alpha month, try numeric date (parse completely in case year
- * has changed)
- */
-
- is_holiday = cp[strlen(cp) - 1] == '*'; /* look for holiday flag */
-
- /* extract month and day fields */
-
- mm = atoi(cp);
- SKIP_FIELD(cp);
-
- dd = atoi(cp);
- SKIP_FIELD(cp);
-
- /* Numeric dates may (or may not) have a year */
-
- if ((yy = atoi(cp)) > 0) {
- if (yy < 100)
- yy += 1900;
- curr_year = yy;
- }
-
- /* if date is valid and significant (text or holiday flag), return it */
-
- if (mm == month && curr_year == year && is_valid(month, dd, year) &&
- (loadwords() || is_holiday))
- return(dd | is_holiday * HOLIDAY);
- return(0);
- }
-
-
- /*
- * getline - read next non-null line of input file into lbuf; return 0 on EOF
- */
- int getline()
- {
- register char *cp;
- register int c;
- int in_comment; /* comments: from '#' to end-of-line */
-
- cp = lbuf;
- do {
- in_comment = FALSE;
- while ((c = getc(dfp)) != '\n' && c != EOF) {
- if (c == '#')
- in_comment = TRUE;
-
- /* ignore comments and leading white space */
- if (in_comment ||
- (cp == lbuf && (c == ' ' || c == '\t')))
- continue;
- *cp++ = c;
- }
- if (c == EOF)
- return(0);
-
- } while (cp == lbuf); /* ignore empty lines */
-
- *cp = '\0';
- return(1);
- }
-
-
- /*
- * getday - find next day entry for specified month and year in the date file
- */
- int getday(month, year, reset)
- register int month, year;
- int reset; /* TRUE: rewind date file */
- {
- static int eof = FALSE;
- int day;
-
- if (dfp == NULL) /* whoops, no date file */
- return(0);
-
- if (reset) { /* rewind file, reset default year, clear eof */
- rewind(dfp);
- curr_year = init_year;
- eof = FALSE;
- }
-
- if (eof)
- return(0);
-
- /* read lines until we find a line we want or until EOF */
-
- do {
- if (!getline()) {
- eof = TRUE;
- return(0);
- }
- } while ( (day = parse(month, year)) == 0);
-
- return(day);
- }
-
- /*
- * Browse through the date file looking for day text in specified month/year
- */
- find_daytext(month, year)
- int month, year;
- {
- register char **s;
- register int oldday = -1;
- register int day;
-
- for (day = getday(month, year, TRUE);
- day != 0;
- day = getday(month, year, FALSE))
- if (*words) {
- day &= ~HOLIDAY;
- if (day != oldday) {
- if (oldday != -1)
- PRT("] daytext\n");
- PRT("%d [ \n", day);
- oldday = day;
- } else
- PRT("(.p)\n");
- for (s = words; *s; s++)
- prt_word(*s);
- }
-
- if (oldday != -1) /* terminate last call to daytext (if any) */
- PRT("] daytext\n");
- }
-
-
- /*
- * Browse through the date file looking for holidays in specified month/year
- */
- find_holidays(month, year)
- int month, year;
- {
- register int day;
- unsigned long holidays = 0;
-
- /* get unique, sorted list of holidays by setting bits in flag word */
-
- for (day = getday(month, year, TRUE);
- day != 0;
- day = getday(month, year, FALSE))
- if (day & HOLIDAY)
- holidays |= 1 << (day & ~HOLIDAY);
-
- PRT("/holidays ["); /* start definition of list */
- for (day = 1; day <= 31; day++)
- if (holidays & (1 << day))
- PRT(" %d", day);
- PRT(" 99 ] def\n"); /* terminate with dummy entry */
- }
-
- /*
- * Browse through the date file looking for "opt" lines; parse any found
- */
- find_options()
- {
- char *cp, **argv;
-
- if (!dfp)
- return;
-
- rewind(dfp);
-
- /* read all lines in date file; if "opt" found, tokenize and parse it */
-
- while (getline()) {
-
- cp = strtok(lbuf, WHITESPACE); /* initialize strtok() */
-
- if (isalpha(*cp) && strncmp(strcap(cp), OPT, strlen(OPT)) == 0) {
- loadwords(); /* tokenize the option line */
- argv = &words[-1]; /* argv[1] points to words[0] */
-
- if (!get_args(argv, OTHER_FLAGS, FALSE)) {
- usage();
- exit(EXIT_FAILURE);
- }
- }
- }
- }
-
-
- /*
- * pmonth - generate calendar for specified month/year
- */
- pmonth(month, year)
- int month, year;
- {
-
- PRT("/year %d def\n", year); /* set up year and month */
- PRT("/month %d def\n", month);
- find_holidays(month, year); /* first pass - make list of holidays */
- PRT("printmonth\n");
- find_daytext(month, year); /* second pass - add text to boxes */
- PRT("showpage\n");
- }
-