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;
struct monthlines {
char lines[7][MAX_WIDTH + 1];
char weeks[MAX_WIDTH + 1];
unsigned int extralen[7];
};
struct weekdays {
wchar_t names[7][4];
};
@ -166,14 +160,15 @@ static int nswitch; /* user defined switch date */
static int nswitchb; /* switch date for backward compatibility */
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 int firstday(int y, int m);
static void highlight(char *dst, char *src, int len, int *extraletters);
static void mkmonthr(int year, int month, int jd_flag,
struct monthlines * monthl, int highlightdate);
static void mkmonthb(int year, int month, int jd_flag,
struct monthlines * monthl, int highlightdate);
static void printweeknumber(int line, int y, int m, int jd_flag);
static void printmonthr(int line, int col, int y, int m, int jd_flag,
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 monthranger(int year, int m, int jd_flag,
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
monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate)
{
struct monthlines year[12];
struct weekdays wds;
char s[MAX_WIDTH], t[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 printyearheader;
int prevyear = -1;
int startline = 0;
int screenlines, screencols;
mpl = jd_flag ? 2 : 3;
mw = jd_flag ? MONTH_WIDTH_B_J : (flag_weeks ? MONTH_WIDTH_B_WW : MONTH_WIDTH_B_NW );
wdss = (mpl == 2) ? " " : "";
getmaxyx(stdscr, screenlines, screencols);
while (before > 0) {
DECREASEMONTH(m, y);
@ -706,25 +703,17 @@ monthrangeb(int y, int m, int jd_flag, int before, int after, int highlightdate)
m = m1;
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. */
if (printyearheader && M2Y(m) != prevyear) {
sprintf(s, "%d", M2Y(m));
printw("%s\n", center(t, s, mpl * mw));
printcentered(startline, s, 1, mpl * mw);
prevyear = M2Y(m);
startline++;
}
/* 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];
compute_month_name(M2M(m + i) - 1, month_name, sizeof(month_name)/sizeof(month_name[0]));
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("\n");
startline++;
/* 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)
printw(" w| %s%ls%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls ",
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[5]);
}
printw("\n");
startline++;
/* And the days of the month. */
for (i = 0; i != 6; i++) {
for (j = 0; j < count; j++)
printw("%-*s ",
MW(mw, year[j].extralen[i]),
year[j].lines[i]+1);
printw("\n");
}
for (i = 0; i != mpl && m + i <= m2; i++)
printmonthb(startline, i*(mw+2), M2Y(m + i), M2M(m + i) - 1, jd_flag, highlightdate);
m += mpl;
startline += 7;
if (startline >= screenlines)
break;
}
}
static void
monthranger(int y, int m, int jd_flag, int before, int after, int highlightdate)
{
struct monthlines year[12];
struct weekdays wds;
char s[MAX_WIDTH], t[MAX_WIDTH];
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 prevyear = -1;
int printyearheader;
int startline = 0;
int screenlines, screencols;
mpl = jd_flag ? 3 : 4;
mw = jd_flag ? MONTH_WIDTH_R_J : MONTH_WIDTH_R;
getmaxyx(stdscr, screenlines, screencols);
while (before > 0) {
DECREASEMONTH(m, y);
@ -808,26 +798,17 @@ monthranger(int y, int m, int jd_flag, int before, int after, int highlightdate)
m = m1;
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. */
if (printyearheader && M2Y(m) != prevyear) {
sprintf(s, "%d", M2Y(m));
printw("%s\n", center(t, s, mpl * mw));
printcentered(startline, s, 1, mpl * mw);
prevyear = M2Y(m);
startline++;
}
/* Month names. */
printw(" ");
for (i = 0; i < count; i++) {
mvaddstr(startline, 1, " ");
for (i = 0; i != mpl && m + i <= m2; i++) {
wchar_t month_name[MAX_WIDTH+1];
compute_month_name(M2M(m + i) - 1, month_name, sizeof(month_name)/sizeof(month_name[0]));
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,
mw - wcslen(month_name) - 1, M2Y(m + i));
}
printw("\n");
startline++;
/* And the days of the month. */
for (i = 0; i != 7; i++) {
/* Week day */
printw("%.2ls", wds.names[i]);
/* Days of the week. */
for (i = 0; i != 7; i++)
mvprintw(startline+i, 0, "%.2ls", wds.names[i]);
/* Full months */
for (j = 0; j < count; j++)
printw("%-*s",
MW(mw, year[j].extralen[i]),
year[j].lines[i]);
printw("\n");
}
/* Dates */
for (i = 0; i != mpl && m + i <= m2; i++)
printmonthr(startline, 3+i*mw, M2Y(m + i), M2M(m + i) - 1, jd_flag, highlightdate);
/* Week numbers. */
if (flag_weeks) {
printw(" ");
for (i = 0; i < count; i++)
printw("%-*s", mw, year[i].weeks);
printw("\n");
mvprintw(startline+7, 0, " ");
for (i = 0; i != mpl && m + i <= m2; i++)
printweeknumber(startline, M2Y(m + i), M2M(m + i) - 1, jd_flag);
}
m += mpl;
startline += 8;
if (flag_weeks)
startline++;
if (startline >= screenlines)
break;
}
return;
}
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 */
int dw; /* width of numbers */
int first; /* first day 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 jan1 = 0; /* the first day of this year */
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.
*/
for (i = 0; i != 7; i++) {
l = 0;
for (j = firstm + i, k = 0; j < last; j += 7, k += dw) {
if (j >= first) {
if (jd_flag)
dt.d = j - jan1 + 1;
else
sdater(j, &dt);
if (j == highlightdate
&& isatty(STDOUT_FILENO))
highlight(mlines->lines[i] + k,
ds + dt.d * dw, dw, &l);
else
memcpy(mlines->lines[i] + k + l,
ds + dt.d * dw, dw);
} else
memcpy(mlines->lines[i] + k + l, " ", dw);
if (j == highlightdate && isatty(STDOUT_FILENO)) {
mvaddstr(line+i, col+k-1, " ");
attron(A_REVERSE);
printw("%-.*s", dw-1, ds + dt.d * dw + 1);
attroff(A_REVERSE);
}
else {
mvprintw(line+i, col+k-1, "%-.*s", dw, ds + dt.d * 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
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 */
int dw; /* width of numbers */
int first; /* first day 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 last; /* the first day of next month */
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.
*/
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;
j++, k += dw) {
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;
else
sdateb(j, &dt);
if (j == highlightdate)
highlight(mlines->lines[i] + k + l,
ds + dt.d * dw, dw, &l);
else
memcpy(mlines->lines[i] + k + l,
ds + dt.d * dw, dw);
} else
memcpy(mlines->lines[i] + k + l, " ", dw);
}
if (k == 0)
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);
if (j == highlightdate) {
attron(A_REVERSE);
mvprintw(line+i, col+k, "%-.*s", dw-1, ds + dt.d*dw + 1);
attroff(A_REVERSE);
}
else {
mvprintw(line+i, col+k, "%-.*s", dw-1, ds + dt.d*dw + 1);
}
} else {
mvprintw(line+i, col+k, "%-.*s", dw, " ");
}
}
/* store only highlighting extralength */
mlines->extralen[i] = l - (flag_weeks ? 4 : 0);
}
/* 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));
}
/* Center string t in string s of length w by putting enough leading blanks. */
static char *
center(char *s, char *t, int w)
/* Print string s centered between columns start and end. */
static void
printcentered(int line, char *s, int start, int end)
{
char blanks[MAX_WIDTH];
memset(blanks, ' ', sizeof(blanks));
sprintf(s, "%.*s%s", (int)(w - strlen(t)) / 2, blanks, t);
return (s);
mvaddstr(line, start + (end - start - strlen(s))/2, s);
}
/* Center string t in string s of length w by putting enough leading blanks. */