imported.
[silc.git] / apps / irssi / src / fe-common / core / fe-messages.c
1 /*
2  fe-messages.c : irssi
3
4     Copyright (C) 2000 Timo Sirainen
5
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.
10
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.
15
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
19 */
20
21 #include "module.h"
22 #include "module-formats.h"
23 #include "signals.h"
24 #include "commands.h"
25 #include "levels.h"
26 #include "misc.h"
27 #include "special-vars.h"
28 #include "settings.h"
29
30 #include "window-items.h"
31 #include "fe-queries.h"
32 #include "channels.h"
33 #include "nicklist.h"
34 #include "hilight-text.h"
35 #include "ignore.h"
36 #include "printtext.h"
37
38 #define ishighalnum(c) ((unsigned char) (c) >= 128 || isalnum(c))
39
40 static GHashTable *printnicks;
41
42 /* convert _underlined_ and *bold* words (and phrases) to use real
43    underlining or bolding */
44 char *expand_emphasis(WI_ITEM_REC *item, const char *text)
45 {
46         GString *str;
47         char *ret;
48         int pos;
49
50         g_return_val_if_fail(text != NULL, NULL);
51
52         str = g_string_new(text);
53
54         for (pos = 0; pos < str->len; pos++) {
55                 char type, *bgn, *end;
56
57                 bgn = str->str + pos;
58
59                 if (*bgn == '*') 
60                         type = 2; /* bold */
61                 else if (*bgn == '_') 
62                         type = 31; /* underlined */
63                 else
64                         continue;
65
66                 /* check that the beginning marker starts a word, and
67                    that the matching end marker ends a word */
68                 if ((pos > 0 && !isspace(bgn[-1])) || !ishighalnum(bgn[1]))
69                         continue;
70                 if ((end = strchr(bgn+1, *bgn)) == NULL)
71                         continue;
72                 if (!ishighalnum(end[-1]) || ishighalnum(end[1]) ||
73                     end[1] == type || end[1] == '*' || end[1] == '_')
74                         continue;
75
76                 if (IS_CHANNEL(item)) {
77                         /* check that this isn't a _nick_, we don't want to
78                            use emphasis on them. */
79                         int found;
80                         char c;
81
82                         c = end[1];
83                         end[1] = '\0';
84                         found = nicklist_find(CHANNEL(item), bgn) != NULL;
85                         end[1] = c;
86                         if (found) continue;
87                 }
88
89                 /* allow only *word* emphasis, not *multiple words* */
90                 if (!settings_get_bool("emphasis_multiword")) {
91                         char *c;
92                         for (c = bgn+1; c != end; c++) {
93                                 if (!ishighalnum(*c))
94                                         break;
95                         }
96                         if (c != end) continue;
97                 }
98
99                 if (settings_get_bool("emphasis_replace")) {
100                         *bgn = *end = type;
101                         pos += (end-bgn);
102                 } else {
103                         g_string_insert_c(str, pos, type);
104                         pos += (end - bgn) + 2;
105                         g_string_insert_c(str, pos++, type);
106                 }
107         }
108
109         ret = str->str;
110         g_string_free(str, FALSE);
111         return ret;
112 }
113
114 char *channel_get_nickmode(CHANNEL_REC *channel, const char *nick)
115 {
116         NICK_REC *nickrec;
117         char *emptystr;
118
119         g_return_val_if_fail(nick != NULL, NULL);
120
121         if (!settings_get_bool("show_nickmode"))
122                 return "";
123
124         emptystr = settings_get_bool("show_nickmode_empty") ? " " : "";
125
126         nickrec = channel == NULL ? NULL :
127                 nicklist_find(channel, nick);
128         return nickrec == NULL ? emptystr :
129                 (nickrec->op ? "@" : (nickrec->voice ? "+" : emptystr));
130 }
131
132 static char *channel_get_nickmode_rec(NICK_REC *nickrec)
133 {
134         char *emptystr;
135
136         if (!settings_get_bool("show_nickmode"))
137                 return "";
138
139         emptystr = settings_get_bool("show_nickmode_empty") ? " " : "";
140
141         return nickrec == NULL ? emptystr :
142                 (nickrec->op ? "@" : (nickrec->voice ? "+" : emptystr));
143 }
144
145 static void sig_message_public(SERVER_REC *server, const char *msg,
146                                const char *nick, const char *address,
147                                const char *target, NICK_REC *nickrec)
148 {
149         CHANNEL_REC *chanrec;
150         const char *nickmode, *printnick;
151         int for_me, print_channel, level;
152         char *color, *freemsg = NULL;
153
154         /* NOTE: this may return NULL if some channel is just closed with
155            /WINDOW CLOSE and server still sends the few last messages */
156         chanrec = channel_find(server, target);
157         if (nickrec == NULL && chanrec != NULL)
158                 nickrec = nicklist_find(chanrec, nick);
159
160         for_me = nick_match_msg(chanrec, msg, server->nick);
161         color = for_me ? NULL :
162                 hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC, msg);
163
164         print_channel = chanrec == NULL ||
165                 !window_item_is_active((WI_ITEM_REC *) chanrec);
166         if (!print_channel && settings_get_bool("print_active_channel") &&
167             window_item_window((WI_ITEM_REC *) chanrec)->items->next != NULL)
168                 print_channel = TRUE;
169
170         level = MSGLEVEL_PUBLIC | (for_me || color != NULL ?
171                                    MSGLEVEL_HILIGHT : MSGLEVEL_NOHILIGHT);
172
173         if (settings_get_bool("emphasis"))
174                 msg = freemsg = expand_emphasis((WI_ITEM_REC *) chanrec, msg);
175
176         /* get nick mode & nick what to print the msg with
177            (in case there's multiple identical nicks) */
178         nickmode = channel_get_nickmode_rec(nickrec);
179         printnick = nickrec == NULL ? nick :
180                 g_hash_table_lookup(printnicks, nickrec);
181         if (printnick == NULL)
182                 printnick = nick;
183
184         if (!print_channel) {
185                 /* message to active channel in window */
186                 if (color != NULL) {
187                         /* highlighted nick */
188                         printformat(server, target, level,
189                                     TXT_PUBMSG_HILIGHT,
190                                     color, printnick, msg, nickmode);
191                 } else {
192                         printformat(server, target, level,
193                                     for_me ? TXT_PUBMSG_ME : TXT_PUBMSG,
194                                     printnick, msg, nickmode);
195                 }
196         } else {
197                 /* message to not existing/active channel */
198                 if (color != NULL) {
199                         /* highlighted nick */
200                         printformat(server, target, level,
201                                     TXT_PUBMSG_HILIGHT_CHANNEL,
202                                     color, printnick, target, msg, nickmode);
203                 } else {
204                         printformat(server, target, level,
205                                     for_me ? TXT_PUBMSG_ME_CHANNEL :
206                                     TXT_PUBMSG_CHANNEL,
207                                     printnick, target, msg, nickmode);
208                 }
209         }
210
211         g_free_not_null(freemsg);
212         g_free_not_null(color);
213 }
214
215 static void sig_message_private(SERVER_REC *server, const char *msg,
216                                 const char *nick, const char *address)
217 {
218         QUERY_REC *query;
219         char *freemsg = NULL;
220
221         query = query_find(server, nick);
222
223         if (settings_get_bool("emphasis"))
224                 msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg);
225
226         printformat(server, nick, MSGLEVEL_MSGS,
227                     query == NULL ? TXT_MSG_PRIVATE :
228                     TXT_MSG_PRIVATE_QUERY, nick, address, msg);
229
230         g_free_not_null(freemsg);
231 }
232
233 static void print_own_channel_message(SERVER_REC *server, CHANNEL_REC *channel,
234                                       const char *target, const char *msg)
235 {
236         WINDOW_REC *window;
237         const char *nickmode;
238         char *freemsg = NULL;
239         int print_channel;
240
241         nickmode = channel_get_nickmode(channel, server->nick);
242
243         window = channel == NULL ? NULL :
244                 window_item_window((WI_ITEM_REC *) channel);
245
246         print_channel = window == NULL ||
247                 window->active != (WI_ITEM_REC *) channel;
248
249         if (!print_channel && settings_get_bool("print_active_channel") &&
250             window != NULL && g_slist_length(window->items) > 1)
251                 print_channel = TRUE;
252
253         if (settings_get_bool("emphasis"))
254                 msg = freemsg = expand_emphasis((WI_ITEM_REC *) channel, msg);
255
256         if (!print_channel) {
257                 printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
258                             TXT_OWN_MSG, server->nick, msg, nickmode);
259         } else {
260                 printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
261                             TXT_OWN_MSG_CHANNEL, server->nick, target, msg, nickmode);
262         }
263
264         g_free_not_null(freemsg);
265 }
266
267 static void sig_message_own_public(SERVER_REC *server, const char *msg,
268                                    const char *target)
269 {
270         CHANNEL_REC *channel;
271
272         g_return_if_fail(server != NULL);
273         g_return_if_fail(msg != NULL);
274
275         channel = channel_find(server, target);
276         print_own_channel_message(server, channel, target, msg);
277 }
278
279 static void sig_message_own_private(SERVER_REC *server, const char *msg,
280                                     const char *target, const char *origtarget)
281 {
282         QUERY_REC *query;
283         char *freemsg = NULL;
284
285         g_return_if_fail(server != NULL);
286         g_return_if_fail(msg != NULL);
287
288         if (target == NULL) {
289                 /* this should only happen if some special target failed and
290                    we should display some error message. currently the special
291                    targets are only ',' and '.'. */
292                 g_return_if_fail(strcmp(origtarget, ",") == 0 ||
293                                  strcmp(origtarget, ".") == 0);
294
295                 printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
296                             *origtarget == ',' ? TXT_NO_MSGS_GOT :
297                             TXT_NO_MSGS_SENT);
298                 signal_stop();
299                 return;
300         }
301
302         query = privmsg_get_query(server, target, TRUE, MSGLEVEL_MSGS);
303
304         if (settings_get_bool("emphasis"))
305                 msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg);
306
307         printformat(server, target,
308                     MSGLEVEL_MSGS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
309                     query == NULL ? TXT_OWN_MSG_PRIVATE :
310                     TXT_OWN_MSG_PRIVATE_QUERY, target, msg, server->nick);
311
312         g_free_not_null(freemsg);
313 }
314
315 static void sig_message_join(SERVER_REC *server, const char *channel,
316                              const char *nick, const char *address)
317 {
318         printformat(server, channel, MSGLEVEL_JOINS,
319                     TXT_JOIN, nick, address, channel);
320 }
321
322 static void sig_message_part(SERVER_REC *server, const char *channel,
323                              const char *nick, const char *address,
324                              const char *reason)
325 {
326         printformat(server, channel, MSGLEVEL_PARTS,
327                     TXT_PART, nick, address, channel, reason);
328 }
329
330 static void sig_message_quit(SERVER_REC *server, const char *nick,
331                              const char *address, const char *reason)
332 {
333         WINDOW_REC *window;
334         GString *chans;
335         GSList *tmp, *windows;
336         char *print_channel;
337         int once, count;
338
339         if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_QUITS))
340                 return;
341
342         print_channel = NULL;
343         once = settings_get_bool("show_quit_once");
344
345         count = 0; windows = NULL;
346         chans = g_string_new(NULL);
347         for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
348                 CHANNEL_REC *rec = tmp->data;
349
350                 if (!nicklist_find(rec, nick))
351                         continue;
352
353                 if (ignore_check(server, nick, address, rec->name,
354                                  reason, MSGLEVEL_QUITS)) {
355                         count++;
356                         continue;
357                 }
358
359                 if (print_channel == NULL ||
360                     active_win->active == (WI_ITEM_REC *) rec)
361                         print_channel = rec->name;
362
363                 if (once)
364                         g_string_sprintfa(chans, "%s,", rec->name);
365                 else {
366                         window = window_item_window((WI_ITEM_REC *) rec);
367                         if (g_slist_find(windows, window) == NULL) {
368                                 windows = g_slist_append(windows, window);
369                                 printformat(server, rec->name, MSGLEVEL_QUITS,
370                                             TXT_QUIT, nick, address, reason,
371                                             rec->name);
372                         }
373                 }
374                 count++;
375         }
376         g_slist_free(windows);
377
378         if (!once) {
379                 /* check if you had query with the nick and
380                    display the quit there too */
381                 QUERY_REC *query = query_find(server, nick);
382                 if (query != NULL) {
383                         printformat(server, nick, MSGLEVEL_QUITS,
384                                     TXT_QUIT, nick, address, reason, "");
385                 }
386         }
387
388         if (once || count == 0) {
389                 if (chans->len > 0)
390                         g_string_truncate(chans, chans->len-1);
391                 printformat(server, print_channel, MSGLEVEL_QUITS,
392                             count <= 1 ? TXT_QUIT : TXT_QUIT_ONCE,
393                             nick, address, reason, chans->str);
394         }
395         g_string_free(chans, TRUE);
396 }
397
398 static void sig_message_kick(SERVER_REC *server, const char *channel,
399                              const char *nick, const char *kicker,
400                              const char *address, const char *reason)
401 {
402         printformat(server, channel, MSGLEVEL_KICKS,
403                     TXT_KICK, nick, channel, kicker, reason);
404 }
405
406 static void print_nick_change_channel(SERVER_REC *server, const char *channel,
407                                       const char *newnick, const char *oldnick,
408                                       const char *address,
409                                       int ownnick)
410 {
411         if (ignore_check(server, oldnick, address,
412                          channel, newnick, MSGLEVEL_NICKS))
413                 return;
414
415         printformat(server, channel, MSGLEVEL_NICKS,
416                     ownnick ? TXT_YOUR_NICK_CHANGED : TXT_NICK_CHANGED,
417                     oldnick, newnick, channel);
418 }
419
420 static void print_nick_change(SERVER_REC *server, const char *newnick,
421                               const char *oldnick, const char *address,
422                               int ownnick)
423 {
424         GSList *tmp, *windows;
425         int msgprint;
426
427         msgprint = FALSE;
428
429         /* Print to each channel/query where the nick is.
430            Don't print more than once to the same window. */
431         windows = NULL;
432         for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
433                 CHANNEL_REC *channel = tmp->data;
434                 WINDOW_REC *window =
435                         window_item_window((WI_ITEM_REC *) channel);
436
437                 if (nicklist_find(channel, newnick) == NULL ||
438                     g_slist_find(windows, window) != NULL)
439                         continue;
440
441                 windows = g_slist_append(windows, window);
442                 print_nick_change_channel(server, channel->name, newnick,
443                                           oldnick, address, ownnick);
444                 msgprint = TRUE;
445         }
446
447         for (tmp = server->queries; tmp != NULL; tmp = tmp->next) {
448                 QUERY_REC *query = tmp->data;
449                 WINDOW_REC *window =
450                         window_item_window((WI_ITEM_REC *) query);
451
452                 if (g_strcasecmp(query->name, oldnick) != 0 ||
453                     g_slist_find(windows, window) != NULL)
454                         continue;
455
456                 windows = g_slist_append(windows, window);
457                 print_nick_change_channel(server, query->name, newnick,
458                                           oldnick, address, ownnick);
459                 msgprint = TRUE;
460         }
461         g_slist_free(windows);
462
463         if (!msgprint && ownnick) {
464                 printformat(server, NULL, MSGLEVEL_NICKS,
465                             TXT_YOUR_NICK_CHANGED, oldnick, newnick, "");
466         }
467 }
468
469 static void sig_message_nick(SERVER_REC *server, const char *newnick,
470                              const char *oldnick, const char *address)
471 {
472         print_nick_change(server, newnick, oldnick, address, FALSE);
473 }
474
475 static void sig_message_own_nick(SERVER_REC *server, const char *newnick,
476                                  const char *oldnick, const char *address)
477 {
478         print_nick_change(server, newnick, oldnick, address, TRUE);
479 }
480
481 static void sig_message_invite(SERVER_REC *server, const char *channel,
482                                const char *nick, const char *address)
483 {
484         char *str;
485
486         str = show_lowascii(channel);
487         printformat(server, NULL, MSGLEVEL_INVITES,
488                     TXT_INVITE, nick, str);
489         g_free(str);
490 }
491
492 static void sig_message_topic(SERVER_REC *server, const char *channel,
493                               const char *topic,
494                               const char *nick, const char *address)
495 {
496         printformat(server, channel, MSGLEVEL_TOPICS,
497                     *topic != '\0' ? TXT_NEW_TOPIC : TXT_TOPIC_UNSET,
498                     nick, channel, topic);
499 }
500
501 static int printnick_exists(NICK_REC *first, NICK_REC *ignore,
502                             const char *nick)
503 {
504         char *printnick;
505
506         while (first != NULL) {
507                 if (first != ignore) {
508                         printnick = g_hash_table_lookup(printnicks, first);
509                         if (printnick != NULL && strcmp(printnick, nick) == 0)
510                                 return TRUE;
511                 }
512
513                 first = first->next;
514         }
515
516         return FALSE;
517 }
518
519 static NICK_REC *printnick_find_original(NICK_REC *nick)
520 {
521         while (nick != NULL) {
522                 if (g_hash_table_lookup(printnicks, nick) == NULL)
523                         return nick;
524
525                 nick = nick->next;
526         }
527
528         return NULL;
529 }
530
531 static void sig_nicklist_new(CHANNEL_REC *channel, NICK_REC *nick)
532 {
533         NICK_REC *firstnick;
534         GString *newnick;
535         char *nickhost, *p;
536         int n;
537
538         if (nick->host == NULL)
539                 return;
540
541         firstnick = g_hash_table_lookup(channel->nicks, nick->nick);
542         if (firstnick->next == NULL)
543                 return;
544
545         if (nick == channel->ownnick) {
546                 /* own nick is being added, might be a nick change and
547                    someone else having the original nick already in use.. */
548                 nick = printnick_find_original(firstnick->next);
549                 if (nick == NULL)
550                         return; /* nope, we have it */
551         }
552
553         /* identical nick already exists, have to change it somehow.. */
554         p = strchr(nick->host, '@');
555         if (p == NULL) p = nick->host; else p++;
556
557         nickhost = g_strdup_printf("%s@%s", nick->nick, p);
558         p = strchr(nickhost+strlen(nick->nick), '.');
559         if (p != NULL) *p = '\0';
560
561         if (!printnick_exists(firstnick, nick, nickhost)) {
562                 /* use nick@host */
563                 g_hash_table_insert(printnicks, nick, nickhost);
564                 return;
565         }
566
567         newnick = g_string_new(NULL);
568         n = 2;
569         do {
570                 g_string_sprintf(newnick, "%s%d", nickhost, n);
571                 n++;
572         } while (printnick_exists(firstnick, nick, newnick->str));
573
574         g_hash_table_insert(printnicks, nick, newnick->str);
575         g_string_free(newnick, FALSE);
576         g_free(nickhost);
577 }
578
579 static void sig_nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick)
580 {
581         char *nickname;
582
583         nickname = g_hash_table_lookup(printnicks, nick);
584         if (nickname != NULL) {
585                 g_free(nickname);
586                 g_hash_table_remove(printnicks, nick);
587         }
588 }
589
590 static void sig_nicklist_changed(CHANNEL_REC *channel, NICK_REC *nick)
591 {
592         sig_nicklist_remove(channel, nick);
593         sig_nicklist_new(channel, nick);
594 }
595
596 static void sig_channel_joined(CHANNEL_REC *channel)
597 {
598         NICK_REC *nick;
599         char *nickname;
600
601         /* channel->ownnick is set at this point - check if our own nick
602            has been changed, if it was set it back to the original nick and
603            change the previous original to something else */
604
605         nickname = g_hash_table_lookup(printnicks, channel->ownnick);
606         if (nickname == NULL)
607                 return;
608
609         g_free(nickname);
610         g_hash_table_remove(printnicks, channel->ownnick);
611
612         /* our own nick is guaranteed to be the first in list */
613         nick = channel->ownnick->next;
614         while (nick != NULL) {
615                 if (g_hash_table_lookup(printnicks, nick) == NULL) {
616                         sig_nicklist_new(channel, nick);
617                         break;
618                 }
619                 nick = nick->next;
620         }
621 }
622
623 static void g_hash_free_value(void *key, void *value)
624 {
625         g_free(value);
626 }
627
628 void fe_messages_init(void)
629 {
630         printnicks = g_hash_table_new((GHashFunc) g_direct_hash,
631                                       (GCompareFunc) g_direct_equal);
632
633         settings_add_bool("lookandfeel", "emphasis", TRUE);
634         settings_add_bool("lookandfeel", "emphasis_replace", FALSE);
635         settings_add_bool("lookandfeel", "emphasis_multiword", FALSE);
636         settings_add_bool("lookandfeel", "show_nickmode", TRUE);
637         settings_add_bool("lookandfeel", "show_nickmode_empty", TRUE);
638         settings_add_bool("lookandfeel", "print_active_channel", FALSE);
639         settings_add_bool("lookandfeel", "show_quit_once", FALSE);
640
641         signal_add("message public", (SIGNAL_FUNC) sig_message_public);
642         signal_add("message private", (SIGNAL_FUNC) sig_message_private);
643         signal_add("message own_public", (SIGNAL_FUNC) sig_message_own_public);
644         signal_add("message own_private", (SIGNAL_FUNC) sig_message_own_private);
645         signal_add("message join", (SIGNAL_FUNC) sig_message_join);
646         signal_add("message part", (SIGNAL_FUNC) sig_message_part);
647         signal_add("message quit", (SIGNAL_FUNC) sig_message_quit);
648         signal_add("message kick", (SIGNAL_FUNC) sig_message_kick);
649         signal_add("message nick", (SIGNAL_FUNC) sig_message_nick);
650         signal_add("message own_nick", (SIGNAL_FUNC) sig_message_own_nick);
651         signal_add("message invite", (SIGNAL_FUNC) sig_message_invite);
652         signal_add("message topic", (SIGNAL_FUNC) sig_message_topic);
653
654         signal_add("nicklist new", (SIGNAL_FUNC) sig_nicklist_new);
655         signal_add("nicklist remove", (SIGNAL_FUNC) sig_nicklist_remove);
656         signal_add("nicklist changed", (SIGNAL_FUNC) sig_nicklist_changed);
657         signal_add("nicklist host changed", (SIGNAL_FUNC) sig_nicklist_new);
658         signal_add("channel joined", (SIGNAL_FUNC) sig_channel_joined);
659 }
660
661 void fe_messages_deinit(void)
662 {
663         g_hash_table_foreach(printnicks, (GHFunc) g_hash_free_value, NULL);
664         g_hash_table_destroy(printnicks);
665
666         signal_remove("message public", (SIGNAL_FUNC) sig_message_public);
667         signal_remove("message private", (SIGNAL_FUNC) sig_message_private);
668         signal_remove("message own_public", (SIGNAL_FUNC) sig_message_own_public);
669         signal_remove("message own_private", (SIGNAL_FUNC) sig_message_own_private);
670         signal_remove("message join", (SIGNAL_FUNC) sig_message_join);
671         signal_remove("message part", (SIGNAL_FUNC) sig_message_part);
672         signal_remove("message quit", (SIGNAL_FUNC) sig_message_quit);
673         signal_remove("message kick", (SIGNAL_FUNC) sig_message_kick);
674         signal_remove("message nick", (SIGNAL_FUNC) sig_message_nick);
675         signal_remove("message own_nick", (SIGNAL_FUNC) sig_message_own_nick);
676         signal_remove("message invite", (SIGNAL_FUNC) sig_message_invite);
677         signal_remove("message topic", (SIGNAL_FUNC) sig_message_topic);
678
679         signal_remove("nicklist new", (SIGNAL_FUNC) sig_nicklist_new);
680         signal_remove("nicklist remove", (SIGNAL_FUNC) sig_nicklist_remove);
681         signal_remove("nicklist changed", (SIGNAL_FUNC) sig_nicklist_changed);
682         signal_remove("nicklist host changed", (SIGNAL_FUNC) sig_nicklist_new);
683         signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined);
684 }