From 1efe24105e1a516d4b16fa44eca821d914a9c387 Mon Sep 17 00:00:00 2001
From: Lars Henriksen <LarsHenriksen@get2net.dk>
Date: Sun, 15 Nov 2020 10:25:46 +0100
Subject: Improve performance of recur_prev_occurrence()

And fix item start day for prev command

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
---
 src/calcurse.c |  6 +++++-
 src/calcurse.h |  1 +
 src/recur.c    | 25 +++++++++++++------------
 3 files changed, 19 insertions(+), 13 deletions(-)

(limited to 'src')

diff --git a/src/calcurse.c b/src/calcurse.c
index 7bd3d67..cd143d6 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -623,8 +623,12 @@ static inline void key_generic_cmd(void)
 			warnbox(error_msg);
 			goto cleanup;
 		}
-		day = date2sec(*ui_calendar_get_slctd_day(), 0, 0);
 		item = ui_day_get_sel();
+		/*
+		 * The selected day need not be the (item) start day
+		 * for multi-day occurrences.
+		 */
+		day = DAY(item->start);
 		if (item->type == RECUR_EVNT) {
 			rev = item->item.rev;
 			more = recur_next_occurrence(rev->day, -1, rev->rpt, &rev->exc,
diff --git a/src/calcurse.h b/src/calcurse.h
index 0c9b603..bd351d6 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -142,6 +142,7 @@
  */
 #define DAYINSEC        (DAYINMIN * MININSEC)
 #define NEXTDAY(date)	date_sec_change((date), 0, 1)
+#define PREVDAY(date)	date_sec_change((date), 0, -1)
 #define DAYLEN(date)	(NEXTDAY(date) - (date))
 #define ENDOFDAY(date)	(NEXTDAY(date) - 1)
 #define HOURINSEC       (HOURINMIN * MININSEC)
diff --git a/src/recur.c b/src/recur.c
index a6c02a8..72cb40f 100644
--- a/src/recur.c
+++ b/src/recur.c
@@ -1852,19 +1852,20 @@ int recur_nth_occurrence(time_t s, long d, struct rpt *r, llist_t *e, int n,
 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;
+	int ret = 0;
 
 	if (day <= DAY(s))
-		return 0;
-	next = *prev = s;
-	while (DAY(next) < day) {
-		/* Set new previous and next. */
-		*prev = next;
-		prev_day = DAY(*prev);
-		recur_next_occurrence(s, d, r, e, prev_day, &next);
-		/* Multi-day appointment */
-		if (next == *prev)
-			next = NEXTDAY(*prev);
+		return ret;
+
+	while (DAY(s) < day) {
+		day = PREVDAY(day);
+		if (recur_item_find_occurrence(s, d, r, e, day, prev)) {
+			/* Multi-day appointment. */
+			if (d != -1 && *prev < day && day < *prev + d)
+				continue;
+			ret = 1;
+			break;
+		}
 	}
-	return 1;
+	return ret;
 }
-- 
cgit v1.2.3-70-g09d2