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 <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
Lars Henriksen 2020-10-07 19:51:18 +02:00 committed by Lukas Fleischer
parent 4d9d50722a
commit 95151e3f0c
3 changed files with 74 additions and 3 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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;
}