From ab0fe682255f01e75b70a6ee3e95795020be8dd7 Mon Sep 17 00:00:00 2001
From: Lars Henriksen <LarsHenriksen@get2net.dk>
Date: Wed, 22 Aug 2018 20:18:36 +0200
Subject: Reload data after resolving save conflict (improved)

After resolving a save conflict with the merge tool, a save operation has,
in effect, occurred, and data files must be reloaded to import the result of
the conflict resolution.

This is a replacement for commit 2fe9c7e. The operations concerned with the user
interface are kept out the io-operations (as in all other cases) and take place
at the command-level in calcurse.c. and not at the io-level (io.c).

Shorter, more concise prompt texts.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
---
 src/calcurse.c |  8 +++++++-
 src/calcurse.h |  9 +++++++-
 src/io.c       | 65 ++++++++++++++++++++++++++++++++--------------------------
 3 files changed, 51 insertions(+), 31 deletions(-)

diff --git a/src/calcurse.c b/src/calcurse.c
index 5a08d53..7739c0f 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -271,7 +271,13 @@ static inline void key_generic_help(void)
 
 static inline void key_generic_save(void)
 {
-	io_save_cal(IO_SAVE_DISPLAY_BAR);
+	if (io_save_cal(IO_SAVE_DISPLAY_BAR) == IO_SAVE_RELOAD) {
+		ui_todo_load_items();
+		ui_todo_sel_reset();
+		do_storage(0);
+		notify_check_next_app(1);
+		ui_calendar_monthly_view_cache_set_invalid();
+	}
 	wins_update(FLAG_ALL);
 }
 
diff --git a/src/calcurse.h b/src/calcurse.h
index 88a0916..9bb714c 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -652,6 +652,13 @@ enum getstr {
 #define PARSE_DATETIME_HAS_DATE (1 << 0)
 #define PARSE_DATETIME_HAS_TIME (1 << 1)
 
+/* Return codes for the io_save_cal() function. */
+enum {
+	IO_SAVE_CTINUE,
+	IO_SAVE_RELOAD,
+	IO_SAVE_CANCEL
+};
+
 /* Week days. */
 enum wday {
 	SUNDAY,
@@ -848,7 +855,7 @@ unsigned io_save_apts(const char *);
 void io_dump_todo(const char *);
 unsigned io_save_todo(const char *);
 unsigned io_save_keys(void);
-void io_save_cal(enum save_display);
+int io_save_cal(enum save_display);
 void io_load_app(struct item_filter *);
 void io_load_todo(struct item_filter *);
 void io_load_data(struct item_filter *);
diff --git a/src/io.c b/src/io.c
index 6e8ae55..9ffd9a8 100644
--- a/src/io.c
+++ b/src/io.c
@@ -448,6 +448,7 @@ static int io_compute_hash(const char *path, char *buf)
 	return 1;
 }
 
+/* A merge implies a save operation and must be followed by reload of data. */
 static void io_merge_data(void)
 {
 	char *path_apts_new, *path_todo_new;
@@ -483,41 +484,48 @@ static void io_merge_data(void)
 	mem_free(path_apts_new);
 	mem_free(path_todo_new);
 
-	io_unset_modified();
-
 	/*
 	 * We do not directly write to the data files here; however, the
 	 * external merge tool will likely have incorporated changes from the
 	 * new file into the main data files at this point.
 	 */
 	run_hook("post-save");
+
+	/*
+	 * The user has merged, so override the modified flag
+	 * (and follow up with reload of the data files).
+	 */
+	io_unset_modified();
 }
 
+/* For the return values, see io_save_cal() below. */
 static int resolve_save_conflict(void)
 {
 	char *msg_um_asktype = NULL;
 	const char *msg_um_prefix =
-			_("Data files were changed since reading:");
+			_("Data files were changed since loaded:");
 	const char *msg_um_overwrite = _("(o)verwrite");
 	const char *msg_um_merge = _("(m)erge");
-	const char *msg_um_keep = _("(k)eep and cancel");
-	const char *msg_um_choice = _("[omk]");
-	int ret = 1;
+	const char *msg_um_keep = _("(c)ancel");
+	const char *msg_um_choice = _("[omc]");
+	int ret;
 
 	asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
 		 msg_um_overwrite, msg_um_merge, msg_um_keep);
 
 	switch (status_ask_choice(msg_um_asktype, msg_um_choice, 3)) {
 	case 1:
-		ret = 0;
+		ret = IO_SAVE_CTINUE;
 		break;
 	case 2:
 		io_merge_data();
+		io_reload_data();
+		ret = IO_SAVE_RELOAD;
 		break;
 	case 3:
 		/* FALLTHROUGH */
 	default:
-		;
+		ret = IO_SAVE_CANCEL;
 	}
 
 	mem_free(msg_um_asktype);
@@ -548,31 +556,29 @@ cleanup:
 	return ret;
 }
 
