diff options
Diffstat (limited to 'src/fe-common/core/command-history.c')
-rw-r--r-- | src/fe-common/core/command-history.c | 232 |
1 files changed, 165 insertions, 67 deletions
diff --git a/src/fe-common/core/command-history.c b/src/fe-common/core/command-history.c index cdf4b5a5..1642c798 100644 --- a/src/fe-common/core/command-history.c +++ b/src/fe-common/core/command-history.c @@ -27,119 +27,215 @@ #include "fe-windows.h" #include "window-items.h" +#include "command-history.h" + /* command history */ -static GList *history, *history_pos; -static int history_lines, history_over_counter; +static HISTORY_REC *global_history; static int window_history; +static GSList *histories; -void command_history_add(WINDOW_REC *window, const char *text) +void command_history_add(HISTORY_REC *history, const char *text) { - GList **phistory, *link; - int *phistory_lines; + GList *link; + g_return_if_fail(history != NULL); g_return_if_fail(text != NULL); - if (window_history) { - /* window specific command history */ - phistory = &window->history; - phistory_lines = &window->history_lines; - } else { - /* global command history */ - phistory = &history; - phistory_lines = &history_lines; - } - - if (settings_get_int("max_command_history") < 1 || *phistory_lines < settings_get_int("max_command_history")) - (*phistory_lines)++; + if (settings_get_int("max_command_history") < 1 || + history->lines < settings_get_int("max_command_history")) + history->lines++; else { - link = *phistory; + link = history->list; g_free(link->data); - *phistory = g_list_remove_link(*phistory, link); + history->list = g_list_remove_link(history->list, link); g_list_free_1(link); } - *phistory = g_list_append(*phistory, g_strdup(text)); + history->list = g_list_append(history->list, g_strdup(text)); } -const char *command_history_prev(WINDOW_REC *window, const char *text) +HISTORY_REC *command_history_find(HISTORY_REC *history) { - GList *pos, **phistory_pos; - int *phistory_over_counter; + GSList *tmp; + tmp = g_slist_find(histories, history); - if (window_history) { - phistory_pos = &window->history_pos; - phistory_over_counter = &window->history_over_counter; - } else { - phistory_pos = &history_pos; - phistory_over_counter = &history_over_counter; + if (tmp == NULL) + return NULL; + else + return tmp->data; +} + +HISTORY_REC *command_history_find_name(const char *name) +{ + GSList *tmp; + + if (name == NULL) + return NULL; + + for (tmp = histories; tmp != NULL; tmp = tmp->next) { + HISTORY_REC *rec = tmp->data; + + if (rec->name != NULL && g_strcasecmp(rec->name, name) == 0) + return rec; } + + return NULL; +} + +HISTORY_REC *command_history_current(WINDOW_REC *window) +{ + HISTORY_REC *rec; - pos = *phistory_pos; - if (*phistory_pos != NULL) { - *phistory_pos = (*phistory_pos)->prev; - if (*phistory_pos == NULL) - (*phistory_over_counter)++; + if (window == NULL) + return global_history; + + if (window_history) + return window->history; + + rec = command_history_find_name(window->history_name); + if (rec != NULL) + return rec; + + return global_history; +} + +const char *command_history_prev(WINDOW_REC *window, const char *text) +{ + HISTORY_REC *history; + GList *pos; + + history = command_history_current(window); + pos = history->pos; + + if (pos != NULL) { + history->pos = history->pos->prev; + if (history->pos == NULL) + history->over_counter++; } else { - *phistory_pos = g_list_last(window_history ? - window->history : history); + history->pos = g_list_last(history->list); } if (*text != '\0' && (pos == NULL || strcmp(pos->data, text) != 0)) { /* save the old entry to history */ - command_history_add(window, text); + command_history_add(history, text); } - return *phistory_pos == NULL ? "" : (*phistory_pos)->data; + return history->pos == NULL ? "" : history->pos->data; } const char *command_history_next(WINDOW_REC *window, const char *text) { - GList *pos, **phistory_pos; - int *phistory_over_counter; + HISTORY_REC *history; + GList *pos; - if (window_history) { - phistory_pos = &window->history_pos; - phistory_over_counter = &window->history_over_counter; - } else { - phistory_pos = &history_pos; - phistory_over_counter = &history_over_counter; - } - - pos = *phistory_pos; + history = command_history_current(window); + pos = history->pos; if (pos != NULL) - *phistory_pos = (*phistory_pos)->next; - else if (*phistory_over_counter > 0) { - (*phistory_over_counter)--; - *phistory_pos = window_history ? window->history : history; + history->pos = history->pos->next; + else if (history->over_counter > 0) { + history->over_counter--; + history->pos = history->list; } if (*text != '\0' && (pos == NULL || strcmp(pos->data, text) != 0)) { /* save the old entry to history */ - command_history_add(window, text); + command_history_add(history, text); } - return *phistory_pos == NULL ? "" : (*phistory_pos)->data; + return history->pos == NULL ? "" : history->pos->data; +} + +void command_history_clear_pos_func(HISTORY_REC *history, gpointer user_data) +{ + history->over_counter = 0; + history->pos = NULL; } void command_history_clear_pos(WINDOW_REC *window) { - window->history_over_counter = 0; - window->history_pos = NULL; - history_over_counter = 0; - history_pos = NULL; + g_slist_foreach(histories, + (GFunc) command_history_clear_pos_func, NULL); +} + +HISTORY_REC *command_history_create(const char *name) +{ + HISTORY_REC *rec; + + rec = g_new0(HISTORY_REC, 1); + + if (name != NULL) + rec->name = g_strdup(name); + + histories = g_slist_append(histories, rec); + + return rec; +} + +void command_history_destroy(HISTORY_REC *history) +{ + g_return_if_fail(history != NULL); + + /* history->refcount should be 0 here, or somthing is wrong... */ + g_return_if_fail(history->refcount == 0); + + histories = g_slist_remove(histories, history); + + g_list_foreach(history->list, (GFunc) g_free, NULL); + g_list_free(history->list); + + g_free_not_null(history->name); + g_free(history); +} + +void command_history_link(const char *name) +{ + HISTORY_REC *rec; + rec = command_history_find_name(name); + + if (rec == NULL) + rec = command_history_create(name); + + rec->refcount++; +} + +void command_history_unlink(const char *name) +{ + HISTORY_REC *rec; + rec = command_history_find_name(name); + + if (rec == NULL) + return; + + if (--(rec->refcount) <= 0) + command_history_destroy(rec); +} + +static void sig_window_created(WINDOW_REC *window, int automatic) +{ + window->history = command_history_create(NULL); } static void sig_window_destroyed(WINDOW_REC *window) { - g_list_foreach(window->history, (GFunc) g_free, NULL); - g_list_free(window->history); + command_history_unlink(window->history_name); + command_history_destroy(window->history); + + g_free_not_null(window->history_name); + g_free_not_null(window->history); +} + +static void sig_window_history_changed(WINDOW_REC *window, const char *oldname) +{ + command_history_link(window->history_name); + command_history_unlink(oldname); } static char *special_history_func(const char *text, void *item, int *free_ret) { WINDOW_REC *window; + HISTORY_REC *history; GList *tmp; char *findtext, *ret; @@ -148,8 +244,8 @@ static char *special_history_func(const char *text, void *item, int *free_ret) findtext = g_strdup_printf("*%s*", text); ret = NULL; - tmp = window_history ? window->history : history; - for (; tmp != NULL; tmp = tmp->next) { + history = command_history_current(window); + for (tmp = history->list; tmp != NULL; tmp = tmp->next) { const char *line = tmp->data; if (match_wildcards(findtext, line)) { @@ -174,19 +270,21 @@ void command_history_init(void) special_history_func_set(special_history_func); - history_lines = 0; history_over_counter = 0; - history = NULL; history_pos = NULL; + global_history = command_history_create(NULL); read_settings(); + signal_add("window created", (SIGNAL_FUNC) sig_window_created); signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed); + signal_add("window history changed", (SIGNAL_FUNC) sig_window_history_changed); signal_add("setup changed", (SIGNAL_FUNC) read_settings); } void command_history_deinit(void) { + signal_remove("window created", (SIGNAL_FUNC) sig_window_created); signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed); + signal_remove("window history changed", (SIGNAL_FUNC) sig_window_history_changed); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); - g_list_foreach(history, (GFunc) g_free, NULL); - g_list_free(history); + command_history_destroy(global_history); } |