diff --git a/lib/event-types.h b/lib/event-types.h index 6984e2326..4ace248a2 100644 --- a/lib/event-types.h +++ b/lib/event-types.h @@ -14,6 +14,7 @@ #define MCEVENT_GROUP_VIEWER "Viewer" /* Events */ +#define MCEVENT_HISTORY_LOAD "history_load" #define MCEVENT_HISTORY_SAVE "history_save" /*** enums ***************************************************************************************/ @@ -65,6 +66,7 @@ typedef struct } ret; } ev_background_parent_call_t; +/* MCEVENT_GROUP_DIALOG:history_load */ /* MCEVENT_GROUP_DIALOG:history_save */ struct mc_config_t; struct Widget; diff --git a/lib/widget/dialog.c b/lib/widget/dialog.c index ef49660a7..b6f9afa58 100644 --- a/lib/widget/dialog.c +++ b/lib/widget/dialog.c @@ -142,6 +142,31 @@ dlg_broadcast_msg_to (Dlg_head * h, widget_msg_t msg, gboolean reverse, int flag /* --------------------------------------------------------------------------------------------- */ +/** + * Read histories from the ${XDG_CACHE_HOME}/mc/history file + */ +static void +dlg_read_history (Dlg_head * h) +{ + char *profile; + ev_history_load_save_t event_data; + + if (num_history_items_recorded == 0) /* this is how to disable */ + return; + + profile = g_build_filename (mc_config_get_cache_path (), MC_HISTORY_FILE, NULL); + event_data.cfg = mc_config_init (profile); + event_data.receiver = NULL; + + /* create all histories in dialog */ + mc_event_raise (h->event_group, MCEVENT_HISTORY_LOAD, &event_data); + + mc_config_deinit (event_data.cfg); + g_free (profile); +} + +/* --------------------------------------------------------------------------------------------- */ + static int dlg_unfocus (Dlg_head * h) { @@ -1082,6 +1107,7 @@ init_dlg (Dlg_head * h) h->callback (h, NULL, DLG_INIT, 0, NULL); dlg_broadcast_msg (h, WIDGET_INIT, FALSE); + dlg_read_history (h); } h->state = DLG_ACTIVE; diff --git a/lib/widget/history.c b/lib/widget/history.c index dc27ee118..e48a44709 100644 --- a/lib/widget/history.c +++ b/lib/widget/history.c @@ -130,22 +130,17 @@ history_dlg_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, vo /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ -/* - This loads the history of an input line to the widget. It is called - with the widgets history name on creation of the widget, and returns - the GList list. +/** + * Load the history from the ${XDG_CACHE_HOME}/mc/history file. + * It is called with the widgets history name and returns the GList list. */ + GList * history_get (const char *input_name) { - size_t i; GList *hist = NULL; char *profile; mc_config_t *cfg; - char **keys; - size_t keys_num = 0; - GIConv conv = INVALID_CONV; - GString *buffer; if (num_history_items_recorded == 0) /* this is how to disable */ return NULL; @@ -155,8 +150,34 @@ history_get (const char *input_name) profile = g_build_filename (mc_config_get_cache_path (), MC_HISTORY_FILE, NULL); cfg = mc_config_init (profile); + hist = history_load (cfg, input_name); + + mc_config_deinit (cfg); + g_free (profile); + + return hist; +} + +/* --------------------------------------------------------------------------------------------- */ + +/** + * Load history form the mc_config + */ +GList * +history_load (struct mc_config_t * cfg, const char *name) +{ + size_t i; + GList *hist = NULL; + char **keys; + size_t keys_num = 0; + GIConv conv = INVALID_CONV; + GString *buffer; + + if (name == NULL || *name == '\0') + return NULL; + /* get number of keys */ - keys = mc_config_get_keys (cfg, input_name, &keys_num); + keys = mc_config_get_keys (cfg, name, &keys_num); g_strfreev (keys); /* create charset conversion handler to convert strings @@ -172,7 +193,7 @@ history_get (const char *input_name) char *this_entry; g_snprintf (key, sizeof (key), "%lu", (unsigned long) i); - this_entry = mc_config_get_string_raw (cfg, input_name, key, ""); + this_entry = mc_config_get_string_raw (cfg, name, key, ""); if (this_entry == NULL) continue; @@ -195,8 +216,6 @@ history_get (const char *input_name) g_string_free (buffer, TRUE); if (conv != INVALID_CONV) str_close_conv (conv); - mc_config_deinit (cfg); - g_free (profile); /* return pointer to the last entry in the list */ return g_list_last (hist); diff --git a/lib/widget/history.h b/lib/widget/history.h index 461995b36..a7f2a64e7 100644 --- a/lib/widget/history.h +++ b/lib/widget/history.h @@ -21,7 +21,10 @@ extern int num_history_items_recorded; /*** declarations of public functions ************************************************************/ +/* read history to the mc_config, but don't save config to file */ GList *history_get (const char *input_name); +/* load history form the mc_config */ +GList *history_load (struct mc_config_t * cfg, const char *name); /* save history to the mc_config, but don't save config to file */ void history_save (struct mc_config_t * cfg, const char *name, GList * h); #if 0 diff --git a/lib/widget/input.c b/lib/widget/input.c index 48f4fa45a..48447b05b 100644 --- a/lib/widget/input.c +++ b/lib/widget/input.c @@ -758,6 +758,48 @@ input_execute_cmd (WInput * in, unsigned long command) /* --------------------------------------------------------------------------------------------- */ +/* "history_load" event handler */ +static gboolean +input_load_history (const gchar * event_group_name, const gchar * event_name, + gpointer init_data, gpointer data) +{ + WInput *in = (WInput *) init_data; + ev_history_load_save_t *ev = (ev_history_load_save_t *) data; + const char *def_text; + size_t buffer_len; + + (void) event_group_name; + (void) event_name; + + in->history = history_load (ev->cfg, in->history_name); + + if (in->init_text == NULL) + def_text = ""; + else if (in->init_text == INPUT_LAST_TEXT) + { + if (in->history != NULL && in->history->data != NULL) + def_text = (const char *) in->history->data; + else + def_text = ""; + + in->init_text = NULL; + } + else + def_text = in->init_text; + + buffer_len = strlen (def_text); + buffer_len = 1 + max ((size_t) in->field_width, buffer_len); + in->current_max_size = buffer_len; + if (buffer_len > (size_t) in->field_width) + in->buffer = g_realloc (in->buffer, buffer_len); + strcpy (in->buffer, def_text); + in->point = str_length (in->buffer); + + return TRUE; +} + +/* --------------------------------------------------------------------------------------------- */ + /* "history_save" event handler */ static gboolean input_save_history (const gchar * event_group_name, const gchar * event_name, @@ -801,10 +843,11 @@ input_destroy (WInput * in) g_list_foreach (in->history, (GFunc) g_free, NULL); g_list_free (in->history); } + g_free (in->history_name); g_free (in->buffer); input_free_completions (in); - g_free (in->history_name); + g_free (in->init_text); g_free (kill_buffer); kill_buffer = NULL; @@ -866,37 +909,11 @@ WInput * input_new (int y, int x, const int *input_colors, int width, const char *def_text, const char *histname, input_complete_t completion_flags) { - WInput *in = g_new (WInput, 1); - size_t initial_buffer_len; + WInput *in; + in = g_new (WInput, 1); init_widget (&in->widget, y, x, 1, width, input_callback, input_event); - - /* history setup */ - in->history_name = NULL; - in->history = NULL; - if ((histname != NULL) && (*histname != '\0')) - { - in->history_name = g_strdup (histname); - in->history = history_get (histname); - } - - if (def_text == NULL) - def_text = ""; - else if (def_text == INPUT_LAST_TEXT) - { - if ((in->history != NULL) && (in->history->data != NULL)) - def_text = (char *) in->history->data; - else - def_text = ""; - } - - initial_buffer_len = strlen (def_text); - initial_buffer_len = 1 + max ((size_t) width, initial_buffer_len); in->widget.options |= W_IS_INPUT; - in->completions = NULL; - in->completion_flags = completion_flags; - in->current_max_size = initial_buffer_len; - in->buffer = g_new (char, initial_buffer_len); memmove (in->color, input_colors, sizeof (input_colors_t)); @@ -908,11 +925,26 @@ input_new (int y, int x, const int *input_colors, int width, const char *def_tex in->mark = 0; in->need_push = TRUE; in->is_password = FALSE; - - strcpy (in->buffer, def_text); - in->point = str_length (in->buffer); in->charpoint = 0; + /* in->buffer will be corrected in "history_load" event handler */ + in->current_max_size = width + 1; + in->buffer = g_new0 (char, in->current_max_size); + in->point = 0; + + in->init_text = (def_text == INPUT_LAST_TEXT) ? INPUT_LAST_TEXT : g_strdup (def_text); + + in->completions = NULL; + in->completion_flags = completion_flags; + + /* prepare to history setup */ + in->history_name = NULL; + in->history = NULL; + if ((histname != NULL) && (*histname != '\0')) + in->history_name = g_strdup (histname); + + /* history will be loaded later */ + return in; } @@ -927,6 +959,8 @@ input_callback (Widget * w, widget_msg_t msg, int parm) switch (msg) { case WIDGET_INIT: + /* subscribe to "history_load" event */ + mc_event_add (w->owner->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w, NULL); /* subscribe to "history_save" event */ mc_event_add (w->owner->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w, NULL); return MSG_HANDLED; @@ -971,6 +1005,8 @@ input_callback (Widget * w, widget_msg_t msg, int parm) return MSG_HANDLED; case WIDGET_DESTROY: + /* unsubscribe from "history_load" event */ + mc_event_del (w->owner->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w); /* unsubscribe from "history_save" event */ mc_event_del (w->owner->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w); input_destroy (in); diff --git a/lib/widget/input.h b/lib/widget/input.h index 25b6c2295..fa5e67ddd 100644 --- a/lib/widget/input.h +++ b/lib/widget/input.h @@ -46,22 +46,23 @@ typedef int input_colors_t[WINPUTC_COUNT_COLORS]; typedef struct { Widget widget; + input_colors_t color; int point; /* cursor position in the input line in characters */ int mark; /* the mark position in characters */ gboolean highlight; /* there is a selected block */ int term_first_shown; /* column of the first shown character */ size_t current_max_size; /* maximum length of input line (bytes) */ int field_width; /* width of the editing field */ - input_colors_t color; gboolean first; /* is first keystroke? */ int disable_update; /* do we want to skip updates? */ gboolean is_password; /* is this a password input line? */ + char *init_text; /* initial text of input line */ char *buffer; /* pointer to editing buffer */ + char *history_name; /* name of history for loading and saving */ GList *history; /* the history */ gboolean need_push; /* need to push the current Input on hist? */ char **completions; /* possible completions array */ input_complete_t completion_flags; - char *history_name; /* name of history for loading and saving */ char charbuf[MB_LEN_MAX]; /* buffer for multibytes characters */ size_t charpoint; /* point to end of mulibyte sequence in charbuf */ } WInput; diff --git a/src/filemanager/layout.c b/src/filemanager/layout.c index 3f03c620d..36789f685 100644 --- a/src/filemanager/layout.c +++ b/src/filemanager/layout.c @@ -41,6 +41,7 @@ #include "lib/vfs/vfs.h" /* For vfs_translate_url() */ #include "lib/strutil.h" #include "lib/widget.h" +#include "lib/event.h" #include "src/consaver/cons.saver.h" #include "src/viewer/mcviewer.h" /* The view widget */ @@ -911,6 +912,14 @@ set_display_type (int num, panel_view_mode_t type) { WPanel *panel = (WPanel *) new_widget; + /* if existing panel changed type to view_listing, then load history */ + if (old_widget != NULL) + { + ev_history_load_save_t event_data = { NULL, new_widget }; + + mc_event_raise (midnight_dlg->event_group, MCEVENT_HISTORY_LOAD, &event_data); + } + if (num == 0) left_panel = panel; else diff --git a/src/filemanager/panel.c b/src/filemanager/panel.c index 24ee4be99..b3f732707 100644 --- a/src/filemanager/panel.c +++ b/src/filemanager/panel.c @@ -1187,6 +1187,32 @@ panel_save_name (WPanel * panel) /* --------------------------------------------------------------------------------------------- */ +/* "history_load" event handler */ +static gboolean +panel_load_history (const gchar * event_group_name, const gchar * event_name, + gpointer init_data, gpointer data) +{ + WPanel *p = (WPanel *) init_data; + ev_history_load_save_t *ev = (ev_history_load_save_t *) data; + + (void) event_group_name; + (void) event_name; + + if (ev->receiver == NULL || ev->receiver == (Widget *) p) + { + if (ev->cfg != NULL) + p->dir_history = history_load (ev->cfg, p->hist_name); + else + p->dir_history = history_get (p->hist_name); + + directory_history_add (p, p->cwd); + } + + return TRUE; +} + +/* --------------------------------------------------------------------------------------------- */ + /* "history_save" event handler */ static gboolean panel_save_history (const gchar * event_group_name, const gchar * event_name, @@ -2930,6 +2956,8 @@ panel_callback (Widget * w, widget_msg_t msg, int parm) switch (msg) { case WIDGET_INIT: + /* subscribe to "history_load" event */ + mc_event_add (w->owner->event_group, MCEVENT_HISTORY_LOAD, panel_load_history, w, NULL); /* subscribe to "history_save" event */ mc_event_add (w->owner->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w, NULL); return MSG_HANDLED; @@ -2982,6 +3010,8 @@ panel_callback (Widget * w, widget_msg_t msg, int parm) return panel_execute_cmd (panel, parm); case WIDGET_DESTROY: + /* unsubscribe from "history_load" event */ + mc_event_del (w->owner->event_group, MCEVENT_HISTORY_LOAD, panel_load_history, w); /* unsubscribe from "history_save" event */ mc_event_del (w->owner->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w); panel_destroy (panel); @@ -3578,8 +3608,7 @@ panel_new_with_dir (const char *panel_name, const char *wpath) strcpy (panel->lwd, "."); panel->hist_name = g_strconcat ("Dir Hist ", panel_name, (char *) NULL); - panel->dir_history = history_get (panel->hist_name); - directory_history_add (panel, panel->cwd); + /* directories history will be get later */ panel->dir.list = g_new (file_entry, MIN_FILES); panel->dir.size = MIN_FILES;