-/* Save the calendar data */
-void io_save_cal(enum save_display display)
+/*
+ * Save the calendar data.
+ * The return value tells how a possible save conflict should be/was resolved:
+ * IO_SAVE_CTINUE: continue save operation and overwrite the data files
+ * IO_SAVE_RELOAD: cancel save operation (data files changed and reloaded)
+ * IO_SAVE_CANCEL: cancel save operation (keep data files, no reload)
+ */
+int io_save_cal(enum save_display display)
 {
 	const char *access_pb = _("Problems accessing data file ...");
 	const char *save_success =
 	    _("The data files were successfully saved");
 	const char *enter = _("Press [ENTER] to continue");
-	int show_bar;
+	int show_bar, ret = IO_SAVE_CTINUE;
 
 	if (read_only)
-		return;
+		return IO_SAVE_CANCEL;
 
-	if (io_check_data_files_modified() && resolve_save_conflict()) {
-		if (io_reload_data()) {
-			day_process_storage(ui_calendar_get_slctd_day(), 1);
-			ui_day_load_items();
-			ui_day_sel_reset();
-			notify_check_next_app(1);
-			ui_calendar_monthly_view_cache_set_invalid();
-			wins_update(FLAG_ALL);
-		}
-		return;
-	}
+	if (io_check_data_files_modified() && (ret = resolve_save_conflict()))
+		return ret;
 
 	run_hook("pre-save");
+	io_mutex_lock();
 
 	show_bar = 0;
 	if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_BAR
@@ -599,11 +605,7 @@ void io_save_cal(enum save_display display)
 	if (!io_save_keys())
 		ERROR_MSG("%s", access_pb);
 
-	io_mutex_lock();
 	io_unset_modified();
-	io_compute_hash(path_apts, apts_sha1);
-	io_compute_hash(path_todo, todo_sha1);
-	io_mutex_unlock();
 
 	/* Print a message telling data were saved */
 	if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_BAR &&
@@ -612,7 +614,12 @@ void io_save_cal(enum save_display display)
 		keys_wait_for_any_key(win[KEY].p);
 	}
 
+	io_compute_hash(path_apts, apts_sha1);
+	io_compute_hash(path_todo, todo_sha1);
+
+	io_mutex_unlock();
 	run_hook("post-save");
+	return ret;
 }
 
 static void io_load_error(const char *filename, unsigned line,
@@ -921,8 +928,8 @@ int io_reload_data(void)
 				_("There are unsaved modifications:");
 		const char *msg_um_discard = _("(d)iscard");
 		const char *msg_um_merge = _("(m)erge");
-		const char *msg_um_keep = _("(k)eep and cancel");
-		const char *msg_um_choice = _("[dmk]");
+		const char *msg_um_keep = _("(c)ancel");
+		const char *msg_um_choice = _("[dmc]");
 
 		asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
 			 msg_um_discard, msg_um_merge, msg_um_keep);
-- 
cgit v1.2.3-70-g09d2