From 9c37e2803b356fb4192d77678f414a5726ec7785 Mon Sep 17 00:00:00 2001 From: katherine Date: Sat, 14 Dec 2019 00:14:09 -0700 Subject: implement entry --- src/calendar.h | 11 +--- src/entry.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/entry.h | 27 +++++++++ src/opt.c | 4 +- 4 files changed, 209 insertions(+), 11 deletions(-) create mode 100644 src/entry.c create mode 100644 src/entry.h diff --git a/src/calendar.h b/src/calendar.h index 060ad99..f5f1286 100644 --- a/src/calendar.h +++ b/src/calendar.h @@ -1,17 +1,10 @@ #ifndef EVERY_CALENDAR_H #define EVERY_CALENDAR_H -enum calendar_entry_type_e { - CALENDAR_ENTRY_TYPE_ON, - CALENDAR_ENTRY_TYPE_EVERY, -}; - -struct calendar_entry_s { - enum calendar_entry_type_e type; -}; +#include "entry.h" struct calendar_s { - struct calendar_entry_s *entries; + struct entry_s *entries; }; #endif diff --git a/src/entry.c b/src/entry.c new file mode 100644 index 0000000..64acdea --- /dev/null +++ b/src/entry.c @@ -0,0 +1,178 @@ +#include "entry.h" + +#include + +static int sub_inc_year(struct tm *t, int n) +{ + if (n == 0) + return 0; + + t->tm_year += n; + + if (mktime(t) == -1) + return -1; + + return 0; +} + +static int sub_inc_month(struct tm *t, int n) +{ + unsigned i; + + if (n == 0) + return 0; + + for (i = 0; i < n; i++) { + t->tm_mon++; + if (mktime(t) == -1) { + t->tm_mon = 0; + if (sub_inc_year(t, 1) == -1) + return -1; + } + } + + return 0; +} + +static int sub_inc_day(struct tm *t, int n) +{ + unsigned i; + + if (n == 0) + return 0; + + for (i = 0; i < n; i++) { + t->tm_mday++; + if (mktime(t) == -1) { + t->tm_mday = 1; + if (sub_inc_month(t, 1) == -1) + return -1; + } + } + + return 0; +} + +static int sub_inc_hour(struct tm *t, int n) +{ + unsigned i; + + if (n == 0) + return 0; + + for (i = 0; i < n; i++) { + t->tm_hour++; + if (mktime(t) == -1) { + t->tm_hour = 0; + if (sub_inc_day(t, 1) == -1) + return -1; + } + } + + return 0; +} + +static int sub_inc_minute(struct tm *t, int n) +{ + unsigned i; + + if (n == 0) + return 0; + + for (i = 0; i < n; i++) { + t->tm_min++; + if (mktime(t) == -1) { + t->tm_min = 0; + if (sub_inc_hour(t, 1) == -1) + return -1; + } + } + + return 0; +} + +static int sub_inc_second(struct tm *t, int n) +{ + time_t r; + struct tm *tmp; + + if (n == 0) + return 0; + + r = mktime(t); + + if (r + n <= r) + return -1; + r += n; + + tmp = localtime(&r); + *t = *tmp; + + return 0; +} + +/* super inefficient, but should best-possible avoid any weird leap + * years/seconds/dst-problems/other future changes */ +bool entry_is_active(struct entry_s *e, time_t now) +{ + struct tm t, *tmp; + time_t rtmp, now_plus_warn; + + assert(e != NULL); + + tmp = localtime(&now); + assert(tmp != NULL); + t = *tmp; + + if (sub_inc_year(&t, e->warn.year)) + return false; + if (sub_inc_month(&t, e->warn.month)) + return false; + if (sub_inc_day(&t, e->warn.day)) + return false; + if (sub_inc_hour(&t, e->warn.hour)) + return false; + if (sub_inc_minute(&t, e->warn.minute)) + return false; + if (sub_inc_second(&t, e->warn.second)) + return false; + + now_plus_warn = mktime(&t); + + if (e->type == ENTRY_TYPE_ON) { + if (e->start >= now && e->start <= now_plus_warn) + return true; + + return false; + } + + tmp = localtime(&(e->start)); + assert(tmp != NULL); + t = *tmp; + + if (e->has_end && now > e->end) + return false; + + for (rtmp = e->start;;) { + rtmp = mktime(&t); + + if (rtmp > now_plus_warn) + return false; + + if (rtmp >= now) + return true; + + if (sub_inc_year(&t, e->every.year)) + return false; + if (sub_inc_month(&t, e->every.month)) + return false; + if (sub_inc_day(&t, e->every.day)) + return false; + if (sub_inc_hour(&t, e->every.hour)) + return false; + if (sub_inc_minute(&t, e->every.minute)) + return false; + if (sub_inc_second(&t, e->every.second)) + return false; + } +} diff --git a/src/entry.h b/src/entry.h new file mode 100644 index 0000000..1420d9b --- /dev/null +++ b/src/entry.h @@ -0,0 +1,27 @@ +#ifndef EVERY_ENTRY_H +#define EVERY_ENTRY_H + +#include +#include + +enum entry_type_e { + ENTRY_TYPE_ON, + ENTRY_TYPE_EVERY, +}; + +struct entry_interval_s { + int year, month, day, hour, minute, second; +}; + +/* type ON uses only start and warn */ +struct entry_s { + enum entry_type_e type; + bool has_end; + time_t start, end; + struct entry_interval_s every, warn; +}; + +/* test if an entry needs warning */ +bool entry_is_active(struct entry_s *e, time_t now); + +#endif diff --git a/src/opt.c b/src/opt.c index eebb248..31b1186 100644 --- a/src/opt.c +++ b/src/opt.c @@ -14,7 +14,7 @@ static struct simple_opt options[] = { { SIMPLE_OPT_FLAG, 'v', "version", false, "print the version of every in use and exit" }, { SIMPLE_OPT_STRING, 'c', "calendar", true, - "path to calendar", "" }, + "path to calendar file", "" }, { SIMPLE_OPT_STRING, 'e', "editor", true, "text editor for editing calendars", "" }, { SIMPLE_OPT_END } @@ -35,7 +35,7 @@ void opt_parse(int argc, char **argv) /* help */ if (options[0].was_seen) { simple_opt_print_usage(stdout, 80, argv[0], - "[-c CALENDAR_FILE] [-m OUTPUT_MODE]", + "[-c CALENDAR_FILE] [-e TEXT_EDITOR] [COMMAND]", "every is a flexible, console-based event calendar", options); -- cgit v1.2.3