From 8fdd1510c68644184c3df9ba002092a41364b482 Mon Sep 17 00:00:00 2001 From: Frederic Culot Date: Sun, 28 Dec 2008 19:41:45 +0000 Subject: Automatic periodic saves implemented --- ChangeLog | 9 +++++ TODO | 1 - src/args.c | 4 +-- src/calcurse.c | 10 +++--- src/custom.c | 112 +++++++++++++++++++++++++++++++++++++++++---------------- src/custom.h | 3 +- src/day.c | 4 +-- src/io.c | 76 ++++++++++++++++++++++++++++++++++++--- src/io.h | 12 +++++-- src/utils.c | 6 ++-- src/vars.c | 3 +- src/vars.h | 21 +++++------ src/wins.c | 4 +-- 13 files changed, 203 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1062c3b..2825575 100755 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,15 @@ * src/notify.c (notify_free_vars, notify_free_bar): new functions * src/vars.c (vars_free): new function + + * src/io.c + * src/custom.c: new option to periodically save data + + * io.c (io_start_psave_thread, io_stop_psave_thread) + (io_psave_thread, display_mark): new functions to implement + periodic saves + + * TODO: updated (auto-save functionality added) 2008-12-27 Frederic Culot diff --git a/TODO b/TODO index 2439ba7..ca6dec4 100755 --- a/TODO +++ b/TODO @@ -20,7 +20,6 @@ Average o Add searching capabilities with support for regex o Implement a daemon to notify user of upcoming appointments even when calcurse is not running - o Add an auto-save function o Add support for CalDAV protocol (rfc4791) o Implement categories to classify appointments and tasks o Add a week view in the calendar panel diff --git a/src/args.c b/src/args.c index c45cb7d..56a5ba2 100755 --- a/src/args.c +++ b/src/args.c @@ -1,4 +1,4 @@ -/* $calcurse: args.c,v 1.42 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: args.c,v 1.43 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -772,7 +772,7 @@ parse_args (int argc, char **argv, conf_t *conf) custom_load_conf (conf, 0); io_load_todo (); io_import_data (IO_IMPORT_ICAL, conf, ifile); - io_save_cal (conf); + io_save_cal (conf, IO_SAVE_DISPLAY_NONE); non_interactive = 1; } if (xflag) diff --git a/src/calcurse.c b/src/calcurse.c index 67253b9..fb2db0f 100755 --- a/src/calcurse.c +++ b/src/calcurse.c @@ -1,4 +1,4 @@ -/* $calcurse: calcurse.c,v 1.74 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: calcurse.c,v 1.75 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -159,7 +159,9 @@ main (int argc, char **argv) wins_slctd_set (CAL); wins_update (); calendar_start_date_thread (); - + if (conf.periodic_save > 0) + io_start_psave_thread (&conf); + /* User input */ for (;;) { @@ -375,7 +377,7 @@ main (int argc, char **argv) break; case KEY_GENERIC_SAVE: - io_save_cal (&conf); + io_save_cal (&conf, IO_SAVE_DISPLAY_BAR); break; case KEY_GENERIC_IMPORT: @@ -492,7 +494,7 @@ main (int argc, char **argv) case KEY_GENERIC_QUIT: if (conf.auto_save) - io_save_cal (&conf); + io_save_cal (&conf, IO_SAVE_DISPLAY_BAR); if (conf.confirm_quit) { diff --git a/src/custom.c b/src/custom.c index cc37c9c..71002ed 100755 --- a/src/custom.c +++ b/src/custom.c @@ -1,4 +1,4 @@ -/* $calcurse: custom.c,v 1.32 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: custom.c,v 1.33 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -239,6 +239,12 @@ custom_load_conf (conf_t *conf, int background) conf->auto_save = fill_config_var (e_conf); var = 0; break; + case CUSTOM_CONF_PERIODICSAVE: + conf->periodic_save = atoi (e_conf); + if (conf->periodic_save < 0) + conf->periodic_save = 0; + var = 0; + break; case CUSTOM_CONF_CONFIRMQUIT: conf->confirm_quit = fill_config_var (e_conf); var = 0; @@ -308,6 +314,8 @@ custom_load_conf (conf_t *conf, int background) if (strncmp (e_conf, "auto_save=", 10) == 0) var = CUSTOM_CONF_AUTOSAVE; + else if (strncmp (e_conf, "periodic_save=", 14) == 0) + var = CUSTOM_CONF_PERIODICSAVE; else if (strncmp (e_conf, "confirm_quit=", 13) == 0) var = CUSTOM_CONF_CONFIRMQUIT; else if (strncmp (e_conf, "confirm_delete=", 15) == 0) @@ -839,69 +847,95 @@ custom_color_theme_name (char *theme_name) static int print_general_options (WINDOW *win, conf_t *conf) { + enum { + AUTO_SAVE, + PERIODIC_SAVE, + CONFIRM_QUIT, + CONFIRM_DELETE, + SKIP_SYSTEM_DIAGS, + SKIP_PROGRESS_BAR, + WEEK_BEGINS_MONDAY, + OUTPUT_DATE_FMT, + INPUT_DATE_FMT, + NB_OPTIONS + }; const int XPOS = 1; const int YOFF = 3; int y; - char *opt1 = _("auto_save = "); - char *opt2 = _("confirm_quit = "); - char *opt3 = _("confirm_delete = "); - char *opt4 = _("skip_system_dialogs = "); - char *opt5 = _("skip_progress_bar = "); - char *opt6 = _("week_begins_on_monday = "); - char *opt7 = _("output_datefmt = "); - char *opt8 = _("input_datefmt = "); + char *opt[NB_OPTIONS] = { + _("auto_save = "), + _("periodic_save = "), + _("confirm_quit = "), + _("confirm_delete = "), + _("skip_system_dialogs = "), + _("skip_progress_bar = "), + _("week_begins_on_monday = "), + _("output_datefmt = "), + _("input_datefmt = ") + }; y = 0; - mvwprintw (win, y, XPOS, "[1] %s ", opt1); + mvwprintw (win, y, XPOS, "[1] %s ", opt[AUTO_SAVE]); print_bool_option_incolor (win, conf->auto_save, y, - XPOS + 4 + strlen (opt1)); + XPOS + 4 + strlen (opt[AUTO_SAVE])); mvwprintw (win, y + 1, XPOS, _("(if set to YES, automatic save is done when quitting)")); y += YOFF; - mvwprintw (win, y, XPOS, "[2] %s ", opt2); + mvwprintw (win, y, XPOS, "[2] %s ", opt[PERIODIC_SAVE]); + custom_apply_attr (win, ATTR_HIGHEST); + mvwprintw (win, y, XPOS + 4 + strlen (opt[PERIODIC_SAVE]), "%d", + conf->periodic_save); + custom_remove_attr (win, ATTR_HIGHEST); + mvwprintw (win, y + 1, XPOS, + _("(if not null, automatically save data every 'periodic_save' " + "minutes)")); + y += YOFF; + mvwprintw (win, y, XPOS, "[3] %s ", opt[CONFIRM_QUIT]); print_bool_option_incolor (win, conf->confirm_quit, y, - XPOS + 4 + strlen (opt2)); + XPOS + 4 + strlen (opt[CONFIRM_QUIT])); mvwprintw (win, y + 1, XPOS, _("(if set to YES, confirmation is required before quitting)")); y += YOFF; - mvwprintw (win, y, XPOS, "[3] %s ", opt3); + mvwprintw (win, y, XPOS, "[4] %s ", opt[CONFIRM_DELETE]); print_bool_option_incolor (win, conf->confirm_delete, y, - XPOS + 4 + strlen (opt3)); + XPOS + 4 + strlen (opt[CONFIRM_DELETE])); mvwprintw (win, y + 1, XPOS, _("(if set to YES, confirmation is required " "before deleting an event)")); y += YOFF; - mvwprintw (win, y, XPOS, "[4] %s ", opt4); + mvwprintw (win, y, XPOS, "[5] %s ", opt[SKIP_SYSTEM_DIAGS]); print_bool_option_incolor (win, conf->skip_system_dialogs, y, - XPOS + 4 + strlen (opt4)); + XPOS + 4 + strlen (opt[SKIP_SYSTEM_DIAGS])); mvwprintw (win, y + 1, XPOS, _("(if set to YES, messages about loaded " "and saved data will not be displayed)")); y += YOFF; - mvwprintw (win, y, XPOS, "[5] %s ", opt5); + mvwprintw (win, y, XPOS, "[6] %s ", opt[SKIP_PROGRESS_BAR]); print_bool_option_incolor (win, conf->skip_progress_bar, y, - XPOS + 4 + strlen (opt5)); + XPOS + 4 + strlen (opt[SKIP_PROGRESS_BAR])); mvwprintw (win, y + 1, XPOS, _("(if set to YES, progress bar will not be displayed " "when saving data)")); y += YOFF; - mvwprintw (win, y, XPOS, "[6] %s ", opt6); + mvwprintw (win, y, XPOS, "[7] %s ", opt[WEEK_BEGINS_MONDAY]); print_bool_option_incolor (win, calendar_week_begins_on_monday (), y, - XPOS + 4 + strlen (opt6)); + XPOS + 4 + strlen (opt[WEEK_BEGINS_MONDAY])); mvwprintw (win, y + 1, XPOS, _("(if set to YES, monday is the first day of the week, " "else it is sunday)")); y += YOFF; - mvwprintw (win, y, XPOS, "[7] %s ", opt7); + mvwprintw (win, y, XPOS, "[8] %s ", opt[OUTPUT_DATE_FMT]); custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, y, XPOS + 4 + strlen (opt7), "%s", conf->output_datefmt); + mvwprintw (win, y, XPOS + 4 + strlen (opt[OUTPUT_DATE_FMT]), "%s", + conf->output_datefmt); custom_remove_attr (win, ATTR_HIGHEST); mvwprintw (win, y + 1, XPOS, _("(Format of the date to be displayed in non-interactive mode)")); y += YOFF; - mvwprintw (win, y, XPOS, "[8] %s ", opt8); + mvwprintw (win, y, XPOS, "[9] %s ", opt[INPUT_DATE_FMT]); custom_apply_attr (win, ATTR_HIGHEST); - mvwprintw (win, y, XPOS + 4 + strlen (opt8), "%d", conf->input_datefmt); + mvwprintw (win, y, XPOS + 4 + strlen (opt[INPUT_DATE_FMT]), "%d", + conf->input_datefmt); custom_remove_attr (win, ATTR_HIGHEST); mvwprintw (win, y + 1, XPOS, _("(Format to be used when entering a date: ")); mvwprintw (win, y + 2, XPOS, _(" 1-mm/dd/yyyy, 2-dd/mm/yyyy, 3-yyyy/mm/dd)")); @@ -936,6 +970,8 @@ custom_general_config (conf_t *conf) _("Enter the date format (see 'man 3 strftime' for possible formats) "); char *input_datefmt_str = _("Enter the date format (1-mm/dd/yyyy, 2-dd/mm/yyyy, 3-yyyy/mm/dd) "); + char *periodic_save_str = + _("Enter the delay, in minutes, between automatic saves (0 to disable) "); int ch; char *buf = (char *) mem_malloc (BUFSIZ); @@ -981,21 +1017,35 @@ custom_general_config (conf_t *conf) conf->auto_save = !conf->auto_save; break; case '2': - conf->confirm_quit = !conf->confirm_quit; + status_mesg (periodic_save_str, ""); + if (updatestring (win[STA].p, &buf, 0, 1) == 0) + { + int val = atoi (buf); + if (val >= 0) + conf->periodic_save = val; + if (conf->periodic_save > 0) + io_start_psave_thread (conf); + else if (conf->periodic_save == 0) + io_stop_psave_thread (); + } + status_mesg (number_str, keys); break; case '3': - conf->confirm_delete = !conf->confirm_delete; + conf->confirm_quit = !conf->confirm_quit; break; case '4': - conf->skip_system_dialogs = !conf->skip_system_dialogs; + conf->confirm_delete = !conf->confirm_delete; break; case '5': - conf->skip_progress_bar = !conf->skip_progress_bar; + conf->skip_system_dialogs = !conf->skip_system_dialogs; break; case '6': - calendar_change_first_day_of_week (); + conf->skip_progress_bar = !conf->skip_progress_bar; break; case '7': + calendar_change_first_day_of_week (); + break; + case '8': status_mesg (output_datefmt_str, ""); (void)strncpy (buf, conf->output_datefmt, strlen (conf->output_datefmt) + 1); @@ -1005,7 +1055,7 @@ custom_general_config (conf_t *conf) } status_mesg (number_str, keys); break; - case '8': + case '9': status_mesg (input_datefmt_str, ""); if (updatestring (win[STA].p, &buf, 0, 1) == 0) { diff --git a/src/custom.h b/src/custom.h index 89ca4fc..9dc00ed 100755 --- a/src/custom.h +++ b/src/custom.h @@ -1,4 +1,4 @@ -/* $calcurse: custom.h,v 1.14 2008/12/20 19:27:31 culot Exp $ */ +/* $calcurse: custom.h,v 1.15 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -49,6 +49,7 @@ enum { /* Configuration variables */ CUSTOM_CONF_NOVARIABLE, CUSTOM_CONF_AUTOSAVE, + CUSTOM_CONF_PERIODICSAVE, CUSTOM_CONF_CONFIRMQUIT, CUSTOM_CONF_CONFIRMDELETE, CUSTOM_CONF_SKIPSYSTEMDIALOGS, diff --git a/src/day.c b/src/day.c index 3c29c16..a3574b9 100755 --- a/src/day.c +++ b/src/day.c @@ -1,4 +1,4 @@ -/* $calcurse: day.c,v 1.43 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: day.c,v 1.44 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -621,7 +621,7 @@ update_rept (struct rpt_s **rpt, const long start, conf_t *conf) do { status_mesg (msg_rpt_type, msg_rpt_ans); - typstr = (char *) mem_malloc (sizeof (char) * SINGLECHAR); + typstr = (char *) mem_calloc (SINGLECHAR, sizeof (char)); (void)snprintf (typstr, SINGLECHAR, "%c", recur_def2char ((*rpt)->type)); cancel = updatestring (win[STA].p, &typstr, 0, 1); if (cancel) diff --git a/src/io.c b/src/io.c index 280be0d..b0f02b2 100755 --- a/src/io.c +++ b/src/io.c @@ -1,4 +1,4 @@ -/* $calcurse: io.c,v 1.50 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: io.c,v 1.51 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -754,9 +754,29 @@ io_extract_data (char *dst_data, const char *org, int len) *dst_data = '\0'; } +void +display_mark (void) +{ + const int DISPLAY_TIME = 1; + WINDOW *mwin; + + mwin = newwin (1, 2, 1, col - 3); + + custom_apply_attr (mwin, ATTR_HIGHEST); + mvwprintw (mwin, 0, 0, "**"); + wrefresh (mwin); + sleep (DISPLAY_TIME); + mvwprintw (mwin, 0, 0, " "); + wrefresh (mwin); + delwin (mwin); + doupdate (); +} + +static pthread_mutex_t io_save_mutex = PTHREAD_MUTEX_INITIALIZER; + /* Save the calendar data */ void -io_save_cal (conf_t *conf) +io_save_cal (conf_t *conf, io_save_display_t display) { FILE *data_file; struct event_s *k; @@ -778,12 +798,18 @@ io_save_cal (conf_t *conf) char *enter = _("Press [ENTER] to continue"); bool show_bar = false; - if (ui_mode == UI_CURSES && !conf->skip_progress_bar) + pthread_mutex_lock (&io_save_mutex); + + if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_BAR + && !conf->skip_progress_bar) show_bar = true; - + else if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_MARK) + display_mark (); + /* Save the user configuration. */ if (show_bar) progress_bar (PROGRESS_BAR_SAVE, PROGRESS_BAR_CONF); + data_file = fopen (path_conf, "w"); if (data_file == NULL) ERROR_MSG (access_pb); @@ -799,6 +825,12 @@ io_save_cal (conf_t *conf) (void)fprintf (data_file, "auto_save=\n"); (void)fprintf (data_file, "%s\n", (conf->auto_save) ? "yes" : "no"); + (void)fprintf (data_file, + "\n# If not null, perform automatic saves every " + "'periodic_save' minutes\n"); + (void)fprintf (data_file, "periodic_save=\n"); + (void)fprintf (data_file, "%d\n", conf->periodic_save); + (void)fprintf (data_file, "\n# If this option is set to yes, " "confirmation is required before quitting\n"); @@ -948,6 +980,8 @@ io_save_cal (conf_t *conf) status_mesg (save_success, enter); (void)wgetch (win[STA].p); } + + pthread_mutex_unlock (&io_save_mutex); } /* @@ -2743,3 +2777,37 @@ io_log_free (io_file_t *log) log->name); mem_free (log); } + +static pthread_t io_t_psave; + +/* Thread used to periodically save data. */ +static void * +io_psave_thread (void *arg) +{ + conf_t *config; + int delay; + + config = (conf_t *)arg; + delay = config->periodic_save; + EXIT_IF (delay < 0, _("Invalid delay")); + + for (;;) + { + (void)sleep (delay * MININSEC); + io_save_cal (config, IO_SAVE_DISPLAY_MARK); + } +} + +/* Launch the thread which handles periodic saves. */ +void +io_start_psave_thread (conf_t *conf) +{ + pthread_create (&io_t_psave, NULL, io_psave_thread, (void *)conf); +} + +/* Stop periodic data saves. */ +void +io_stop_psave_thread (void) +{ + pthread_cancel (io_t_psave); +} diff --git a/src/io.h b/src/io.h index 2741c52..ee70da6 100755 --- a/src/io.h +++ b/src/io.h @@ -1,4 +1,4 @@ -/* $calcurse: io.h,v 1.17 2008/12/07 09:20:38 culot Exp $ */ +/* $calcurse: io.h,v 1.18 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -40,6 +40,12 @@ typedef enum { IO_EXPORT_NBTYPES } export_type_t; +typedef enum { + IO_SAVE_DISPLAY_BAR, + IO_SAVE_DISPLAY_MARK, + IO_SAVE_DISPLAY_NONE +} io_save_display_t; + typedef struct { FILE *fd; char name[BUFSIZ]; @@ -47,7 +53,7 @@ typedef struct { void io_init (char *, char *); void io_extract_data (char *, const char *, int); -void io_save_cal (conf_t *); +void io_save_cal (conf_t *, io_save_display_t); void io_load_app (void); void io_load_todo (void); void io_load_keys (char *); @@ -60,5 +66,7 @@ io_file_t *io_log_init (void); void io_log_print (io_file_t *, int, char *); void io_log_display (io_file_t *, char *, char *); void io_log_free (io_file_t *); +void io_start_psave_thread (conf_t *); +void io_stop_psave_thread (void); #endif /* !CALCURSE_IO_H */ diff --git a/src/utils.c b/src/utils.c index 23cd32d..cee945f 100755 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,4 @@ -/* $calcurse: utils.c,v 1.62 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: utils.c,v 1.63 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -40,6 +40,7 @@ #include "wins.h" #include "custom.h" #include "keys.h" +#include "io.h" #include "recur.h" #include "apoint.h" #include "todo.h" @@ -68,6 +69,7 @@ exit_calcurse (int status) ui_mode = UI_CMDLINE; } calendar_stop_date_thread (); + io_stop_psave_thread (); vars_free (); notify_free_vars (); notify_free_bar (); @@ -536,7 +538,7 @@ date_sec2date_str (long sec, char *datefmt) time_t t; char *datestr; - datestr = (char *) mem_malloc (sizeof (char) * BUFSIZ); + datestr = (char *) mem_calloc (BUFSIZ, sizeof (char)); if (sec == 0) (void)snprintf (datestr, BUFSIZ, "0"); diff --git a/src/vars.c b/src/vars.c index 8a80e09..2283067 100755 --- a/src/vars.c +++ b/src/vars.c @@ -1,4 +1,4 @@ -/* $calcurse: vars.c,v 1.12 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: vars.c,v 1.13 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -111,6 +111,7 @@ vars_init (conf_t *conf) conf->confirm_quit = true; conf->confirm_delete = true; conf->auto_save = true; + conf->periodic_save = 0; conf->skip_system_dialogs = false; conf->skip_progress_bar = false; (void)strncpy (conf->output_datefmt, "%D", 3); diff --git a/src/vars.h b/src/vars.h index d0a1d3c..b8961cd 100755 --- a/src/vars.h +++ b/src/vars.h @@ -1,4 +1,4 @@ -/* $calcurse: vars.h,v 1.27 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: vars.h,v 1.28 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -94,15 +94,16 @@ struct nbar_s /* General configuration variables */ typedef struct { - bool auto_save; - bool confirm_quit; - bool confirm_delete; - bool skip_system_dialogs; - bool skip_progress_bar; - char *editor; - char *pager; - char output_datefmt[BUFSIZ]; /* format for displaying date */ - int input_datefmt; /* format for reading date */ + bool auto_save; + unsigned periodic_save; + bool confirm_quit; + bool confirm_delete; + bool skip_system_dialogs; + bool skip_progress_bar; + char *editor; + char *pager; + char output_datefmt[BUFSIZ]; /* format for displaying date */ + int input_datefmt; /* format for reading date */ } conf_t; diff --git a/src/wins.c b/src/wins.c index 8dde1f7..36655a5 100755 --- a/src/wins.c +++ b/src/wins.c @@ -1,4 +1,4 @@ -/* $calcurse: wins.c,v 1.20 2008/12/28 13:13:59 culot Exp $ */ +/* $calcurse: wins.c,v 1.21 2008/12/28 19:41:45 culot Exp $ */ /* * Calcurse - text-based organizer @@ -453,7 +453,7 @@ wins_launch_external (const char *file, const char *cmd) /* Beware of space between cmd and file. */ len = strlen (file) + strlen (cmd) + 2; - p = (char *) mem_malloc (sizeof (char) * len); + p = (char *) mem_calloc (len, sizeof (char)); if (snprintf (p, len, "%s %s", cmd, file) == -1) { mem_free (p); -- cgit v1.2.3-70-g09d2