From 95151e3f0c2a9935abe6e498fd056a57075ea0c5 Mon Sep 17 00:00:00 2001 From: Lars Henriksen Date: Wed, 7 Oct 2020 19:51:18 +0200 Subject: Add p(revious) command The p(rev) command finds the previous occurrence of a recurrent item, analogous to the n(ext) command. A bug in the next command is corrected.. Signed-off-by: Lars Henriksen Signed-off-by: Lukas Fleischer --- src/calcurse.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/calcurse.h | 1 + src/recur.c | 24 ++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/calcurse.c b/src/calcurse.c index 8a65fba..3083f86 100644 --- a/src/calcurse.c +++ b/src/calcurse.c @@ -557,7 +557,8 @@ static inline void key_generic_cmd(void) int valid = 0, force = 0, ret; char *error_msg; - status_mesg(_("Command: [ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) ]"), ""); + status_mesg(_("Command: " + "[ h(elp) | w(rite)(!) | q(uit)(!) | wq(!) | n(ext) | p(rev) ]"), ""); if (getstring(win[STA].p, cmd, BUFSIZ, 0, 1) != GETSTRING_VALID) goto cleanup; cmd_name = strtok(cmd, " "); @@ -638,17 +639,62 @@ static inline void key_generic_cmd(void) goto cleanup; } if (!more) { - error_msg = _("Last repetition."); + error_msg = _("Last occurrence."); warnbox(error_msg); goto cleanup; } - item->start = next; + item->order = next; ui_calendar_set_slctd_day(sec2date(next)); day_set_sel_data(item); do_storage(1); valid = 1; } + if (!strcmp(cmd_name, "prev") || !strcmp(cmd_name, "p")) { + struct day_item *item; + time_t day, prev; + struct recur_apoint *rapt; + struct recur_event *rev; + int more = 0; + + if (wins_slctd() != APP) { + error_msg = _("Select a repeating item in the" + " appointments panel."); + warnbox(error_msg); + goto cleanup; + } + item = ui_day_get_sel(); + /* + * The selected day need not be the (item) start day + * for multi-day occurrences. + */ + day = update_time_in_date(item->start, 0, 0); + if (item->type == RECUR_EVNT) { + rev = item->item.rev; + more = recur_prev_occurrence(rev->day, -1, rev->rpt, + &rev->exc, day, &prev); + } else if (item->type == RECUR_APPT) { + rapt = item->item.rapt; + more = recur_prev_occurrence(rapt->start, rapt->dur, + rapt->rpt, &rapt->exc, + day, &prev); + } else { + error_msg = _("Not a repeating item."); + warnbox(error_msg); + goto cleanup; + } + if (!more) { + error_msg = _("First occurrence."); + warnbox(error_msg); + goto cleanup; + } + item->order = prev; + ui_calendar_set_slctd_day(sec2date(prev)); + day_set_sel_data(item); + do_storage(1); + + valid = 1; + } if (!valid) { asprintf(&error_msg, _("No such command: %s"), cmd); diff --git a/src/calcurse.h b/src/calcurse.h index 39a2af1..dca9d8b 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -1105,6 +1105,7 @@ void recur_event_paste_item(struct recur_event *, time_t); void recur_apoint_paste_item(struct recur_apoint *, time_t); int recur_next_occurrence(time_t, long, struct rpt *, llist_t *, time_t, time_t *); int recur_nth_occurrence(time_t, long, struct rpt *, llist_t *, int, time_t *); +int recur_prev_occurrence(time_t, long, struct rpt *, llist_t *, time_t, time_t *); /* sigs.c */ diff --git a/src/recur.c b/src/recur.c index 3c93de2..3a16d1e 100644 --- a/src/recur.c +++ b/src/recur.c @@ -1846,3 +1846,27 @@ int recur_nth_occurrence(time_t s, long d, struct rpt *r, llist_t *e, int n, } return !n; } + +/* + * Finds the previous occurrence - the most recent before day - and returns it + * in the provided buffer. + */ +int recur_prev_occurrence(time_t s, long d, struct rpt *r, llist_t *e, + time_t day, time_t *prev) +{ + time_t prev_day, next; + + if (day <= update_time_in_date(s, 0, 0)) + return 0; + next = *prev = s; + while (update_time_in_date(next, 0, 0) < day) { + /* Set new previous and next. */ + *prev = next; + prev_day = update_time_in_date(*prev, 0, 0); + recur_next_occurrence(s, d, r, e, prev_day, &next); + /* Multi-day appointment */ + if (next == *prev) + next = NEXTDAY(*prev); + } + return 1; +} -- cgit v1.2.3-54-g00ecf