2 command-history.c : irssi
4 Copyright (C) 1999 Timo Sirainen
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "special-vars.h"
27 #include "fe-windows.h"
28 #include "window-items.h"
30 #include "command-history.h"
33 static HISTORY_REC *global_history;
34 static int window_history;
35 static GSList *histories;
37 void command_history_add(HISTORY_REC *history, const char *text)
41 g_return_if_fail(history != NULL);
42 g_return_if_fail(text != NULL);
44 link = g_list_last(history->list);
45 if (link != NULL && strcmp(link->data, text) == 0)
46 return; /* same as previous entry */
48 if (settings_get_int("max_command_history") < 1 ||
49 history->lines < settings_get_int("max_command_history"))
54 history->list = g_list_remove_link(history->list, link);
58 history->list = g_list_append(history->list, g_strdup(text));
61 HISTORY_REC *command_history_find(HISTORY_REC *history)
64 tmp = g_slist_find(histories, history);
72 HISTORY_REC *command_history_find_name(const char *name)
79 for (tmp = histories; tmp != NULL; tmp = tmp->next) {
80 HISTORY_REC *rec = tmp->data;
82 if (rec->name != NULL && g_strcasecmp(rec->name, name) == 0)
89 HISTORY_REC *command_history_current(WINDOW_REC *window)
94 return global_history;
97 return window->history;
99 rec = command_history_find_name(window->history_name);
103 return global_history;
106 const char *command_history_prev(WINDOW_REC *window, const char *text)
108 HISTORY_REC *history;
111 history = command_history_current(window);
115 history->pos = history->pos->prev;
116 if (history->pos == NULL)
117 history->over_counter++;
119 history->pos = g_list_last(history->list);
123 (pos == NULL || strcmp(pos->data, text) != 0)) {
124 /* save the old entry to history */
125 command_history_add(history, text);
128 return history->pos == NULL ? "" : history->pos->data;
131 const char *command_history_next(WINDOW_REC *window, const char *text)
133 HISTORY_REC *history;
136 history = command_history_current(window);
140 history->pos = history->pos->next;
141 else if (history->over_counter > 0) {
142 history->over_counter--;
143 history->pos = history->list;
147 (pos == NULL || strcmp(pos->data, text) != 0)) {
148 /* save the old entry to history */
149 command_history_add(history, text);
151 return history->pos == NULL ? "" : history->pos->data;
154 void command_history_clear_pos_func(HISTORY_REC *history, gpointer user_data)
156 history->over_counter = 0;
160 void command_history_clear_pos(WINDOW_REC *window)
162 g_slist_foreach(histories,
163 (GFunc) command_history_clear_pos_func, NULL);
166 HISTORY_REC *command_history_create(const char *name)
170 rec = g_new0(HISTORY_REC, 1);
173 rec->name = g_strdup(name);
175 histories = g_slist_append(histories, rec);
180 void command_history_destroy(HISTORY_REC *history)
182 g_return_if_fail(history != NULL);
184 /* history->refcount should be 0 here, or somthing is wrong... */
185 g_return_if_fail(history->refcount == 0);
187 histories = g_slist_remove(histories, history);
189 g_list_foreach(history->list, (GFunc) g_free, NULL);
190 g_list_free(history->list);
192 g_free_not_null(history->name);
196 void command_history_link(const char *name)
199 rec = command_history_find_name(name);
202 rec = command_history_create(name);
207 void command_history_unlink(const char *name)
210 rec = command_history_find_name(name);
215 if (--(rec->refcount) <= 0)
216 command_history_destroy(rec);
219 static void sig_window_created(WINDOW_REC *window, int automatic)
221 window->history = command_history_create(NULL);
224 static void sig_window_destroyed(WINDOW_REC *window)
226 command_history_unlink(window->history_name);
227 command_history_destroy(window->history);
228 g_free_not_null(window->history_name);
231 static void sig_window_history_changed(WINDOW_REC *window, const char *oldname)
233 command_history_link(window->history_name);
234 command_history_unlink(oldname);
237 static char *special_history_func(const char *text, void *item, int *free_ret)
240 HISTORY_REC *history;
242 char *findtext, *ret;
244 window = item == NULL ? active_win : window_item_window(item);
246 findtext = g_strdup_printf("*%s*", text);
249 history = command_history_current(window);
250 for (tmp = history->list; tmp != NULL; tmp = tmp->next) {
251 const char *line = tmp->data;
253 if (match_wildcards(findtext, line)) {
255 ret = g_strdup(line);
263 static void read_settings(void)
265 window_history = settings_get_bool("window_history");
268 void command_history_init(void)
270 settings_add_int("history", "max_command_history", 100);
271 settings_add_bool("history", "window_history", FALSE);
273 special_history_func_set(special_history_func);
275 global_history = command_history_create(NULL);
278 signal_add("window created", (SIGNAL_FUNC) sig_window_created);
279 signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
280 signal_add("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
281 signal_add("setup changed", (SIGNAL_FUNC) read_settings);
284 void command_history_deinit(void)
286 signal_remove("window created", (SIGNAL_FUNC) sig_window_created);
287 signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
288 signal_remove("window history changed", (SIGNAL_FUNC) sig_window_history_changed);
289 signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
291 command_history_destroy(global_history);