2 server-redirect.c : irssi
4 Copyright (C) 1999-2000 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
26 #include "servers-redirect.h"
28 static int redirect_group;
30 static void server_eventtable_destroy(char *key, GSList *value)
36 for (tmp = value; tmp != NULL; tmp = tmp->next) {
37 REDIRECT_REC *rec = tmp->data;
39 g_free_not_null(rec->arg);
46 static void server_eventgrouptable_destroy(gpointer key, GSList *value)
48 g_slist_foreach(value, (GFunc) g_free, NULL);
52 static void server_cmdtable_destroy(char *key, REDIRECT_CMD_REC *value)
56 g_slist_foreach(value->events, (GFunc) g_free, NULL);
57 g_slist_free(value->events);
61 static void sig_disconnected(SERVER_REC *server)
63 g_return_if_fail(IS_SERVER(server));
65 if (server->eventtable != NULL) {
66 g_hash_table_foreach(server->eventtable,
67 (GHFunc) server_eventtable_destroy, NULL);
68 g_hash_table_destroy(server->eventtable);
71 g_hash_table_foreach(server->eventgrouptable,
72 (GHFunc) server_eventgrouptable_destroy, NULL);
73 g_hash_table_destroy(server->eventgrouptable);
75 if (server->cmdtable != NULL) {
76 g_hash_table_foreach(server->cmdtable,
77 (GHFunc) server_cmdtable_destroy, NULL);
78 g_hash_table_destroy(server->cmdtable);
82 void server_redirect_initv(SERVER_REC *server, const char *command,
83 int last, GSList *list)
85 REDIRECT_CMD_REC *rec;
87 g_return_if_fail(IS_SERVER(server));
88 g_return_if_fail(command != NULL);
89 g_return_if_fail(last > 0);
91 if (g_hash_table_lookup(server->cmdtable, command) != NULL) {
92 /* already in hash table. list of events SHOULD be the same. */
93 g_slist_foreach(list, (GFunc) g_free, NULL);
98 rec = g_new(REDIRECT_CMD_REC, 1);
101 g_hash_table_insert(server->cmdtable, g_strdup(command), rec);
104 void server_redirect_init(SERVER_REC *server, const char *command,
111 va_start(args, last);
113 while ((event = va_arg(args, gchar *)) != NULL)
114 list = g_slist_append(list, g_strdup(event));
117 server_redirect_initv(server, command, last, list);
120 int server_redirect_single_event(SERVER_REC *server, const char *arg,
121 int last, int group, const char *event,
122 const char *signal, int argpos)
125 GSList *list, *grouplist;
128 g_return_val_if_fail(IS_SERVER(server), 0);
129 g_return_val_if_fail(event != NULL, 0);
130 g_return_val_if_fail(signal != NULL, 0);
131 g_return_val_if_fail(arg != NULL || argpos == -1, 0);
133 if (group == 0) group = ++redirect_group;
135 rec = g_new0(REDIRECT_REC, 1);
136 rec->arg = arg == NULL ? NULL : g_strdup(arg);
137 rec->argpos = argpos;
138 rec->name = g_strdup(signal);
142 if (g_hash_table_lookup_extended(server->eventtable, event,
143 (gpointer *) &origkey,
144 (gpointer *) &list)) {
145 g_hash_table_remove(server->eventtable, origkey);
148 origkey = g_strdup(event);
151 grouplist = g_hash_table_lookup(server->eventgrouptable,
152 GINT_TO_POINTER(group));
153 if (grouplist != NULL) {
154 g_hash_table_remove(server->eventgrouptable,
155 GINT_TO_POINTER(group));
158 list = g_slist_append(list, rec);
159 grouplist = g_slist_append(grouplist, g_strdup(event));
161 g_hash_table_insert(server->eventtable, origkey, list);
162 g_hash_table_insert(server->eventgrouptable,
163 GINT_TO_POINTER(group), grouplist);
168 void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...)
171 char *event, *signal;
174 g_return_if_fail(IS_SERVER(server));
176 va_start(args, last);
179 while ((event = va_arg(args, gchar *)) != NULL) {
180 signal = va_arg(args, gchar *);
181 argpos = va_arg(args, gint);
183 group = server_redirect_single_event(server, arg, last > 0,
184 group, event, signal,
192 void server_redirect_default(SERVER_REC *server, const char *command)
194 REDIRECT_CMD_REC *cmdrec;
196 GSList *events, *list, *grouplist;
197 char *event, *origkey;
200 g_return_if_fail(IS_SERVER(server));
201 g_return_if_fail(command != NULL);
203 if (server->cmdtable == NULL)
204 return; /* not connected yet */
206 cmdrec = g_hash_table_lookup(server->cmdtable, command);
207 if (cmdrec == NULL) return;
209 /* add all events used by command to eventtable and eventgrouptable */
210 redirect_group++; grouplist = NULL; last = cmdrec->last;
211 for (events = cmdrec->events; events != NULL; events = events->next) {
212 event = events->data;
214 if (g_hash_table_lookup_extended(server->eventtable, event,
215 (gpointer *) &origkey,
216 (gpointer *) &list)) {
217 g_hash_table_remove(server->eventtable, origkey);
220 origkey = g_strdup(event);
223 rec = g_new0(REDIRECT_REC, 1);
225 rec->name = g_strdup(event);
226 rec->group = redirect_group;
227 rec->last = last > 0;
229 grouplist = g_slist_append(grouplist, g_strdup(event));
230 list = g_slist_append(list, rec);
231 g_hash_table_insert(server->eventtable, origkey, list);
236 g_hash_table_insert(server->eventgrouptable,
237 GINT_TO_POINTER(redirect_group), grouplist);
240 void server_redirect_remove_next(SERVER_REC *server, const char *event,
244 GSList *grouplist, *list, *events, *tmp;
248 g_return_if_fail(IS_SERVER(server));
249 g_return_if_fail(event != NULL);
251 if (!g_hash_table_lookup_extended(server->eventtable, event,
252 (gpointer *) &origkey,
256 rec = item == NULL ? list->data : item->data;
258 /* this wasn't last expected event */
263 /* get list of events from this group */
264 grouplist = g_hash_table_lookup(server->eventgrouptable,
265 GINT_TO_POINTER(group));
267 /* remove all of them */
268 for (list = grouplist; list != NULL; list = list->next) {
269 char *event = list->data;
271 if (!g_hash_table_lookup_extended(server->eventtable, event,
272 (gpointer *) &origkey,
273 (gpointer *) &events)) {
274 g_warning("server_redirect_remove_next() : "
275 "event in eventgrouptable but not in "
280 /* remove the right group */
281 for (tmp = events; tmp != NULL; tmp = tmp->next) {
284 if (rec->group == group)
289 g_warning("server_redirect_remove_next() : "
290 "event in eventgrouptable but not in "
291 "eventtable (group)");
297 events = g_slist_remove(events, rec);
298 g_free_not_null(rec->arg);
302 /* update hash table */
303 g_hash_table_remove(server->eventtable, origkey);
307 g_hash_table_insert(server->eventtable,
312 g_hash_table_remove(server->eventgrouptable, GINT_TO_POINTER(group));
313 g_slist_free(grouplist);
316 GSList *server_redirect_getqueue(SERVER_REC *server, const char *event,
324 g_return_val_if_fail(IS_SERVER(server), NULL);
325 g_return_val_if_fail(event != NULL, NULL);
327 list = g_hash_table_lookup(server->eventtable, event);
329 for (; list != NULL; list = list->next) {
331 if (rec->argpos == -1)
334 if (rec->arg == NULL || args == NULL)
337 /* we need to check that the argument is right.. */
338 arglist = g_strsplit(args, " ", -1);
339 found = (strarray_length(arglist) > rec->argpos &&
340 find_substr(rec->arg, arglist[rec->argpos]));
349 void servers_redirect_init(void)
353 signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);
356 void servers_redirect_deinit(void)
358 signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);