diff options
Diffstat (limited to 'usr.bin/ncal/ncal.c')
-rw-r--r-- | usr.bin/ncal/ncal.c | 250 |
1 files changed, 170 insertions, 80 deletions
diff --git a/usr.bin/ncal/ncal.c b/usr.bin/ncal/ncal.c index 22d9344..9f077fb 100644 --- a/usr.bin/ncal/ncal.c +++ b/usr.bin/ncal/ncal.c @@ -163,25 +163,25 @@ int flag_nohighlight; /* user doesn't want a highlighted today */ int flag_weeks; /* user wants number of week */ int nswitch; /* user defined switch date */ int nswitchb; /* switch date for backward compatibility */ -int today; +int highlightdate; char *center(char *s, char *t, int w); wchar_t *wcenter(wchar_t *s, wchar_t *t, int w); +int firstday(int y, int m); +void highlight(char *dst, char *src, int len, int *extraletters); void mkmonthr(int year, int month, int jd_flag, struct monthlines * monthl); void mkmonthb(int year, int month, int jd_flag, struct monthlines * monthl); void mkweekdays(struct weekdays * wds); +void monthranger(int year, int m, int jd_flag, int before, int after); +void monthrangeb(int year, int m, int jd_flag, int before, int after); int parsemonth(const char *s, int *m, int *y); void printcc(void); void printeaster(int year, int julian, int orthodox); -int firstday(int y, int m); date *sdater(int ndays, struct date * d); date *sdateb(int ndays, struct date * d); int sndaysr(struct date * d); int sndaysb(struct date * d); static void usage(void); -void monthranger(int year, int jd_flag, int m, int before, int after); -void monthrangeb(int year, int jd_flag, int m, int before, int after); -void highlight(char *dst, char *src, int len, int *extraletters); int main(int argc, char *argv[]) @@ -194,15 +194,21 @@ main(int argc, char *argv[]) int m = 0; /* month */ int y = 0; /* year */ int flag_backward = 0; /* user called cal--backward compat. */ - int flag_hole_year = 0; /* user wants the whole year */ + int flag_wholeyear = 0; /* user wants the whole year */ int flag_julian_cal = 0; /* user wants Julian Calendar */ - int flag_julian_day = 0; /* user wants the Julian day - * numbers */ - int flag_orthodox = 0; /* use wants Orthodox easter */ - int flag_easter = 0; /* use wants easter date */ + int flag_julian_day = 0; /* user wants the Julian day numbers */ + int flag_orthodox = 0; /* user wants Orthodox easter */ + int flag_easter = 0; /* user wants easter date */ + int flag_3months = 0; /* user wants 3 month display (-3) */ + int flag_after = 0; /* user wants to see months after */ + int flag_before = 0; /* user wants to see months before */ + int flag_specifiedmonth = 0;/* user wants to see this month (-m) */ + int flag_givenmonth = 0; /* user has specified month [n] */ + int flag_givenyear = 0; /* user has specified year [n] */ char *cp; /* character pointer */ + char *flag_today = NULL; /* debug: use date as being today */ char *flag_month = NULL; /* requested month as string */ - char *flag_highlightdate = NULL; + char *flag_highlightdate = NULL; /* debug: date to highlight */ int before, after; const char *locale; /* locale to get country code */ @@ -250,20 +256,26 @@ main(int argc, char *argv[]) before = after = -1; - while ((ch = getopt(argc, argv, "A:B:3Jbd:ehjm:ops:wy")) != -1) + while ((ch = getopt(argc, argv, "A:B:3Jbd:eH:hjm:ops:wy")) != -1) switch (ch) { case '3': - before = after = 1; + flag_3months = 1; break; case 'A': - after = strtol(optarg, NULL, 10); - if (after < 0) - errx(1, "Argument to -A must be positive"); + if (flag_after > 0) + errx(EX_USAGE, "Double -A specified"); + flag_after = strtol(optarg, NULL, 10); + if (flag_after <= 0) + errx(EX_USAGE, + "Argument to -A must be positive"); break; case 'B': - before = strtol(optarg, NULL, 10); - if (before < 0) - errx(1, "Argument to -B must be positive"); + if (flag_before > 0) + errx(EX_USAGE, "Double -A specified"); + flag_before = strtol(optarg, NULL, 10); + if (flag_before <= 0) + errx(EX_USAGE, + "Argument to -B must be positive"); break; case 'J': if (flag_backward) @@ -275,6 +287,9 @@ main(int argc, char *argv[]) flag_backward = 1; break; case 'd': + flag_today = optarg; + break; + case 'H': flag_highlightdate = optarg; break; case 'h': @@ -289,9 +304,10 @@ main(int argc, char *argv[]) flag_julian_day = 1; break; case 'm': + if (flag_specifiedmonth) + errx(EX_USAGE, "Double -m specified"); flag_month = optarg; - before = 0; - after = 0; + flag_specifiedmonth = 1; break; case 'o': if (flag_backward) @@ -324,7 +340,7 @@ main(int argc, char *argv[]) flag_weeks = 1; break; case 'y': - flag_hole_year = 1; + flag_wholeyear = 1; break; default: usage(); @@ -338,22 +354,21 @@ main(int argc, char *argv[]) if (flag_easter) usage(); flag_month = *argv++; - before = 0; - after = 0; + flag_givenmonth = 1; m = strtol(flag_month, NULL, 10); /* FALLTHROUGH */ case 1: - y = atoi(*argv++); + y = atoi(*argv); if (y < 1 || y > 9999) - errx(EX_USAGE, "year %d not in range 1..9999", y); - if (before == -1 && after == -1) { - before = 0; - after = 11; - m = 1; - } + errx(EX_USAGE, "year `%s' not in range 1..9999", *argv); + argv++; + flag_givenyear = 1; break; case 0: - { + if (flag_today != NULL) { + y = strtol(flag_today, NULL, 10); + m = strtol(flag_today + 5, NULL, 10); + } else { time_t t; struct tm *tm; @@ -361,22 +376,12 @@ main(int argc, char *argv[]) tm = localtime(&t); y = tm->tm_year + 1900; m = tm->tm_mon + 1; - if (before == -1) - before = 0; - if (after == -1) - after = 0; } break; default: usage(); } - if (flag_hole_year) { - m = 1; - before = 0; - after = 11; - } - if (flag_month != NULL) { if (parsemonth(flag_month, &m, &y)) { errx(EX_USAGE, @@ -385,6 +390,84 @@ main(int argc, char *argv[]) } } + /* + * What is not supported: + * -3 with -A or -B + * -3 displays 3 months, -A and -B change that behaviour. + * -3 with -y + * -3 displays 3 months, -y says display a whole year. + * -3 with a given year but no given month or without -m + * -3 displays 3 months, no month specified doesn't make clear + * which three months. + * -m with a given month + * conflicting arguments, both specify the same field. + * -y with -m + * -y displays the whole year, -m displays a single month. + * -y with a given month + * -y displays the whole year, the given month displays a single + * month. + * -y with -A or -B + * -y displays the whole year, -A and -B display extra months. + */ + + /* -3 together with -A or -B. */ + if (flag_3months && (flag_after || flag_before)) + errx(EX_USAGE, "-3 together with -A and -B is not supported."); + /* -3 together with -y. */ + if (flag_3months && flag_wholeyear) + errx(EX_USAGE, "-3 together with -y is not supported."); + /* -3 together with givenyear but no givenmonth. */ + if (flag_3months && flag_givenyear && + !(flag_givenmonth || flag_specifiedmonth)) + errx(EX_USAGE, + "-3 together with a given year but no given month is " + "not supported."); + /* -m together with xx xxxx. */ + if (flag_specifiedmonth && flag_givenmonth) + errx(EX_USAGE, + "-m together with a given month is not supported."); + /* -y together with -m. */ + if (flag_wholeyear && flag_specifiedmonth) + errx(EX_USAGE, "-y together with -m is not supported."); + /* -y together with xx xxxx. */ + if (flag_wholeyear && flag_givenmonth) + errx(EX_USAGE, "-y together a given month is not supported."); + /* -y together with -A or -B. */ + if (flag_wholeyear && (flag_before > 0 || flag_after > 0)) + errx(EX_USAGE, "-y together a -A or -B is not supported."); + /* The rest should be fine. */ + + /* Select the period to display, in order of increasing priority .*/ + if (flag_wholeyear || + (flag_givenyear && !(flag_givenmonth || flag_specifiedmonth))) { + m = 1; + before = 0; + after = 11; + } + if (flag_givenyear && flag_givenmonth) { + before = 0; + after = 0; + } + if (flag_specifiedmonth) { + before = 0; + after = 0; + } + if (flag_before) { + before = flag_before; + } + if (flag_after) { + after = flag_after; + } + if (flag_3months) { + before = 1; + after = 1; + } + if (after == -1) + after = 0; + if (before == -1) + before = 0; + + /* Highlight a specified day or today .*/ if (flag_highlightdate != NULL) { dt.y = strtol(flag_highlightdate, NULL, 10); dt.m = strtol(flag_highlightdate + 5, NULL, 10); @@ -399,15 +482,16 @@ main(int argc, char *argv[]) dt.m = tm1->tm_mon + 1; dt.d = tm1->tm_mday; } - today = sndaysb(&dt); + highlightdate = sndaysb(&dt); + /* And now we finally start to calculate and output calendars. */ if (flag_easter) printeaster(y, flag_julian_cal, flag_orthodox); else if (flag_backward) - monthrangeb(y, flag_julian_day, m, before, after); + monthrangeb(y, m, flag_julian_day, before, after); else - monthranger(y, flag_julian_day, m, before, after); + monthranger(y, m, flag_julian_day, before, after); return (0); } @@ -420,12 +504,12 @@ usage(void) " cal [-hj] [-m month] [year]\n" " ncal [-hJjpwy] [-s country_code] [[month] year]\n" " ncal [-hJeo] [year]\n" - "for debug the highlighting: [-b] [-d yyyy-mm-dd]\n", + "for debug the highlighting: [-b] [-H yyyy-mm-dd] [-d yyyy-mm]\n", stderr); exit(EX_USAGE); } -/* print the assumed switches for all countries */ +/* Print the assumed switches for all countries. */ void printcc(void) { @@ -446,7 +530,7 @@ printcc(void) printf(FSTR"\n", FSTRARG(p)); } -/* print the date of easter sunday */ +/* Print the date of easter sunday. */ void printeaster(int y, int julian, int orthodox) { @@ -491,8 +575,9 @@ printeaster(int y, int julian, int orthodox) #define M2Y(m) ((m) / 12) #define M2M(m) (1 + (m) % 12) +/* Print all months for the period in the range [ before .. y-m .. after ]. */ void -monthrangeb(int y, int jd_flag, int m, int before, int after) +monthrangeb(int y, int m, int jd_flag, int before, int after) { struct monthlines year[12]; struct weekdays wds; @@ -539,14 +624,14 @@ monthrangeb(int y, int jd_flag, int m, int before, int after) if (m != m1) printf("\n"); - /* Year at the top */ + /* Year at the top. */ if (printyearheader && M2Y(m) != prevyear) { sprintf(s, "%d", M2Y(m)); printf("%s\n", center(t, s, mpl * mw)); prevyear = M2Y(m); } - /* Month names */ + /* Month names. */ for (i = 0; i < count; i++) if (printyearheader) wprintf(L"%-*ls ", @@ -558,7 +643,7 @@ monthrangeb(int y, int jd_flag, int m, int before, int after) } printf("\n"); - /* Day of the week names */ + /* Day of the week names. */ for (i = 0; i < count; i++) { wprintf(L"%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls ", wdss, wds.names[6], wdss, wds.names[0], @@ -568,6 +653,7 @@ monthrangeb(int y, int jd_flag, int m, int before, int after) } printf("\n"); + /* And the days of the month. */ for (i = 0; i != 6; i++) { for (j = 0; j < count; j++) printf("%-*s ", @@ -581,7 +667,7 @@ monthrangeb(int y, int jd_flag, int m, int before, int after) } void -monthranger(int y, int jd_flag, int m, int before, int after) +monthranger(int y, int m, int jd_flag, int before, int after) { struct monthlines year[12]; struct weekdays wds; @@ -621,18 +707,18 @@ monthranger(int y, int jd_flag, int m, int before, int after) count++; } - /* Empty line between two rows of months */ + /* Empty line between two rows of months. */ if (m != m1) printf("\n"); - /* Year at the top */ + /* Year at the top. */ if (printyearheader && M2Y(m) != prevyear) { sprintf(s, "%d", M2Y(m)); printf("%s\n", center(t, s, mpl * mw)); prevyear = M2Y(m); } - /* Month names */ + /* Month names. */ wprintf(L" "); for (i = 0; i < count; i++) if (printyearheader) @@ -642,6 +728,7 @@ monthranger(int y, int jd_flag, int m, int before, int after) mw - wcslen(year[i].name) - 1, M2Y(m + i)); printf("\n"); + /* And the days of the month. */ for (i = 0; i != 7; i++) { /* Week day */ wprintf(L"%.2ls", wds.names[i]); @@ -654,6 +741,7 @@ monthranger(int y, int jd_flag, int m, int before, int after) printf("\n"); } + /* Week numbers. */ if (flag_weeks) { printf(" "); for (i = 0; i < count; i++) @@ -709,7 +797,7 @@ mkmonthr(int y, int m, int jd_flag, struct monthlines *mlines) */ firstm = first - weekday(first); - /* Set ds (daystring) and dw (daywidth) according to the jd_flag */ + /* Set ds (daystring) and dw (daywidth) according to the jd_flag. */ if (jd_flag) { ds = jdaystr; dw = 4; @@ -731,7 +819,7 @@ mkmonthr(int y, int m, int jd_flag, struct monthlines *mlines) dt.d = j - jan1 + 1; else sdater(j, &dt); - if (j == today && !flag_nohighlight) + if (j == highlightdate && !flag_nohighlight) highlight(mlines->lines[i] + k, ds + dt.d * dw, dw, &l); else @@ -744,7 +832,7 @@ mkmonthr(int y, int m, int jd_flag, struct monthlines *mlines) mlines->extralen[i] = l; } - /* fill the weeknumbers */ + /* fill the weeknumbers. */ if (flag_weeks) { for (j = firstm, k = 0; j < last; k += dw, j += 7) if (j <= nswitch) @@ -781,7 +869,7 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines) dw = 3; } - /* Set name of month centered */ + /* Set name of month centered. */ memset(&tm, 0, sizeof(tm)); tm.tm_mon = m; wcsftime(mlines->name, sizeof(mlines->name) / sizeof(mlines->name[0]), @@ -835,7 +923,7 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines) dt.d = j - jan1 + 1; else sdateb(j, &dt); - if (j == today && !flag_nohighlight) + if (j == highlightdate && !flag_nohighlight) highlight(mlines->lines[i] + k, ds + dt.d * dw, dw, &l); else @@ -852,7 +940,7 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines) } } -/* Put the local names of weekdays into the wds */ +/* Put the local names of weekdays into the wds. */ void mkweekdays(struct weekdays *wds) { @@ -878,9 +966,8 @@ mkweekdays(struct weekdays *wds) } /* - * Compute the day number of the first - * existing date after the first day in month. - * (the first day in month and even the month might not exist!) + * Compute the day number of the first existing date after the first day in + * month. (the first day in month and even the month might not exist!) */ int firstday(int y, int m) @@ -933,7 +1020,7 @@ sndaysb(struct date *d) return (ndaysj(d)); } -/* Inverse of sndays */ +/* Inverse of sndays. */ struct date * sdater(int nd, struct date *d) { @@ -944,7 +1031,7 @@ sdater(int nd, struct date *d) return (jdate(nd, d)); } -/* Inverse of sndaysb */ +/* Inverse of sndaysb. */ struct date * sdateb(int nd, struct date *d) { @@ -955,7 +1042,7 @@ sdateb(int nd, struct date *d) return (jdate(nd, d)); } -/* Center string t in string s of length w by putting enough leading blanks */ +/* Center string t in string s of length w by putting enough leading blanks. */ char * center(char *s, char *t, int w) { @@ -966,7 +1053,7 @@ center(char *s, char *t, int w) return (s); } -/* Center string t in string s of length w by putting enough leading blanks */ +/* Center string t in string s of length w by putting enough leading blanks. */ wchar_t * wcenter(wchar_t *s, wchar_t *t, int w) { @@ -1021,7 +1108,7 @@ highlight(char *dst, char *src, int len, int *extralen) term_se = term_so = NULL; - /* On how to highlight on this type of terminal (if any) */ + /* On how to highlight on this type of terminal (if any). */ if (isatty(STDOUT_FILENO) && tgetent(tbuf, NULL) == 1) { b = cbuf; term_so = tgetstr("so", &b); @@ -1040,42 +1127,45 @@ highlight(char *dst, char *src, int len, int *extralen) return; } - /* If it is a real terminal, use the data from the termcap database. */ + /* + * If it is a real terminal, use the data from the termcap database. + */ if (term_so != NULL && term_se != NULL) { - /* separator */ + /* separator. */ dst[0] = ' '; dst++; - /* highlight on */ + /* highlight on. */ memcpy(dst, term_so, strlen(term_so)); dst += strlen(term_so); - /* the actual text (minus leading space) */ + /* the actual text. (minus leading space) */ len--; src++; memcpy(dst, src, len); dst += len; - /* highlight off */ + /* highlight off. */ memcpy(dst, term_se, strlen(term_se)); *extralen = strlen(term_so) + strlen(term_se); return; } /* - * Otherwise, print a _, backspace and the letter + * Otherwise, print a _, backspace and the letter. */ *extralen = 0; - /* skip leading space */ + /* skip leading space. */ src++; len--; - /* separator */ + /* separator. */ dst[0] = ' '; dst++; while (len > 0) { - /* _ and backspace */ + /* _ and backspace. */ memcpy(dst, "_\010", 2); dst += 2; *extralen += 2; - /* the character */ + /* the character. */ *dst++ = *src++; len--; } + return; } |