From 82b27ead4d9a26eafe236e25c842dc4dba156e1e Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 3 May 2011 17:24:56 +0400 Subject: [PATCH] Optimization of history load. Formerly, each widget loaded its history self in its constructor. Thus, history file was read as many times as many widgets with history are in dialog. Now all widget histories are read from ${XDG_CACHE_HOME}/mc/history file at one time after dialog initialization. The ev_history_load_save_t event is apllied to load histories. Signed-off-by: Andrew Borodin --- lib/event-types.h | 2 + lib/widget/dialog.c | 26 ++++++++++ lib/widget/history.c | 45 +++++++++++++----- lib/widget/history.h | 3 ++ lib/widget/input.c | 100 ++++++++++++++++++++++++++------------- lib/widget/input.h | 5 +- src/filemanager/layout.c | 9 ++++ src/filemanager/panel.c | 33 ++++++++++++- 8 files changed, 174 insertions(+), 49 deletions(-) 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;