From e3fc73e0c76addc0893ad3ceeba7ef8442133a51 Mon Sep 17 00:00:00 2001 From: Morgan Seltzer Date: Mon, 7 Jun 2021 17:13:23 -0400 Subject: Backend changes for first day of week Previously only Sunday and Monday were allowed for the first day of the week, and was internally treated as a binary variable. This patch changes the backend so all days are accepted, a future patch will allow users to actually select other days. Addresses GitHub feature request #321. Signed-off-by: Morgan Seltzer Signed-off-by: Lukas Fleischer --- src/calcurse.h | 6 ++- src/config.c | 7 ++-- src/custom.c | 2 +- src/pcal.c | 4 +- src/ui-calendar.c | 108 ++++++++++++++++++------------------------------------ src/utils.c | 36 ++++++++++++++++++ 6 files changed, 82 insertions(+), 81 deletions(-) diff --git a/src/calcurse.h b/src/calcurse.h index 8d9e3d8..db8dd51 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -152,7 +152,7 @@ * The argument (d) is the "Sunday"-numbering of member tm_wday in struct tm. */ #define WDAY(d) \ - (ui_calendar_week_begins_on_monday() ? ((d ? d : WEEKINDAYS) - 1) : d) + (modify_wday(d, -ui_calendar_get_wday_start())) /* Key definitions. */ #define CTRLVAL 0x1F @@ -811,7 +811,7 @@ void ui_calendar_set_current_date(void); struct date *ui_calendar_get_today(void); void ui_calendar_set_first_day_of_week(enum wday); void ui_calendar_change_first_day_of_week(void); -unsigned ui_calendar_week_begins_on_monday(void); +int ui_calendar_get_wday_start(void); void ui_calendar_store_current_date(struct date *); void ui_calendar_init_slctd_day(void); struct date *ui_calendar_get_slctd_day(void); @@ -1234,6 +1234,8 @@ time_t date_sec_change(time_t, int, int); time_t update_time_in_date(time_t, unsigned, unsigned); time_t get_sec_date(struct date); long min2sec(unsigned); +int modify_wday(int,int); +char *get_wday_default_string(int); void draw_scrollbar(struct scrollwin *, int); void item_in_popup(const char *, const char *, const char *, const char *); time_t get_today(void); diff --git a/src/config.c b/src/config.c index b309c28..2df2559 100644 --- a/src/config.c +++ b/src/config.c @@ -468,10 +468,9 @@ static int config_serialize_default_panel(char **buf, void *dummy) static int config_serialize_first_day_of_week(char **buf, void *dummy) { - if (ui_calendar_week_begins_on_monday()) - *buf = mem_strdup("monday"); - else - *buf = mem_strdup("sunday"); + *buf = mem_strdup(get_wday_default_string(ui_calendar_get_wday_start())); + /* now stores string with uppercase first letter, changing to lower */ + **buf = tolower(**buf); return 1; } diff --git a/src/custom.c b/src/custom.c index 889772e..5f66194 100644 --- a/src/custom.c +++ b/src/custom.c @@ -702,7 +702,7 @@ static void print_general_option(int i, WINDOW *win, int y, int hilt, void *cb_d case FIRST_DAY_OF_WEEK: custom_apply_attr(win, ATTR_HIGHEST); mvwaddstr(win, y, XPOS + strlen(opt[FIRST_DAY_OF_WEEK]), - ui_calendar_week_begins_on_monday()? _("Monday") : + ui_calendar_get_wday_start()? _("Monday") : _("Sunday")); custom_remove_attr(win, ATTR_HIGHEST); mvwaddstr(win, y + 1, XPOS, diff --git a/src/pcal.c b/src/pcal.c index 78da0bb..16c3b9f 100644 --- a/src/pcal.c +++ b/src/pcal.c @@ -102,8 +102,8 @@ static void pcal_export_header(FILE * stream) { fputs("# calcurse pcal export\n", stream); fputs("\n# =======\n# options\n# =======\n", stream); - fprintf(stream, "opt -A -K -l -m -F %s\n", - ui_calendar_week_begins_on_monday()? "Monday" : "Sunday"); + fprintf(stream, "opt -A -K -l -m -F %s\n", get_wday_default_string( + ui_calendar_get_wday_start())); fputs("# Display week number (i.e. 1-52) on every Monday\n", stream); fprintf(stream, "all monday in all week %%w\n"); diff --git a/src/ui-calendar.c b/src/ui-calendar.c index 4a8ef44..e4d5289 100644 --- a/src/ui-calendar.c +++ b/src/ui-calendar.c @@ -45,14 +45,14 @@ #include "calcurse.h" static struct date today, slctd_day; -static unsigned ui_calendar_view, week_begins_on_monday; +static unsigned ui_calendar_view; +static int wday_start; /* this is used in signed arithmetic */ static pthread_mutex_t date_thread_mutex = PTHREAD_MUTEX_INITIALIZER; -static void draw_monthly_view(struct scrollwin *, struct date *, unsigned); -static void draw_weekly_view(struct scrollwin *, struct date *, unsigned); -static void (*draw_calendar[CAL_VIEWS]) (struct scrollwin *, struct date *, - unsigned) = { -draw_monthly_view, draw_weekly_view}; +static void draw_monthly_view(struct scrollwin *, struct date *); +static void draw_weekly_view(struct scrollwin *, struct date *); +static void (*draw_calendar[CAL_VIEWS]) (struct scrollwin *, + struct date *) = {draw_monthly_view, draw_weekly_view}; /* Six weeks cover a month. */ static int monthly_view_cache[WEEKINDAYS * 6]; @@ -148,30 +148,24 @@ struct date *ui_calendar_get_today(void) /* Needed to display sunday or monday as the first day of week in calendar. */ void ui_calendar_set_first_day_of_week(enum wday first_day) { - switch (first_day) { - case SUNDAY: - week_begins_on_monday = 0; - break; - case MONDAY: - week_begins_on_monday = 1; - break; - default: + if (first_day >= 0 && first_day <= 6) + wday_start = first_day; + else { ERROR_MSG(_("ERROR setting first day of week")); - week_begins_on_monday = 0; - /* NOTREACHED */ + wday_start = 0; } } /* Swap first day of week in calendar. */ void ui_calendar_change_first_day_of_week(void) { - week_begins_on_monday = !week_begins_on_monday; + wday_start = !wday_start; } /* Return 1 if week begins on monday, 0 otherwise. */ -unsigned ui_calendar_week_begins_on_monday(void) +int ui_calendar_get_wday_start(void) { - return week_begins_on_monday; + return wday_start; } /* Fill in the given variable with the current date. */ @@ -219,18 +213,14 @@ void ui_calendar_monthly_view_cache_set_invalid(void) monthly_view_cache_valid = 0; } -static int weeknum(const struct tm *t, int firstweekday) +static int weeknum(const struct tm *t, int wday_start) { int wday, wnum; wday = t->tm_wday; - if (firstweekday == MONDAY) { - if (wday == SUNDAY) - wday = 6; - else - wday--; - } - wnum = ((t->tm_yday + WEEKINDAYS - wday) / WEEKINDAYS); + wnum = ((t->tm_yday + WEEKINDAYS + -modify_wday(wday, -wday_start)) + / WEEKINDAYS); + if (wnum < 0) wnum = 0; @@ -296,7 +286,7 @@ static int ISO8601weeknum(const struct tm *t) * Return the tm structure for the first day of the first week * (containing a day) of the selected month. */ -static struct tm get_first_day(unsigned sunday_first) +static struct tm get_first_day(int wday_start) { struct tm t; struct date d; @@ -308,26 +298,20 @@ static struct tm get_first_day(unsigned sunday_first) t = date2tm(d, 0, 0); mktime(&t); /* get the first day of the week */ - date_change(&t, 0, - -(sunday_first ? - t.tm_wday : - (t.tm_wday + WEEKINDAYS - 1) % WEEKINDAYS)); + date_change(&t, 0, -modify_wday(t.tm_wday, -wday_start)); + return t; } -static struct tm get_first_weekday(unsigned sunday_first) +static struct tm get_first_weekday(int wday_start) { - int c_wday, days_to_remove; + int c_wday; 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); + + date_change(&t, 0, -modify_wday(c_wday, -wday_start)); return t; } @@ -346,8 +330,7 @@ static void draw_week_number(struct scrollwin *sw, struct tm t) /* Draw the monthly view inside calendar panel. */ static void -draw_monthly_view(struct scrollwin *sw, struct date *current_day, - unsigned sunday_first) +draw_monthly_view(struct scrollwin *sw, struct date *current_day) { struct date c_day; int slctd, w_day, numdays, j, week = 0; @@ -373,7 +356,7 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day, * Step forward by week until past the last day of the month. * The first day of the first week may belong to the previous month. */ - t = t_first = get_first_day(sunday_first); + t = t_first = get_first_day(wday_start); t.tm_mday += WEEKINDAYS; mktime(&t); last_day += WEEKINDAYS; @@ -423,7 +406,7 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day, custom_apply_attr(sw->inner, ATTR_HIGHEST); for (j = 0; j < WEEKINDAYS; j++) { mvwaddstr(sw->inner, ofs_y, ofs_x + weekw + 4 * j, - nl_langinfo(ABDAY_1 + (1 + j - sunday_first) % WEEKINDAYS)); + nl_langinfo(ABDAY_1 + modify_wday(j, wday_start))); } custom_remove_attr(sw->inner, ATTR_HIGHEST); WINS_CALENDAR_UNLOCK; @@ -449,11 +432,9 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day, if (j == first_day || (mo == 1 && j == WEEKINDAYS) || (mo == 12 && j >= 4 * WEEKINDAYS)) { - if (sunday_first) - date_change(&t, 0, 1); + date_change(&t, 0, WDAY(MONDAY)); week = ISO8601weeknum(&t); - if (sunday_first) - date_change(&t, 0, -1); + date_change(&t, 0, -WDAY(MONDAY)); } else week++; } @@ -506,8 +487,7 @@ draw_monthly_view(struct scrollwin *sw, struct date *current_day, /* Draw the weekly view inside calendar panel. */ static void -draw_weekly_view(struct scrollwin *sw, struct date *current_day, - unsigned sunday_first) +draw_weekly_view(struct scrollwin *sw, struct date *current_day) { #define DAYSLICESNO 6 const int WCALWIDTH = 28; @@ -520,14 +500,14 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day, OFFX = (wins_sbar_width() - 2 - WCALWIDTH) / 2; /* Print the week number, calculated from monday. */ - t = get_first_weekday(0); + t = get_first_weekday(MONDAY); draw_week_number(sw, t); /* Now draw calendar view. */ for (j = 0; j < WEEKINDAYS; j++) { /* get next day */ if (j == 0) - t = get_first_weekday(sunday_first); + t = get_first_weekday(wday_start); else date_change(&t, 0, 1); @@ -538,7 +518,7 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day, /* print the day names, with regards to the first day of the week */ custom_apply_attr(sw->inner, ATTR_HIGHEST); mvwaddstr(sw->inner, OFFY, OFFX + 4 * j, - nl_langinfo(ABDAY_1 + (1 + j - sunday_first) % WEEKINDAYS)); + nl_langinfo(ABDAY_1 + modify_wday(j, wday_start))); custom_remove_attr(sw->inner, ATTR_HIGHEST); /* Check if the day to be printed has an item or not. */ @@ -624,11 +604,9 @@ draw_weekly_view(struct scrollwin *sw, struct date *current_day, void ui_calendar_update_panel(void) { struct date current_day; - unsigned sunday_first; ui_calendar_store_current_date(¤t_day); - sunday_first = !ui_calendar_week_begins_on_monday(); - draw_calendar[ui_calendar_view] (&sw_cal, ¤t_day, sunday_first); + draw_calendar[ui_calendar_view] (&sw_cal, ¤t_day); wins_scrollwin_display(&sw_cal, NOHILT); } @@ -728,28 +706,14 @@ void ui_calendar_move(enum move move, int count) ret = date_change(&t, count * YEARINMONTHS, 0); break; case WEEK_START: - /* Normalize struct tm to get week day number. */ mktime(&t); - if (ui_calendar_week_begins_on_monday()) - days_to_remove = - ((t.tm_wday == - 0) ? WEEKINDAYS - 1 : t.tm_wday - 1); - else - days_to_remove = - ((t.tm_wday == 0) ? 0 : t.tm_wday); + days_to_remove = WDAY(t.tm_wday); days_to_remove += (count - 1) * WEEKINDAYS; ret = date_change(&t, 0, -days_to_remove); break; case WEEK_END: mktime(&t); - if (ui_calendar_week_begins_on_monday()) - days_to_add = - ((t.tm_wday == - 0) ? 0 : WEEKINDAYS - t.tm_wday); - else - days_to_add = ((t.tm_wday == 0) ? - WEEKINDAYS - 1 : WEEKINDAYS - 1 - - t.tm_wday); + days_to_add = modify_wday(-t.tm_wday, wday_start - 1); days_to_add += (count - 1) * WEEKINDAYS; ret = date_change(&t, 0, days_to_add); break; diff --git a/src/utils.c b/src/utils.c index 1a480df..f631c8c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -626,6 +626,42 @@ long min2sec(unsigned minutes) return minutes * MININSEC; } +int modify_wday(int wday, int shift) +{ + return (WEEKINDAYS + wday + shift) % WEEKINDAYS; +} + +/* returns char* representing a wday, used for internal functions */ +char *get_wday_default_string(int wday) +{ + switch(wday) { + case MONDAY: + return "Monday"; + break; + case TUESDAY: + return "Tuesday"; + break; + case WEDNESDAY: + return "Wednesday"; + break; + case THURSDAY: + return "Thursday"; + break; + case FRIDAY: + return "Friday"; + break; + case SATURDAY: + return "Saturday"; + break; + case SUNDAY: + return "Sunday"; + break; + default: + return "Sunday"; + break; + } +} + /* * Display a scroll bar when there are so many items that they * can not be displayed inside the corresponding panel. -- cgit v1.2.3