diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 215 |
1 files changed, 176 insertions, 39 deletions
diff --git a/src/utils.c b/src/utils.c index a9a9e68..2d30bfc 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,7 +1,7 @@ /* * Calcurse - text-based organizer * - * Copyright (c) 2004-2017 calcurse Development Team <misc@calcurse.org> + * Copyright (c) 2004-2023 calcurse Development Team <misc@calcurse.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -112,7 +112,7 @@ void free_user_data(void) apoint_llist_free(); recur_apoint_llist_free(); recur_event_llist_free(); - for (i = 0; i <= 37; i++) + for (i = 0; i <= REG_BLACK_HOLE; i++) ui_day_item_cut_free(i); todo_free_list(); notify_free_app(); @@ -235,6 +235,8 @@ int status_ask_choice(const char *message, const char choice[], return i + 1; if (ch == ESCAPE) return (-1); + if (ch == RETURN) + return (-2); if (resize) { resize = 0; wins_reset(); @@ -421,22 +423,25 @@ struct date sec2date(time_t t) return d; } -time_t utcdate2sec(struct date day, unsigned hour, unsigned min) +time_t tzdate2sec(struct date day, unsigned hour, unsigned min, char *tznew) { - char *tz; + char *tzold; time_t t; - tz = getenv("TZ"); - if (tz) - tz = mem_strdup(tz); - setenv("TZ", "", 1); + if (!tznew) + return date2sec(day, hour, min); + + tzold = getenv("TZ"); + if (tzold) + tzold = mem_strdup(tzold); + setenv("TZ", tznew, 1); tzset(); t = date2sec(day, hour, min); - if (tz) { - setenv("TZ", tz, 1); - mem_free(tz); + if (tzold) { + setenv("TZ", tzold, 1); + mem_free(tzold); } else { unsetenv("TZ"); } @@ -621,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. @@ -985,11 +1026,11 @@ parse_date_interactive(const char *datestr, int *year, int *month, int *day) } /* - * Convert a date duration string into a number of days. + * Convert a date increment string into a number of days. * If start is non-zero, the final end time is validated. * * Allowed formats in lenient BNF: - * <duration> ::= <days> | <period> + * <increment>::= <days> | <period> * <period> ::= [ <weeks>w ][ <days>d ] * Notes: * <days> and <weeks> are any integer >= 0. @@ -997,7 +1038,7 @@ parse_date_interactive(const char *datestr, int *year, int *month, int *day) * * Returns 1 on success and 0 on failure. */ -int parse_date_duration(const char *string, unsigned *days, time_t start) +int parse_date_increment(const char *string, unsigned *days, time_t start) { enum { STATE_INITIAL, @@ -1007,7 +1048,7 @@ int parse_date_duration(const char *string, unsigned *days, time_t start) const char *p; unsigned in = 0, frac = 0, denom = 1; - unsigned dur = 0; + unsigned incr = 0; if (!string || *string == '\0') return 0; @@ -1028,10 +1069,10 @@ int parse_date_duration(const char *string, unsigned *days, time_t start) switch (state) { case STATE_INITIAL: if (*p == 'w') { - dur += in * WEEKINDAYS / denom; + incr += in * WEEKINDAYS / denom; state = STATE_WWDD_DD; } else if (*p == 'd') { - dur += in / denom; + incr += in / denom; state = STATE_DONE; } else { return 0; @@ -1039,7 +1080,7 @@ int parse_date_duration(const char *string, unsigned *days, time_t start) break; case STATE_WWDD_DD: if (*p == 'd') { - dur += in / denom; + incr += in / denom; state = STATE_DONE; } else { return 0; @@ -1055,18 +1096,18 @@ int parse_date_duration(const char *string, unsigned *days, time_t start) } if (state == STATE_DONE && in > 0) return 0; - dur += in; + incr += in; if (start) { - /* wanted: start = start + dur * DAYINSEC */ + /* wanted: start = start + incr * DAYINSEC */ long p; - if (overflow_mul(dur, DAYINSEC, &p)) + if (overflow_mul(incr, DAYINSEC, &p)) return 0; if (overflow_add(start, p, &start)) return 0; if (!check_sec(&start)) return 0; } - *days = dur; + *days = incr; return 1; } @@ -1312,21 +1353,32 @@ void psleep(unsigned secs) /* * Fork and execute an external process. * - * If pfdin and/or pfdout point to a valid address, a pipe is created and the - * appropriate file descriptors are written to pfdin/pfdout. + * If pfdin/pfdout/pfderr point to a valid address, a pipe is created and the + * appropriate file descriptors are written to pfdin/pfdout/pfderr. + * + * If new_session is non-zero, setsid() is called after forking. */ -int fork_exec(int *pfdin, int *pfdout, const char *path, - const char *const *arg) +int fork_exec(int *pfdin, int *pfdout, int *pfderr, int new_session, + const char *path, const char *const *arg) { - int pin[2], pout[2]; + int pin[2], pout[2], perr[2]; int pid; if (pfdin && (pipe(pin) == -1)) return 0; if (pfdout && (pipe(pout) == -1)) return 0; + if (pfderr && (pipe(perr) == -1)) + return 0; if ((pid = fork()) == 0) { + if (pfderr) { + if (dup2(perr[0], STDERR_FILENO) < 0) + _exit(127); + close(perr[0]); + close(perr[1]); + } + if (pfdout) { if (dup2(pout[0], STDIN_FILENO) < 0) _exit(127); @@ -1341,6 +1393,11 @@ int fork_exec(int *pfdin, int *pfdout, const char *path, close(pin[1]); } + if (new_session) { + if ((setsid() < 0)) + _exit(127); + } + execvp(path, (char *const *)arg); _exit(127); } else { @@ -1348,6 +1405,8 @@ int fork_exec(int *pfdin, int *pfdout, const char *path, close(pin[1]); if (pfdout) close(pout[0]); + if (pfderr) + close(perr[0]); if (pid > 0) { if (pfdin) { @@ -1358,11 +1417,17 @@ int fork_exec(int *pfdin, int *pfdout, const char *path, fcntl(pout[1], F_SETFD, FD_CLOEXEC); *pfdout = pout[1]; } + if (pfderr) { + fcntl(perr[1], F_SETFD, FD_CLOEXEC); + *pfderr = perr[1]; + } } else { if (pfdin) close(pin[0]); if (pfdout) close(pout[1]); + if (pfderr) + close(perr[1]); return 0; } } @@ -1371,8 +1436,8 @@ int fork_exec(int *pfdin, int *pfdout, const char *path, /* Execute an external program in a shell. */ int -shell_exec(int *pfdin, int *pfdout, const char *path, - const char *const *arg) +shell_exec(int *pfdin, int *pfdout, int *pfderr, int new_session, + const char *path, const char *const *arg) { int argc, i; const char **narg; @@ -1401,7 +1466,7 @@ shell_exec(int *pfdin, int *pfdout, const char *path, narg[3] = NULL; } - ret = fork_exec(pfdin, pfdout, *narg, narg); + ret = fork_exec(pfdin, pfdout, pfderr, new_session, *narg, narg); if (arg0) mem_free(arg0); @@ -1411,7 +1476,7 @@ shell_exec(int *pfdin, int *pfdout, const char *path, } /* Wait for a child process to terminate. */ -int child_wait(int *pfdin, int *pfdout, int pid) +int child_wait(int *pfdin, int *pfdout, int *pfderr, int pid) { int stat; @@ -1419,9 +1484,13 @@ int child_wait(int *pfdin, int *pfdout, int pid) close(*pfdin); if (pfdout) close(*pfdout); + if (pfderr) + close(*pfderr); - waitpid(pid, &stat, 0); - return stat; + if (waitpid(pid, &stat, 0) == pid) + return stat; + else + return -1; } /* Display "Press any key to continue..." and wait for a key press. */ @@ -1636,7 +1705,7 @@ static void print_date(time_t date, time_t day, const char *extformat) if (!strcmp(extformat, "epoch")) { printf("%ld", (long)date); } else { - time_t day_start = update_time_in_date(day, 0, 0); + time_t day_start = DAY(day); time_t day_end = date_sec_change(day_start, 0, 1); struct tm lt; @@ -1971,11 +2040,6 @@ int hash_matches(const char *pattern, const char *hash) return (starts_with(hash, pattern) != invert); } -int show_dialogs(void) -{ - return (!quiet) && conf.system_dialogs; -} - /* * Overflow check for addition with positive second term. */ @@ -2009,3 +2073,76 @@ long overflow_mul(long x, long y, long *z) *z = x * y; return 0; } + +/* + * Return the upcoming weekday from day (possibly day itself). + */ +time_t next_wday(time_t day, int weekday) +{ + struct tm tm; + + localtime_r(&day, &tm); + return date_sec_change( + day, 0, (weekday - tm.tm_wday + WEEKINDAYS) % WEEKINDAYS + ); + +} + +/* + * Return the number of weekdays of the year. + */ +int wday_per_year(int year, int weekday) +{ + struct tm y_end; + struct date day; + int last_wday; + + /* Find weekday and yearday of the last day of the year. */ + day.dd = 31; + day.mm = 12; + day.yyyy = year; + y_end = date2tm(day, 0, 0); + mktime(&y_end); + + /* Find date of the last weekday of the year. */ + last_wday = (y_end.tm_yday + 1) - (y_end.tm_wday - weekday + 7) % 7; + + return last_wday / 7 + (last_wday % 7 > 0); +} + +/* + * Return the number of weekdays in month of year. + */ +int wday_per_month(int month, int year, int weekday) +{ + struct tm m_end; + struct date day; + int last_wday, m_days = days[month - 1] + (month == 2 && ISLEAP(year) ? 1 : 0); + + /* Find weekday of the last day of the month. */ + day.dd = m_days; + day.mm = month; + day.yyyy = year; + m_end = date2tm(day, 0, 0); + mktime(&m_end); + + /* Find date of the last weekday of the month. */ + last_wday = m_days - (m_end.tm_wday - weekday + 7) % 7; + + return last_wday / 7 + (last_wday % 7 > 0); +} + +/* + * Return allocated string with day of 't' inserted in 'template' in the user's + * preferred format; template must be a "printf" template with exactly one + * string conversion (%s). + */ +char *day_ins(char **template, time_t t) +{ + char *day, *msg; + + day = date_sec2date_str(DAY(t), DATEFMT(conf.input_datefmt)); + asprintf(&msg, *template, day); + mem_free(day); + return msg; +} |