commit c6f1e8aa20bc6f49b8d47b85c687d910c5b5ec2f
Author: Greg Reagle <greg.reagle_AT_umbc.edu>
Date: Fri Jan 2 13:12:59 2015 +0000
Various cal(1) improvements
1) No limit on number of months (removed MONTHMAX)
2) Strings printed to stdout rather than copied to an internal buffer
3) Rewritten date calculation algorithms
diff --git a/LICENSE b/LICENSE
index bb81bfd..e9d33fc 100644
--- a/LICENSE
+++ b/LICENSE
_AT_@ -54,3 +54,4 @@ Authors/contributors include:
© 2014 Ari Malinen <ari.malinen_AT_gmail.com>
© 2014 Brandon Mulcahy <brandon_AT_jangler.info>
© 2014 Adria Garriga <rhaps0dy_AT_installgentoo.com>
+© 2014 Greg Reagle <greg.reagle_AT_umbc.edu>
diff --git a/cal.c b/cal.c
index dca2313..28e58fe 100644
--- a/cal.c
+++ b/cal.c
_AT_@ -5,97 +5,100 @@
#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 void drawcal(int, int, int, int, int, int);
-static int dayofweek(int, int, int, int);
-static int isleap(int);
-static void usage(void);
+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];
+}
+
+/* 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 +175,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;
}
Received on Fri Jan 02 2015 - 14:14:47 CET