Home | History | Annotate | Line # | Download | only in cal
cal.c revision 1.19
      1  1.19     lukem /*	$NetBSD: cal.c,v 1.19 2005/06/02 01:38:50 lukem Exp $	*/
      2   1.6     glass 
      3   1.1       cgd /*
      4   1.6     glass  * Copyright (c) 1989, 1993, 1994
      5   1.6     glass  *	The Regents of the University of California.  All rights reserved.
      6   1.1       cgd  *
      7   1.1       cgd  * This code is derived from software contributed to Berkeley by
      8   1.1       cgd  * Kim Letkeman.
      9   1.1       cgd  *
     10   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     11   1.1       cgd  * modification, are permitted provided that the following conditions
     12   1.1       cgd  * are met:
     13   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     14   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     15   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     17   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     18  1.18       agc  * 3. Neither the name of the University nor the names of its contributors
     19   1.1       cgd  *    may be used to endorse or promote products derived from this software
     20   1.1       cgd  *    without specific prior written permission.
     21   1.1       cgd  *
     22   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32   1.1       cgd  * SUCH DAMAGE.
     33   1.1       cgd  */
     34   1.1       cgd 
     35   1.7     lukem #include <sys/cdefs.h>
     36   1.1       cgd #ifndef lint
     37   1.7     lukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
     38   1.7     lukem 	The Regents of the University of California.  All rights reserved.\n");
     39   1.1       cgd #endif /* not lint */
     40   1.1       cgd 
     41   1.1       cgd #ifndef lint
     42   1.6     glass #if 0
     43   1.6     glass static char sccsid[] = "@(#)cal.c	8.4 (Berkeley) 4/2/94";
     44   1.6     glass #else
     45  1.19     lukem __RCSID("$NetBSD: cal.c,v 1.19 2005/06/02 01:38:50 lukem Exp $");
     46   1.6     glass #endif
     47   1.1       cgd #endif /* not lint */
     48   1.1       cgd 
     49   1.1       cgd #include <sys/types.h>
     50   1.6     glass 
     51   1.6     glass #include <ctype.h>
     52   1.6     glass #include <err.h>
     53  1.14      yamt #include <errno.h>
     54  1.14      yamt #include <limits.h>
     55   1.1       cgd #include <stdio.h>
     56   1.6     glass #include <stdlib.h>
     57   1.4       cgd #include <string.h>
     58  1.15    atatat #include <termcap.h>
     59   1.6     glass #include <time.h>
     60   1.8  christos #include <tzfile.h>
     61   1.6     glass #include <unistd.h>
     62   1.1       cgd 
     63   1.1       cgd #define	SATURDAY 		6		/* 1 Jan 1 was a Saturday */
     64   1.1       cgd 
     65  1.17    atatat #define	FIRST_MISSING_DAY 	reform->first_missing_day
     66  1.17    atatat #define	NUMBER_MISSING_DAYS 	reform->missing_days
     67   1.1       cgd 
     68   1.1       cgd #define	MAXDAYS			42		/* max slots in a month array */
     69   1.1       cgd #define	SPACE			-1		/* used in day array */
     70   1.1       cgd 
     71   1.1       cgd static int days_in_month[2][13] = {
     72   1.1       cgd 	{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     73   1.1       cgd 	{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     74   1.1       cgd };
     75   1.1       cgd 
     76  1.17    atatat int empty[MAXDAYS] = {
     77   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     78   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     79   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     80   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     81   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     82   1.1       cgd 	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,	SPACE,
     83   1.1       cgd };
     84  1.17    atatat int shift_days[2][4][MAXDAYS + 1];
     85   1.1       cgd 
     86   1.1       cgd char *month_names[12] = {
     87   1.1       cgd 	"January", "February", "March", "April", "May", "June",
     88   1.1       cgd 	"July", "August", "September", "October", "November", "December",
     89   1.1       cgd };
     90   1.1       cgd 
     91   1.1       cgd char *day_headings = " S  M Tu  W Th  F  S";
     92   1.1       cgd char *j_day_headings = "  S   M  Tu   W  Th   F   S";
     93   1.1       cgd 
     94  1.17    atatat /* leap years according to the julian calendar */
     95  1.17    atatat #define j_leap_year(y, m, d) \
     96  1.17    atatat 	(((m) > 2) && \
     97  1.17    atatat 	 !((y) % 4))
     98  1.17    atatat 
     99  1.17    atatat /* leap years according to the gregorian calendar */
    100  1.17    atatat #define g_leap_year(y, m, d) \
    101  1.17    atatat 	(((m) > 2) && \
    102  1.17    atatat 	 ((!((y) % 4) && ((y) % 100)) || \
    103  1.17    atatat 	  !((y) % 400)))
    104  1.17    atatat 
    105  1.17    atatat /* leap year -- account for gregorian reformation at some point */
    106   1.1       cgd #define	leap_year(yr) \
    107  1.17    atatat 	((yr) <= reform->year ? j_leap_year((yr), 3, 1) : \
    108  1.17    atatat 	g_leap_year((yr), 3, 1))
    109   1.1       cgd 
    110  1.17    atatat /* number of julian leap days that have passed by a given date */
    111  1.17    atatat #define j_leap_days(y, m, d) \
    112  1.17    atatat 	((((y) - 1) / 4) + j_leap_year(y, m, d))
    113  1.17    atatat 
    114  1.17    atatat /* number of gregorian leap days that have passed by a given date */
    115  1.17    atatat #define g_leap_days(y, m, d) \
    116  1.17    atatat 	((((y) - 1) / 4) - (((y) - 1) / 100) + (((y) - 1) / 400) + \
    117  1.17    atatat 	g_leap_year(y, m, d))
    118  1.17    atatat 
    119  1.17    atatat /*
    120  1.17    atatat  * Subtracting the gregorian leap day count (for a given date) from
    121  1.17    atatat  * the julian leap day count (for the same date) describes the number
    122  1.17    atatat  * of days from the date before the shift to the next date that
    123  1.17    atatat  * appears in the calendar.  Since we want to know the number of
    124  1.17    atatat  * *missing* days, not the number of days that the shift spans, we
    125  1.17    atatat  * subtract 2.
    126  1.17    atatat  *
    127  1.17    atatat  * Alternately...
    128  1.17    atatat  *
    129  1.17    atatat  * There's a reason they call the Dark ages the Dark Ages.  Part of it
    130  1.17    atatat  * is that we don't have that many records of that period of time.
    131  1.17    atatat  * One of the reasons for this is that a lot of the Dark Ages never
    132  1.17    atatat  * actually took place.  At some point in the first millenium A.D., a
    133  1.17    atatat  * ruler of some power decided that he wanted the number of the year
    134  1.17    atatat  * to be different than what it was, so he changed it to coincide
    135  1.17    atatat  * nicely with some event (a birthday or anniversary, perhaps a
    136  1.17    atatat  * wedding, or maybe a centennial for a largish city).  One of the
    137  1.17    atatat  * side effects of this upon the Gregorian reform is that two Julian
    138  1.17    atatat  * leap years (leap days celebrated during centennial years that are
    139  1.17    atatat  * not quatro-centennial years) were skipped.
    140  1.17    atatat  */
    141  1.17    atatat #define GREGORIAN_MAGIC 2
    142  1.17    atatat 
    143  1.17    atatat /* number of centuries since the reform, not inclusive */
    144  1.17    atatat #define	centuries_since_reform(yr) \
    145  1.17    atatat 	((yr) > reform->year ? ((yr) / 100) - (reform->year / 100) : 0)
    146  1.17    atatat 
    147  1.17    atatat /* number of centuries since the reform whose modulo of 400 is 0 */
    148  1.17    atatat #define	quad_centuries_since_reform(yr) \
    149  1.17    atatat 	((yr) > reform->year ? ((yr) / 400) - (reform->year / 400) : 0)
    150   1.1       cgd 
    151   1.1       cgd /* number of leap years between year 1 and this year, not inclusive */
    152   1.1       cgd #define	leap_years_since_year_1(yr) \
    153  1.17    atatat 	((yr) / 4 - centuries_since_reform(yr) + quad_centuries_since_reform(yr))
    154  1.17    atatat 
    155  1.17    atatat struct reform {
    156  1.17    atatat 	const char *country;
    157  1.17    atatat 	int ambiguity, year, month, date;
    158  1.17    atatat 	long first_missing_day;
    159  1.17    atatat 	int missing_days;
    160  1.17    atatat 	/*
    161  1.17    atatat 	 * That's 2 for standard/julian display, 4 for months possibly
    162  1.17    atatat 	 * affected by the Gregorian shift, and MAXDAYS + 1 for the
    163  1.17    atatat 	 * days that get displayed, plus a crib slot.
    164  1.17    atatat 	 */
    165  1.17    atatat } *reform, reforms[] = {
    166  1.17    atatat 	{ "DEFAULT",		0, 1752,  9,  3 },
    167  1.17    atatat 	{ "Italy",		1, 1582, 10,  5 },
    168  1.17    atatat 	{ "Spain",		1, 1582, 10,  5 },
    169  1.17    atatat 	{ "Portugal",		1, 1582, 10,  5 },
    170  1.17    atatat 	{ "Poland",		1, 1582, 10,  5 },
    171  1.17    atatat 	{ "France",		2, 1582, 12, 10 },
    172  1.17    atatat 	{ "Luxembourg",		2, 1582, 12, 22 },
    173  1.17    atatat 	{ "Netherlands",	2, 1582, 12, 22 },
    174  1.17    atatat 	{ "Bavaria",		0, 1583, 10,  6 },
    175  1.17    atatat 	{ "Austria",		2, 1584,  1,  7 },
    176  1.17    atatat 	{ "Switzerland",	2, 1584,  1, 12 },
    177  1.17    atatat 	{ "Hungary",		0, 1587, 10, 22 },
    178  1.17    atatat 	{ "Germany",		0, 1700,  2, 19 },
    179  1.17    atatat 	{ "Norway",		0, 1700,  2, 19 },
    180  1.17    atatat 	{ "Denmark",		0, 1700,  2, 19 },
    181  1.17    atatat 	{ "Great Britain",	0, 1752,  9,  3 },
    182  1.17    atatat 	{ "England",		0, 1752,  9,  3 },
    183  1.17    atatat 	{ "America",		0, 1752,  9,  3 },
    184  1.17    atatat 	{ "Sweden",		0, 1753,  2, 18 },
    185  1.17    atatat 	{ "Finland",		0, 1753,  2, 18 },
    186  1.17    atatat 	{ "Japan",		0, 1872, 12, 20 },
    187  1.17    atatat 	{ "China",		0, 1911, 11,  7 },
    188  1.17    atatat 	{ "Bulgaria",		0, 1916,  4,  1 },
    189  1.17    atatat 	{ "U.S.S.R.",		0, 1918,  2,  1 },
    190  1.17    atatat 	{ "Serbia",		0, 1919,  1, 19 },
    191  1.17    atatat 	{ "Romania",		0, 1919,  1, 19 },
    192  1.17    atatat 	{ "Greece",		0, 1924,  3, 10 },
    193  1.17    atatat 	{ "Turkey",		0, 1925, 12, 19 },
    194  1.17    atatat 	{ "Egypt",		0, 1928,  9, 18 },
    195  1.17    atatat 	{ NULL,			0,    0,  0,  0 },
    196  1.17    atatat };
    197   1.1       cgd 
    198   1.1       cgd int julian;
    199  1.17    atatat int dow;
    200  1.15    atatat int hilite;
    201  1.15    atatat char *md, *me;
    202   1.1       cgd 
    203  1.15    atatat void	init_hilite(void);
    204  1.14      yamt int	getnum(const char *);
    205  1.17    atatat void	gregorian_reform(const char *);
    206  1.17    atatat void	reform_day_array(int, int, int *, int *, int *,int *,int *,int *);
    207  1.15    atatat int	ascii_day(char *, int);
    208  1.12     perry void	center(char *, int, int);
    209  1.12     perry void	day_array(int, int, int *);
    210  1.12     perry int	day_in_week(int, int, int);
    211  1.12     perry int	day_in_year(int, int, int);
    212  1.14      yamt void	monthrange(int, int, int, int, int);
    213  1.12     perry int	main(int, char **);
    214  1.12     perry void	trim_trailing_spaces(char *);
    215  1.12     perry void	usage(void);
    216   1.6     glass 
    217   1.6     glass int
    218  1.12     perry main(int argc, char **argv)
    219   1.1       cgd {
    220   1.1       cgd 	struct tm *local_time;
    221   1.6     glass 	time_t now;
    222  1.14      yamt 	int ch, month, year, yflag;
    223  1.17    atatat 	int before, after, use_reform;
    224  1.14      yamt 	int yearly = 0;
    225  1.17    atatat 	char *when;
    226   1.1       cgd 
    227  1.14      yamt 	before = after = 0;
    228  1.17    atatat 	use_reform = yflag = year = 0;
    229  1.17    atatat 	when = NULL;
    230  1.17    atatat 	while ((ch = getopt(argc, argv, "A:B:d:hjR:ry3")) != -1) {
    231  1.12     perry 		switch (ch) {
    232  1.14      yamt 		case 'A':
    233  1.14      yamt 			after = getnum(optarg);
    234  1.14      yamt 			break;
    235  1.14      yamt 		case 'B':
    236  1.14      yamt 			before = getnum(optarg);
    237  1.14      yamt 			break;
    238  1.17    atatat 		case 'd':
    239  1.17    atatat 			dow = getnum(optarg);
    240  1.17    atatat 			if (dow < 0 || dow > 6)
    241  1.17    atatat 				errx(1, "illegal day of week value: use 0-6");
    242  1.17    atatat 			break;
    243  1.15    atatat 		case 'h':
    244  1.15    atatat 			init_hilite();
    245  1.15    atatat 			break;
    246   1.1       cgd 		case 'j':
    247   1.1       cgd 			julian = 1;
    248   1.1       cgd 			break;
    249  1.17    atatat 		case 'R':
    250  1.17    atatat 			when = optarg;
    251  1.17    atatat 			break;
    252  1.17    atatat 		case 'r':
    253  1.17    atatat 			use_reform = 1;
    254  1.17    atatat 			break;
    255   1.1       cgd 		case 'y':
    256   1.1       cgd 			yflag = 1;
    257   1.1       cgd 			break;
    258  1.13     perry 		case '3':
    259  1.14      yamt 			before = after = 1;
    260  1.13     perry 			break;
    261   1.1       cgd 		case '?':
    262   1.1       cgd 		default:
    263   1.1       cgd 			usage();
    264  1.12     perry 			/* NOTREACHED */
    265   1.1       cgd 		}
    266  1.12     perry 	}
    267  1.13     perry 
    268   1.1       cgd 	argc -= optind;
    269   1.1       cgd 	argv += optind;
    270   1.1       cgd 
    271  1.17    atatat 	if (when != NULL)
    272  1.17    atatat 		gregorian_reform(when);
    273  1.17    atatat 	if (reform == NULL)
    274  1.17    atatat 		gregorian_reform("DEFAULT");
    275  1.17    atatat 
    276   1.1       cgd 	month = 0;
    277  1.12     perry 	switch (argc) {
    278   1.1       cgd 	case 2:
    279   1.6     glass 		if ((month = atoi(*argv++)) < 1 || month > 12)
    280   1.6     glass 			errx(1, "illegal month value: use 1-12");
    281   1.1       cgd 		/* FALLTHROUGH */
    282   1.1       cgd 	case 1:
    283   1.6     glass 		if ((year = atoi(*argv)) < 1 || year > 9999)
    284   1.6     glass 			errx(1, "illegal year value: use 1-9999");
    285   1.1       cgd 		break;
    286   1.1       cgd 	case 0:
    287   1.1       cgd 		(void)time(&now);
    288   1.1       cgd 		local_time = localtime(&now);
    289  1.17    atatat 		if (use_reform)
    290  1.17    atatat 			year = reform->year;
    291  1.17    atatat 		else
    292  1.17    atatat 			year = local_time->tm_year + TM_YEAR_BASE;
    293  1.17    atatat 		if (!yflag) {
    294  1.17    atatat 			if (use_reform)
    295  1.17    atatat 				month = reform->month;
    296  1.17    atatat 			else
    297  1.17    atatat 				month = local_time->tm_mon + 1;
    298  1.17    atatat 		}
    299   1.1       cgd 		break;
    300   1.1       cgd 	default:
    301   1.1       cgd 		usage();
    302   1.1       cgd 	}
    303   1.1       cgd 
    304  1.14      yamt 	if (!month) {
    305  1.14      yamt 		/* yearly */
    306  1.14      yamt 		month = 1;
    307  1.14      yamt 		before = 0;
    308  1.14      yamt 		after = 11;
    309  1.14      yamt 		yearly = 1;
    310  1.14      yamt 	}
    311  1.14      yamt 
    312  1.14      yamt 	monthrange(month, year, before, after, yearly);
    313  1.13     perry 
    314   1.1       cgd 	exit(0);
    315   1.1       cgd }
    316   1.1       cgd 
    317   1.1       cgd #define	DAY_LEN		3		/* 3 spaces per day */
    318   1.1       cgd #define	J_DAY_LEN	4		/* 4 spaces per day */
    319   1.1       cgd #define	WEEK_LEN	20		/* 7 * 3 - one space at the end */
    320   1.1       cgd #define	J_WEEK_LEN	27		/* 7 * 4 - one space at the end */
    321   1.1       cgd #define	HEAD_SEP	2		/* spaces between day headings */
    322   1.1       cgd #define	J_HEAD_SEP	2
    323  1.14      yamt #define	MONTH_PER_ROW	3		/* how many monthes in a row */
    324  1.14      yamt #define	J_MONTH_PER_ROW	2
    325   1.1       cgd 
    326   1.6     glass void
    327  1.14      yamt monthrange(int month, int year, int before, int after, int yearly)
    328   1.1       cgd {
    329  1.14      yamt 	int startmonth, startyear;
    330  1.14      yamt 	int endmonth, endyear;
    331  1.14      yamt 	int i, row;
    332  1.14      yamt 	int days[3][MAXDAYS];
    333  1.15    atatat 	char lineout[256];
    334  1.14      yamt 	int inayear;
    335  1.14      yamt 	int newyear;
    336  1.14      yamt 	int day_len, week_len, head_sep;
    337  1.14      yamt 	int month_per_row;
    338  1.15    atatat 	int skip, r_off, w_off;
    339  1.14      yamt 
    340  1.14      yamt 	if (julian) {
    341  1.14      yamt 		day_len = J_DAY_LEN;
    342  1.14      yamt 		week_len = J_WEEK_LEN;
    343  1.14      yamt 		head_sep = J_HEAD_SEP;
    344  1.14      yamt 		month_per_row = J_MONTH_PER_ROW;
    345  1.14      yamt 	}
    346  1.14      yamt 	else {
    347  1.14      yamt 		day_len = DAY_LEN;
    348  1.14      yamt 		week_len = WEEK_LEN;
    349  1.14      yamt 		head_sep = HEAD_SEP;
    350  1.14      yamt 		month_per_row = MONTH_PER_ROW;
    351  1.14      yamt 	}
    352  1.14      yamt 
    353  1.14      yamt 	month--;
    354  1.14      yamt 
    355  1.14      yamt 	startyear = year - (before + 12 - 1 - month) / 12;
    356  1.14      yamt 	startmonth = 12 - 1 - ((before + 12 - 1 - month) % 12);
    357  1.14      yamt 	endyear = year + (month + after) / 12;
    358  1.14      yamt 	endmonth = (month + after) % 12;
    359   1.1       cgd 
    360  1.14      yamt 	if (startyear < 0 || endyear > 9999) {
    361  1.14      yamt 		errx(1, "year should be in 1-9999\n");
    362   1.1       cgd 	}
    363   1.1       cgd 
    364  1.14      yamt 	year = startyear;
    365  1.14      yamt 	month = startmonth;
    366  1.14      yamt 	inayear = newyear = (year != endyear || yearly);
    367  1.14      yamt 	if (inayear) {
    368  1.14      yamt 		skip = month % month_per_row;
    369  1.14      yamt 		month -= skip;
    370  1.14      yamt 	}
    371  1.14      yamt 	else {
    372  1.14      yamt 		skip = 0;
    373  1.14      yamt 	}
    374  1.14      yamt 
    375  1.14      yamt 	do {
    376  1.14      yamt 		if (newyear) {
    377  1.14      yamt 			(void)snprintf(lineout, sizeof(lineout), "%d", year);
    378  1.14      yamt 			center(lineout, week_len * month_per_row +
    379  1.14      yamt 			    head_sep * (month_per_row - 1), 0);
    380  1.14      yamt 			(void)printf("\n\n");
    381  1.14      yamt 			newyear = 0;
    382  1.14      yamt 		}
    383  1.14      yamt 
    384  1.14      yamt 		for (i = 0; i < skip; i++)
    385  1.14      yamt 			center("", week_len, head_sep);
    386  1.14      yamt 
    387  1.14      yamt 		for (; i < month_per_row; i++) {
    388  1.14      yamt 			int sep;
    389  1.14      yamt 
    390  1.14      yamt 			if (year == endyear && month + i > endmonth)
    391  1.14      yamt 				break;
    392  1.14      yamt 
    393  1.14      yamt 			sep = (i == month_per_row - 1) ? 0 : head_sep;
    394  1.14      yamt 			day_array(month + i + 1, year, days[i]);
    395  1.14      yamt 			if (inayear) {
    396  1.14      yamt 				center(month_names[month + i], week_len, sep);
    397  1.14      yamt 			}
    398  1.14      yamt 			else {
    399  1.14      yamt 				snprintf(lineout, sizeof(lineout), "%s %d",
    400  1.14      yamt 				    month_names[month + i], year);
    401  1.14      yamt 				center(lineout, week_len, sep);
    402   1.1       cgd 			}
    403   1.1       cgd 		}
    404  1.14      yamt 		printf("\n");
    405  1.14      yamt 
    406  1.14      yamt 		for (i = 0; i < skip; i++)
    407  1.14      yamt 			center("", week_len, head_sep);
    408  1.14      yamt 
    409  1.14      yamt 		for (; i < month_per_row; i++) {
    410  1.14      yamt 			int sep;
    411  1.14      yamt 
    412  1.14      yamt 			if (year == endyear && month + i > endmonth)
    413  1.14      yamt 				break;
    414  1.14      yamt 
    415  1.14      yamt 			sep = (i == month_per_row - 1) ? 0 : head_sep;
    416  1.17    atatat 			if (dow) {
    417  1.17    atatat 				printf("%s ", (julian) ?
    418  1.17    atatat 				    j_day_headings + 4 * dow :
    419  1.17    atatat 				    day_headings + 3 * dow);
    420  1.17    atatat 				printf("%.*s", dow * (julian ? 4 : 3) - 1,
    421  1.17    atatat 				       (julian) ? j_day_headings : day_headings);
    422  1.17    atatat 			} else
    423  1.17    atatat 				printf("%s", (julian) ? j_day_headings : day_headings);
    424  1.17    atatat 			printf("%*s", sep, "");
    425  1.14      yamt 		}
    426  1.14      yamt 		printf("\n");
    427   1.1       cgd 
    428   1.1       cgd 		for (row = 0; row < 6; row++) {
    429  1.19     lukem 			char *p = NULL;
    430  1.16      yamt 
    431  1.16      yamt 			memset(lineout, ' ', sizeof(lineout));
    432  1.14      yamt 			for (i = 0; i < skip; i++) {
    433  1.16      yamt 				/* nothing */
    434  1.14      yamt 			}
    435  1.15    atatat 			w_off = 0;
    436  1.14      yamt 			for (; i < month_per_row; i++) {
    437  1.14      yamt 				int col, *dp;
    438  1.14      yamt 
    439  1.14      yamt 				if (year == endyear && month + i > endmonth)
    440  1.14      yamt 					break;
    441  1.14      yamt 
    442  1.15    atatat 				p = lineout + i * (week_len + 2) + w_off;
    443  1.14      yamt 				dp = &days[i][row * 7];
    444  1.15    atatat 				for (col = 0; col < 7;
    445  1.15    atatat 				     col++, p += day_len + r_off) {
    446  1.15    atatat 					r_off = ascii_day(p, *dp++);
    447  1.15    atatat 					w_off += r_off;
    448  1.15    atatat 				}
    449   1.1       cgd 			}
    450   1.3       cgd 			*p = '\0';
    451   1.1       cgd 			trim_trailing_spaces(lineout);
    452   1.1       cgd 			(void)printf("%s\n", lineout);
    453   1.1       cgd 		}
    454  1.13     perry 
    455  1.14      yamt 		skip = 0;
    456  1.14      yamt 		month += month_per_row;
    457  1.14      yamt 		if (month >= 12) {
    458  1.14      yamt 			month -= 12;
    459  1.14      yamt 			year++;
    460  1.14      yamt 			newyear = 1;
    461  1.13     perry 		}
    462  1.14      yamt 	} while (year < endyear || (year == endyear && month <= endmonth));
    463  1.13     perry }
    464  1.13     perry 
    465   1.1       cgd /*
    466   1.1       cgd  * day_array --
    467   1.1       cgd  *	Fill in an array of 42 integers with a calendar.  Assume for a moment
    468   1.1       cgd  *	that you took the (maximum) 6 rows in a calendar and stretched them
    469   1.1       cgd  *	out end to end.  You would have 42 numbers or spaces.  This routine
    470   1.1       cgd  *	builds that array for any month from Jan. 1 through Dec. 9999.
    471   1.1       cgd  */
    472   1.6     glass void
    473  1.12     perry day_array(int month, int year, int *days)
    474   1.1       cgd {
    475   1.6     glass 	int day, dw, dm;
    476  1.15    atatat 	time_t t;
    477  1.15    atatat 	struct tm *tm;
    478  1.15    atatat 
    479  1.15    atatat 	t = time(NULL);
    480  1.15    atatat 	tm = localtime(&t);
    481  1.15    atatat 	tm->tm_year += TM_YEAR_BASE;
    482  1.15    atatat 	tm->tm_mon++;
    483  1.15    atatat 	tm->tm_yday++; /* jan 1 is 1 for us, not 0 */
    484   1.1       cgd 
    485  1.17    atatat 	for (dm = month + year * 12, dw = 0; dw < 4; dw++) {
    486  1.17    atatat 		if (dm == shift_days[julian][dw][MAXDAYS]) {
    487  1.17    atatat 			memmove(days, shift_days[julian][dw],
    488  1.17    atatat 				MAXDAYS * sizeof(int));
    489  1.17    atatat 			return;
    490  1.17    atatat 		}
    491   1.1       cgd 	}
    492  1.17    atatat 
    493   1.6     glass 	memmove(days, empty, MAXDAYS * sizeof(int));
    494   1.1       cgd 	dm = days_in_month[leap_year(year)][month];
    495   1.1       cgd 	dw = day_in_week(1, month, year);
    496   1.1       cgd 	day = julian ? day_in_year(1, month, year) : 1;
    497  1.15    atatat 	while (dm--) {
    498  1.15    atatat 		if (hilite && year == tm->tm_year &&
    499  1.15    atatat 		    (julian ? (day == tm->tm_yday) :
    500  1.15    atatat 		     (month == tm->tm_mon && day == tm->tm_mday)))
    501  1.17    atatat 			days[dw++] = SPACE - day++;
    502  1.15    atatat 		else
    503  1.15    atatat 			days[dw++] = day++;
    504  1.15    atatat 	}
    505   1.1       cgd }
    506   1.1       cgd 
    507   1.1       cgd /*
    508   1.1       cgd  * day_in_year --
    509   1.1       cgd  *	return the 1 based day number within the year
    510   1.1       cgd  */
    511   1.6     glass int
    512  1.12     perry day_in_year(int day, int month, int year)
    513   1.1       cgd {
    514   1.6     glass 	int i, leap;
    515   1.1       cgd 
    516   1.1       cgd 	leap = leap_year(year);
    517   1.1       cgd 	for (i = 1; i < month; i++)
    518   1.1       cgd 		day += days_in_month[leap][i];
    519   1.6     glass 	return (day);
    520   1.1       cgd }
    521   1.1       cgd 
    522   1.1       cgd /*
    523   1.1       cgd  * day_in_week
    524   1.1       cgd  *	return the 0 based day number for any date from 1 Jan. 1 to
    525  1.17    atatat  *	31 Dec. 9999.  Returns the day of the week of the first
    526  1.17    atatat  *	missing day for any given Gregorian shift.
    527   1.1       cgd  */
    528   1.6     glass int
    529  1.12     perry day_in_week(int day, int month, int year)
    530   1.1       cgd {
    531   1.1       cgd 	long temp;
    532   1.1       cgd 
    533   1.1       cgd 	temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
    534   1.1       cgd 	    + day_in_year(day, month, year);
    535   1.1       cgd 	if (temp < FIRST_MISSING_DAY)
    536  1.17    atatat 		return ((temp - dow + 6 + SATURDAY) % 7);
    537   1.1       cgd 	if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS))
    538  1.17    atatat 		return (((temp - dow + 6 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
    539  1.17    atatat 	return ((FIRST_MISSING_DAY - dow + 6 + SATURDAY) % 7);
    540   1.1       cgd }
    541   1.1       cgd 
    542  1.15    atatat int
    543  1.12     perry ascii_day(char *p, int day)
    544   1.1       cgd {
    545  1.15    atatat 	int display, val, rc;
    546  1.15    atatat 	char *b;
    547   1.1       cgd 	static char *aday[] = {
    548   1.1       cgd 		"",
    549   1.1       cgd 		" 1", " 2", " 3", " 4", " 5", " 6", " 7",
    550   1.1       cgd 		" 8", " 9", "10", "11", "12", "13", "14",
    551   1.1       cgd 		"15", "16", "17", "18", "19", "20", "21",
    552   1.1       cgd 		"22", "23", "24", "25", "26", "27", "28",
    553   1.1       cgd 		"29", "30", "31",
    554   1.1       cgd 	};
    555   1.1       cgd 
    556   1.1       cgd 	if (day == SPACE) {
    557   1.1       cgd 		memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
    558  1.15    atatat 		return (0);
    559   1.1       cgd 	}
    560  1.17    atatat 	if (day < SPACE) {
    561  1.15    atatat 		b = p;
    562  1.17    atatat 		day = SPACE - day;
    563  1.15    atatat 	} else
    564  1.15    atatat 		b = NULL;
    565   1.1       cgd 	if (julian) {
    566   1.7     lukem 		if ((val = day / 100) != 0) {
    567   1.1       cgd 			day %= 100;
    568   1.1       cgd 			*p++ = val + '0';
    569   1.1       cgd 			display = 1;
    570   1.1       cgd 		} else {
    571   1.1       cgd 			*p++ = ' ';
    572   1.1       cgd 			display = 0;
    573   1.1       cgd 		}
    574   1.1       cgd 		val = day / 10;
    575   1.1       cgd 		if (val || display)
    576   1.1       cgd 			*p++ = val + '0';
    577   1.1       cgd 		else
    578   1.1       cgd 			*p++ = ' ';
    579   1.1       cgd 		*p++ = day % 10 + '0';
    580   1.1       cgd 	} else {
    581   1.1       cgd 		*p++ = aday[day][0];
    582   1.1       cgd 		*p++ = aday[day][1];
    583   1.1       cgd 	}
    584  1.15    atatat 
    585  1.15    atatat 	rc = 0;
    586  1.15    atatat 	if (b != NULL) {
    587  1.15    atatat 		char *t, h[64];
    588  1.15    atatat 		int l;
    589  1.15    atatat 
    590  1.15    atatat 		l = p - b;
    591  1.15    atatat 		memcpy(h, b, l);
    592  1.15    atatat 		p = b;
    593  1.15    atatat 
    594  1.15    atatat 		if (md != NULL) {
    595  1.15    atatat 			for (t = md; *t; rc++)
    596  1.15    atatat 				*p++ = *t++;
    597  1.15    atatat 			memcpy(p, h, l);
    598  1.15    atatat 			p += l;
    599  1.15    atatat 			for (t = me; *t; rc++)
    600  1.15    atatat 				*p++ = *t++;
    601  1.15    atatat 		} else {
    602  1.15    atatat 			for (t = &h[0]; l--; t++) {
    603  1.15    atatat 				*p++ = *t;
    604  1.15    atatat 				rc++;
    605  1.15    atatat 				*p++ = '\b';
    606  1.15    atatat 				rc++;
    607  1.15    atatat 				*p++ = *t;
    608  1.15    atatat 			}
    609  1.15    atatat 		}
    610  1.15    atatat 	}
    611  1.15    atatat 
    612   1.1       cgd 	*p = ' ';
    613  1.15    atatat 	return (rc);
    614   1.1       cgd }
    615   1.1       cgd 
    616   1.6     glass void
    617  1.12     perry trim_trailing_spaces(char *s)
    618   1.1       cgd {
    619   1.6     glass 	char *p;
    620   1.1       cgd 
    621   1.6     glass 	for (p = s; *p; ++p)
    622   1.6     glass 		continue;
    623  1.11  christos 	while (p > s && isspace((unsigned char)*--p))
    624   1.6     glass 		continue;
    625   1.1       cgd 	if (p > s)
    626   1.1       cgd 		++p;
    627   1.1       cgd 	*p = '\0';
    628   1.1       cgd }
    629   1.1       cgd 
    630   1.6     glass void
    631  1.12     perry center(char *str, int len, int separate)
    632   1.1       cgd {
    633   1.6     glass 
    634   1.1       cgd 	len -= strlen(str);
    635   1.1       cgd 	(void)printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
    636   1.1       cgd 	if (separate)
    637   1.1       cgd 		(void)printf("%*s", separate, "");
    638   1.1       cgd }
    639   1.1       cgd 
    640  1.17    atatat /*
    641  1.17    atatat  * gregorian_reform --
    642  1.17    atatat  *	Given a description of date on which the Gregorian Reform was
    643  1.17    atatat  *	applied.  The argument can be any of the "country" names
    644  1.17    atatat  *	listed in the reforms array (case insensitive) or a date of
    645  1.17    atatat  *	the form YYYY/MM/DD.  The date and month can be omitted if
    646  1.17    atatat  *	doing so would not select more than one different built-in
    647  1.17    atatat  *	reform point.
    648  1.17    atatat  */
    649  1.17    atatat void
    650  1.17    atatat gregorian_reform(const char *p)
    651  1.17    atatat {
    652  1.17    atatat 	int year, month, date;
    653  1.17    atatat 	int i, days, diw, diy;
    654  1.17    atatat 	char c;
    655  1.17    atatat 
    656  1.17    atatat 	i = sscanf(p, "%d%*[/,-]%d%*[/,-]%d%c", &year, &month, &date, &c);
    657  1.17    atatat 	switch (i) {
    658  1.17    atatat 	case 4:
    659  1.17    atatat 		/*
    660  1.17    atatat 		 * If the character was sscanf()ed, then there's more
    661  1.17    atatat 		 * stuff than we need.
    662  1.17    atatat 		 */
    663  1.17    atatat 		errx(1, "date specifier %s invalid", p);
    664  1.17    atatat 	case 0:
    665  1.17    atatat 		/*
    666  1.17    atatat 		 * Not a form we can sscanf(), so void these, and we
    667  1.17    atatat 		 * can try matching "country" names later.
    668  1.17    atatat 		 */
    669  1.17    atatat 		year = month = date = -1;
    670  1.17    atatat 		break;
    671  1.17    atatat 	case 1:
    672  1.17    atatat 		month = 0;
    673  1.17    atatat 		/*FALLTHROUGH*/
    674  1.17    atatat 	case 2:
    675  1.17    atatat 		date = 0;
    676  1.17    atatat 		/*FALLTHROUGH*/
    677  1.17    atatat 	    case 3:
    678  1.17    atatat 		/*
    679  1.17    atatat 		 * At last, some sanity checking on the values we were
    680  1.17    atatat 		 * given.
    681  1.17    atatat 		 */
    682  1.17    atatat 		if (year < 1 || year > 9999)
    683  1.17    atatat 			errx(1, "%d: illegal year value: use 1-9999", year);
    684  1.17    atatat 		if (i > 1 && (month < 1 || month > 12))
    685  1.17    atatat 			errx(1, "%d: illegal month value: use 1-12", month);
    686  1.17    atatat 		if ((i == 3 && date < 1) || date < 0 ||
    687  1.17    atatat 		    date > days_in_month[1][month])
    688  1.17    atatat 			/*
    689  1.17    atatat 			 * What about someone specifying a leap day in
    690  1.17    atatat 			 * a non-leap year?  Well...that's a tricky
    691  1.17    atatat 			 * one.  We can't yet *say* whether the year
    692  1.17    atatat 			 * in question is a leap year.  What if the
    693  1.17    atatat 			 * date given was, for example, 1700/2/29?  is
    694  1.17    atatat 			 * that a valid leap day?
    695  1.17    atatat 			 *
    696  1.17    atatat 			 * So...we punt, and hope that saying 29 in
    697  1.17    atatat 			 * the case of February isn't too bad an idea.
    698  1.17    atatat 			 */
    699  1.17    atatat 			errx(1, "%d: illegal date value: use 1-%d", date,
    700  1.17    atatat 			     days_in_month[1][month]);
    701  1.17    atatat 		break;
    702  1.17    atatat 	}
    703  1.17    atatat 
    704  1.17    atatat 	/*
    705  1.17    atatat 	 * A complete date was specified, so use the other pope.
    706  1.17    atatat 	 */
    707  1.17    atatat 	if (date > 0) {
    708  1.17    atatat 		static struct reform Goestheveezl;
    709  1.17    atatat 
    710  1.17    atatat 		reform = &Goestheveezl;
    711  1.17    atatat 		reform->country = "Bompzidaize";
    712  1.17    atatat 		reform->year = year;
    713  1.17    atatat 		reform->month = month;
    714  1.17    atatat 		reform->date = date;
    715  1.17    atatat 	}
    716  1.17    atatat 
    717  1.17    atatat 	/*
    718  1.17    atatat 	 * No date information was specified, so let's try to match on
    719  1.17    atatat 	 * country name.
    720  1.17    atatat 	 */
    721  1.17    atatat 	else if (year == -1) {
    722  1.17    atatat 		for (reform = &reforms[0]; reform->year; reform++) {
    723  1.17    atatat 			if (strcasecmp(p, reform->country) == 0)
    724  1.17    atatat 				break;
    725  1.17    atatat 		}
    726  1.17    atatat 	}
    727  1.17    atatat 
    728  1.17    atatat 	/*
    729  1.17    atatat 	 * We have *some* date information, but not a complete date.
    730  1.17    atatat 	 * Let's see if we have enough to pick a single entry from the
    731  1.17    atatat 	 * list that's not ambiguous.
    732  1.17    atatat 	 */
    733  1.17    atatat 	else {
    734  1.17    atatat 		for (reform = &reforms[0]; reform->year; reform++) {
    735  1.17    atatat 			if ((year == 0 || year == reform->year) &&
    736  1.17    atatat 			    (month == 0 || month == reform->month) &&
    737  1.17    atatat 			    (date == 0 || month == reform->date))
    738  1.17    atatat 				break;
    739  1.17    atatat 		}
    740  1.17    atatat 
    741  1.17    atatat 		if (i <= reform->ambiguity)
    742  1.17    atatat 			errx(1, "%s: ambiguous short reform date specification", p);
    743  1.17    atatat 	}
    744  1.17    atatat 
    745  1.17    atatat 	/*
    746  1.17    atatat 	 * Oops...we reached the end of the list.
    747  1.17    atatat 	 */
    748  1.17    atatat 	if (reform->year == 0)
    749  1.17    atatat 		errx(1, "reform name %s invalid", p);
    750  1.17    atatat 
    751  1.17    atatat 	/*
    752  1.17    atatat 	 *
    753  1.17    atatat 	 */
    754  1.17    atatat 	reform->missing_days =
    755  1.17    atatat 		j_leap_days(reform->year, reform->month, reform->date) -
    756  1.17    atatat 		g_leap_days(reform->year, reform->month, reform->date) -
    757  1.17    atatat 		GREGORIAN_MAGIC;
    758  1.17    atatat 
    759  1.17    atatat 	reform->first_missing_day =
    760  1.17    atatat 		(reform->year - 1) * 365 +
    761  1.17    atatat 		day_in_year(reform->date, reform->month, reform->year) +
    762  1.17    atatat 		date +
    763  1.17    atatat 		j_leap_days(reform->year, reform->month, reform->date);
    764  1.17    atatat 
    765  1.17    atatat 	/*
    766  1.17    atatat 	 * Once we know the day of the week of the first missing day,
    767  1.17    atatat 	 * skip back to the first of the month's day of the week.
    768  1.17    atatat 	 */
    769  1.17    atatat 	diw = day_in_week(reform->date, reform->month, reform->year);
    770  1.17    atatat 	diw = (diw + 8 - (reform->date % 7)) % 7;
    771  1.17    atatat 	diy = day_in_year(1, reform->month, reform->year);
    772  1.17    atatat 
    773  1.17    atatat 	/*
    774  1.17    atatat 	 * We might need all four of these (if you switch from Julian
    775  1.17    atatat 	 * to Gregorian at some point after 9900, you get a gap of 73
    776  1.17    atatat 	 * days, and that can affect four months), and it doesn't hurt
    777  1.17    atatat 	 * all that much to precompute them, so there.
    778  1.17    atatat 	 */
    779  1.17    atatat 	date = 1;
    780  1.17    atatat 	days = 0;
    781  1.17    atatat 	for (i = 0; i < 4; i++)
    782  1.17    atatat 		reform_day_array(reform->month + i, reform->year,
    783  1.17    atatat 				 &days, &date, &diw, &diy,
    784  1.17    atatat 				 shift_days[0][i],
    785  1.17    atatat 				 shift_days[1][i]);
    786  1.17    atatat }
    787  1.17    atatat 
    788  1.17    atatat /*
    789  1.17    atatat  * reform_day_array --
    790  1.17    atatat  *	Pre-calculates the given month's calendar (in both "standard"
    791  1.17    atatat  *	and "julian day" representations) with respect for days
    792  1.17    atatat  *	skipped during a reform period.
    793  1.17    atatat  */
    794  1.17    atatat void
    795  1.17    atatat reform_day_array(int month, int year, int *done, int *date, int *diw, int *diy,
    796  1.17    atatat 	int *scal, int *jcal)
    797  1.17    atatat {
    798  1.17    atatat 	int mdays;
    799  1.17    atatat 
    800  1.17    atatat 	/*
    801  1.17    atatat 	 * If the reform was in the month of october or later, then
    802  1.17    atatat 	 * the month number from the caller could "overflow".
    803  1.17    atatat 	 */
    804  1.17    atatat 	if (month > 12) {
    805  1.17    atatat 		month -= 12;
    806  1.17    atatat 		year++;
    807  1.17    atatat 	}
    808  1.17    atatat 
    809  1.17    atatat 	/*
    810  1.17    atatat 	 * Erase months, and set crib number.  The crib number is used
    811  1.17    atatat 	 * later to determine if the month to be displayed is here or
    812  1.17    atatat 	 * should be built on the fly with the generic routine
    813  1.17    atatat 	 */
    814  1.17    atatat 	memmove(scal, empty, MAXDAYS * sizeof(int));
    815  1.17    atatat 	scal[MAXDAYS] = month + year * 12;
    816  1.17    atatat 	memmove(jcal, empty, MAXDAYS * sizeof(int));
    817  1.17    atatat 	jcal[MAXDAYS] = month + year * 12;
    818  1.17    atatat 
    819  1.17    atatat 	/*
    820  1.17    atatat 	 * It doesn't matter what the actual month is when figuring
    821  1.17    atatat 	 * out if this is a leap year or not, just so long as February
    822  1.17    atatat 	 * gets the right number of days in it.
    823  1.17    atatat 	 */
    824  1.17    atatat 	mdays = days_in_month[g_leap_year(year, 3, 1)][month];
    825  1.17    atatat 
    826  1.17    atatat 	/*
    827  1.17    atatat 	 * Bounce back to the first "row" in the day array, and fill
    828  1.17    atatat 	 * in any days that actually occur.
    829  1.17    atatat 	 */
    830  1.17    atatat 	for (*diw %= 7; (*date - *done) <= mdays; (*date)++, (*diy)++) {
    831  1.17    atatat 		/*
    832  1.17    atatat 		 * "date" doesn't get reset by the caller across calls
    833  1.17    atatat 		 * to this routine, so we can actually tell that we're
    834  1.17    atatat 		 * looking at April the 41st.  Much easier than trying
    835  1.17    atatat 		 * to calculate the absolute julian day for a given
    836  1.17    atatat 		 * date and then checking that.
    837  1.17    atatat 		 */
    838  1.17    atatat 		if (*date < reform->date ||
    839  1.17    atatat 		    *date >= reform->date + reform->missing_days) {
    840  1.17    atatat 			scal[*diw] = *date - *done;
    841  1.17    atatat 			jcal[*diw] = *diy;
    842  1.17    atatat 			(*diw)++;
    843  1.17    atatat 		}
    844  1.17    atatat 	}
    845  1.17    atatat 	*done += mdays;
    846  1.17    atatat }
    847  1.17    atatat 
    848  1.14      yamt int
    849  1.14      yamt getnum(const char *p)
    850  1.14      yamt {
    851  1.14      yamt 	long result;
    852  1.14      yamt 	char *ep;
    853  1.14      yamt 
    854  1.14      yamt 	errno = 0;
    855  1.14      yamt 	result = strtoul(p, &ep, 10);
    856  1.14      yamt 	if (p[0] == '\0' || *ep != '\0')
    857  1.14      yamt 		goto error;
    858  1.14      yamt 	if (errno == ERANGE && result == ULONG_MAX)
    859  1.14      yamt 		goto error;
    860  1.14      yamt 	if (result > INT_MAX)
    861  1.14      yamt 		goto error;
    862  1.14      yamt 
    863  1.14      yamt 	return (int)result;
    864  1.14      yamt 
    865  1.14      yamt error:
    866  1.14      yamt 	errx(1, "bad number: %s", p);
    867  1.14      yamt 	/*NOTREACHED*/
    868  1.14      yamt }
    869  1.14      yamt 
    870   1.6     glass void
    871  1.15    atatat init_hilite(void)
    872  1.15    atatat {
    873  1.15    atatat 	static char control[128];
    874  1.15    atatat 	char cap[1024];
    875  1.15    atatat 	char *tc;
    876  1.15    atatat 
    877  1.15    atatat 	hilite++;
    878  1.15    atatat 
    879  1.15    atatat 	if (!isatty(fileno(stdout)))
    880  1.15    atatat 		return;
    881  1.15    atatat 
    882  1.15    atatat 	tc = getenv("TERM");
    883  1.15    atatat 	if (tc == NULL)
    884  1.15    atatat 		tc = "dumb";
    885  1.15    atatat 	if (tgetent(&cap[0], tc) != 1)
    886  1.15    atatat 		return;
    887  1.15    atatat 
    888  1.15    atatat 	tc = &control[0];
    889  1.15    atatat 	if ((md = tgetstr(hilite > 1 ? "mr" : "md", &tc)))
    890  1.15    atatat 		*tc++ = '\0';
    891  1.15    atatat 	if ((me = tgetstr("me", &tc)))
    892  1.15    atatat 		*tc++ = '\0';
    893  1.15    atatat 	if (me == NULL || md == NULL)
    894  1.15    atatat 		md = me = NULL;
    895  1.15    atatat }
    896  1.15    atatat 
    897  1.15    atatat void
    898  1.12     perry usage(void)
    899   1.1       cgd {
    900   1.6     glass 
    901  1.14      yamt 	(void)fprintf(stderr,
    902  1.17    atatat 	    "usage: cal [-hjry3] [-d day-of-week] [-B before] [-A after] "
    903  1.17    atatat 	    "[-R reform-spec]\n           [[month] year]\n");
    904   1.1       cgd 	exit(1);
    905   1.1       cgd }
    906