summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/args.c4
-rw-r--r--src/calcurse.c53
-rw-r--r--src/calcurse.h13
-rw-r--r--src/io.c22
-rw-r--r--src/vars.c7
-rw-r--r--src/wins.c16
6 files changed, 97 insertions, 18 deletions
diff --git a/src/args.c b/src/args.c
index 8b62cb8..8a9aa49 100644
--- a/src/args.c
+++ b/src/args.c
@@ -707,8 +707,8 @@ int parse_args(int argc, char **argv)
io_load_app();
io_load_todo();
io_import_data(IO_IMPORT_ICAL, ifile);
- io_save_apts();
- io_save_todo();
+ io_save_apts(path_apts);
+ io_save_todo(path_todo);
non_interactive = 1;
}
if (xflag) {
diff --git a/src/calcurse.c b/src/calcurse.c
index 149d7bb..cfe8298 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -256,11 +256,54 @@ static inline void key_generic_save(void)
static inline void key_generic_reload(void)
{
- if (io_get_modified() && status_ask_bool(_("By reloading items, you "
- "will lose any unsaved modifications. "
- "Continue?")) != 1) {
- wins_update(FLAG_STA);
- return;
+ if (io_get_modified()) {
+ const char *msg_um_prefix =
+ _("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]");
+
+ char msg_um_asktype[BUFSIZ];
+ snprintf(msg_um_asktype, BUFSIZ, "%s %s, %s, %s",
+ msg_um_prefix, msg_um_discard, msg_um_merge,
+ msg_um_keep);
+
+ char *path_apts_backup, *path_todo_backup;
+ const char *backup_ext = ".sav";
+
+ switch (status_ask_choice(msg_um_asktype, msg_um_choice, 3)) {
+ case 1:
+ break;
+ case 2:
+ path_apts_backup = xmalloc(strlen(path_apts) +
+ strlen(backup_ext) + 1);
+ path_todo_backup = xmalloc(strlen(path_todo) +
+ strlen(backup_ext) + 1);
+ sprintf(path_apts_backup, "%s%s", path_apts,
+ backup_ext);
+ sprintf(path_todo_backup, "%s%s", path_todo,
+ backup_ext);
+
+ io_save_mutex_lock();
+ io_save_apts(path_apts_backup);
+ io_save_todo(path_todo_backup);
+ io_save_mutex_unlock();
+
+ wins_launch_external2(path_apts, path_apts_backup,
+ conf.mergetool);
+ wins_launch_external2(path_todo, path_todo_backup,
+ conf.mergetool);
+
+ xfree(path_apts_backup);
+ xfree(path_todo_backup);
+ break;
+ case 3:
+ /* FALLTHROUGH */
+ default:
+ wins_update(FLAG_STA);
+ return;
+ }
}
/* Reinitialize data structures. */
diff --git a/src/calcurse.h b/src/calcurse.h
index ca85690..a1cf9bb 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -103,8 +103,9 @@
#define DPID_PATH DIR_NAME DPID_PATH_NAME
#define NOTES_DIR DIR_NAME NOTES_DIR_NAME
-#define DEFAULT_EDITOR "vi"
-#define DEFAULT_PAGER "less"
+#define DEFAULT_EDITOR "vi"
+#define DEFAULT_PAGER "less"
+#define DEFAULT_MERGETOOL "vimdiff"
#define ATTR_FALSE 0
#define ATTR_TRUE 1
@@ -259,6 +260,7 @@ struct conf {
unsigned progress_bar;
const char *editor;
const char *pager;
+ const char *mergetool;
char output_datefmt[BUFSIZ]; /* format for displaying date */
int input_datefmt; /* format for reading date */
};
@@ -753,8 +755,10 @@ void ical_export_data(FILE *);
unsigned io_fprintln(const char *, const char *, ...);
void io_init(const char *, const char *);
void io_extract_data(char *, const char *, int);
-unsigned io_save_apts(void);
-unsigned io_save_todo(void);
+void io_save_mutex_lock(void);
+void io_save_mutex_unlock(void);
+unsigned io_save_apts(const char *);
+unsigned io_save_todo(const char *);
unsigned io_save_keys(void);
void io_save_cal(enum save_display);
void io_load_app(void);
@@ -1121,6 +1125,7 @@ void wins_reset(void);
void wins_prepare_external(void);
void wins_unprepare_external(void);
void wins_launch_external(const char *, const char *);
+void wins_launch_external2(const char *, const char *, const char *);
void wins_status_bar(void);
void wins_erase_status_bar(void);
void wins_other_status_page(int);
diff --git a/src/io.c b/src/io.c
index acf624b..f24b0f7 100644
--- a/src/io.c
+++ b/src/io.c
@@ -319,12 +319,22 @@ void io_extract_data(char *dst_data, const char *org, int len)
static pthread_mutex_t io_save_mutex = PTHREAD_MUTEX_INITIALIZER;
+void io_save_mutex_lock(void)
+{
+ pthread_mutex_lock(&io_save_mutex);
+}
+
+void io_save_mutex_unlock(void)
+{
+ pthread_mutex_unlock(&io_save_mutex);
+}
+
/*
* Save the apts data file, which contains the
* appointments first, and then the events.
* Recursive items are written first.
*/
-unsigned io_save_apts(void)
+unsigned io_save_apts(const char *aptsfile)
{
llist_item_t *i;
FILE *fp;
@@ -332,7 +342,7 @@ unsigned io_save_apts(void)
if (read_only)
return 1;
- if ((fp = fopen(path_apts, "w")) == NULL)
+ if ((fp = fopen(aptsfile, "w")) == NULL)
return 0;
recur_save_data(fp);
@@ -356,7 +366,7 @@ unsigned io_save_apts(void)
}
/* Save the todo data file. */
-unsigned io_save_todo(void)
+unsigned io_save_todo(const char *todofile)
{
llist_item_t *i;
FILE *fp;
@@ -364,7 +374,7 @@ unsigned io_save_todo(void)
if (read_only)
return 1;
- if ((fp = fopen(path_todo, "w")) == NULL)
+ if ((fp = fopen(todofile, "w")) == NULL)
return 0;
LLIST_FOREACH(&todolist, i) {
@@ -419,12 +429,12 @@ void io_save_cal(enum save_display display)
if (show_bar)
progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_TODO);
- if (!io_save_todo())
+ if (!io_save_todo(path_todo))
ERROR_MSG("%s", access_pb);
if (show_bar)
progress_bar(PROGRESS_BAR_SAVE, PROGRESS_BAR_APTS);
- if (!io_save_apts())
+ if (!io_save_apts(path_apts))
ERROR_MSG("%s", access_pb);
if (show_bar)
diff --git a/src/vars.c b/src/vars.c
index 52a1ed2..16b892a 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -126,7 +126,7 @@ struct dmon_conf dmon;
*/
void vars_init(void)
{
- const char *ed, *pg;
+ const char *ed, *pg, *mt;
/* Variables for user configuration */
conf.confirm_quit = 1;
@@ -159,6 +159,11 @@ void vars_init(void)
pg = DEFAULT_PAGER;
conf.pager = pg;
+ mt = getenv("MERGETOOL");
+ if (mt == NULL || mt[0] == '\0')
+ mt = DEFAULT_MERGETOOL;
+ conf.mergetool = mt;
+
wins_set_layout(1);
ui_calendar_set_first_day_of_week(MONDAY);
diff --git a/src/wins.c b/src/wins.c
index d4b93d5..7545a59 100644
--- a/src/wins.c
+++ b/src/wins.c
@@ -611,6 +611,22 @@ void wins_launch_external(const char *file, const char *cmd)
wins_unprepare_external();
}
+/*
+ * While inside interactive mode, launch the external command cmd on the given
+ * two files.
+ */
+void wins_launch_external2(const char *file1, const char *file2,
+ const char *cmd)
+{
+ const char *arg[] = { cmd, file1, file2, NULL };
+ int pid;
+
+ wins_prepare_external();
+ if ((pid = shell_exec(NULL, NULL, *arg, arg)))
+ child_wait(NULL, NULL, pid);
+ wins_unprepare_external();
+}
+
#define NB_CAL_CMDS 28 /* number of commands while in cal view */
#define NB_APP_CMDS 33 /* same thing while in appointment view */
#define NB_TOD_CMDS 32 /* same thing while in todo view */