From e44fe4712140774b677de466affc31e0581ee335 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Fri, 24 May 2013 22:52:16 +0100 Subject: cal: remove arbitrary limit of maxium year being 9999 The change limits year to be unsigned long. In case a year + month name exceed a column width two lines are used for them. Signed-off-by: Sami Kerola --- misc-utils/cal.c | 121 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 41 deletions(-) (limited to 'misc-utils/cal.c') diff --git a/misc-utils/cal.c b/misc-utils/cal.c index 9575db4d2..0142fd0ec 100644 --- a/misc-utils/cal.c +++ b/misc-utils/cal.c @@ -177,7 +177,6 @@ enum { #define SPACE -1 /* used in day array */ #define SMALLEST_YEAR 1 -#define GREATEST_YEAR 9999 #define DAY_LEN 3 /* 3 spaces per day */ #define WEEK_LEN (DAYS_IN_WEEK * DAY_LEN) @@ -191,7 +190,7 @@ enum { #define TODAY_FLAG 0x400 /* flag day for highlighting */ -#define FMT_ST_LINES 8 +#define FMT_ST_LINES 9 #define FMT_ST_CHARS 300 /* 90 suffices in most locales */ struct fmt_st { @@ -233,17 +232,18 @@ int weekstart = SUNDAY; int julian; /* function prototypes */ -static int leap_year(int year); +static int leap_year(long year); static char * ascii_day(char *, int); static int center_str(const char* src, char* dest, size_t dest_size, size_t width); static void center(const char *, size_t, int); -static void day_array(int, int, int, int *); +static void day_array(int, int, long, int *); static int day_in_week(int, int, int); -static int day_in_year(int, int, int); -static void yearly(int, int, int); -static void do_monthly(int, int, int, struct fmt_st*); -static void monthly(int, int, int); -static void monthly3(int, int, int); +static int day_in_year(int, int, long); +static void yearly(int, long, int); +static int do_monthly(int, int, long, struct fmt_st*, int); +static void monthly(int, int, long); +static int two_header_lines(int month, long year); +static void monthly3(int, int, long); static void __attribute__ ((__noreturn__)) usage(FILE * out); static void headers_init(int); @@ -251,7 +251,8 @@ int main(int argc, char **argv) { struct tm *local_time; time_t now; - int ch, day = 0, month = 0, year = 0, yflag = 0; + int ch, day = 0, month = 0, yflag = 0; + long year; int num_months = NUM_MONTHS; int colormode = UL_COLORMODE_AUTO; @@ -379,15 +380,15 @@ main(int argc, char **argv) { errx(EXIT_FAILURE, _("illegal month value: use 1-12")); /* FALLTHROUGH */ case 1: - year = strtos32_or_err(*argv++, _("illegal year value: use 1-9999")); - if (year < SMALLEST_YEAR || GREATEST_YEAR < year) - errx(EXIT_FAILURE, _("illegal year value: use 1-9999")); + year = strtol_or_err(*argv++, _("illegal year value")); + if (year < SMALLEST_YEAR) + errx(EXIT_FAILURE, _("illegal year value: use positive integer")); if (day) { int dm = days_in_month[leap_year(year)][month]; if (day > dm) errx(EXIT_FAILURE, _("illegal day value: use 1-%d"), dm); day = day_in_year(day, month, year); - } else if ((local_time->tm_year + 1900) == year) { + } else if ((long) (local_time->tm_year + 1900) == year) { day = local_time->tm_yday + 1; } if (!month) @@ -417,7 +418,7 @@ main(int argc, char **argv) { } /* leap year -- account for gregorian reformation in 1752 */ -static int leap_year(int year) +static int leap_year(long year) { if (year <= REFORMATION_YEAR) return !(year % 4); @@ -449,11 +450,12 @@ static void headers_init(int julian) full_month[i] = nl_langinfo(MON_1 + i); } -static void -do_monthly(int day, int month, int year, struct fmt_st *out) { +static int +do_monthly(int day, int month, long year, struct fmt_st *out, int header_hint) { int col, row, days[MAXDAYS]; char *p, lineout[FMT_ST_CHARS]; - int width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1; + size_t width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1; + int pos = 0; day_array(day, month, year, days); @@ -463,11 +465,23 @@ do_monthly(int day, int month, int year, struct fmt_st *out) { * Basque the translation should be: "%2$dko %1$s", and * the Vietnamese should be "%s na(m %d", etc. */ - snprintf(lineout, sizeof(lineout), _("%s %d"), + if (header_hint < 0) + header_hint = two_header_lines(month, year); + if (header_hint) { + snprintf(lineout, sizeof(lineout), _("%s"), full_month[month - 1]); + center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width); + pos++; + snprintf(lineout, sizeof(lineout), _("%lu"), year); + center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width); + pos++; + } else { + snprintf(lineout, sizeof(lineout), _("%s %lu"), full_month[month - 1], year); - center_str(lineout, out->s[0], ARRAY_SIZE(out->s[0]), width); + center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width); + pos++; + } - snprintf(out->s[1], FMT_ST_CHARS, "%s", day_headings); + snprintf(out->s[pos++], FMT_ST_CHARS, "%s", day_headings); for (row = 0; row < DAYS_IN_WEEK - 1; row++) { int has_hl = 0; for (col = 0, p = lineout; col < DAYS_IN_WEEK; col++) { @@ -477,35 +491,54 @@ do_monthly(int day, int month, int year, struct fmt_st *out) { p = ascii_day(p, xd); } *p = '\0'; - snprintf(out->s[row+2], FMT_ST_CHARS, "%s", lineout); + snprintf(out->s[row+pos], FMT_ST_CHARS, "%s", lineout); if (has_hl) - Hrow = out->s[row+2]; + Hrow = out->s[row+pos]; } + pos += row; + return pos; } static void -monthly(int day, int month, int year) { - int i; +monthly(int day, int month, long year) { + int i, rows; struct fmt_st out; - do_monthly(day, month, year, &out); - for (i = 0; i < FMT_ST_LINES; i++) { + rows = do_monthly(day, month, year, &out, -1); + for (i = 0; i < rows; i++) { my_putstring(out.s[i]); my_putstring("\n"); } } +static int +two_header_lines(int month, long year) +{ + char lineout[FMT_ST_CHARS]; + size_t width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1; + size_t len; + snprintf(lineout, sizeof(lineout), "%lu", year); + len = strlen(lineout); + len += strlen(full_month[month - 1]) + 1; + if (width < len) + return 1; + return 0; +} + static void -monthly3(int day, int month, int year) { +monthly3(int day, int month, long year) { char lineout[FMT_ST_CHARS]; int i; - int width; + int width, rows, two_lines; struct fmt_st out_prev; struct fmt_st out_curm; struct fmt_st out_next; - int prev_month, prev_year; - int next_month, next_year; + int prev_month, next_month; + long prev_year, next_year; + memset(&out_prev, 0, sizeof(struct fmt_st)); + memset(&out_curm, 0, sizeof(struct fmt_st)); + memset(&out_next, 0, sizeof(struct fmt_st)); if (month == 1) { prev_month = MONTHS_IN_YEAR; prev_year = year - 1; @@ -520,18 +553,24 @@ monthly3(int day, int month, int year) { next_month = month + 1; next_year = year; } - - do_monthly(day, prev_month, prev_year, &out_prev); - do_monthly(day, month, year, &out_curm); - do_monthly(day, next_month, next_year, &out_next); + two_lines = two_header_lines(prev_month, prev_year); + two_lines += two_header_lines(month, year); + two_lines += two_header_lines(next_month, next_year); + if (0 < two_lines) + rows = FMT_ST_LINES; + else + rows = FMT_ST_LINES - 1; + do_monthly(day, prev_month, prev_year, &out_prev, two_lines); + do_monthly(day, month, year, &out_curm, two_lines); + do_monthly(day, next_month, next_year, &out_next, two_lines); width = (julian ? J_WEEK_LEN : WEEK_LEN) -1; - for (i = 0; i < 2; i++) { + for (i = 0; i < (two_lines ? 3 : 2); i++) { snprintf(lineout, sizeof(lineout), "%s %s %s\n", out_prev.s[i], out_curm.s[i], out_next.s[i]); my_putstring(lineout); } - for (i = 2; i < FMT_ST_LINES; i++) { + for (i = two_lines ? 3 : 2; i < rows; i++) { int w1, w2, w3; w1 = w2 = w3 = width; @@ -551,7 +590,7 @@ monthly3(int day, int month, int year) { } static void -yearly(int day, int year, int julian) { +yearly(int day, long year, int julian) { int col, *dp, i, month, row, which_cal; int maxrow, sep_len, week_len; int days[MONTHS_IN_YEAR][MAXDAYS]; @@ -566,7 +605,7 @@ yearly(int day, int year, int julian) { sep_len = HEAD_SEP; week_len = WEEK_LEN; } - snprintf(lineout, sizeof(lineout), "%d", year); + snprintf(lineout, sizeof(lineout), "%lu", year); /* 2013-04-28: The -1 near sep_len makes year header to be * aligned exactly how it has been aligned for long time, but it * is unexplainable. */ @@ -615,7 +654,7 @@ yearly(int day, int year, int julian) { * builds that array for any month from Jan. 1 through Dec. 9999. */ static void -day_array(int day, int month, int year, int *days) { +day_array(int day, int month, long year, int *days) { int julday, daynum, dw, dm; int *sep1752; @@ -646,7 +685,7 @@ day_array(int day, int month, int year, int *days) { * return the 1 based day number within the year */ static int -day_in_year(int day, int month, int year) { +day_in_year(int day, int month, long year) { int i, leap; leap = leap_year(year); -- cgit v1.2.3-55-g7522