Subject: implementation of silly change
To: None <tech-userlevel@netbsd.org>
From: Perry E. Metzger <perry@piermont.com>
List: tech-userlevel
Date: 06/21/2002 17:42:48
"Perry E. Metzger" <perry@wasabisystems.com> writes:
> No, I'm here for the stupidest of all reasons. I've wracked my brain
> for half an hour and I can't figure out a decent letter to use for the
> "show three months" switch.

Okay, the crowd says "-3".

Here's my patch to do it. I hate that I needed an all new function
duplicating what the already duplicative functions do, but I think the
benefit of working hard to rewrite half of cal to be properly modular
is minimal. Well, maybe not minimal given that the reason doing
arbitrary month ranges is hard is because cal was never done very
modularly, of course, but again, I'm not going to do that work...

Note that I print the year by every month name in -3 mode -- mostly
because I prefer it that way.

Any comments before I fire it into the tree?

Index: cal.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/cal/cal.c,v
retrieving revision 1.12
diff -u -r1.12 cal.c
--- cal.c	2002/06/21 19:58:48	1.12
+++ cal.c	2002/06/21 21:33:04
@@ -131,6 +131,7 @@
 int	day_in_week(int, int, int);
 int	day_in_year(int, int, int);
 void	j_yearly(int);
+void	month3(int, int);
 void	monthly(int, int);
 int	main(int, char **);
 void	trim_trailing_spaces(char *);
@@ -142,10 +143,11 @@
 {
 	struct tm *local_time;
 	time_t now;
-	int ch, month, year, yflag;
+	int ch, month, year, yflag, threeflag;
 
 	yflag = year = 0;
-	while ((ch = getopt(argc, argv, "jy")) != -1) {
+	threeflag = 0;
+	while ((ch = getopt(argc, argv, "jy3")) != -1) {
 		switch (ch) {
 		case 'j':
 			julian = 1;
@@ -153,12 +155,20 @@
 		case 'y':
 			yflag = 1;
 			break;
+		case '3':
+			threeflag = 1;
+			break;
 		case '?':
 		default:
 			usage();
 			/* NOTREACHED */
 		}
 	}
+
+	if (threeflag && (yflag || julian)) {
+		usage();
+	}
+
 	argc -= optind;
 	argv += optind;
 
@@ -183,12 +193,15 @@
 		usage();
 	}
 
-	if (month)
+	if (threeflag)
+		month3(month, year);
+	else if (month)
 		monthly(month, year);
 	else if (julian)
 		j_yearly(year);
 	else
 		yearly(year);
+
 	exit(0);
 }
 
@@ -290,6 +303,46 @@
 	(void)printf("\n");
 }
 
+void
+month3(int month, int year)
+{
+	int col, *dp, i, row, which_cal;
+	int days[12][MAXDAYS];
+	char *p, lineout[80];
+
+	for (i = 0; i < 12; i++)
+		day_array(i + 1, year, days[i]);
+
+	month--;
+	
+	snprintf(lineout, sizeof(lineout), "%s %d",
+	    month_names[month], year);
+	center(lineout, WEEK_LEN, HEAD_SEP);
+	snprintf(lineout, sizeof(lineout), "%s %d",
+	    month_names[month+1], year);
+	center(lineout, WEEK_LEN, HEAD_SEP);
+	snprintf(lineout, sizeof(lineout), "%s %d",
+	    month_names[month+2], year);
+	center(lineout, WEEK_LEN, 0);
+
+	(void)memset(lineout, ' ', sizeof(lineout) - 1);
+	lineout[sizeof(lineout) - 1] = '\0';
+
+	(void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
+	    "", day_headings, HEAD_SEP, "", day_headings);
+	for (row = 0; row < 6; row++) {
+		for (which_cal = 0; which_cal < 3; which_cal++) {
+			p = lineout + which_cal * (WEEK_LEN + 2);
+			dp = &days[month + which_cal][row * 7];
+			for (col = 0; col < 7; col++, p += DAY_LEN)
+				ascii_day(p, *dp++);
+		}
+		*p = '\0';
+		trim_trailing_spaces(lineout);
+		(void)printf("%s\n", lineout);
+	}
+}
+
 /*
  * day_array --
  *	Fill in an array of 42 integers with a calendar.  Assume for a moment
@@ -418,6 +471,6 @@
 usage(void)
 {
 
-	(void)fprintf(stderr, "usage: cal [-jy] [[month] year]\n");
+	(void)fprintf(stderr, "usage: cal [-jy3] [[month] year]\n");
 	exit(1);
 }