drop an intermediate data structure

This commit is contained in:
Kartik K. Agaram 2022-02-16 23:17:38 -08:00
parent 4d87706a3d
commit f84f43ac69
1 changed files with 132 additions and 120 deletions

252
ncal.c
View File

@ -59,12 +59,6 @@ __FBSDID("$FreeBSD: head/usr.bin/ncal/ncal.c 326276 2017-11-27 15:37:16Z pfg $")
typedef struct date date; typedef struct date date;
struct monthlines {
char lines[7][MAX_WIDTH + 1];
char weeks[MAX_WIDTH + 1];
unsigned int extralen[7];
};
struct weekdays { struct weekdays {
wchar_t names[7][4]; wchar_t names[7][4];
}; };
@ -166,14 +160,15 @@ static int nswitch; /* user defined switch date */
static int nswitchb; /* switch date for backward compatibility */ static int nswitchb; /* switch date for backward compatibility */
int weekstart = -1; /* day the week starts on (Sun [0] - Sat [6]) */ int weekstart = -1; /* day the week starts on (Sun [0] - Sat [6]) */
static char *center(char *s, char *t, int w); static void printcentered(int line, char *s, int start, int end);
static wchar_t *wcenter(wchar_t *s, wchar_t *t, int w); static wchar_t *wcenter(wchar_t *s, wchar_t *t, int w);
static int firstday(int y, int m); static int firstday(int y, int m);
static void highlight(char *dst, char *src, int len, int *extraletters); static void highlight(char *dst, char *src, int len, int *extraletters);
static void mkmonthr(int year, int month, int jd_flag, static void printweeknumber(int line, int y, int m, int jd_flag);
struct monthlines * monthl, int highlightdate); static void printmonthr(int line, int col, int y, int m, int jd_flag,
static void mkmonthb(int year, int month, int jd_flag, int highlightdate);
struct monthlines * monthl, int highlightdate); static void printmonthb(int line, int col, int y, int m, int jd_flag,
int highlightdate);
static void mkweekdays(struct weekdays * wds); static void mkweekdays(struct weekdays * wds);
static void monthranger(int year, int m, int jd_flag, static void monthranger(int year, int m, int jd_flag,
int before, int after, int highlightdate); int before, int after, int highlightdate);
@ -666,7 +661,6 @@ static void compute_month_name(int month_index, wchar_t *month_name, int mlen) {
static void static void
monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate) monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate)
{ {
struct monthlines year[12];
struct weekdays wds; struct weekdays wds;
char s[MAX_WIDTH], t[MAX_WIDTH]; char s[MAX_WIDTH], t[MAX_WIDTH];
wchar_t ws[MAX_WIDTH], ws1[MAX_WIDTH]; wchar_t ws[MAX_WIDTH], ws1[MAX_WIDTH];
@ -677,10 +671,13 @@ monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate)
int m1, m2; int m1, m2;
int printyearheader; int printyearheader;
int prevyear = -1; int prevyear = -1;
int startline = 0;
int screenlines, screencols;
mpl = jd_flag ? 2 : 3; mpl = jd_flag ? 2 : 3;
mw = jd_flag ? MONTH_WIDTH_B_J : (flag_weeks ? MONTH_WIDTH_B_WW : MONTH_WIDTH_B_NW ); mw = jd_flag ? MONTH_WIDTH_B_J : (flag_weeks ? MONTH_WIDTH_B_WW : MONTH_WIDTH_B_NW );
wdss = (mpl == 2) ? " " : ""; wdss = (mpl == 2) ? " " : "";
getmaxyx(stdscr, screenlines, screencols);
while (before > 0) { while (before > 0) {
DECREASEMONTH(m, y); DECREASEMONTH(m, y);
@ -706,25 +703,17 @@ monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate)
m = m1; m = m1;
while (m <= m2) { while (m <= m2) {
int count = 0;
for (i = 0; i != mpl && m + i <= m2; i++) {
mkmonthb(M2Y(m + i), M2M(m + i) - 1, jd_flag, &year[i], highlightdate);
count++;
}
/* Empty line between two rows of months */
if (m != m1)
printw("\n");
/* Year at the top. */ /* Year at the top. */
if (printyearheader && M2Y(m) != prevyear) { if (printyearheader && M2Y(m) != prevyear) {
sprintf(s, "%d", M2Y(m)); sprintf(s, "%d", M2Y(m));
printw("%s\n", center(t, s, mpl * mw)); printcentered(startline, s, 1, mpl * mw);
prevyear = M2Y(m); prevyear = M2Y(m);
startline++;
} }
/* Month names. */ /* Month names. */
for (i = 0; i < count; i++) { mvaddstr(startline, 0, "");
for (i = 0; i != mpl && m + i <= m2; i++) {
wchar_t month_name[MAX_WIDTH+1]; wchar_t month_name[MAX_WIDTH+1];
compute_month_name(M2M(m + i) - 1, month_name, sizeof(month_name)/sizeof(month_name[0])); compute_month_name(M2M(m + i) - 1, month_name, sizeof(month_name)/sizeof(month_name[0]));
if (printyearheader) if (printyearheader)
@ -736,10 +725,11 @@ monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate)
printw("%-*ls ", mw, wcenter(ws1, ws, mw)); printw("%-*ls ", mw, wcenter(ws1, ws, mw));
} }
} }
printw("\n"); startline++;
/* Day of the week names. */ /* Day of the week names. */
for (i = 0; i < count; i++) { mvaddstr(startline, 0, "");
for (i = 0; i != mpl && m + i <= m2; i++) {
if (flag_weeks) if (flag_weeks)
printw(" w| %s%ls%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls ", printw(" w| %s%ls%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls ",
wdss, wds.names[6], wdss, wds.names[0], wdss, wds.names[6], wdss, wds.names[0],
@ -753,25 +743,22 @@ monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate)
wdss, wds.names[3], wdss, wds.names[4], wdss, wds.names[3], wdss, wds.names[4],
wdss, wds.names[5]); wdss, wds.names[5]);
} }
printw("\n"); startline++;
/* And the days of the month. */ /* And the days of the month. */
for (i = 0; i != 6; i++) { for (i = 0; i != mpl && m + i <= m2; i++)
for (j = 0; j < count; j++) printmonthb(startline, i*(mw+2), M2Y(m + i), M2M(m + i) - 1, jd_flag, highlightdate);
printw("%-*s ",
MW(mw, year[j].extralen[i]),
year[j].lines[i]+1);
printw("\n");
}
m += mpl; m += mpl;
startline += 7;
if (startline >= screenlines)
break;
} }
} }
static void static void
monthranger(int y, int m, int jd_flag, int before, int after, int highlightdate) monthranger(int y, int m, int jd_flag, int before, int after, int highlightdate)
{ {
struct monthlines year[12];
struct weekdays wds; struct weekdays wds;
char s[MAX_WIDTH], t[MAX_WIDTH]; char s[MAX_WIDTH], t[MAX_WIDTH];
int i, j; int i, j;
@ -780,9 +767,12 @@ monthranger(int y, int m, int jd_flag, int before, int after, int highlightdate)
int m1, m2; int m1, m2;
int prevyear = -1; int prevyear = -1;
int printyearheader; int printyearheader;
int startline = 0;
int screenlines, screencols;
mpl = jd_flag ? 3 : 4; mpl = jd_flag ? 3 : 4;
mw = jd_flag ? MONTH_WIDTH_R_J : MONTH_WIDTH_R; mw = jd_flag ? MONTH_WIDTH_R_J : MONTH_WIDTH_R;
getmaxyx(stdscr, screenlines, screencols);
while (before > 0) { while (before > 0) {
DECREASEMONTH(m, y); DECREASEMONTH(m, y);
@ -808,26 +798,17 @@ monthranger(int y, int m, int jd_flag, int before, int after, int highlightdate)
m = m1; m = m1;
while (m <= m2) { while (m <= m2) {
int count = 0;
for (i = 0; i != mpl && m + i <= m2; i++) {
mkmonthr(M2Y(m + i), M2M(m + i) - 1, jd_flag, &year[i], highlightdate);
count++;
}
/* Empty line between two rows of months. */
if (m != m1)
printw("\n");
/* Year at the top. */ /* Year at the top. */
if (printyearheader && M2Y(m) != prevyear) { if (printyearheader && M2Y(m) != prevyear) {
sprintf(s, "%d", M2Y(m)); sprintf(s, "%d", M2Y(m));
printw("%s\n", center(t, s, mpl * mw)); printcentered(startline, s, 1, mpl * mw);
prevyear = M2Y(m); prevyear = M2Y(m);
startline++;
} }
/* Month names. */ /* Month names. */
printw(" "); mvaddstr(startline, 1, " ");
for (i = 0; i < count; i++) { for (i = 0; i != mpl && m + i <= m2; i++) {
wchar_t month_name[MAX_WIDTH+1]; wchar_t month_name[MAX_WIDTH+1];
compute_month_name(M2M(m + i) - 1, month_name, sizeof(month_name)/sizeof(month_name[0])); compute_month_name(M2M(m + i) - 1, month_name, sizeof(month_name)/sizeof(month_name[0]));
if (printyearheader) if (printyearheader)
@ -836,43 +817,42 @@ monthranger(int y, int m, int jd_flag, int before, int after, int highlightdate)
printw("%-ls %-*d", month_name, printw("%-ls %-*d", month_name,
mw - wcslen(month_name) - 1, M2Y(m + i)); mw - wcslen(month_name) - 1, M2Y(m + i));
} }
printw("\n"); startline++;
/* And the days of the month. */ /* Days of the week. */
for (i = 0; i != 7; i++) { for (i = 0; i != 7; i++)
/* Week day */ mvprintw(startline+i, 0, "%.2ls", wds.names[i]);
printw("%.2ls", wds.names[i]);
/* Full months */ /* Dates */
for (j = 0; j < count; j++) for (i = 0; i != mpl && m + i <= m2; i++)
printw("%-*s", printmonthr(startline, 3+i*mw, M2Y(m + i), M2M(m + i) - 1, jd_flag, highlightdate);
MW(mw, year[j].extralen[i]),
year[j].lines[i]);
printw("\n");
}
/* Week numbers. */ /* Week numbers. */
if (flag_weeks) { if (flag_weeks) {
printw(" "); mvprintw(startline+7, 0, " ");
for (i = 0; i < count; i++) for (i = 0; i != mpl && m + i <= m2; i++)
printw("%-*s", mw, year[i].weeks); printweeknumber(startline, M2Y(m + i), M2M(m + i) - 1, jd_flag);
printw("\n");
} }
m += mpl; m += mpl;
startline += 8;
if (flag_weeks)
startline++;
if (startline >= screenlines)
break;
} }
return; return;
} }
static void static void
mkmonthr(int y, int m, int jd_flag, struct monthlines *mlines, int highlightdate) printmonthr(int line, int col, int y, int m, int jd_flag, int highlightdate)
{ {
date dt; /* handy date */ date dt; /* handy date */
int dw; /* width of numbers */ int dw; /* width of numbers */
int first; /* first day of month */ int first; /* first day of month */
int firstm; /* first day of first week of month */ int firstm; /* first day of first week of month */
int i, j, k, l; /* just indices */ int i, j, k; /* just indices */
int last; /* the first day of next month */ int last; /* the first day of next month */
int jan1 = 0; /* the first day of this year */ int jan1 = 0; /* the first day of this year */
char *ds; /* pointer to day strings (daystr or char *ds; /* pointer to day strings (daystr or
@ -916,48 +896,95 @@ mkmonthr(int y, int m, int jd_flag, struct monthlines *mlines, int highlightdate
* column is one day number. print column index: k. * column is one day number. print column index: k.
*/ */
for (i = 0; i != 7; i++) { for (i = 0; i != 7; i++) {
l = 0;
for (j = firstm + i, k = 0; j < last; j += 7, k += dw) { for (j = firstm + i, k = 0; j < last; j += 7, k += dw) {
if (j >= first) { if (j >= first) {
if (jd_flag) if (jd_flag)
dt.d = j - jan1 + 1; dt.d = j - jan1 + 1;
else else
sdater(j, &dt); sdater(j, &dt);
if (j == highlightdate if (j == highlightdate && isatty(STDOUT_FILENO)) {
&& isatty(STDOUT_FILENO)) mvaddstr(line+i, col+k-1, " ");
highlight(mlines->lines[i] + k, attron(A_REVERSE);
ds + dt.d * dw, dw, &l); printw("%-.*s", dw-1, ds + dt.d * dw + 1);
else attroff(A_REVERSE);
memcpy(mlines->lines[i] + k + l, }
ds + dt.d * dw, dw); else {
} else mvprintw(line+i, col+k-1, "%-.*s", dw, ds + dt.d * dw);
memcpy(mlines->lines[i] + k + l, " ", dw); }
} else {
mvprintw(line+i, col+k-1, "%-.*s", dw, " ");
}
} }
mlines->lines[i][k + l] = '\0';
mlines->extralen[i] = l;
}
/* fill the weeknumbers. */
if (flag_weeks) {
for (j = firstm, k = 0; j < last; k += dw, j += 7)
if (j <= nswitch)
memset(mlines->weeks + k, ' ', dw);
else
memcpy(mlines->weeks + k,
ds + week(j, &i)*dw, dw);
mlines->weeks[k] = '\0';
} }
} }
static void static void
mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines, int highlightdate) printweeknumber(int line, int y, int m, int jd_flag)
{
date dt; /* handy date */
int dw; /* width of numbers */
int first; /* first day of month */
int firstm; /* first day of first week of month */
int i, j, k; /* just indices */
int last; /* the first day of next month */
int jan1 = 0; /* the first day of this year */
char *ds; /* pointer to day strings (daystr or
* jdaystr) */
/*
* Set first and last to the day number of the first day of this
* month and the first day of next month respectively. Set jan1 to
* the day number of the first day of this year.
*/
first = firstday(y, m + 1);
if (m == 11)
last = firstday(y + 1, 1);
else
last = firstday(y, m + 2);
if (jd_flag)
jan1 = firstday(y, 1);
/*
* Set firstm to the day number of the day starting the first week of
* this month. (This might be in the last month)
*/
if (weekstart == 0)
firstm = first - (weekday(first) + 1) % 7;
else
firstm = first - weekday(first);
/* Set ds (daystring) and dw (daywidth) according to the jd_flag. */
if (jd_flag) {
ds = jdaystr;
dw = 4;
} else {
ds = daystr;
dw = 3;
}
if (flag_weeks) {
for (j = firstm, k = 0; j < last; k += dw, j += 7)
if (j <= nswitch)
printw("%-.*s", dw, "");
else
printw("%-.*s", dw, ds + week(j, &i)*dw);
k /= dw;
for (; k < 6; k++)
printw("%-.*s", dw, " ");
}
}
/* Print all months for the period in the range [ before .. y-m .. after ]. */
static void
printmonthb(int line, int col, int y, int m, int jd_flag, int highlightdate)
{ {
date dt; /* handy date */ date dt; /* handy date */
int dw; /* width of numbers */ int dw; /* width of numbers */
int first; /* first day of month */ int first; /* first day of month */
int firsts; /* first day of first week of month */ int firsts; /* first day of first week of month */
int i, j, k, l; /* just indices */ int i, j, k; /* just indices */
int jan1 = 0; /* the first day of this year */ int jan1 = 0; /* the first day of this year */
int last; /* the first day of next month */ int last; /* the first day of next month */
char *ds; /* pointer to day strings (daystr or char *ds; /* pointer to day strings (daystr or
@ -1016,8 +1043,6 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines, int highlightdate
* column is one day number. print column index: k. * column is one day number. print column index: k.
*/ */
for (i = 0; i != 6; i++) { for (i = 0; i != 6; i++) {
/* additional shift to make space for weeks */
l = flag_weeks ? 4 : 0;
for (j = firsts + 7 * i, k = 0; j < last && k != dw * 7; for (j = firsts + 7 * i, k = 0; j < last && k != dw * 7;
j++, k += dw) { j++, k += dw) {
if (j >= first) { if (j >= first) {
@ -1025,27 +1050,18 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines, int highlightdate
dt.d = j - jan1 + 1; dt.d = j - jan1 + 1;
else else
sdateb(j, &dt); sdateb(j, &dt);
if (j == highlightdate) if (j == highlightdate) {
highlight(mlines->lines[i] + k + l, attron(A_REVERSE);
ds + dt.d * dw, dw, &l); mvprintw(line+i, col+k, "%-.*s", dw-1, ds + dt.d*dw + 1);
else attroff(A_REVERSE);
memcpy(mlines->lines[i] + k + l, }
ds + dt.d * dw, dw); else {
} else mvprintw(line+i, col+k, "%-.*s", dw-1, ds + dt.d*dw + 1);
memcpy(mlines->lines[i] + k + l, " ", dw); }
} } else {
if (k == 0) mvprintw(line+i, col+k, "%-.*s", dw, " ");
mlines->lines[i][1] = '\0';
else {
mlines->lines[i][k + l] = '\0';
if (flag_weeks) {
int year;
memcpy(mlines->lines[i], ds + week(firsts + 7 * i, &year)*dw, dw);
memcpy(mlines->lines[i] + 3, "|", 1);
} }
} }
/* store only highlighting extralength */
mlines->extralen[i] = l - (flag_weeks ? 4 : 0);
} }
/* redo the shift from ncal_backward to correct week number assignment */ /* redo the shift from ncal_backward to correct week number assignment */
@ -1154,15 +1170,11 @@ sdateb(int nd, struct date *d)
return (jdate(nd, d)); return (jdate(nd, d));
} }
/* Center string t in string s of length w by putting enough leading blanks. */ /* Print string s centered between columns start and end. */
static char * static void
center(char *s, char *t, int w) printcentered(int line, char *s, int start, int end)
{ {
char blanks[MAX_WIDTH]; mvaddstr(line, start + (end - start - strlen(s))/2, s);
memset(blanks, ' ', sizeof(blanks));
sprintf(s, "%.*s%s", (int)(w - strlen(t)) / 2, blanks, t);
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. */