[dev] [PATCH] - no limit on number of months: removed MONTHMAX - strings printed to stdout rather than copied to memory - rewritten date calculation algorithms

From: Greg Reagle <greg.reagle_AT_umbc.edu>
Date: Tue, 23 Dec 2014 12:28:08 -0500

---
 cal.c | 153
 ++++++++++++++++++++++++++++++++++--------------------------------
 1 file changed, 78 insertions(+), 75 deletions(-)
diff --git a/cal.c b/cal.c
index dca2313..20d26be 100644
--- a/cal.c
+++ b/cal.c
_AT_@ -1,101 +1,105 @@
 /* See LICENSE file for copyright and license details. */
+/* © 2014 Greg Reagle <greg.reagle_AT_umbc.edu> */
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
 #include "util.h"
 
-#define MONTHMAX 100
+static int
+isleap(int year)
+{
+       if (year % 400 == 0)
+               return 1;
+       if (year % 100 == 0)
+               return 0;
+       return (year % 4 == 0);
+}
+
+static int
+monthlength(int year, int month)
+{
+       int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
+       return (month==1 && isleap(year))  ?  29  :  mdays[month];
+}
 
-static void drawcal(int, int, int, int, int, int);
-static int dayofweek(int, int, int, int);
-static int isleap(int);
-static void usage(void);
+/* From http://www.tondering.dk/claus/cal/chrweek.php#calcdow */
+static int
+dayofweek(int year, int month, int dom)
+{
+       int m, y, a;
+       month += 1;  /*  in this formula, 1 <= month <= 12  */
+       a = (14 - month) / 12;
+       y = year - a;
+       m = month + 12*a - 2;
+       return (dom + y + y/4 - y/100 + y/400 +((31*m)/12)) % 7;
+}
+
+static void 
+printgrid(int year, int month, int fday, int line)
+{
+       int dom, offset, d=0;
+
+       offset = dayofweek(year, month, 1) - fday;
+       if (offset < 0)
+               offset += 7;
+       if (line==1) {
+               for ( ; d < offset; ++d)
+                       printf("   ");
+               dom = 1;
+       } else {
+               dom = 8-offset + (line-2)*7;
+       }
+       for ( ; d < 7 && dom <= monthlength(year, month); ++d, ++dom)
+               printf("%2d ", dom);
+       for ( ; d < 7; ++d)
+               printf("   ");
+}
 
 static void
 drawcal(int year, int month, int day, int ncols, int nmons, int fday)
 {
-       char str[21];
-       int count[MONTHMAX];
-       int d, i, r, j;
-       int moff, yoff, cur, last, ndays, day1;
-       char *smon[] = {
-               "    January", "    February", "     March",
-               "     April", "      May", "      June",
-               "      July", "     August", "   September",
-               "    October", "    November", "    December" };
-       int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
-       int row = 0;
+       char *smon[] = {"  January", " February", "    March", "   
April",
+                       "      May", "     June", "     July", "  
August",
+                       "September", "  October", " November", "
December" };
 	char *days[] = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", };
-
-       if (!ncols)
-               ncols = nmons;
-       while (nmons > 0) {
-               last = MIN(nmons, ncols);
-               for (i = 0; i < last; i++) {
-                       moff = month + ncols * row + i - 1;
-                       cur = moff % 12;
-                       yoff = year + moff / 12;
-
-                       snprintf(str, sizeof(str), "%s %d", smon[cur],
yoff);
-                       printf("%-20s   ", str);
-                       count[i] = 1;
+       int m, n, col, cur_year, cur_month, line, dow;
+
+       for (m = 0; m < nmons; ) {
+               n = m;
+               for (col = 0; m < nmons && col < ncols; ++col, ++m) {
+                       cur_year = year + m/12;
+                       cur_month = month + m%12;
+                       if (cur_month > 11) {
+                               cur_month -= 12;
+                               cur_year += 1;
+                       }
+                       printf("   %s %d    ", smon[cur_month],
cur_year);
+                       printf("  ");
 		}
 		printf("\n");
-
-               for (i = 0; i < last; i++) {
-                       for (j = fday; j < LEN(days); j++)
-                               printf("%s ", days[j]);
-                       for (j = 0; j < fday; j++)
-                               printf("%s ", days[j]);
+               for (col = 0, m = n; m < nmons && col < ncols; ++col,
++m) {
+                       for (dow = fday; dow < (fday+7); ++dow)
+                               printf("%s ", days[dow%7]);
 			printf("  ");
 		}
 		printf("\n");
-
-               for (r = 0; r < 6; r++) {
-                       for (i = 0; i < last; i++) {
-                               moff = month + ncols * row + i - 1;
-                               cur = moff % 12;
-                               yoff = year + moff / 12;
-
-                               ndays = mdays[cur] + ((cur == 1) &&
isleap(yoff));
-                               day1 = dayofweek(yoff, cur, 1, fday);
-
-                               for (d = 0; d < 7; d++) {
-                                       if ((r || d >= day1) && count[i]
<= ndays)
-                                               printf("%2d ",
count[i]++);
-                                       else
-                                               printf("   ");
+               for (line=1; line<=6; ++line) {
+                       for (col=0, m=n; m<nmons && col<ncols; ++col,
++m) {
+                               cur_year = year + m/12;
+                               cur_month = month + m%12;
+                               if (cur_month > 11) {
+                                       cur_month -= 12;
+                                       cur_year += 1;
 				}
+                               printgrid(cur_year, cur_month, fday,
line);
 				printf("  ");
 			}
 			printf("\n");
 		}
-               nmons -= ncols;
-               row++;
 	}
 }
 
-static int
-dayofweek(int year, int month, int day, int fday)
-{
-       static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
-
-       day += 7 - fday;
-       year -= month < 2;
-       return (year + year / 4 - year / 100 + year / 400 + t[month] +
day) % 7;
-}
-
-static int
-isleap(int year)
-{
-       if (year % 400 == 0)
-               return 1;
-       if (year % 100 == 0)
-               return 0;
-       return (year % 4 == 0);
-}
-
 static void
 usage(void)
 {
_AT_@ -172,12 +176,11 @@ main(int argc, char *argv[])
 		usage();
 	}
 
-       if (ncols < 0 || month < 1 || month > 12 || nmons < 1 \
-                       || nmons > MONTHMAX || fday < 0 || fday > 6) {
+       if (ncols < 0 || month < 1 || month > 12 || nmons < 1 || fday <
0 || fday > 6) {
 		usage();
 	}
 
-       drawcal(year, month, day, ncols, nmons, fday);
+       drawcal(year, month-1, day, ncols, nmons, fday);
 
 	return 0;
 }
-- 
2.1.3
-- 
http://www.fastmail.com - Or how I learned to stop worrying and
                          love email again
Received on Tue Dec 23 2014 - 18:28:08 CET

This archive was generated by hypermail 2.3.0 : Tue Dec 23 2014 - 18:36:08 CET