From: Sami Kerola <kerolasa@iki.fi>
To: util-linux@vger.kernel.org
Cc: kerolasa@iki.fi
Subject: [PATCH 11/13] cal: add month contents structure
Date: Sun, 10 Nov 2013 18:23:38 +0000 [thread overview]
Message-ID: <1384107820-498-12-git-send-email-kerolasa@iki.fi> (raw)
In-Reply-To: <1384107820-498-1-git-send-email-kerolasa@iki.fi>
This changes determination of calendar month content completely, as well
as outputing.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
misc-utils/cal.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 169 insertions(+), 7 deletions(-)
diff --git a/misc-utils/cal.c b/misc-utils/cal.c
index 0a6cd8d..a3eff48 100644
--- a/misc-utils/cal.c
+++ b/misc-utils/cal.c
@@ -251,11 +251,22 @@ struct cal_control {
header_hint:1; /* does month name + year need two lines to fit */
};
+struct cal_month {
+ int days[MAXDAYS]; /* the day numbers, or SPACE */
+ int weeks[MAXDAYS / DAYS_IN_WEEK];
+ int month;
+ long year;
+ struct cal_month *next;
+};
+
/* function prototypes */
static int leap_year(long year);
static void headers_init(struct cal_control *ctl);
static int do_monthly(int day, int month, long year, struct fmt_st *out,
const struct cal_control *ctl);
+static void cal_fill_month(struct cal_month *month, const struct cal_control *ctl);
+static void cal_output_header(struct cal_month *month, const struct cal_control *ctl);
+static void cal_output_months(struct cal_month *month, const struct cal_control *ctl);
static void monthly(const struct cal_control *ctl);
static void monthly3(const struct cal_control *ctl);
static char *append_weeknum(char *p, int *dp, int month, long year, int cal, int row,
@@ -597,18 +608,169 @@ static int do_monthly(int day, int month, long year, struct fmt_st *out,
return pos;
}
-static void monthly(const struct cal_control *ctl)
+static void cal_fill_month(struct cal_month *month, const struct cal_control *ctl)
{
- int i, rows;
- struct fmt_st out;
+ int first_week_day = day_in_week(1, month->month, month->year);
+ int month_days;
+ int i, j, weeklines = 0;
+
+ if (ctl->julian)
+ j = day_in_year(1, month->month, month->year);
+ else
+ j = 1;
+ month_days = j + days_in_month[leap_year(month->year)][month->month];
+
+ /* True when Sunday is not first day in the output week. */
+ if (ctl->weekstart) {
+ first_week_day -= ctl->weekstart;
+ if (first_week_day < 0)
+ first_week_day = DAYS_IN_WEEK - ctl->weekstart;
+ month_days += ctl->weekstart - 1;
+ }
+
+ /* Fill day array. */
+ for (i = 0; i < MAXDAYS; i++) {
+ if (0 < first_week_day) {
+ month->days[i] = SPACE;
+ first_week_day--;
+ continue;
+ }
+ if (j < month_days) {
+ if (month->year == 1752 && month->month == 9 && (j == 3 || j == 247))
+ j += NUMBER_MISSING_DAYS;
+ month->days[i] = j;
+ j++;
+ continue;
+ }
+ month->days[i] = SPACE;
+ weeklines++;
+ }
- rows = do_monthly(ctl->req.day, ctl->req.month, ctl->req.year, &out, ctl);
- for (i = 0; i < rows; i++) {
- my_putstring(out.s[i]);
- my_putstring("\n");
+ /* Add week numbers */
+ if (ctl->weektype) {
+ int weeknum = week_number(1, month->month, month->year, ctl);
+ weeklines = MAXDAYS / DAYS_IN_WEEK - weeklines / DAYS_IN_WEEK;
+ for (i = 0; i < MAXDAYS / DAYS_IN_WEEK; i++) {
+ if (0 < weeklines)
+ month->weeks[i] = weeknum++;
+ else
+ month->weeks[i] = SPACE;
+ weeklines--;
+ if (52 < weeknum && i == 0)
+ weeknum = week_number(month->days[DAYS_IN_WEEK * (i + 1)], 1, month->year, ctl);
+ else if (52 < weeknum)
+ weeknum = week_number(31, 12, month->year, ctl);
+ }
}
}
+static void cal_output_header(struct cal_month *month, const struct cal_control *ctl)
+{
+ char out[FMT_ST_CHARS];
+ struct cal_month *i;
+
+ if (ctl->header_hint) {
+ for (i = month; i; i = i->next) {
+ sprintf(out, _("%s"), ctl->full_month[i->month - 1]);
+ center(out, ctl->week_width - 1, i->next == NULL ? 0 : 2);
+ }
+ fputs("\n", stdout);
+ for (i = month; i; i = i->next) {
+ sprintf(out, _("%ld"), i->year);
+ center(out, ctl->week_width - 1, i->next == NULL ? 0 : 2);
+ }
+ } else {
+ for (i = month; i; i = i->next) {
+ sprintf(out, _("%s %ld"), ctl->full_month[i->month - 1], i->year);
+ center(out, ctl->week_width - 1, i->next == NULL ? 0 : 2);
+ }
+ }
+ puts("");
+ for (i = month; i; i = i->next) {
+ if (ctl->weektype) {
+ if (ctl->julian)
+ printf("%*s%s", (int)ctl->day_width - 1, "", day_headings);
+ else
+ printf("%*s%s", (int)ctl->day_width, "", day_headings);
+ } else
+ fputs(day_headings, stdout);
+ if (i->next != NULL)
+ fputs(" ", stdout);
+ }
+ puts("");
+}
+
+static void cal_output_months(struct cal_month *month, const struct cal_control *ctl)
+{
+ int reqday, week_line, d;
+ int skip;
+ struct cal_month *i;
+
+ for (week_line = 0; week_line < MAXDAYS / DAYS_IN_WEEK; week_line++) {
+ for (i = month; i; i = i->next) {
+ /* Determine the day that should be highlighted. */
+ reqday = 0;
+ if (i->month == ctl->req.month && i->year == ctl->req.year) {
+ if (ctl->julian)
+ reqday = ctl->req.day;
+ else
+ reqday =
+ ctl->req.day + 1 - day_in_year(1, i->month,
+ i->year);
+ }
+
+ if (ctl->weektype) {
+ if (0 < i->weeks[week_line]) {
+ if ((ctl->weektype & WEEK_NUM_MASK) ==
+ i->weeks[week_line])
+ printf("%s%2d%s", Senter, i->weeks[week_line],
+ Sexit);
+ else
+ printf("%2d", i->weeks[week_line]);
+ } else
+ printf("%2s", "");
+ skip = ctl->day_width;
+ } else
+ /* First day of the week is one char narrower than the other days,
+ * unless week number is printed. */
+ skip = ctl->day_width - 1;
+
+ for (d = DAYS_IN_WEEK * week_line;
+ d < DAYS_IN_WEEK * week_line + DAYS_IN_WEEK; d++) {
+ if (0 < i->days[d]) {
+ if (reqday == i->days[d])
+ printf("%*s%s%*d%s", skip - (ctl->julian ? 3 : 2),
+ "", Senter, (ctl->julian ? 3 : 2),
+ i->days[d], Sexit);
+ else
+ printf("%*d", skip, i->days[d]);
+ } else
+ printf("%*s", skip, "");
+ if (skip < (int)ctl->day_width)
+ skip++;
+ }
+ if (i->next != NULL)
+ fputs(" ", stdout);
+ }
+ if (i == NULL)
+ fputs(" \n", stdout);
+ }
+}
+
+static void monthly(const struct cal_control *ctl)
+{
+ struct cal_month month;
+
+ month.month = ctl->req.month;
+ month.year = ctl->req.year;
+ month.next = NULL;
+
+ cal_fill_month(&month, ctl);
+
+ cal_output_header(&month, ctl);
+ cal_output_months(&month, ctl);
+}
+
static void monthly3(const struct cal_control *ctl)
{
char lineout[FMT_ST_CHARS];
--
1.8.4.2
next prev parent reply other threads:[~2013-11-10 18:25 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-10 18:23 [PATCH 00/13] pull: cal: code revisit part I try II Sami Kerola
2013-11-10 18:23 ` [PATCH 01/13] cal: use control structure for run time configuration Sami Kerola
2013-11-10 18:23 ` [PATCH 02/13] cal: rename ascii_wnum() to ascii_weeknum() Sami Kerola
2013-11-10 18:23 ` [PATCH 03/13] cal: add input variable names to function prototypes Sami Kerola
2013-11-10 18:23 ` [PATCH 04/13] cal: make day_in_week() use same variable names as other functions Sami Kerola
2013-11-10 18:23 ` [PATCH 05/13] cal: simplify ascii_weeknum() function Sami Kerola
2013-11-10 18:23 ` [PATCH 06/13] cal: determine output width at beginning of run and reuse result Sami Kerola
2013-11-10 18:23 ` [PATCH 07/13] tests: cal: take account week numbers when determing month lenght Sami Kerola
2013-11-10 18:23 ` [PATCH 08/13] cal: make user request to be part of read-only control struct Sami Kerola
2013-11-10 18:23 ` [PATCH 09/13] tests: cal: do not let --week=<num> to adjust requested month Sami Kerola
2013-11-10 18:23 ` [PATCH 10/13] cal: determine how many header lines are needed at initialization Sami Kerola
2013-11-10 18:23 ` Sami Kerola [this message]
2013-11-10 18:23 ` [PATCH 12/13] cal: use month contents structure for --three printing Sami Kerola
2013-12-06 10:07 ` Karel Zak
2013-11-10 18:23 ` [PATCH 13/13] cal: use month contents structure for --year printing Sami Kerola
2013-12-06 10:02 ` [PATCH 00/13] pull: cal: code revisit part I try II 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=1384107820-498-12-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