Skip to contentSkip to conversation

cal: Output unaligned with "-3" option and libtermcap

PATCH Karel Zak 2 participants 6 messages Feb 15, 2007 1 message not in the archive Util-Linux package

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Karel Zak

author maintainer
#1 lore raw

Hi Christian,

some ideas from your patch are really good, but the rest is not so perfect after all.

Review

Quoted 5 lines · Christian Schlotter
(quoted diff) +1 -3
+monthly3(int day, int month, int year, const int show_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);

This is basic idea of the old monthly3() implementation and I think it's definitely good idea. There must be only one place (= do_monthly()) where we generate output for months.

Quoted 12 lines
(quoted diff) +4 -8
-        width = (julian ? J_WEEK_LEN : WEEK_LEN) -1;
-	for (i = 0; i < 2; i++)
-		printf("%s  %s  %s\n", out_prev.s[i], out_curm.s[i], out_next.s[i]);
-	for (i = 2; i < FMT_ST_LINES; i++) {
-		snprintf(lineout, SIZE(lineout), "%-*s  %-*s  %-*s\n",
-		       width, out_prev.s[i],
-		       width, out_curm.s[i],
-		       width, out_next.s[i]);
+    memset(lineout, ' ', sizeof(lineout) - 1);
+    lineout[sizeof(lineout) - 1] = '\0';
+
+    for (i = 0; i < 3; i++) {

Review

Quoted 10 lines
(quoted diff) +10 -0
+	    day_array(day, months[i], years[i], days[i]);
+	    if (show_year) {
+		    snprintf(head, sizeof(head), _("%s %d"),
+			     full_month[months[i] - 1], years[i]);
+	    } else {
+		    snprintf(head, sizeof(head), _("%s"),
+			     full_month[months[i] - 1]);
+	    }
+	    center(head, week_len, (i == 2) ? 0 : head_sep);
+    }

Here you *duplicate* functionality from do_monthly(). I think a better way will be add support for the "show_year" option to the do_monthly() function.

Should be something like:

monthly3(int day, int month, int year, const int show_year) {

for (i = 0; i < 3; i++)

      do_monthly(day, month[i], year[i], out[i], show_year);

}

Review

Quoted 1 line
(quoted diff) +1 -0
+		my_putstring(lineout);putchar('\n');

Ah.., please, two lines:

     my_putstring(lineout);
     putchar('\n');

:-)

Review

Quoted 5 lines

yearly(int day, int year) {

(quoted diff) +2 -0
+	for (month = 0; month < 12; month += 3)
+		monthly3(day, month + 2, year, show_year);
 }

Good idea.

yearly = 4 * monthly3
monthly3 = 3 * do_monthly

Karel

Signature · 1 line
 Karel Zak  <[email protected]>
#2 lore raw
Quoted 4 lines · Karel Zak

Hi Christian,

some ideas from your patch are really good, but the rest is not so perfect after all.

Sorry I missed the original mail/patch.
Can you send again?

For reference I did the "highlight today" functionality in cal a couple of years back which has alignment issues, and have been trying to get the fix in since then:
http://www.pixelbeat.org/patches/cal-2.12q-highlight.diff

Incidentally I also fixed the weekday alignment for multibyte locales in the changes I did a couple of years ago.

Pádraig.

author maintainer
#3 lore raw
Quoted 2 lines · Pádraig Brady

Sorry I missed the original mail/patch.
Can you send again?

There is a small display error when using cal from util-linux-2.13-pre7 with the command line "cal -3m". On Sep 27th 2006 it produced the following output (Sep 27th is highlighted):

August 2006 September 2006 October 2006
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su

    1  2  3  4  5  6               1  2  3                     1
 7  8  9 10 11 12 13   4  5  6  7  8  9 10   2  3  4  5  6  7  8
14 15 16 17 18 19 20  11 12 13 14 15 16 17   9 10 11 12 13 14 15
21 22 23 24 25 26 27  18 19 20 21 22 23 24  16 17 18 19 20 21 22
28 29 30 31           25 26 27 28 29 30  23 24 25 26 27 28 29
                                            30 31

As one can see, the second but last row of October is misaligned because the characters used for highlighting are not taken into account when aligning the last line of September.

This patch fixes the erroneous display by adopting the style of the yearly(...) function. The patch also removes one unused variable "len" and unifies the amount of whitespace used for separating two month displays.

---
 misc-utils/cal.c |  124
+++++++++++++++++++++++++-----------------------------
 1 files changed, 57 insertions(+), 67 deletions(-)
misc-utils/cal.c +4 -3
index 339a610..9719c12 100644
@@ -232,7 +232,7 @@ void yearly(int, int);
 void j_yearly(int, int);
 void do_monthly(int, int, int, struct fmt_st*);
 void monthly(int, int, int);
-void monthly3(int, int, int);
+void monthly3(int, int, int, const int);
 void trim_trailing_spaces(char *);
 void usage(void);
 void headers_init(void);
@@ -245,6 +245,7 @@ main(int argc, char **argv) {
 	int ch, day, month, year, yflag;
 	char *progname, *p;
 	int num_months = NUM_MONTHS;
+	const int show_year = 1;
 
 	progname = argv[0];
 	if ((p = strrchr(progname, '/')) != NULL)
@@ -347,7 +348,7 @@ main(int argc, char **argv) {
 	if (month && num_months == 1)
 		monthly(day, month, year);
 	else if (month && num_months == 3)
-		monthly3(day, month, year);
+		monthly3(day, month, year, show_year);
 	else if (julian)
 		j_yearly(day, year);
 	else
@@ -424,7 +425,7 @@ void headers_init(void)
 
 void
 do_monthly(int day, int month, int year, struct fmt_st *out) {
-	int col, row, len, days[MAXDAYS];
+	int col, row, days[MAXDAYS];
 	char *p, lineout[FMT_ST_CHARS];
 	int width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1;
 
@@ -436,7 +437,7 @@ 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. */
- len = sprintf(lineout, _("%s %d"), full_month[month - 1], year);
+ sprintf(lineout, _("%s %d"), full_month[month - 1], year);
center_str(lineout, out->s[0], SIZE(out->s[0]), width);

sprintf(out->s[1],"%s",
@@ -466,46 +467,62 @@ monthly(int day, int month, int year) {
}

void
-monthly3(int day, int month, int year) {
- char lineout[FMT_ST_CHARS];
- int i;
- int width;
- 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;
-
+monthly3(int day, int month, int year, const int show_year) {
+ char *p, lineout[FMT_ST_CHARS], head[FMT_ST_CHARS / 3];
+ int *dp, days[3][MAXDAYS], months[3], years[3], row, col, i;
+ const int week_len = (julian) ? J_WEEK_LEN : WEEK_LEN;
+ const int head_sep = (julian) ? J_HEAD_SEP : HEAD_SEP;
+ const char * const headings = (julian) ? j_day_headings : day_headings;
+
+ /* previous, current and next month/year */
if (month == 1) {
- prev_month = 12;
- prev_year = year - 1;
+ months[0] = 12;
+ years[0] = year - 1;
} else {
- prev_month = month - 1;
- prev_year = year;
+ months[0] = month - 1;
+ years[0] = year;
}
+ months[1] = month;
+ years[1] = year;
if (month == 12) {
- next_month = 1;
- next_year = year + 1;
+ months[2] = 1;
+ years[2] = year + 1;
} else {
- next_month = month + 1;
- next_year = year;
+ months[2] = month + 1;
+ years[2] = 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);
- width = (julian ? J_WEEK_LEN : WEEK_LEN) -1;
- for (i = 0; i < 2; i++)
- printf("%s %s %s\n", out_prev.s[i], out_curm.s[i], out_next.s[i]);
- for (i = 2; i < FMT_ST_LINES; i++) {
- snprintf(lineout, SIZE(lineout), "%-*s %-*s %-*s\n",

-		       width, out_prev.s[i],
-		       width, out_curm.s[i],
-		       width, out_next.s[i]);

+ memset(lineout, ' ', sizeof(lineout) - 1);
+ lineout[sizeof(lineout) - 1] = '\0';
+
+ for (i = 0; i < 3; i++) {
+ day_array(day, months[i], years[i], days[i]);
+ if (show_year) {
+ snprintf(head, sizeof(head), _("%s %d"),
+ full_month[months[i] - 1], years[i]);
+ } else {
+ snprintf(head, sizeof(head), _("%s"),
+ full_month[months[i] - 1]);
+ }
+ center(head, week_len, (i == 2) ? 0 : head_sep);

+    }
+    printf("\n%s%*s %s%*s %s\n", headings, head_sep, "", headings,
+	   head_sep, "", headings);
+    for (row = 0; row < 6; row++) {

+ p = lineout;
+ for (i = 0; i < 3; i++) {
+ dp = &days[i][row * 7];
+ for (col = 0; col < 7; col++) {
+ p = ascii_day(p, *dp++);
+ }
+ p += sprintf(p, " ");

+	    }
+	    *p = '\0';
+	    trim_trailing_spaces(lineout);

#if defined(HAVE_NCURSES) || defined(HAVE_LIBTERMCAP)
- my_putstring(lineout);
+ my_putstring(lineout);putchar('\n');
#else
- fputs(lineout,stdout);
+ puts(lineout);
#endif
}
}
@@ -546,47 +563,20 @@ j_yearly(int day, int year) {
#endif
}
}
- printf("\n");
}

void
yearly(int day, int year) {
- int col, *dp, i, month, row, which_cal;
- int days[12][MAXDAYS];
- char *p, lineout[100];
+ int month;
+ char lineout[100];
+ const int show_year = 0;

sprintf(lineout, "%d", year); center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0); printf("\n\n");

- for (i = 0; i < 12; i++)
- day_array(day, i + 1, year, days[i]);
- memset(lineout, ' ', sizeof(lineout) - 1);
- lineout[sizeof(lineout) - 1] = '\0';
- for (month = 0; month < 12; month += 3) {
- center(full_month[month], WEEK_LEN, HEAD_SEP);
- center(full_month[month + 1], WEEK_LEN, HEAD_SEP);
- center(full_month[month + 2], WEEK_LEN, 0);
- printf("\n%s%*s %s%*s %s\n", day_headings, HEAD_SEP,
- "", day_headings, HEAD_SEP, "", day_headings);
- for (row = 0; row < 6; row++) {
- p = lineout;
- for (which_cal = 0; which_cal < 3; which_cal++) {
- dp = &days[month + which_cal][row * 7];
- for (col = 0; col < 7; col++)
- p = ascii_day(p, *dp++);
- p += sprintf(p, " ");
- }
- *p = '\0';
- trim_trailing_spaces(lineout);
-#if defined(HAVE_NCURSES) || defined(HAVE_LIBTERMCAP)
- my_putstring(lineout);putchar('\n');
-#else
- puts(lineout);
-#endif
- }
- }
- printf("\n");
+ for (month = 0; month < 12; month += 3)
+ monthly3(day, month + 2, year, show_year);
}

/*

Signature · 5 lines
1.4.4.2


-- 
 Karel Zak  <[email protected]>
#4 lore raw
Quoted 18 lines · Karel Zak
Quoted 2 lines · Pádraig Brady

Sorry I missed the original mail/patch.
Can you send again?

There is a small display error when using cal from util-linux-2.13-pre7 with the command line "cal -3m". On Sep 27th 2006 it produced the following output (Sep 27th is highlighted):

August 2006 September 2006 October 2006
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su

    1  2  3  4  5  6               1  2  3                     1
 7  8  9 10 11 12 13   4  5  6  7  8  9 10   2  3  4  5  6  7  8
14 15 16 17 18 19 20  11 12 13 14 15 16 17   9 10 11 12 13 14 15
21 22 23 24 25 26 27  18 19 20 21 22 23 24  16 17 18 19 20 21 22
28 29 30 31           25 26 27 28 29 30  23 24 25 26 27 28 29
                                            30 31
Quoted 3 lines

As one can see, the second but last row of October is misaligned because the characters used for highlighting are not taken into account when aligning the last line of September.

Yes, that is exactly the issue my patch fixes.

Pádraig.

author maintainer
#5 lore raw
In reply to Pádraig Brady
Quoted 8 lines · Pádraig Brady
Quoted 4 lines · Karel Zak

Hi Christian,

some ideas from your patch are really good, but the rest is not so perfect after all.

Sorry I missed the original mail/patch.
Can you send again?

Done.

Quoted 4 lines

For reference I did the "highlight today" functionality in cal a couple of years back which has alignment issues, and have been trying to get the fix in since then:
http://www.pixelbeat.org/patches/cal-2.12q-highlight.diff

This patch is already in my mail box ;-)

Well, Christian's patch is more about code refactoring rather than about simple bug fix only. (It might good idea to cleanup the code.)

Quoted 2 lines

Incidentally I also fixed the weekday alignment for multibyte locales in the changes I did a couple of years ago

There is also other multibyte fix (by RH):

http://people.redhat.com/kzak/util-linux/util-linux-2.12p-cal-wide.patch

My plan is write some regression tests for the "cal" before playing with these patches.

Karel

Signature · 1 line
 Karel Zak  <[email protected]>
#6 lore raw
Quoted 16 lines · Karel Zak
Quoted 7 lines · Pádraig Brady
Quoted 4 lines · Karel Zak

Hi Christian,

some ideas from your patch are really good, but the rest is not so perfect after all.

Sorry I missed the original mail/patch.
Can you send again?

Done.

Quoted 4 lines

For reference I did the "highlight today" functionality in cal a couple of years back which has alignment issues, and have been trying to get the fix in since then:
http://www.pixelbeat.org/patches/cal-2.12q-highlight.diff

Quoted 4 lines

This patch is already in my mail box ;-)

Well, Christian's patch is more about code refactoring rather than about simple bug fix only. (It might good idea to cleanup the code.)

Yes the code can definitely be refactored.
I was wary of changing format though when I looked at it, in case I broke scripts depending on whitespace etc.

Quoted 10 lines
Quoted 3 lines

Incidentally I also fixed the weekday alignment for multibyte locales in the changes I did a couple of years ago

There is also other multibyte fix (by RH):

http://people.redhat.com/kzak/util-linux/util-linux-2.12p-cal-wide.patch

My plan is write some regression tests for the "cal" before playing with these patches.

I used the following 2 scripts to test my changes:

[ ! -e "./cal" ] && CAL=cal || CAL=./cal
LANG=ga_IE.utf8 $CAL -3 11 2004 #truncation (first month)
LANG=zh_HK.utf8 $CAL -3 #multibyte centering
$CAL | cat #no highlight
TERM= $CAL #no highlight
TERM=vt100 $CAL #highlight, with characters to be stripped by putp $CAL -y | head | tr ' ' . #3 spaces between cols?
$CAL -3 | tr ' ' . #2 spaces between cols and trailing spaces?

locale -a |
grep utf8 |
uniq -w2 |
while read LANG; do

    cal -3 |
    head -2 | tail -1;

done

Pádraig