Split out code for drawing week numbers

This allows for easily adding week numbers to other panel modes, such as
the monthly view.

Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
This commit is contained in:
Lukas Fleischer 2015-04-10 09:29:17 +02:00
parent 5ac3d43e9a
commit ebb8116056
3 changed files with 116 additions and 99 deletions

View File

@ -1051,6 +1051,7 @@ int is_all_digit(const char *);
long get_item_time(long);
int get_item_hour(long);
int get_item_min(long);
struct tm date2tm(struct date, unsigned, unsigned);
time_t date2sec(struct date, unsigned, unsigned);
time_t utcdate2sec(struct date, unsigned, unsigned);
char *date_sec2date_str(long, const char *);

View File

@ -281,6 +281,109 @@ void ui_calendar_monthly_view_cache_set_invalid(void)
monthly_view_cache_valid = 0;
}
static int weeknum(const struct tm *t, int firstweekday)
{
int wday, wnum;
wday = t->tm_wday;
if (firstweekday == MONDAY) {
if (wday == SUNDAY)
wday = 6;
else
wday--;
}
wnum = ((t->tm_yday + WEEKINDAYS - wday) / WEEKINDAYS);
if (wnum < 0)
wnum = 0;
return wnum;
}
/*
* Compute the week number according to ISO 8601.
*/
static int ISO8601weeknum(const struct tm *t)
{
int wnum, jan1day;
wnum = weeknum(t, MONDAY);
jan1day = t->tm_wday - (t->tm_yday % WEEKINDAYS);
if (jan1day < 0)
jan1day += WEEKINDAYS;
switch (jan1day) {
case MONDAY:
break;
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
wnum++;
break;
case FRIDAY:
case SATURDAY:
case SUNDAY:
if (wnum == 0) {
/* Get week number of last week of last year. */
struct tm dec31ly; /* 12/31 last year */
dec31ly = *t;
dec31ly.tm_year--;
dec31ly.tm_mon = 11;
dec31ly.tm_mday = 31;
dec31ly.tm_wday =
(jan1day == SUNDAY) ? 6 : jan1day - 1;
dec31ly.tm_yday =
364 + ISLEAP(dec31ly.tm_year + 1900);
wnum = ISO8601weeknum(&dec31ly);
}
break;
}
if (t->tm_mon == 11) {
int wday, mday;
wday = t->tm_wday;
mday = t->tm_mday;
if ((wday == MONDAY && (mday >= 29 && mday <= 31))
|| (wday == TUESDAY && (mday == 30 || mday == 31))
|| (wday == WEDNESDAY && mday == 31))
wnum = 1;
}
return wnum;
}
static struct tm get_first_weekday(unsigned sunday_first)
{
int c_wday, days_to_remove;
struct tm t;
c_wday = ui_calendar_get_wday(&slctd_day);
if (sunday_first)
days_to_remove = c_wday;
else
days_to_remove = c_wday == 0 ? WEEKINDAYS - 1 : c_wday - 1;
t = date2tm(slctd_day, 0, 0);
date_change(&t, 0, -days_to_remove);
return t;
}
static void draw_week_number(struct scrollwin *sw, struct tm t)
{
int weeknum = ISO8601weeknum(&t);
WINS_CALENDAR_LOCK;
werase(sw_cal.inner);
custom_apply_attr(sw->inner, ATTR_HIGHEST);
mvwprintw(sw->win, conf.compact_panels ? 0 : 2, sw->w - 9,
"(# %02d)", weeknum);
custom_remove_attr(sw->inner, ATTR_HIGHEST);
WINS_CALENDAR_UNLOCK;
}
/* Draw the monthly view inside calendar panel. */
static void
draw_monthly_view(struct scrollwin *sw, struct date *current_day,
@ -398,79 +501,6 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day,
monthly_view_cache_valid = 1;
}
static int weeknum(const struct tm *t, int firstweekday)
{
int wday, wnum;
wday = t->tm_wday;
if (firstweekday == MONDAY) {
if (wday == SUNDAY)
wday = 6;
else
wday--;
}
wnum = ((t->tm_yday + WEEKINDAYS - wday) / WEEKINDAYS);
if (wnum < 0)
wnum = 0;
return wnum;
}
/*
* Compute the week number according to ISO 8601.
*/
static int ISO8601weeknum(const struct tm *t)
{
int wnum, jan1day;
wnum = weeknum(t, MONDAY);
jan1day = t->tm_wday - (t->tm_yday % WEEKINDAYS);
if (jan1day < 0)
jan1day += WEEKINDAYS;
switch (jan1day) {
case MONDAY:
break;
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
wnum++;
break;
case FRIDAY:
case SATURDAY:
case SUNDAY:
if (wnum == 0) {
/* Get week number of last week of last year. */
struct tm dec31ly; /* 12/31 last year */
dec31ly = *t;
dec31ly.tm_year--;
dec31ly.tm_mon = 11;
dec31ly.tm_mday = 31;
dec31ly.tm_wday =
(jan1day == SUNDAY) ? 6 : jan1day - 1;
dec31ly.tm_yday =
364 + ISLEAP(dec31ly.tm_year + 1900);
wnum = ISO8601weeknum(&dec31ly);
}
break;
}
if (t->tm_mon == 11) {
int wday, mday;
wday = t->tm_wday;
mday = t->tm_mday;
if ((wday == MONDAY && (mday >= 29 && mday <= 31))
|| (wday == TUESDAY && (mday == 30 || mday == 31))
|| (wday == WEDNESDAY && mday == 31))
wnum = 1;
}
return wnum;
}
/* Draw the weekly view inside calendar panel. */
static void
draw_weekly_view(struct scrollwin *sw, struct date *current_day,
@ -478,35 +508,14 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day,
{
#define DAYSLICESNO 6
const int WCALWIDTH = 28;
struct tm t;
int OFFY, OFFX, j, c_wday, days_to_remove, weeknum;
struct tm t = get_first_weekday(sunday_first);
int OFFY, OFFX, j;
OFFY = 0;
OFFX = (wins_sbar_width() - 2 - WCALWIDTH) / 2;
/* Fill in a tm structure with the first day of the selected week. */
c_wday = ui_calendar_get_wday(&slctd_day);
if (sunday_first)
days_to_remove = c_wday;
else
days_to_remove = c_wday == 0 ? WEEKINDAYS - 1 : c_wday - 1;
memset(&t, 0, sizeof(struct tm));
t.tm_mday = slctd_day.dd;
t.tm_mon = slctd_day.mm - 1;
t.tm_year = slctd_day.yyyy - 1900;
mktime(&t);
date_change(&t, 0, -days_to_remove);
/* Print the week number. */
weeknum = ISO8601weeknum(&t);
WINS_CALENDAR_LOCK;
werase(sw_cal.inner);
custom_apply_attr(sw->inner, ATTR_HIGHEST);
mvwprintw(sw->win, conf.compact_panels ? 0 : 2, sw->w - 9,
"(# %02d)", weeknum);
custom_remove_attr(sw->inner, ATTR_HIGHEST);
WINS_CALENDAR_UNLOCK;
draw_week_number(sw, t);
/* Now draw calendar view. */
for (j = 0; j < WEEKINDAYS; j++) {

View File

@ -363,7 +363,7 @@ int get_item_min(long date)
return lt.tm_min;
}
time_t date2sec(struct date day, unsigned hour, unsigned min)
struct tm date2tm(struct date day, unsigned hour, unsigned min)
{
time_t t = now();
struct tm start;
@ -378,7 +378,14 @@ time_t date2sec(struct date day, unsigned hour, unsigned min)
start.tm_sec = 0;
start.tm_isdst = -1;
t = mktime(&start);
return start;
}
time_t date2sec(struct date day, unsigned hour, unsigned min)
{
struct tm start = date2tm(day, hour, min);
time_t t = mktime(&start);
EXIT_IF(t == -1, _("failure in mktime"));
return t;