From: Sami Kerola <kerolasa@iki.fi>
To: util-linux@vger.kernel.org
Cc: kerolasa@iki.fi
Subject: [PATCH 05/10] cal: determine output width at beginning of run and reuse result
Date: Sun, 27 Oct 2013 20:42:31 +0000 [thread overview]
Message-ID: <1382906556-16442-6-git-send-email-kerolasa@iki.fi> (raw)
In-Reply-To: <1382906556-16442-1-git-send-email-kerolasa@iki.fi>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/cal.c | 90 +++++++++++++++++++++++++++-----------------------------
1 file changed, 43 insertions(+), 47 deletions(-)
diff --git a/misc-utils/cal.c b/misc-utils/cal.c
index 44c1af1..df92cdd 100644
--- a/misc-utils/cal.c
+++ b/misc-utils/cal.c
@@ -187,11 +187,6 @@ enum {
#define MONTH_COLS 3 /* month columns in year view */
#define WNUM_LEN 3
-#define J_DAY_LEN 4 /* 4 spaces per day */
-#define J_WEEK_LEN (DAYS_IN_WEEK * J_DAY_LEN)
-#define J_HEAD_SEP 2
-#define J_MONTH_COLS 2
-
#define TODAY_FLAG 0x400 /* flag day for highlighting */
#define FMT_ST_LINES 9
@@ -233,12 +228,18 @@ enum {
};
/* utf-8 can have up to 6 bytes per char; and an extra byte for ending \0 */
-static char day_headings[J_WEEK_LEN * 6 + 1];
+static char day_headings[(WEEK_LEN + 1) * 6 + 1];
+
+struct cal_width {
+ size_t dy; /* day width in characters in printout */
+ size_t wk; /* week width == (7 * dlen + possible week num) */
+};
struct cal_control {
const char *full_month[MONTHS_IN_YEAR]; /* month names */
int colormode; /* day and week number highlight */
int num_months; /* number of months horizontally in print out */
+ struct cal_width width; /* width of output */
int weekstart; /* day the week starts, often Sun or Mon */
int wflag; /* uses WEEK_NUM_ enum */
int wnum; /* requested --week=number */
@@ -278,7 +279,8 @@ int main(int argc, char **argv)
.weekstart = SUNDAY,
.num_months = NUM_MONTHS,
.colormode = UL_COLORMODE_AUTO,
- .wflag = WEEK_NUM_DISABLED
+ .wflag = WEEK_NUM_DISABLED,
+ .width.dy = DAY_LEN
};
enum {
@@ -367,6 +369,7 @@ int main(int argc, char **argv)
break;
case 'j':
ctl.julian = 1;
+ ctl.width.dy = DAY_LEN + 1;
break;
case 'y':
ctl.yflag = 1;
@@ -400,7 +403,9 @@ int main(int argc, char **argv)
if (ctl.wflag) {
ctl.wflag = ctl.wnum & WEEK_NUM_MASK;
ctl.wflag |= (ctl.weekstart == MONDAY ? WEEK_NUM_ISO : WEEK_NUM_US);
- }
+ ctl.width.wk = (ctl.width.dy * DAYS_IN_WEEK) + WNUM_LEN;
+ } else
+ ctl.width.wk = (ctl.width.dy * DAYS_IN_WEEK);
time(&now);
local_time = localtime(&now);
@@ -474,9 +479,13 @@ int main(int argc, char **argv)
ctl.wflag &= ~WEEK_NUM_MASK;
}
- if (ctl.yflag)
+ if (ctl.yflag) {
+ if (ctl.julian)
+ ctl.num_months = MONTH_COLS - 1;
+ else
+ ctl.num_months = MONTH_COLS;
yearly(day, year, &ctl);
- else if (ctl.num_months == 1)
+ } else if (ctl.num_months == 1)
monthly(day, month, year, &ctl);
else if (ctl.num_months == 3)
monthly3(day, month, year, &ctl);
@@ -495,7 +504,7 @@ static int leap_year(long year)
static void headers_init(struct cal_control *ctl)
{
- size_t i, wd, spaces = ctl->julian ? J_DAY_LEN - 1 : DAY_LEN - 1;
+ size_t i, wd;
char *cur_dh = day_headings;
for (i = 0; i < DAYS_IN_WEEK; i++) {
@@ -506,10 +515,10 @@ static void headers_init(struct cal_control *ctl)
strcat(cur_dh++, " ");
space_left = sizeof(day_headings) - (cur_dh - day_headings);
- if (space_left <= spaces)
+ if (space_left <= (ctl->width.dy - 1))
break;
cur_dh += center_str(nl_langinfo(ABDAY_1 + wd), cur_dh,
- space_left, spaces);
+ space_left, ctl->width.dy - 1);
}
for (i = 0; i < MONTHS_IN_YEAR; i++)
@@ -521,8 +530,6 @@ static int do_monthly(int day, int month, long year, struct fmt_st *out,
{
int col, row, days[MAXDAYS];
char *p, lineout[FMT_ST_CHARS];
- size_t width = (ctl->julian ? J_WEEK_LEN : WEEK_LEN) - 1
- + (ctl->wflag ? WNUM_LEN : 0);
int pos = 0;
day_array(day, month, year, days, ctl);
@@ -531,10 +538,10 @@ static int do_monthly(int day, int month, long year, struct fmt_st *out,
header_hint = two_header_lines(month, year, ctl);
if (header_hint) {
snprintf(lineout, sizeof(lineout), _("%s"), ctl->full_month[month - 1]);
- center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width);
+ center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), ctl->width.wk - 1);
pos++;
snprintf(lineout, sizeof(lineout), _("%ld"), year);
- center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width);
+ center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), ctl->width.wk - 1);
pos++;
} else {
/* TRANSLATORS: %s is the month name, %ld the year number.
@@ -543,7 +550,7 @@ static int do_monthly(int day, int month, long year, struct fmt_st *out,
*/
snprintf(lineout, sizeof(lineout), _("%s %ld"),
ctl->full_month[month - 1], year);
- center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width);
+ center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), ctl->width.wk - 1);
pos++;
}
@@ -595,12 +602,11 @@ static void monthly(int day, int month, long year, const struct cal_control *ctl
static int two_header_lines(int month, long year, const struct cal_control *ctl)
{
char lineout[FMT_ST_CHARS];
- size_t width = (ctl->julian ? J_WEEK_LEN : WEEK_LEN) - 1;
size_t len;
snprintf(lineout, sizeof(lineout), "%ld", year);
len = strlen(lineout);
len += strlen(ctl->full_month[month - 1]) + 1;
- if (width < len)
+ if (ctl->width.wk - 1 < len)
return 1;
return 0;
}
@@ -609,7 +615,7 @@ static void monthly3(int day, int month, long year, const struct cal_control *ct
{
char lineout[FMT_ST_CHARS];
int i;
- int width, rows, two_lines;
+ int rows, two_lines;
struct fmt_st out_prev;
struct fmt_st out_curm;
struct fmt_st out_next;
@@ -644,7 +650,6 @@ static void monthly3(int day, int month, long year, const struct cal_control *ct
do_monthly(day, month, year, &out_curm, two_lines, ctl);
do_monthly(day, next_month, next_year, &out_next, two_lines, ctl);
- width = (ctl->julian ? J_WEEK_LEN : WEEK_LEN) -1;
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]);
@@ -652,7 +657,7 @@ static void monthly3(int day, int month, long year, const struct cal_control *ct
}
for (i = two_lines ? 3 : 2; i < rows; i++) {
int w1, w2, w3;
- w1 = w2 = w3 = width;
+ w1 = w2 = w3 = ctl->width.wk;
#if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW) || defined(HAVE_LIBTERMCAP)
/* adjust width to allow for non printable characters */
@@ -692,7 +697,6 @@ static char *append_wnum(char *p, int *dp,
static void yearly(int day, long year, const struct cal_control *ctl)
{
int col, i, month, row, which_cal;
- int maxrow, sep_len, week_len;
int days[MONTHS_IN_YEAR][MAXDAYS];
char *p;
/* three weeks + separators + \0 */
@@ -700,50 +704,42 @@ static void yearly(int day, long year, const struct cal_control *ctl)
char lineout[ wnumlen + sizeof(day_headings) + 2 +
wnumlen + sizeof(day_headings) + 2 +
wnumlen + sizeof(day_headings) + 1 ];
- if (ctl->julian) {
- maxrow = J_MONTH_COLS;
- sep_len = J_HEAD_SEP;
- week_len = J_WEEK_LEN + wnumlen;
- } else {
- maxrow = MONTH_COLS;
- sep_len = HEAD_SEP;
- week_len = WEEK_LEN + wnumlen;
- }
+
snprintf(lineout, sizeof(lineout), "%ld", year);
- /* 2013-04-28: The -1 near sep_len makes year header to be aligned
+ /* 2013-04-28: The -1 near HEAD_SEP makes year header to be aligned
* exactly how it has been aligned for long time, but it is
* unexplainable. */
- center(lineout, (week_len + sep_len) * maxrow - sep_len - 1, 0);
+ center(lineout, (ctl->width.wk + HEAD_SEP) * ctl->num_months - HEAD_SEP - 1, 0);
my_putstring("\n\n");
for (i = 0; i < MONTHS_IN_YEAR; i++)
day_array(day, i + 1, year, days[i], ctl);
- for (month = 0; month < MONTHS_IN_YEAR; month += maxrow) {
- center(ctl->full_month[month], week_len - 1, sep_len + 1);
+ for (month = 0; month < MONTHS_IN_YEAR; month += ctl->num_months) {
+ center(ctl->full_month[month], ctl->width.wk - 1, HEAD_SEP + 1);
if (ctl->julian) {
- center(ctl->full_month[month + 1], week_len - 1, 0);
+ center(ctl->full_month[month + 1], ctl->width.wk - 1, 0);
} else {
- center(ctl->full_month[month + 1], week_len - 1, sep_len + 1);
- center(ctl->full_month[month + 2], week_len - 1, 0);
+ center(ctl->full_month[month + 1], ctl->width.wk - 1, HEAD_SEP + 1);
+ center(ctl->full_month[month + 2], ctl->width.wk - 1, 0);
}
if (ctl->julian)
snprintf(lineout, sizeof(lineout),
"\n%*s%s%*s %*s%s\n",
- wnumlen,"", day_headings, sep_len, "",
+ wnumlen,"", day_headings, HEAD_SEP, "",
wnumlen,"", day_headings);
else
snprintf(lineout, sizeof(lineout),
"\n%*s%s%*s %*s%s%*s %*s%s\n",
- wnumlen,"", day_headings, sep_len, "",
- wnumlen,"", day_headings, sep_len, "",
+ wnumlen,"", day_headings, HEAD_SEP, "",
+ wnumlen,"", day_headings, HEAD_SEP, "",
wnumlen,"", day_headings);
my_putstring(lineout);
for (row = 0; row < DAYS_IN_WEEK - 1; row++) {
p = lineout;
- for (which_cal = 0; which_cal < maxrow; which_cal++) {
+ for (which_cal = 0; which_cal < ctl->num_months; which_cal++) {
int *dp = &days[month + which_cal][row * DAYS_IN_WEEK];
if (ctl->wflag)
@@ -919,6 +915,7 @@ static int week_to_day(long year, const struct cal_control *ctl)
return yday;
}
+
static char *ascii_day(char *p, int day, const struct cal_control *ctl)
{
int display, val;
@@ -933,9 +930,8 @@ static char *ascii_day(char *p, int day, const struct cal_control *ctl)
};
if (day == SPACE) {
- int len = ctl->julian ? J_DAY_LEN : DAY_LEN;
- memset(p, ' ', len);
- return p+len;
+ memset(p, ' ', ctl->width.dy);
+ return p + ctl->width.dy;
}
if (day & TODAY_FLAG) {
day &= ~TODAY_FLAG;
--
1.8.4.1
next prev parent reply other threads:[~2013-10-27 20:42 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-27 20:42 [0000/0010] cal: code revisit part I Sami Kerola
2013-10-27 20:42 ` [PATCH 01/10] cal: use control structure for run time configuration Sami Kerola
2013-10-31 11:29 ` Karel Zak
2013-10-27 20:42 ` [PATCH 02/10] cal: add input variable names to function prototypes Sami Kerola
2013-10-27 20:42 ` [PATCH 03/10] cal: make day_in_week() use same variable names as other functions Sami Kerola
2013-10-27 20:42 ` [PATCH 04/10] cal: simplify ascii_wnum() function Sami Kerola
2013-10-27 20:42 ` Sami Kerola [this message]
2013-10-31 11:34 ` [PATCH 05/10] cal: determine output width at beginning of run and reuse result Karel Zak
2013-10-27 20:42 ` [PATCH 06/10] tests: cal: take account week numbers when determing month lenght Sami Kerola
2013-10-27 20:42 ` [PATCH 07/10] cal: make user request to be part of read-only control struct Sami Kerola
2013-10-31 11:49 ` Karel Zak
2013-11-01 9:29 ` Sami Kerola
2013-10-27 20:42 ` [PATCH 08/10] cal: determine how many header lines are needed at initialization Sami Kerola
2013-10-27 20:42 ` [PATCH 09/10] cal: add month contents structure Sami Kerola
2013-10-27 20:42 ` [PATCH 10/10] cal: make cal --three to use content structures Sami Kerola
2013-10-31 12:14 ` [0000/0010] cal: code revisit part I Karel Zak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1382906556-16442-6-git-send-email-kerolasa@iki.fi \
--to=kerolasa@iki.fi \
--cc=util-linux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox