From 8b39637a628cba915e81f836aad74ec05bf0c285 Mon Sep 17 00:00:00 2001
From: Lars Henriksen <LarsHenriksen@get2net.dk>
Date: Sun, 26 Aug 2018 14:45:58 +0200
Subject: Move user information after save/reload to the command level

Moving user information to calcurse.c makes it easier to perform the actual
save/reload operatons in io.c, e.g. it is possible to load instead of
reload after a merge in conflict resolving.

The save/reload operations are of such importance that the user should always be
informed of the result (it's a bit disquieting when there is no reaction to a
save or reload command). Hence, the save/reload status messages are no longer
conditioned by show_dialogs(). No confirmation is asked for, so a message stays
until the status bar is updated by another action.

Care is taken to inform about save/reload actions that result in no change.

Texts are kept concise because of the limited message area. When conflicts are
present, whether saving or reloading, the "continue/merge/cancel" pattern seems
easier to grasp.

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
---
 src/calcurse.c | 44 ++++++++++++++++++++++++++++++++++++++++--
 src/calcurse.h | 14 ++++++++++++--
 src/io.c       | 60 +++++++++++++++++++++++++---------------------------------
 3 files changed, 80 insertions(+), 38 deletions(-)

(limited to 'src')

diff --git a/src/calcurse.c b/src/calcurse.c
index 533f78c..4560e5c 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -271,7 +271,12 @@ static inline void key_generic_help(void)
 
 static inline void key_generic_save(void)
 {
-	if (io_save_cal(IO_SAVE_DISPLAY_BAR) == IO_SAVE_RELOAD) {
+	char *msg = NULL;
+	int ret;
+
+	ret = io_save_cal(IO_SAVE_DISPLAY_BAR);
+
+	if (ret == IO_SAVE_RELOAD) {
 		ui_todo_load_items();
 		ui_todo_sel_reset();
 		do_storage(0);
@@ -279,11 +284,30 @@ static inline void key_generic_save(void)
 		ui_calendar_monthly_view_cache_set_invalid();
 	}
 	wins_update(FLAG_ALL);
+	switch (ret) {
+	case IO_SAVE_CTINUE:
+		msg = _("Data were saved successfully");
+		break;
+	case IO_SAVE_RELOAD:
+		msg = _("Data were saved/reloaded successfully");
+		break;
+	case IO_SAVE_CANCEL:
+		msg = _("Save cancelled");
+		break;
+	case IO_SAVE_NOOP:
+		msg = _("Data were already saved");
+		break;
+	}
+	status_mesg(msg, "");
 }
 
 static inline void key_generic_reload(void)
 {
-	if (io_reload_data()) {
+	char *msg = NULL;
+	int ret;
+
+	ret = io_reload_data();
+	if (ret != IO_RELOAD_CANCEL && ret != IO_RELOAD_NOOP) {
 		ui_todo_load_items();
 		ui_todo_sel_reset();
 		do_storage(0);
@@ -291,6 +315,22 @@ static inline void key_generic_reload(void)
 		ui_calendar_monthly_view_cache_set_invalid();
 	}
 	wins_update(FLAG_ALL);
+	switch (ret) {
+	case IO_RELOAD_LOAD:
+	case IO_RELOAD_CTINUE:
+		msg = _("Data were reloaded successfully");
+		break;
+	case IO_RELOAD_MERGE:
+		msg = _("Date were merged/reloaded successfully");
+		break;
+	case IO_RELOAD_CANCEL:
+		msg = _("Reload cancelled");
+		break;
+	case IO_RELOAD_NOOP:
+		msg = _("Data were already loaded");
+		break;
+	}
+	status_mesg(msg, "");
 }
 
 static inline void key_generic_import(void)
diff --git a/src/calcurse.h b/src/calcurse.h
index ddeec21..bec2a93 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -658,7 +658,17 @@ enum getstr {
 enum {
 	IO_SAVE_CTINUE,
 	IO_SAVE_RELOAD,
-	IO_SAVE_CANCEL
+	IO_SAVE_CANCEL,
+	IO_SAVE_NOOP
+};
+
+/* Return codes for the io_reload_data() function. */
+enum {
+	IO_RELOAD_LOAD,
+	IO_RELOAD_CTINUE,
+	IO_RELOAD_MERGE,
+	IO_RELOAD_CANCEL,
+	IO_RELOAD_NOOP
 };
 
 /* Week days. */
@@ -860,7 +870,7 @@ unsigned io_save_keys(void);
 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 *, int);
+int io_load_data(struct item_filter *, int);
 int io_reload_data(void);
 void io_load_keys(const char *);
 int io_check_dir(const char *);
diff --git a/src/io.c b/src/io.c
index 1ca2c2f..e63182d 100644
--- a/src/io.c
+++ b/src/io.c
@@ -503,12 +503,12 @@ static int resolve_save_conflict(void)
 {
 	char *msg_um_asktype = NULL;
 	const char *msg_um_prefix =
-			_("Data have changed since loaded:");
-	const char *msg_um_overwrite = _("(o)verwrite");
+			_("Data files have changed and will be overwritten:");
+	const char *msg_um_overwrite = _("(c)ontinue");
 	const char *msg_um_merge = _("(m)erge");
-	const char *msg_um_keep = _("(c)ancel");
-	const char *msg_um_choice = _("[omc]");
-	int ret;
+	const char *msg_um_keep = _("c(a)ncel");
+	const char *msg_um_choice = _("[cma]");
+	int ret = IO_SAVE_CANCEL;
 
 	asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
 		 msg_um_overwrite, msg_um_merge, msg_um_keep);
@@ -519,7 +519,7 @@ static int resolve_save_conflict(void)
 		break;
 	case 2:
 		io_merge_data();
-		io_reload_data();
+		io_load_data(NULL, FORCE);
 		ret = IO_SAVE_RELOAD;
 		break;
 	case 3:
@@ -573,14 +573,12 @@ cleanup:
  * 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)
+ * IO_SAVE_CANCEL: cancel save operation (user's decision, keep data files, no reload)
+ * IO_SAVE_NOOP: cancel save operation (nothing has changed)
  */
 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, ret = IO_SAVE_CTINUE;
 
 	if (read_only)
@@ -591,7 +589,7 @@ int io_save_cal(enum save_display display)
 			return ret;
 	} else
 		if (!io_get_modified())
-			return IO_SAVE_CANCEL;
+			return IO_SAVE_NOOP;
 
 	run_hook("pre-save");
 	io_mutex_lock();
@@ -623,13 +621,6 @@ int io_save_cal(enum save_display display)
 
 	io_unset_modified();
 
-	/* Print a message telling data were saved */
-	if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_BAR &&
-	    show_dialogs()) {
-		status_mesg(save_success, enter);
-		keys_wait_for_any_key(win[KEY].p);
-	}
-
 	io_compute_hash(path_apts, apts_sha1);
 	io_compute_hash(path_todo, todo_sha1);
 
@@ -925,8 +916,9 @@ void io_load_todo(struct item_filter *filter)
  * Load appointments and todo items.
  * Unless told otherwise, the function will only load a file that has changed
  * since last saved or loaded, see new_data() return codes.
+ * Return codes are for use in io_reload_data() only.
  */
-void io_load_data(struct item_filter *filter, int force)
+int io_load_data(struct item_filter *filter, int force)
 {
 	run_hook("pre-load");
 	if (force)
@@ -957,24 +949,25 @@ void io_load_data(struct item_filter *filter, int force)
 
 	io_mutex_unlock();
 	run_hook("post-load");
+	return force;
 }
 
+/*
+ * The return codes reflect the user choice in case of unsaved in-memory changes.
+ */
 int io_reload_data(void)
 {
 	char *msg_um_asktype = NULL;
-	const char *reload_success =
-		_("The data files were reloaded successfully");
-	const char *enter = _("Press [ENTER] to continue");
-	int ret = 0;
 	int load = NOFORCE;
+	int ret = IO_RELOAD_LOAD;
 
 	if (io_get_modified()) {
 		const char *msg_um_prefix =
-				_("There are unsaved modifications:");
-		const char *msg_um_discard = _("(d)iscard");
+				_("Screen data have changed and will be lost:");
+		const char *msg_um_discard = _("(c)ontinue");
 		const char *msg_um_merge = _("(m)erge");
-		const char *msg_um_keep = _("(c)ancel");
-		const char *msg_um_choice = _("[dmc]");
+		const char *msg_um_keep = _("c(a)ncel");
+		const char *msg_um_choice = _("[cma]");
 
 		asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
 			 msg_um_discard, msg_um_merge, msg_um_keep);
@@ -982,26 +975,25 @@ int io_reload_data(void)
 		switch (status_ask_choice(msg_um_asktype, msg_um_choice, 3)) {
 		case 1:
 			load = FORCE;
+			ret = IO_RELOAD_CTINUE;
 			break;
 		case 2:
 			io_merge_data();
 			load = FORCE;
+			ret = IO_RELOAD_MERGE;
 			break;
 		case 3:
+			ret = IO_RELOAD_CANCEL;
 			/* FALLTHROUGH */
 		default:
 			goto cleanup;
 		}
 	}
 
-	io_load_data(NULL, load);
-
-	if (show_dialogs()) {
-		status_mesg(reload_success, enter);
-		keys_wait_for_any_key(win[KEY].p);
-	}
+	load = io_load_data(NULL, load);
+	if (load == NONEW)
+		ret = IO_RELOAD_NOOP;
 
-	ret = 1;
 cleanup:
 	mem_free(msg_um_asktype);
 	return ret;
-- 
cgit v1.2.3-70-g09d2