diff options
author | Timo Sirainen <cras@irssi.org> | 2000-04-26 08:03:38 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2000-04-26 08:03:38 +0000 |
commit | c95034c6de1bf72536595e1e3431d8ec64b9880e (patch) | |
tree | e51aa4528257ed8aa9d53640649519f299aaf0c7 /src/fe-common/irc | |
parent | d01b094151705d433bc43cae9eeb304e6f110a17 (diff) | |
download | irssi-c95034c6de1bf72536595e1e3431d8ec64b9880e.zip |
..adding new files..
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@171 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/fe-common/irc')
30 files changed, 4870 insertions, 0 deletions
diff --git a/src/fe-common/irc/Makefile.am b/src/fe-common/irc/Makefile.am new file mode 100644 index 00000000..440f14bd --- /dev/null +++ b/src/fe-common/irc/Makefile.am @@ -0,0 +1,32 @@ +SUBDIRS = dcc flood notifylist + +noinst_LTLIBRARIES = libfe_common_irc.la + +INCLUDES = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/core/ \ + -I$(top_srcdir)/src/irc/core/ \ + -I$(top_srcdir)/src/fe-common/core/ \ + -DHELPDIR=\""$(datadir)/irssi/help"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" + +libfe_common_irc_la_SOURCES = \ + completion.c \ + fe-channels.c \ + fe-irc-commands.c \ + fe-ctcp.c \ + fe-events.c \ + fe-events-numeric.c \ + fe-ignore.c \ + fe-query.c \ + fe-common-irc.c \ + irc-nick-hilight.c \ + irc-hilight-text.c \ + module-formats.c + +noinst_HEADERS = \ + completion.h \ + fe-common-irc.h \ + irc-hilight-text.h \ + module-formats.h diff --git a/src/fe-common/irc/completion.c b/src/fe-common/irc/completion.c new file mode 100644 index 00000000..444a3a06 --- /dev/null +++ b/src/fe-common/irc/completion.c @@ -0,0 +1,628 @@ +/* + completion.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "signals.h" +#include "commands.h" +#include "misc.h" +#include "lib-config/iconfig.h" +#include "settings.h" + +#include "irc.h" +#include "server.h" +#include "channels.h" +#include "nicklist.h" + +#include "completion.h" +#include "window-items.h" + +typedef struct { + time_t time; + char *nick; +} COMPLETION_REC; + +#define replace_find(replace) \ + iconfig_list_find("replaces", "text", replace, "replace") + +#define completion_find(completion) \ + iconfig_list_find("completions", "short", completion, "long") + +static gint comptag; +static GList *complist; + +static COMPLETION_REC *nick_completion_find(GSList *list, gchar *nick) +{ + GSList *tmp; + + for (tmp = list; tmp != NULL; tmp = tmp->next) + { + COMPLETION_REC *rec = tmp->data; + + if (g_strcasecmp(rec->nick, nick) == 0) return rec; + } + + return NULL; +} + +static void completion_destroy(GSList **list, COMPLETION_REC *rec) +{ + *list = g_slist_remove(*list, rec); + + g_free(rec->nick); + g_free(rec); +} + +static COMPLETION_REC *nick_completion_create(GSList **list, time_t time, gchar *nick) +{ + COMPLETION_REC *rec; + + rec = nick_completion_find(*list, nick); + if (rec != NULL) + { + /* remove the old one */ + completion_destroy(list, rec); + } + + rec = g_new(COMPLETION_REC, 1); + *list = g_slist_prepend(*list, rec); + + rec->time = time; + rec->nick = g_strdup(nick); + return rec; +} + +static void completion_checklist(GSList **list, gint timeout, time_t t) +{ + GSList *tmp, *next; + + for (tmp = *list; tmp != NULL; tmp = next) + { + COMPLETION_REC *rec = tmp->data; + + next = tmp->next; + if (t-rec->time > timeout) + completion_destroy(list, rec); + } +} + +static gint completion_timeout(void) +{ + GSList *tmp, *link; + time_t t; + gint len; + + t = time(NULL); + for (tmp = servers; tmp != NULL; tmp = tmp->next) + { + IRC_SERVER_REC *rec = tmp->data; + + len = g_slist_length(rec->lastmsgs); + if (len > 0 && len >= settings_get_int("completion_keep_privates")) + { + link = g_slist_last(rec->lastmsgs); + g_free(link->data); + rec->lastmsgs = g_slist_remove_link(rec->lastmsgs, link); + g_slist_free_1(link); + } + } + + for (tmp = channels; tmp != NULL; tmp = tmp->next) + { + CHANNEL_REC *rec = tmp->data; + + completion_checklist(&rec->lastownmsgs, settings_get_int("completion_keep_ownpublics"), t); + completion_checklist(&rec->lastmsgs, settings_get_int("completion_keep_publics"), t); + } + + return 1; +} + +static void add_private_msg(IRC_SERVER_REC *server, gchar *nick) +{ + GSList *link; + + link = gslist_find_icase_string(server->lastmsgs, nick); + if (link != NULL) + { + g_free(link->data); + server->lastmsgs = g_slist_remove_link(server->lastmsgs, link); + g_slist_free_1(link); + } + server->lastmsgs = g_slist_prepend(server->lastmsgs, g_strdup(nick)); +} + +static void event_privmsg(gchar *data, IRC_SERVER_REC *server, gchar *nick) +{ + gchar *params, *target, *msg; + GSList **list; + + g_return_if_fail(server != NULL); + if (nick == NULL) return; /* from server */ + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + + if (*msg == 1) + { + /* ignore ctcp messages */ + g_free(params); + return; + } + + if (ischannel(*target)) + { + /* channel message */ + CHANNEL_REC *channel; + + channel = channel_find(server, target); + if (channel == NULL) + { + g_free(params); + return; + } + + list = completion_msgtoyou((SERVER_REC *) server, msg) ? + &channel->lastownmsgs : + &channel->lastmsgs; + nick_completion_create(list, time(NULL), nick); + } + else + { + /* private message */ + add_private_msg(server, nick); + } + + g_free(params); +} + +static void cmd_msg(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *target, *msg; + + g_return_if_fail(data != NULL); + + params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (*target != '\0' && *msg != '\0') + { + if (!ischannel(*target) && *target != '=' && server != NULL) + add_private_msg(server, target); + } + + g_free(params); +} + +int completion_msgtoyou(SERVER_REC *server, const char *msg) +{ + gchar *stripped, *nick; + gboolean ret; + gint len; + + g_return_val_if_fail(msg != NULL, FALSE); + + if (g_strncasecmp(msg, server->nick, strlen(server->nick)) == 0 && + !isalnum((gint) msg[strlen(server->nick)])) return TRUE; + + stripped = nick_strip(server->nick); + nick = nick_strip(msg); + + len = strlen(stripped); + ret = *stripped != '\0' && + g_strncasecmp(nick, stripped, len) == 0 && + !isalnum((gint) nick[len]) && + (guchar) nick[len] < 128; + + g_free(nick); + g_free(stripped); + return ret; +} + +static void complete_list(GList **outlist, GSList *list, gchar *nick) +{ + GSList *tmp; + gint len; + + len = strlen(nick); + for (tmp = list; tmp != NULL; tmp = tmp->next) + { + COMPLETION_REC *rec = tmp->data; + + if (g_strncasecmp(rec->nick, nick, len) == 0 && + glist_find_icase_string(*outlist, rec->nick) == NULL) + *outlist = g_list_append(*outlist, g_strdup(rec->nick)); + } +} + +static GList *completion_getlist(CHANNEL_REC *channel, gchar *nick) +{ + GSList *nicks, *tmp; + GList *list; + gint len; + + g_return_val_if_fail(channel != NULL, NULL); + g_return_val_if_fail(nick != NULL, NULL); + if (*nick == '\0') return NULL; + + list = NULL; + complete_list(&list, channel->lastownmsgs, nick); + complete_list(&list, channel->lastmsgs, nick); + + len = strlen(nick); + nicks = nicklist_getnicks(channel); + for (tmp = nicks; tmp != NULL; tmp = tmp->next) + { + NICK_REC *rec = tmp->data; + + if (g_strncasecmp(rec->nick, nick, len) == 0 && + glist_find_icase_string(list, rec->nick) == NULL && + g_strcasecmp(rec->nick, channel->server->nick) != 0) + list = g_list_append(list, g_strdup(rec->nick)); + } + g_slist_free(nicks); + + return list; +} + +static GList *completion_getmsglist(IRC_SERVER_REC *server, gchar *nick) +{ + GSList *tmp; + GList *list; + gint len; + + list = NULL; len = strlen(nick); + for (tmp = server->lastmsgs; tmp != NULL; tmp = tmp->next) + { + if (len == 0 || g_strncasecmp(tmp->data, nick, len) == 0) + list = g_list_append(list, g_strdup(tmp->data)); + } + + return list; +} + +static void event_command(gchar *line, IRC_SERVER_REC *server, WI_IRC_REC *item) +{ + CHANNEL_REC *channel; + GList *comp; + gchar *str, *ptr; + + g_return_if_fail(line != NULL); + + if (!irc_item_check(item)) + return; + + if (strchr(settings_get_str("cmdchars"), *line) != NULL) + return; + + line = g_strdup(line); + + /* check for nick completion */ + if (settings_get_bool("completion_disable_auto") || *settings_get_str("completion_char") == '\0') + { + ptr = NULL; + comp = NULL; + } + else + { + ptr = strchr(line, *settings_get_str("completion_char")); + if (ptr != NULL) *ptr++ = '\0'; + + channel = irc_item_channel(item); + + comp = ptr == NULL || channel == NULL || + nicklist_find(channel, line) != NULL ? NULL : + completion_getlist(channel, line); + } + + /* message to channel */ + if (ptr == NULL) + str = g_strdup_printf("%s %s", item->name, line); + else + { + str = g_strdup_printf("%s %s%s%s", item->name, + comp != NULL ? (gchar *) comp->data : line, + settings_get_str("completion_char"), ptr); + } + signal_emit("command msg", 3, str, server, item); + + g_free(str); + g_free(line); + + if (comp != NULL) + { + g_list_foreach(comp, (GFunc) g_free, NULL); + g_list_free(comp); + } + + signal_stop(); +} + +static GList *completion_joinlist(GList *list1, GList *list2) +{ + while (list2 != NULL) + { + if (!glist_find_icase_string(list1, list2->data)) + list1 = g_list_append(list1, list2->data); + else + g_free(list2->data); + + list2 = list2->next; + } + g_list_free(list2); + return list1; +} + +char *auto_completion(const char *line, int *pos) +{ + const char *replace; + gchar *word, *ret; + gint spos, epos, n, wordpos; + GString *result; + + g_return_val_if_fail(line != NULL, NULL); + g_return_val_if_fail(pos != NULL, NULL); + + spos = *pos; + + /* get the word we are completing.. */ + while (spos > 0 && isspace((gint) line[spos-1])) spos--; + epos = spos; + while (spos > 0 && !isspace((gint) line[spos-1])) spos--; + while (line[epos] != '\0' && !isspace((gint) line[epos])) epos++; + + word = g_strdup(line+spos); + word[epos-spos] = '\0'; + + /* word position in line */ + wordpos = 0; + for (n = 0; n < spos; ) + { + while (n < spos && isspace((gint) line[n])) n++; + while (n < spos && !isspace((gint) line[n])) n++; + if (n < spos) wordpos++; + } + + result = g_string_new(line); + g_string_erase(result, spos, epos-spos); + + /* check for words in autocompletion list */ + replace = replace_find(word); g_free(word); + if (replace != NULL) + { + *pos = spos+strlen(replace); + + g_string_insert(result, spos, replace); + ret = result->str; + g_string_free(result, FALSE); + return ret; + } + + g_string_free(result, TRUE); + return NULL; +} + +#define issplit(a) ((a) == ',' || (a) == ' ') + +char *completion_line(WINDOW_REC *window, const char *line, int *pos) +{ + static gboolean msgcomp = FALSE; + const char *completion; + CHANNEL_REC *channel; + SERVER_REC *server; + gchar *word, *ret; + gint spos, epos, len, n, wordpos; + gboolean msgcompletion; + GString *result; + + g_return_val_if_fail(window != NULL, NULL); + g_return_val_if_fail(line != NULL, NULL); + g_return_val_if_fail(pos != NULL, NULL); + + spos = *pos; + + /* get the word we are completing.. */ + while (spos > 0 && issplit((gint) line[spos-1])) spos--; + epos = spos; + if (line[epos] == ',') epos++; + while (spos > 0 && !issplit((gint) line[spos-1])) spos--; + while (line[epos] != '\0' && !issplit((gint) line[epos])) epos++; + + word = g_strdup(line+spos); + word[epos-spos] = '\0'; + + /* word position in line */ + wordpos = 0; + for (n = 0; n < spos; ) + { + while (n < spos && issplit((gint) line[n])) n++; + while (n < spos && !issplit((gint) line[n])) n++; + if (n < spos) wordpos++; + } + + server = window->active == NULL ? window->active_server : window->active->server; + msgcompletion = server != NULL && + (*line == '\0' || ((wordpos == 0 || wordpos == 1) && g_strncasecmp(line, "/msg ", 5) == 0)); + + if (msgcompletion && wordpos == 0 && issplit((gint) line[epos])) + { + /* /msg <tab> */ + *word = '\0'; epos++; spos = epos; wordpos = 1; + } + + /* are we completing the same nick as last time? + if not, forget the old completion.. */ + len = strlen(word)-(msgcomp == FALSE && word[strlen(word)-1] == *settings_get_str("completion_char")); + if (complist != NULL && (strlen(complist->data) != len || g_strncasecmp(complist->data, word, len) != 0)) + { + g_list_foreach(complist, (GFunc) g_free, NULL); + g_list_free(complist); + + complist = NULL; + } + + result = g_string_new(line); + g_string_erase(result, spos, epos-spos); + + /* check for words in completion list */ + completion = completion_find(word); + if (completion != NULL) + { + g_free(word); + *pos = spos+strlen(completion); + + g_string_insert(result, spos, completion); + ret = result->str; + g_string_free(result, FALSE); + return ret; + } + + channel = irc_item_channel(window->active); + if (complist == NULL && !msgcompletion && channel == NULL) + { + /* don't try nick completion */ + g_free(word); + g_string_free(result, TRUE); + return NULL; + } + + if (complist == NULL) + { + /* start new nick completion */ + complist = channel == NULL ? NULL : completion_getlist(channel, word); + + if (!msgcompletion) + { + /* nick completion in channel */ + msgcomp = FALSE; + } + else + { + GList *tmpcomp; + + /* /msg completion */ + msgcomp = TRUE; + + /* first get the list of msg nicks and then nicks from current + channel. */ + tmpcomp = complist; + complist = completion_getmsglist((IRC_SERVER_REC *) server, word); + complist = completion_joinlist(complist, tmpcomp); + if (*line == '\0') + { + /* completion in empty line -> /msg <nick> */ + g_free(word); + g_string_free(result, TRUE); + + if (complist == NULL) + ret = g_strdup("/msg "); + else + ret = g_strdup_printf("/msg %s ", (gchar *) complist->data); + *pos = strlen(ret); + return ret; + } + } + + if (complist == NULL) + { + g_free(word); + g_string_free(result, TRUE); + return NULL; + } + } + else + { + /* continue the last completion */ + complist = complist->next == NULL ? g_list_first(complist) : complist->next; + } + g_free(word); + + /* insert the nick.. */ + g_string_insert(result, spos, complist->data); + *pos = spos+strlen(complist->data); + + if (!msgcomp && wordpos == 0) + { + /* insert completion character */ + g_string_insert(result, *pos, settings_get_str("completion_char")); + *pos += strlen(settings_get_str("completion_char")); + } + if (msgcomp || wordpos == 0) + { + if (!issplit((gint) result->str[*pos])) + { + /* insert space */ + g_string_insert(result, *pos, " "); + } + (*pos)++; + } + + ret = result->str; + g_string_free(result, FALSE); + return ret; +} + +static void completion_deinit_server(IRC_SERVER_REC *server) +{ + g_return_if_fail(server != NULL); + + g_slist_foreach(server->lastmsgs, (GFunc) g_free, NULL); + g_slist_free(server->lastmsgs); +} + +static void completion_deinit_channel(CHANNEL_REC *channel) +{ + g_return_if_fail(channel != NULL); + + while (channel->lastmsgs != NULL) + completion_destroy(&channel->lastmsgs, channel->lastmsgs->data); + while (channel->lastownmsgs != NULL) + completion_destroy(&channel->lastownmsgs, channel->lastownmsgs->data); + g_slist_free(channel->lastmsgs); + g_slist_free(channel->lastownmsgs); +} + +void completion_init(void) +{ + settings_add_str("completion", "completion_char", ":"); + settings_add_bool("completion", "completion_disable_auto", FALSE); + settings_add_int("completion", "completion_keep_publics", 180); + settings_add_int("completion", "completion_keep_ownpublics", 360); + settings_add_int("completion", "completion_keep_privates", 10); + + signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_add("send command", (SIGNAL_FUNC) event_command); + signal_add("server disconnected", (SIGNAL_FUNC) completion_deinit_server); + signal_add("channel destroyed", (SIGNAL_FUNC) completion_deinit_channel); + command_bind("msg", NULL, (SIGNAL_FUNC) cmd_msg); + + comptag = g_timeout_add(1000, (GSourceFunc) completion_timeout, NULL); + complist = NULL; +} + +void completion_deinit(void) +{ + g_list_foreach(complist, (GFunc) g_free, NULL); + g_list_free(complist); + + g_source_remove(comptag); + + signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_remove("send command", (SIGNAL_FUNC) event_command); + signal_remove("server disconnected", (SIGNAL_FUNC) completion_deinit_server); + signal_remove("channel destroyed", (SIGNAL_FUNC) completion_deinit_channel); + command_unbind("msg", (SIGNAL_FUNC) cmd_msg); +} diff --git a/src/fe-common/irc/completion.h b/src/fe-common/irc/completion.h new file mode 100644 index 00000000..3ecb0339 --- /dev/null +++ b/src/fe-common/irc/completion.h @@ -0,0 +1,13 @@ +#ifndef __COMPLETION_H +#define __COMPLETION_H + +#include "window-items.h" + +int completion_msgtoyou(SERVER_REC *server, const char *msg); +char *completion_line(WINDOW_REC *window, const char *line, int *pos); +char *auto_completion(const char *line, int *pos); + +void completion_init(void); +void completion_deinit(void); + +#endif diff --git a/src/fe-common/irc/dcc/Makefile.am b/src/fe-common/irc/dcc/Makefile.am new file mode 100644 index 00000000..0424c7b2 --- /dev/null +++ b/src/fe-common/irc/dcc/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libfe_common_irc_dcc.la + +INCLUDES = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/core/ \ + -I$(top_srcdir)/src/irc/core/ \ + -I$(top_srcdir)/src/fe-common/core/ \ + -DHELPDIR=\""$(datadir)/irssi/help"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" + +libfe_common_irc_dcc_la_SOURCES = \ + fe-dcc.c \ + module-formats.c + +noinst_HEADERS = \ + module-formats.h diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c new file mode 100644 index 00000000..d798b0a3 --- /dev/null +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -0,0 +1,457 @@ +/* + fe-dcc.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "commands.h" +#include "network.h" + +#include "levels.h" +#include "irc.h" +#include "channels.h" + +#include "irc/dcc/dcc.h" + +#include "windows.h" + +static void dcc_connected(DCC_REC *dcc) +{ + gchar *str; + + g_return_if_fail(dcc != NULL); + + switch (dcc->dcc_type) + { + case DCC_TYPE_CHAT: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_CONNECTED, + dcc->nick, dcc->addrstr, dcc->port); + + str = g_strconcat("=", dcc->nick, NULL); + /*FIXME: dcc_chat_create(dcc->server, str, FALSE);*/ + g_free(str); + break; + case DCC_TYPE_SEND: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_CONNECTED, + dcc->arg, dcc->nick, dcc->addrstr, dcc->port); + break; + case DCC_TYPE_GET: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_CONNECTED, + dcc->arg, dcc->nick, dcc->addrstr, dcc->port); + break; + } +} + +static void dcc_rejected(DCC_REC *dcc) +{ + g_return_if_fail(dcc != NULL); + + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CLOSE, + dcc_type2str(dcc->dcc_type), dcc->nick, dcc->arg); +} + +static void dcc_closed(DCC_REC *dcc) +{ + time_t secs; + gdouble kbs; + + g_return_if_fail(dcc != NULL); + + secs = dcc->starttime == 0 ? -1 : time(NULL)-dcc->starttime; + kbs = (gdouble) (dcc->transfd-dcc->skipped) / (secs == 0 ? 1 : secs) / 1024.0; + + switch (dcc->dcc_type) + { + case DCC_TYPE_CHAT: + { + /* nice kludge :) if connection was lost, close the channel. + after closed channel (can be done with /unquery too) + prints the disconnected-text.. */ + CHANNEL_REC *channel; + gchar *str; + + str = g_strdup_printf("=%s", dcc->nick); + printformat(dcc->server, str, MSGLEVEL_DCC, + IRCTXT_DCC_CHAT_DISCONNECTED, dcc->nick); + + channel = channel_find(dcc->server, str); + if (channel != NULL) + channel_destroy(channel); + g_free(str); + } + break; + case DCC_TYPE_SEND: + if (secs == -1) + { + /* aborted */ + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_ABORTED, + dcc->arg, dcc->nick); + } + else + { + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_COMPLETE, + dcc->arg, dcc->transfd/1024, dcc->nick, (glong) secs, kbs); + } + break; + case DCC_TYPE_GET: + if (secs == -1) + { + /* aborted */ + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_ABORTED, + dcc->arg, dcc->nick); + } + else + { + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_COMPLETE, + dcc->arg, dcc->transfd/1024, dcc->nick, (glong) secs, kbs); + } + break; + } +} + +static void dcc_chat_in_action(gchar *msg, DCC_REC *dcc) +{ + gchar *sender; + + g_return_if_fail(dcc != NULL); + g_return_if_fail(msg != NULL); + + sender = g_strconcat("=", dcc->nick, NULL); + printformat(NULL, sender, MSGLEVEL_DCC, + IRCTXT_ACTION_DCC, dcc->nick, msg); + g_free(sender); +} + +static void dcc_chat_ctcp(gchar *msg, DCC_REC *dcc) +{ + gchar *sender; + + g_return_if_fail(dcc != NULL); + g_return_if_fail(msg != NULL); + + sender = g_strconcat("=", dcc->nick, NULL); + printformat(NULL, sender, MSGLEVEL_DCC, IRCTXT_DCC_CTCP, dcc->nick, msg); + g_free(sender); +} + +static void dcc_chat_msg(DCC_REC *dcc, gchar *msg) +{ + gchar *nick; + + g_return_if_fail(dcc != NULL); + g_return_if_fail(msg != NULL); + + nick = g_strconcat("=", dcc->nick, NULL); + printformat(NULL, nick, MSGLEVEL_DCC, IRCTXT_DCC_MSG, dcc->nick, msg); + g_free(nick); +} + +static void dcc_request(DCC_REC *dcc) +{ + g_return_if_fail(dcc != NULL); + + switch (dcc->dcc_type) + { + case DCC_TYPE_CHAT: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT, + dcc->nick, dcc->addrstr, dcc->port); + break; + case DCC_TYPE_GET: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND, + dcc->nick, dcc->addrstr, dcc->port, dcc->arg, dcc->size); + break; + } +} + +static void dcc_error_connect(DCC_REC *dcc) +{ + g_return_if_fail(dcc != NULL); + + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CONNECT_ERROR, dcc->addrstr, dcc->port); +} + +static void dcc_error_file_create(DCC_REC *dcc, gchar *fname) +{ + g_return_if_fail(dcc != NULL); + + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CANT_CREATE, fname); +} + +static void dcc_error_file_not_found(gchar *nick, gchar *fname) +{ + g_return_if_fail(nick != NULL); + g_return_if_fail(fname != NULL); + + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_FILE_NOT_FOUND, fname); +} + +static void dcc_error_get_not_found(gchar *nick) +{ + g_return_if_fail(nick != NULL); + + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_NOT_FOUND, nick); +} + +static void dcc_error_send_exists(gchar *nick, gchar *fname) +{ + g_return_if_fail(nick != NULL); + g_return_if_fail(fname != NULL); + + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_EXISTS, fname, nick); +} + +static void dcc_error_unknown_type(gchar *type) +{ + g_return_if_fail(type != NULL); + + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_TYPE, type); +} + +static void dcc_error_close_not_found(gchar *type, gchar *nick, gchar *fname) +{ + g_return_if_fail(type != NULL); + g_return_if_fail(nick != NULL); + g_return_if_fail(fname != NULL); + + if (fname == '\0') fname = "(ANY)"; + switch (dcc_str2type(type)) + { + case DCC_TYPE_CHAT: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_NOT_FOUND, nick); + break; + case DCC_TYPE_SEND: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_NOT_FOUND, nick, fname); + break; + case DCC_TYPE_GET: + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_NOT_FOUND, nick, fname); + break; + } +} + +static void dcc_unknown_ctcp(gchar *data, gchar *sender) +{ + gchar *params, *type, *args; + + g_return_if_fail(data != NULL); + + params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args); + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_CTCP, type, sender, args); + g_free(params); +} + +static void dcc_unknown_reply(gchar *data, gchar *sender) +{ + gchar *params, *type, *args; + + g_return_if_fail(data != NULL); + + params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args); + printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_REPLY, type, sender, args); + g_free(params); +} + +static void dcc_chat_write(gchar *data) +{ + DCC_REC *dcc; + gchar *params, *text, *target; + + g_return_if_fail(data != NULL); + + params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text); + + if (*target == '=') + { + /* dcc msg */ + dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL); + if (dcc == NULL) + { + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, + IRCTXT_DCC_CHAT_NOT_FOUND, target+1); + return; + } + + printformat(NULL, target, MSGLEVEL_DCC, IRCTXT_OWN_DCC, target+1, text); + } + + g_free(params); +} + +static void dcc_chat_out_me(gchar *data, SERVER_REC *server, WI_IRC_REC *item) +{ + DCC_REC *dcc; + + g_return_if_fail(data != NULL); + + dcc = irc_item_dcc_chat(item); + if (dcc == NULL) return; + + printformat(NULL, item->name, MSGLEVEL_DCC, + IRCTXT_OWN_ME, dcc->mynick, data); +} + +static void dcc_chat_out_action(const char *data, SERVER_REC *server, WI_IRC_REC *item) +{ + char *params, *target, *text; + DCC_REC *dcc; + + g_return_if_fail(data != NULL); + + if (*data != '=') { + /* handle only DCC actions */ + return; + } + + params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text); + if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL); + if (dcc == NULL){ + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, + IRCTXT_DCC_CHAT_NOT_FOUND, target+1); + } else { + printformat(NULL, item->name, MSGLEVEL_DCC, + IRCTXT_OWN_ME, dcc->mynick, text); + } + g_free(params); +} + +static void dcc_chat_out_ctcp(gchar *data, SERVER_REC *server) +{ + char *params, *target, *ctcpcmd, *ctcpdata; + DCC_REC *dcc; + + g_return_if_fail(data != NULL); + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + + params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + if (*target != '=') { + /* handle only DCC CTCPs */ + g_free(params); + return; + } + + dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL); + if (dcc == NULL) { + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, + IRCTXT_DCC_CHAT_NOT_FOUND, target+1); + } else { + g_strup(ctcpcmd); + printformat(server, target, MSGLEVEL_DCC, IRCTXT_OWN_CTCP, + target, ctcpcmd, ctcpdata); + } + + g_free(params); +} + +static void cmd_dcc_list(gchar *data) +{ + GSList *tmp; + time_t going; + + g_return_if_fail(data != NULL); + + printtext(NULL, NULL, MSGLEVEL_DCC, "%gDCC connections"); + for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) + { + DCC_REC *dcc = tmp->data; + + going = time(NULL) - dcc->starttime; + if (going == 0) going = 1; /* no division by zeros :) */ + + if (dcc->dcc_type == DCC_TYPE_CHAT) + printtext(NULL, NULL, MSGLEVEL_DCC, "%g %s %s", dcc->nick, dcc_type2str(dcc->dcc_type)); + else + printtext(NULL, NULL, MSGLEVEL_DCC, "%g %s %s: %luk of %luk (%d%%) - %fkB/s - %s", + dcc->nick, dcc_type2str(dcc->dcc_type), dcc->transfd/1024, dcc->size/1024, + dcc->size == 0 ? 0 : (100*dcc->transfd/dcc->size), + (gdouble) (dcc->transfd-dcc->skipped)/going/1024, dcc->arg); + } +} + +static void dcc_chat_closed(WINDOW_REC *window, WI_IRC_REC *item) +{ + DCC_REC *dcc; + + dcc = irc_item_dcc_chat(item); + if (dcc == NULL) return; + + /* check that we haven't got here from dcc_destroy() so we won't try to + close the dcc again.. */ + if (!dcc->destroyed) { + /* DCC query window closed, close the dcc chat too. */ + dcc_destroy(dcc); + } +} + +void fe_dcc_init(void) +{ + signal_add("dcc connected", (SIGNAL_FUNC) dcc_connected); + signal_add("dcc rejected", (SIGNAL_FUNC) dcc_rejected); + signal_add("dcc closed", (SIGNAL_FUNC) dcc_closed); + signal_add("dcc chat message", (SIGNAL_FUNC) dcc_chat_msg); + signal_add("dcc ctcp action", (SIGNAL_FUNC) dcc_chat_in_action); + signal_add("default dcc ctcp", (SIGNAL_FUNC) dcc_chat_ctcp); + signal_add("dcc request", (SIGNAL_FUNC) dcc_request); + signal_add("dcc error connect", (SIGNAL_FUNC) dcc_error_connect); + signal_add("dcc error file create", (SIGNAL_FUNC) dcc_error_file_create); + signal_add("dcc error file not found", (SIGNAL_FUNC) dcc_error_file_not_found); + signal_add("dcc error get not found", (SIGNAL_FUNC) dcc_error_get_not_found); + signal_add("dcc error send exists", (SIGNAL_FUNC) dcc_error_send_exists); + signal_add("dcc error unknown type", (SIGNAL_FUNC) dcc_error_unknown_type); + signal_add("dcc error close not found", (SIGNAL_FUNC) dcc_error_close_not_found); + signal_add("dcc unknown ctcp", (SIGNAL_FUNC) dcc_unknown_ctcp); + signal_add("dcc unknown reply", (SIGNAL_FUNC) dcc_unknown_reply); + command_bind("msg", NULL, (SIGNAL_FUNC) dcc_chat_write); + command_bind("me", NULL, (SIGNAL_FUNC) dcc_chat_out_me); + command_bind("action", NULL, (SIGNAL_FUNC) dcc_chat_out_action); + command_bind("ctcp", NULL, (SIGNAL_FUNC) dcc_chat_out_ctcp); + command_bind("dcc ", NULL, (SIGNAL_FUNC) cmd_dcc_list); + command_bind("dcc list", NULL, (SIGNAL_FUNC) cmd_dcc_list); + signal_add("window item remove", (SIGNAL_FUNC) dcc_chat_closed); +} + +void fe_dcc_deinit(void) +{ + signal_remove("dcc connected", (SIGNAL_FUNC) dcc_connected); + signal_remove("dcc rejected", (SIGNAL_FUNC) dcc_rejected); + signal_remove("dcc closed", (SIGNAL_FUNC) dcc_closed); + signal_remove("dcc chat message", (SIGNAL_FUNC) dcc_chat_msg); + signal_remove("dcc ctcp action", (SIGNAL_FUNC) dcc_chat_in_action); + signal_remove("default dcc ctcp", (SIGNAL_FUNC) dcc_chat_ctcp); + signal_remove("dcc request", (SIGNAL_FUNC) dcc_request); + signal_remove("dcc error connect", (SIGNAL_FUNC) dcc_error_connect); + signal_remove("dcc error file create", (SIGNAL_FUNC) dcc_error_file_create); + signal_remove("dcc error file not found", (SIGNAL_FUNC) dcc_error_file_not_found); + signal_remove("dcc error get not found", (SIGNAL_FUNC) dcc_error_get_not_found); + signal_remove("dcc error send exists", (SIGNAL_FUNC) dcc_error_send_exists); + signal_remove("dcc error unknown type", (SIGNAL_FUNC) dcc_error_unknown_type); + signal_remove("dcc error close not found", (SIGNAL_FUNC) dcc_error_close_not_found); + signal_remove("dcc unknown ctcp", (SIGNAL_FUNC) dcc_unknown_ctcp); + signal_remove("dcc unknown reply", (SIGNAL_FUNC) dcc_unknown_reply); + command_unbind("msg", (SIGNAL_FUNC) dcc_chat_write); + command_unbind("me", (SIGNAL_FUNC) dcc_chat_out_me); + command_unbind("action", (SIGNAL_FUNC) dcc_chat_out_action); + command_unbind("ctcp", (SIGNAL_FUNC) dcc_chat_out_ctcp); + command_unbind("dcc ", (SIGNAL_FUNC) cmd_dcc_list); + command_unbind("dcc list", (SIGNAL_FUNC) cmd_dcc_list); + signal_remove("window item remove", (SIGNAL_FUNC) dcc_chat_closed); +} diff --git a/src/fe-common/irc/dcc/module-formats.c b/src/fe-common/irc/dcc/module-formats.c new file mode 100644 index 00000000..d26fbf49 --- /dev/null +++ b/src/fe-common/irc/dcc/module-formats.c @@ -0,0 +1,57 @@ +/* + module-formats.c : irssi + + Copyright (C) 2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "printtext.h" + +FORMAT_REC fecommon_irc_dcc_formats[] = +{ + { MODULE_NAME, N_("IRC"), 0 }, + + /* ---- */ + { NULL, N_("DCC"), 0 }, + + { "own_dcc", N_("%K[%rdcc%K(%R$0%K)]%n $1"), 2, { 0, 0 } }, + { "dcc_msg", N_("%K[%G$0%K(%gdcc%K)]%n $1"), 2, { 0, 0 } }, + { "action_dcc", N_("%W (*dcc*) $0%n $1"), 2, { 0, 0 } }, + { "dcc_ctcp", N_("%g>>> DCC CTCP received from %_$0%_%K: %g$1"), 2, { 0, 0 } }, + { "dcc_chat", N_("%gDCC CHAT from %_$0%_ %K[%g$1 port $2%K]"), 3, { 0, 0, 1 } }, + { "dcc_chat_not_found", N_("%gNo DCC CHAT connection open to %_$0"), 1, { 0 } }, + { "dcc_chat_connected", N_("%gDCC %_CHAT%_ connection with %_$0%_ %K%K[%g$1 port $2%K]%g established"), 3, { 0, 0, 1 } }, + { "dcc_chat_disconnected", N_("%gDCC lost chat to %_$0"), 1, { 0 } }, + { "dcc_send", N_("%gDCC SEND from %_$0%_ %K[%g$1 port $2%K]: %g$3 %K[%g$4 bytes%K]"), 5, { 0, 0, 1, 0, 2 } }, + { "dcc_send_exists", N_("%gDCC already sending file %G$0%g for %_$1%_"), 2, { 0, 0 } }, + { "dcc_send_not_found", N_("%gDCC not sending file %G$1%g to %_$0"), 2, { 0, 0 } }, + { "dcc_send_file_not_found", N_("%gDCC file not found: %G$0%g"), 1, { 0 } }, + { "dcc_send_connected", N_("%gDCC sending file %G$0%g for %_$1%_ %K[%g$2 port $3%K]"), 4, { 0, 0, 0, 1 } }, + { "dcc_send_complete", N_("%gDCC sent file $0 %K[%g%_$1%_kb%K]%g for %_$2%_ in %_$3%_ secs %K[%g%_$4kb/s%_%K]"), 5, { 0, 2, 0, 2, 3 } }, + { "dcc_send_aborted", N_("%gDCC aborted sending file $0 for %_$1%_"), 2, { 0, 0 } }, + { "dcc_get_not_found", N_("%gDCC no file offered by %_$0"), 1, { 0 } }, + { "dcc_get_connected", N_("%gDCC receiving file %G$0%g from %_$1%_ %K[%g$2 port $3%K]"), 4, { 0, 0, 0, 1 } }, + { "dcc_get_complete", N_("%gDCC received file %G$0%g %K[%g$1kb%K]%g from %_$2%_ in %_$3%_ secs %K[%g$4kb/s%K]"), 5, { 0, 2, 0, 2, 3 } }, + { "dcc_get_aborted", N_("%gDCC aborted receiving file $0 from %_$1%_"), 2, { 0, 0 } }, + { "dcc_unknown_ctcp", N_("%gDCC unknown ctcp %G$0%g from %_$1%_ %K[%g$2%K]"), 3, { 0, 0, 0 } }, + { "dcc_unknown_reply", N_("%gDCC unknown reply %G$0%g from %_$1%_ %K[%g$2%K]"), 3, { 0, 0, 0 } }, + { "dcc_unknown_type", N_("%gDCC unknown type %_$0"), 1, { 0 } }, + { "dcc_connect_error", N_("%gDCC can't connect to %_$0%_ port %_$1"), 2, { 0, 1 } }, + { "dcc_cant_create", N_("%gDCC can't create file %G$0%g"), 1, { 0 } }, + { "dcc_rejected", N_("%gDCC %G$0%g was rejected by %_$1%_ %K[%G$2%K]"), 3, { 0, 0, 0 } }, + { "dcc_close", N_("%gDCC %G$0%g close for %_$1%_ %K[%G$2%K]"), 3, { 0, 0, 0 } } +}; diff --git a/src/fe-common/irc/dcc/module-formats.h b/src/fe-common/irc/dcc/module-formats.h new file mode 100644 index 00000000..ef0459db --- /dev/null +++ b/src/fe-common/irc/dcc/module-formats.h @@ -0,0 +1,37 @@ +#include "printtext.h" + +enum { + IRCTXT_MODULE_NAME, + + IRCTXT_FILL_1, + + IRCTXT_OWN_DCC, + IRCTXT_DCC_MSG, + IRCTXT_ACTION_DCC, + IRCTXT_DCC_CTCP, + IRCTXT_DCC_CHAT, + IRCTXT_DCC_CHAT_NOT_FOUND, + IRCTXT_DCC_CHAT_CONNECTED, + IRCTXT_DCC_CHAT_DISCONNECTED, + IRCTXT_DCC_SEND, + IRCTXT_DCC_SEND_EXISTS, + IRCTXT_DCC_SEND_NOT_FOUND, + IRCTXT_DCC_SEND_FILE_NOT_FOUND, + IRCTXT_DCC_SEND_CONNECTED, + IRCTXT_DCC_SEND_COMPLETE, + IRCTXT_DCC_SEND_ABORTED, + IRCTXT_DCC_GET_NOT_FOUND, + IRCTXT_DCC_GET_CONNECTED, + IRCTXT_DCC_GET_COMPLETE, + IRCTXT_DCC_GET_ABORTED, + IRCTXT_DCC_UNKNOWN_CTCP, + IRCTXT_DCC_UNKNOWN_REPLY, + IRCTXT_DCC_UNKNOWN_TYPE, + IRCTXT_DCC_CONNECT_ERROR, + IRCTXT_DCC_CANT_CREATE, + IRCTXT_DCC_REJECTED, + IRCTXT_DCC_CLOSE, +}; + +extern FORMAT_REC fecommon_irc_dcc_formats[]; +#define MODULE_FORMATS fecommon_irc_dcc_formats diff --git a/src/fe-common/irc/fe-channels.c b/src/fe-common/irc/fe-channels.c new file mode 100644 index 00000000..c95e6411 --- /dev/null +++ b/src/fe-common/irc/fe-channels.c @@ -0,0 +1,123 @@ +/* + fe-channels.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "modules.h" +#include "signals.h" +#include "commands.h" +#include "levels.h" + +#include "irc.h" +#include "channels.h" + +#include "windows.h" +#include "window-items.h" + +static void signal_channel_created(CHANNEL_REC *channel, gpointer automatic) +{ + window_item_create((WI_ITEM_REC *) channel, GPOINTER_TO_INT(automatic)); +} + +static void signal_channel_created_curwin(CHANNEL_REC *channel) +{ + g_return_if_fail(channel != NULL); + + window_add_item(active_win, (WI_ITEM_REC *) channel, FALSE); + signal_stop(); +} + +static void signal_channel_destroyed(CHANNEL_REC *channel) +{ + WINDOW_REC *window; + + g_return_if_fail(channel != NULL); + + window = window_item_window((WI_ITEM_REC *) channel); + if (window != NULL) window_remove_item(window, (WI_ITEM_REC *) channel); +} + +static void signal_window_item_removed(WINDOW_REC *window, WI_ITEM_REC *item) +{ + CHANNEL_REC *channel; + + g_return_if_fail(window != NULL); + + channel = irc_item_channel(item); + if (channel != NULL) channel_destroy(channel); +} + +static void sig_disconnected(IRC_SERVER_REC *server) +{ + WINDOW_REC *window; + GSList *tmp; + + g_return_if_fail(server != NULL); + if (!irc_server_check(server)) + return; + + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *channel = tmp->data; + + window = window_item_window((WI_ITEM_REC *) channel); + window->waiting_channels = + g_slist_append(window->waiting_channels, g_strdup_printf("%s %s", server->tag, channel->name)); + } +} + +static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item) +{ + g_return_if_fail(item != NULL); + + if (g_slist_length(window->items) > 1 && irc_item_channel(item)) { + printformat(item->server, item->name, MSGLEVEL_CLIENTNOTICE, + IRCTXT_TALKING_IN, item->name); + signal_stop(); + } +} + +static void cmd_wjoin(const char *data, void *server, WI_ITEM_REC *item) +{ + signal_add("channel created", (SIGNAL_FUNC) signal_channel_created_curwin); + signal_emit("command join", 3, data, server, item); + signal_remove("channel created", (SIGNAL_FUNC) signal_channel_created_curwin); +} + +void fe_channels_init(void) +{ + signal_add("channel created", (SIGNAL_FUNC) signal_channel_created); + signal_add("channel destroyed", (SIGNAL_FUNC) signal_channel_destroyed); + signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_removed); + signal_add_last("window item changed", (SIGNAL_FUNC) signal_window_item_changed); + signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected); + + command_bind("wjoin", NULL, (SIGNAL_FUNC) cmd_wjoin); +} + +void fe_channels_deinit(void) +{ + signal_remove("channel created", (SIGNAL_FUNC) signal_channel_created); + signal_remove("channel destroyed", (SIGNAL_FUNC) signal_channel_destroyed); + signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_removed); + signal_remove("window item changed", (SIGNAL_FUNC) signal_window_item_changed); + signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); + + command_unbind("wjoin", (SIGNAL_FUNC) cmd_wjoin); +} diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c new file mode 100644 index 00000000..b8166f5e --- /dev/null +++ b/src/fe-common/irc/fe-common-irc.c @@ -0,0 +1,172 @@ +/* + fe-common-irc.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "signals.h" +#include "args.h" +#include "misc.h" +#include "lib-config/iconfig.h" +#include "settings.h" + +#include "server-setup.h" + +#include "completion.h" + +void fe_channels_init(void); +void fe_channels_deinit(void); + +void fe_irc_commands_init(void); +void fe_irc_commands_deinit(void); + +void fe_ctcp_init(void); +void fe_ctcp_deinit(void); + +void fe_dcc_init(void); +void fe_dcc_deinit(void); + +void fe_events_init(void); +void fe_events_deinit(void); + +void fe_events_numeric_init(void); +void fe_events_numeric_deinit(void); + +void fe_ignore_init(void); +void fe_ignore_deinit(void); + +void fe_query_init(void); +void fe_query_deinit(void); + +void irc_nick_hilight_init(void); +void irc_nick_hilight_deinit(void); + +void fe_notifylist_init(void); +void fe_notifylist_deinit(void); + +void fe_flood_init(void); +void fe_flood_deinit(void); + +static char *autocon_server; +static char *autocon_password; +static int autocon_port; +static int no_autoconnect; +static char *cmdline_nick; +static char *cmdline_hostname; + +void fe_common_irc_init(void) +{ + static struct poptOption options[] = { + { "connect", 'c', POPT_ARG_STRING, &autocon_server, 0, N_("Automatically connect to server/ircnet"), N_("SERVER") }, + { "password", 'w', POPT_ARG_STRING, &autocon_password, 0, N_("Autoconnect password"), N_("SERVER") }, + { "port", 'p', POPT_ARG_INT, &autocon_port, 0, N_("Autoconnect port"), N_("PORT") }, + { "noconnect", '!', POPT_ARG_NONE, &no_autoconnect, 0, N_("Disable autoconnecting"), NULL }, + { "nick", 'n', POPT_ARG_STRING, &cmdline_nick, 0, N_("Specify nick to use"), NULL }, + { "hostname", 'h', POPT_ARG_STRING, &cmdline_hostname, 0, N_("Specify host name to use"), NULL }, + { NULL, '\0', 0, NULL } + }; + + autocon_server = NULL; + autocon_password = NULL; + autocon_port = 6667; + no_autoconnect = FALSE; + cmdline_nick = NULL; + cmdline_hostname = NULL; + args_register(options); + + settings_add_str("lookandfeel", "beep_on_msg", ""); + settings_add_bool("lookandfeel", "beep_when_away", TRUE); + settings_add_bool("lookandfeel", "show_away_once", TRUE); + settings_add_bool("lookandfeel", "show_quit_once", FALSE); + + fe_channels_init(); + fe_irc_commands_init(); + fe_ctcp_init(); + fe_dcc_init(); + fe_events_init(); + fe_events_numeric_init(); + fe_ignore_init(); + fe_notifylist_init(); + fe_flood_init(); + fe_query_init(); + completion_init(); + irc_nick_hilight_init(); +} + +void fe_common_irc_deinit(void) +{ + fe_channels_deinit(); + fe_irc_commands_deinit(); + fe_ctcp_deinit(); + fe_dcc_deinit(); + fe_events_deinit(); + fe_events_numeric_deinit(); + fe_ignore_deinit(); + fe_notifylist_deinit(); + fe_flood_deinit(); + fe_query_deinit(); + completion_deinit(); + irc_nick_hilight_deinit(); +} + +void fe_common_irc_finish_init(void) +{ + GSList *tmp, *ircnets; + char *str; + + if (cmdline_nick != NULL) { + /* override nick found from setup */ + iconfig_set_str("settings", "default_nick", cmdline_nick); + } + + if (cmdline_hostname != NULL) { + /* override host name found from setup */ + iconfig_set_str("settings", "hostname", cmdline_hostname); + } + + if (autocon_server != NULL) { + /* connect to specified server */ + str = g_strdup_printf(autocon_password == NULL ? "%s %d" : "%s %d %s", + autocon_server, autocon_port, autocon_password); + signal_emit("command connect", 1, str); + g_free(str); + return; + } + + if (no_autoconnect) { + /* don't autoconnect */ + return; + } + + /* connect to autoconnect servers */ + ircnets = NULL; + for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { + SETUP_SERVER_REC *rec = tmp->data; + + if (rec->autoconnect && (*rec->ircnet == '\0' || gslist_find_icase_string(ircnets, rec->ircnet) == NULL)) { + if (*rec->ircnet != '\0') + ircnets = g_slist_append(ircnets, rec->ircnet); + + str = g_strdup_printf("%s %d", rec->server, rec->port); + signal_emit("command connect", 1, str); + g_free(str); + } + } + + g_slist_free(ircnets); +} diff --git a/src/fe-common/irc/fe-common-irc.h b/src/fe-common/irc/fe-common-irc.h new file mode 100644 index 00000000..0ad3a564 --- /dev/null +++ b/src/fe-common/irc/fe-common-irc.h @@ -0,0 +1,8 @@ +#ifndef __FE_COMMON_IRC_H +#define __FE_COMMON_IRC_H + +void fe_common_irc_init(void); +void fe_common_irc_deinit(void); +void fe_common_irc_finish_init(void); + +#endif diff --git a/src/fe-common/irc/fe-ctcp.c b/src/fe-common/irc/fe-ctcp.c new file mode 100644 index 00000000..a8d9a1c5 --- /dev/null +++ b/src/fe-common/irc/fe-ctcp.c @@ -0,0 +1,110 @@ +/* + fe-ctcp.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "misc.h" +#include "settings.h" + +#include "irc.h" +#include "levels.h" +#include "server.h" +#include "channels.h" +#include "query.h" +#include "ignore.h" + +#include "windows.h" +#include "window-items.h" + +static void ctcp_print(const char *pre, const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +{ + char *str; + + g_return_if_fail(data != NULL); + + str = g_strconcat(pre, " ", data, NULL); + printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS, + IRCTXT_CTCP_REQUESTED, nick, addr, str, target); + g_free(str); +} + +static void ctcp_default_msg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +{ + return ctcp_print("unknown CTCP", data, server, nick, addr, target); +} + +static void ctcp_ping_msg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +{ + return ctcp_print("CTCP PING", data, server, nick, addr, target); +} + +static void ctcp_version_msg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +{ + return ctcp_print("CTCP VERSION", data, server, nick, addr, target); +} + +static void ctcp_default_reply(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +{ + char *ptr, *str; + + g_return_if_fail(data != NULL); + + str = g_strdup(data); + ptr = strchr(str, ' '); + if (ptr != NULL) *ptr++ = '\0'; else ptr = ""; + + printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS, + IRCTXT_CTCP_REPLY, str, nick, ptr); + g_free(str); +} + +static void ctcp_ping_reply(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +{ + GTimeVal tv, tv2; + long usecs; + + g_return_if_fail(data != NULL); + + if (sscanf(data, "%ld %ld", &tv2.tv_sec, &tv2.tv_usec) != 2) + return; + + g_get_current_time(&tv); + usecs = get_timeval_diff(&tv, &tv2); + printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS, + IRCTXT_CTCP_PING_REPLY, nick, usecs/1000, usecs%1000); +} + +void fe_ctcp_init(void) +{ + signal_add("default ctcp msg", (SIGNAL_FUNC) ctcp_default_msg); + signal_add("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping_msg); + signal_add("ctcp msg version", (SIGNAL_FUNC) ctcp_version_msg); + signal_add("default ctcp reply", (SIGNAL_FUNC) ctcp_default_reply); + signal_add("ctcp reply ping", (SIGNAL_FUNC) ctcp_ping_reply); +} + +void fe_ctcp_deinit(void) +{ + signal_remove("default ctcp msg", (SIGNAL_FUNC) ctcp_default_msg); + signal_remove("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping_msg); + signal_remove("ctcp msg version", (SIGNAL_FUNC) ctcp_version_msg); + signal_remove("default ctcp reply", (SIGNAL_FUNC) ctcp_default_reply); + signal_remove("ctcp reply ping", (SIGNAL_FUNC) ctcp_ping_reply); +} diff --git a/src/fe-common/irc/fe-events-numeric.c b/src/fe-common/irc/fe-events-numeric.c new file mode 100644 index 00000000..17a7f9ae --- /dev/null +++ b/src/fe-common/irc/fe-events-numeric.c @@ -0,0 +1,707 @@ +/* + fe-events-numeric.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "settings.h" + +#include "irc.h" +#include "levels.h" +#include "server.h" +#include "channels.h" +#include "nicklist.h" + +static char *last_away_nick = NULL; +static char *last_away_msg = NULL; + +static void event_user_mode(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *mode; + + g_return_if_fail(data != NULL); + g_return_if_fail(server != NULL); + + params = event_get_params(data, 2, NULL, &mode); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_USER_MODE, mode); + g_free(params); +} + +static void event_ison(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *online; + + g_return_if_fail(data != NULL); + g_return_if_fail(server != NULL); + + params = event_get_params(data, 2, NULL, &online); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_ONLINE, online); + g_free(params); +} + +static void event_names_list(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel, *names; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 4, NULL, NULL, &channel, &names); + if (channel_find(server, channel) == NULL) + printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_NAMES, channel, names); + g_free(params); +} + +static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist, gint items, gint max) +{ + NICK_REC *rec, *last; + GString *str; + GSList *tmp; + gint lines, cols, line, col, skip; + gchar *linebuf; + + max++; /* op/voice */ + str = g_string_new(NULL); + + cols = max > 65 ? 1 : (65 / (max+3)); /* "[] " */ + lines = items <= cols ? 1 : items / cols+1; + + last = NULL; linebuf = g_malloc(max+1); linebuf[max] = '\0'; + for (line = 0, col = 0, skip = 1, tmp = nicklist; line < lines; last = rec, tmp = tmp->next) + { + rec = tmp->data; + + if (--skip == 0) + { + skip = lines; + memset(linebuf, ' ', max); + linebuf[0] = rec->op ? '@' : rec->voice ? '+' : ' '; + memcpy(linebuf+1, rec->nick, strlen(rec->nick)); + g_string_sprintfa(str, "%%K[%%n%%_%c%%_%s%%K] ", linebuf[0], linebuf+1); + cols++; + } + + if (col == cols || tmp->next == NULL) + { + printtext(channel->server, channel->name, MSGLEVEL_CLIENTCRAP, str->str); + g_string_truncate(str, 0); + col = 0; line++; + tmp = g_slist_nth(nicklist, line-1); skip = 1; + } + } + if (str->len != 0) + printtext(channel->server, channel->name, MSGLEVEL_CLIENTCRAP, str->str); + g_string_free(str, TRUE); + g_free(linebuf); +} + +static void display_nicks(CHANNEL_REC *channel) +{ + NICK_REC *nick; + GSList *tmp, *nicklist, *sorted; + gint nicks, normal, voices, ops, len, max; + + nicks = normal = voices = ops = 0; + nicklist = nicklist_getnicks(channel); + sorted = NULL; + + /* sort the nicklist */ + max = 0; + for (tmp = nicklist; tmp != NULL; tmp = tmp->next) + { + nick = tmp->data; + + sorted = g_slist_insert_sorted(sorted, nick, (GCompareFunc) nicklist_compare); + if (nick->op) + ops++; + else if (nick->voice) + voices++; + else + normal++; + nicks++; + + len = strlen(nick->nick); + if (len > max) max = len; + } + g_slist_free(nicklist); + + /* display the nicks */ + printformat(channel->server, channel->name, MSGLEVEL_CRAP, IRCTXT_NAMES, channel->name, ""); + display_sorted_nicks(channel, sorted, nicks, max); + g_slist_free(sorted); + + printformat(channel->server, channel->name, MSGLEVEL_CRAP, IRCTXT_ENDOFNAMES, + channel->name, nicks, ops, voices, normal); +} + +static void event_end_of_names(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel; + CHANNEL_REC *chanrec; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + + chanrec = channel_find(server, channel); + if (chanrec == NULL) + printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_ENDOFNAMES, channel, 0, 0, 0, 0); + else + display_nicks(chanrec); + g_free(params); +} + +static void event_who(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick, *channel, *user, *host, *stat, *realname, *hops; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 8, NULL, &channel, &user, &host, NULL, &nick, &stat, &realname); + + /* split hops/realname */ + hops = realname; + while (*realname != '\0' && *realname != ' ') realname++; + while (*realname == ' ') realname++; + if (realname > hops) realname[-1] = '\0'; + + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHO, + channel, nick, stat, hops, user, host, realname); + + g_free(params); +} + +static void event_end_of_who(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_END_OF_WHO, channel); + g_free(params); +} + +static void event_ban_list(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel, *ban, *setby, *tims; + glong secs, tim; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims); + + if (sscanf(tims, "%ld", &tim) != 1) tim = (glong) time(NULL); + secs = (glong) time(NULL)-tim; + + printformat(server, channel, MSGLEVEL_CRAP, + *setby == '\0' ? IRCTXT_BANLIST : IRCTXT_BANLIST_LONG, + channel, ban, setby, secs); + + g_free(params); +} + +static void event_eban_list(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel, *ban, *setby, *tims; + glong secs, tim; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims); + + if (sscanf(tims, "%ld", &tim) != 1) tim = (glong) time(NULL); + secs = (glong) time(NULL)-tim; + + printformat(server, channel, MSGLEVEL_CRAP, + *setby == '\0' ? IRCTXT_EBANLIST : IRCTXT_EBANLIST_LONG, + channel, ban, setby, secs); + + g_free(params); +} + +static void event_invite_list(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel, *invite; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 3, NULL, &channel, &invite); + printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_INVITELIST, channel, invite); + g_free(params); +} + +static void event_nick_in_use(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &nick); + if (server->connected) + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NICK_IN_USE, nick); + + g_free(params); +} + +static void event_topic_get(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel, *topic; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 3, NULL, &channel, &topic); + printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_TOPIC, channel, topic); + g_free(params); +} + +static void event_topic_info(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *timestr, *channel, *topicby, *topictime; + glong ltime; + time_t t; + struct tm *tim; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 4, NULL, &channel, &topicby, &topictime); + + if (sscanf(topictime, "%lu", <ime) != 1) ltime = 0; /* topic set date */ + t = (time_t) ltime; + tim = localtime(&t); + timestr = g_strdup(asctime(tim)); + if (timestr[strlen(timestr)-1] == '\n') timestr[strlen(timestr)-1] = '\0'; + + printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_TOPIC_INFO, topicby, timestr); + g_free(timestr); + g_free(params); +} + +static void event_channel_mode(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel, *mode; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 3 | PARAM_FLAG_GETREST, NULL, &channel, &mode); + printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_CHANNEL_MODE, channel, mode); + g_free(params); +} + +static void event_channel_created(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel, *times, *timestr; + glong timeval; + time_t t; + struct tm *tim; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 3, NULL, &channel, ×); + + if (sscanf(times, "%ld", &timeval) != 1) timeval = 0; + t = (time_t) timeval; + tim = localtime(&t); + timestr = g_strdup(asctime(tim)); + if (timestr[strlen(timestr)-1] == '\n') timestr[strlen(timestr)-1] = '\0'; + + printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_CHANNEL_CREATED, channel, timestr); + g_free(timestr); + g_free(params); +} + +static void event_away(gchar *data, IRC_SERVER_REC *server) +{ + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_AWAY); +} + +static void event_unaway(gchar *data, IRC_SERVER_REC *server) +{ + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_UNAWAY); +} + +static void event_userhost(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *hosts; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &hosts); + printtext(server, NULL, MSGLEVEL_CRAP, "%s", hosts); + g_free(params); +} + +static void event_whois(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick, *user, *host, *realname; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS, nick, user, host, realname); + g_free(params); +} + +static void event_whois_idle(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick, *secstr, *signon, *rest; + glong secs, lsignon; + gint h, m, s; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 5 | PARAM_FLAG_GETREST, NULL, &nick, &secstr, &signon, &rest); + if (sscanf(secstr, "%ld", &secs) == 0) secs = 0; + lsignon = 0; + if (strstr(rest, ", signon time") != NULL) + sscanf(signon, "%ld", &lsignon); + + h = secs/3600; m = (secs%3600)/60; s = secs%60; + if (lsignon == 0) + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_IDLE, nick, h, m, s); + else + { + gchar *timestr; + struct tm *tim; + time_t t; + + t = (time_t) lsignon; + tim = localtime(&t); + timestr = g_strdup(asctime(tim)); + if (timestr[strlen(timestr)-1] == '\n') timestr[strlen(timestr)-1] = '\0'; + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_IDLE_SIGNON, nick, h, m, s, timestr); + g_free(timestr); + } + g_free(params); +} + +static void event_whois_server(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick, *whoserver, *desc; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 4, NULL, &nick, &whoserver, &desc); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_SERVER, nick, whoserver, desc); + g_free(params); +} + +static void event_whois_oper(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &nick); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_OPER, nick); + g_free(params); +} + +static void event_whois_channels(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick, *chans; + GString *str; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 3, NULL, &nick, &chans); + + str = g_string_new(NULL); + for (; *chans != '\0'; chans++) + { + if ((unsigned char) *chans >= 32) + g_string_append_c(str, *chans); + else + { + g_string_append_c(str, '^'); + g_string_append_c(str, *chans+'A'-1); + } + } + + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_CHANNELS, nick, str->str); + g_free(params); + g_string_free(str, TRUE); +} + +static void event_whois_away(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick, *awaymsg; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 3, NULL, &nick, &awaymsg); + if (server->whois_coming || !settings_get_bool("show_away_once") || + last_away_nick == NULL || g_strcasecmp(last_away_nick, nick) != 0 || + last_away_msg == NULL || g_strcasecmp(last_away_msg, awaymsg) != 0) { + /* don't show the same away message from the same nick all the time */ + g_free_not_null(last_away_nick); + g_free_not_null(last_away_msg); + last_away_nick = g_strdup(nick); + last_away_msg = g_strdup(awaymsg); + + printformat(server, NULL, MSGLEVEL_CRAP, server->whois_coming ? + IRCTXT_WHOIS_AWAY : IRCTXT_NICK_AWAY, nick, awaymsg); + } + g_free(params); +} + +static void event_end_of_whois(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &nick); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_END_OF_WHOIS, nick); + g_free(params); +} + +static void event_target_unavailable(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + if (!ischannel(*channel)) + { + /* nick unavailable */ + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NICK_UNAVAILABLE, channel); + } + else + { + /* channel is unavailable. */ + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_JOINERROR_UNAVAIL, channel); + } + + g_free(params); +} + +static void event_no_such_nick(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &nick); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NO_SUCH_NICK, nick); + g_free(params); +} + +static void event_no_such_channel(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NO_SUCH_CHANNEL, channel); + g_free(params); +} + +static void cannot_join(gchar *data, IRC_SERVER_REC *server, gint format) +{ + gchar *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + printformat(server, NULL, MSGLEVEL_CRAP, format, channel); + g_free(params); +} + +static void event_too_many_channels(gchar *data, IRC_SERVER_REC *server) +{ + cannot_join(data, server, IRCTXT_JOINERROR_TOOMANY); +} + +static void event_channel_is_full(gchar *data, IRC_SERVER_REC *server) +{ + cannot_join(data, server, IRCTXT_JOINERROR_FULL); +} + +static void event_invite_only(gchar *data, IRC_SERVER_REC *server) +{ + cannot_join(data, server, IRCTXT_JOINERROR_INVITE); +} + +static void event_banned(gchar *data, IRC_SERVER_REC *server) +{ + cannot_join(data, server, IRCTXT_JOINERROR_BANNED); +} + +static void event_bad_channel_key(gchar *data, IRC_SERVER_REC *server) +{ + cannot_join(data, server, IRCTXT_JOINERROR_BAD_KEY); +} + +static void event_bad_channel_mask(gchar *data, IRC_SERVER_REC *server) +{ + cannot_join(data, server, IRCTXT_JOINERROR_BAD_MASK); +} + +static void event_unknown_mode(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *mode; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &mode); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_UNKNOWN_MODE, mode); + g_free(params); +} + +static void event_not_chanop(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NOT_CHANOP, channel); + g_free(params); +} + +static void event_received(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + gchar *params, *args, *ptr; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, NULL, &args); + ptr = strstr(args, " :"); + if (ptr != NULL) *(ptr+1) = ' '; + printtext(server, NULL, MSGLEVEL_CRAP, "%s", args); + g_free(params); +} + +static void event_motd(gchar *data, SERVER_REC *server, gchar *nick, gchar *addr) +{ + /* numeric event. */ + gchar *params, *args, *ptr; + + if (settings_get_bool("toggle_skip_motd")) + return; + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, NULL, &args); + ptr = strstr(args, " :"); + if (ptr != NULL) *(ptr+1) = ' '; + printtext(server, NULL, MSGLEVEL_CRAP, "%s", args); + g_free(params); +} + +void fe_events_numeric_init(void) +{ + last_away_nick = NULL; + last_away_msg = NULL; + + signal_add("event 221", (SIGNAL_FUNC) event_user_mode); + signal_add("event 303", (SIGNAL_FUNC) event_ison); + signal_add("event 353", (SIGNAL_FUNC) event_names_list); + signal_add("event 366", (SIGNAL_FUNC) event_end_of_names); + signal_add("event 352", (SIGNAL_FUNC) event_who); + signal_add("event 315", (SIGNAL_FUNC) event_end_of_who); + signal_add("event 367", (SIGNAL_FUNC) event_ban_list); + signal_add("event 348", (SIGNAL_FUNC) event_eban_list); + signal_add("event 346", (SIGNAL_FUNC) event_invite_list); + signal_add("event 433", (SIGNAL_FUNC) event_nick_in_use); + signal_add("event 332", (SIGNAL_FUNC) event_topic_get); + signal_add("event 333", (SIGNAL_FUNC) event_topic_info); + signal_add("event 324", (SIGNAL_FUNC) event_channel_mode); + signal_add("event 329", (SIGNAL_FUNC) event_channel_created); + signal_add("event 306", (SIGNAL_FUNC) event_away); + signal_add("event 305", (SIGNAL_FUNC) event_unaway); + signal_add("event 311", (SIGNAL_FUNC) event_whois); + signal_add("event 301", (SIGNAL_FUNC) event_whois_away); + signal_add("event 312", (SIGNAL_FUNC) event_whois_server); + signal_add("event 313", (SIGNAL_FUNC) event_whois_oper); + signal_add("event 317", (SIGNAL_FUNC) event_whois_idle); + signal_add("event 318", (SIGNAL_FUNC) event_end_of_whois); + signal_add("event 319", (SIGNAL_FUNC) event_whois_channels); + signal_add("event 302", (SIGNAL_FUNC) event_userhost); + + signal_add("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_add("event 401", (SIGNAL_FUNC) event_no_such_nick); + signal_add("event 403", (SIGNAL_FUNC) event_no_such_channel); + signal_add("event 405", (SIGNAL_FUNC) event_too_many_channels); + signal_add("event 471", (SIGNAL_FUNC) event_channel_is_full); + signal_add("event 472", (SIGNAL_FUNC) event_unknown_mode); + signal_add("event 473", (SIGNAL_FUNC) event_invite_only); + signal_add("event 474", (SIGNAL_FUNC) event_banned); + signal_add("event 475", (SIGNAL_FUNC) event_bad_channel_key); + signal_add("event 476", (SIGNAL_FUNC) event_bad_channel_mask); + signal_add("event 482", (SIGNAL_FUNC) event_not_chanop); + signal_add("event 375", (SIGNAL_FUNC) event_motd); + signal_add("event 376", (SIGNAL_FUNC) event_motd); + signal_add("event 372", (SIGNAL_FUNC) event_motd); + + signal_add("event 004", (SIGNAL_FUNC) event_received); + signal_add("event 364", (SIGNAL_FUNC) event_received); + signal_add("event 365", (SIGNAL_FUNC) event_received); +} + +void fe_events_numeric_deinit(void) +{ + g_free_not_null(last_away_nick); + g_free_not_null(last_away_msg); + + signal_remove("event 221", (SIGNAL_FUNC) event_user_mode); + signal_remove("event 303", (SIGNAL_FUNC) event_ison); + signal_remove("event 353", (SIGNAL_FUNC) event_names_list); + signal_remove("event 366", (SIGNAL_FUNC) event_end_of_names); + signal_remove("event 352", (SIGNAL_FUNC) event_who); + signal_remove("event 315", (SIGNAL_FUNC) event_end_of_who); + signal_remove("event 367", (SIGNAL_FUNC) event_ban_list); + signal_remove("event 348", (SIGNAL_FUNC) event_eban_list); + signal_remove("event 346", (SIGNAL_FUNC) event_invite_list); + signal_remove("event 433", (SIGNAL_FUNC) event_nick_in_use); + signal_remove("event 332", (SIGNAL_FUNC) event_topic_get); + signal_remove("event 333", (SIGNAL_FUNC) event_topic_info); + signal_remove("event 324", (SIGNAL_FUNC) event_channel_mode); + signal_remove("event 329", (SIGNAL_FUNC) event_channel_created); + signal_remove("event 306", (SIGNAL_FUNC) event_away); + signal_remove("event 305", (SIGNAL_FUNC) event_unaway); + signal_remove("event 311", (SIGNAL_FUNC) event_whois); + signal_remove("event 301", (SIGNAL_FUNC) event_whois_away); + signal_remove("event 312", (SIGNAL_FUNC) event_whois_server); + signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper); + signal_remove("event 317", (SIGNAL_FUNC) event_whois_idle); + signal_remove("event 318", (SIGNAL_FUNC) event_end_of_whois); + signal_remove("event 319", (SIGNAL_FUNC) event_whois_channels); + signal_remove("event 302", (SIGNAL_FUNC) event_userhost); + + signal_remove("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_remove("event 401", (SIGNAL_FUNC) event_no_such_nick); + signal_remove("event 403", (SIGNAL_FUNC) event_no_such_channel); + signal_remove("event 405", (SIGNAL_FUNC) event_too_many_channels); + signal_remove("event 471", (SIGNAL_FUNC) event_channel_is_full); + signal_remove("event 472", (SIGNAL_FUNC) event_unknown_mode); + signal_remove("event 473", (SIGNAL_FUNC) event_invite_only); + signal_remove("event 474", (SIGNAL_FUNC) event_banned); + signal_remove("event 475", (SIGNAL_FUNC) event_bad_channel_key); + signal_remove("event 476", (SIGNAL_FUNC) event_bad_channel_mask); + signal_remove("event 482", (SIGNAL_FUNC) event_not_chanop); + signal_remove("event 375", (SIGNAL_FUNC) event_motd); + signal_remove("event 376", (SIGNAL_FUNC) event_motd); + signal_remove("event 372", (SIGNAL_FUNC) event_motd); + + signal_remove("event 004", (SIGNAL_FUNC) event_received); + signal_remove("event 364", (SIGNAL_FUNC) event_received); + signal_remove("event 365", (SIGNAL_FUNC) event_received); +} diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c new file mode 100644 index 00000000..7ea6ea25 --- /dev/null +++ b/src/fe-common/irc/fe-events.c @@ -0,0 +1,682 @@ +/* + fe-events.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "settings.h" + +#include "irc.h" +#include "levels.h" +#include "server.h" +#include "server-redirect.h" +#include "server-reconnect.h" +#include "channels.h" +#include "query.h" +#include "nicklist.h" +#include "ignore.h" + +#include "irc-hilight-text.h" +#include "windows.h" + +#include "completion.h" + +static int beep_msg_level, beep_when_away; + +static void msg_beep_check(IRC_SERVER_REC *server, int level) +{ + if (level != 0 && (beep_msg_level & level) && + (!server->usermode_away || beep_when_away)) { + printbeep(); + } +} + +static void event_privmsg(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + CHANNEL_REC *chanrec; + WI_ITEM_REC *item; + gchar *params, *target, *msg, *nickmode; + int level; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (nick == NULL) nick = server->real_address; + + level = 0; + if (*msg == 1) + { + /* ctcp message, handled in fe-ctcp.c */ + } + else if (ignore_check(server, nick, addr, target, msg, + ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS)) + { + /* ignored */ + } + else if (ischannel(*target)) + { + /* message to some channel */ + WINDOW_REC *window; + NICK_REC *nickrec; + gboolean toyou; + gchar *color; + + chanrec = channel_find(server, target); + toyou = completion_msgtoyou((SERVER_REC *) server, msg); + color = irc_hilight_find_nick(target, nick, addr); + + nickrec = chanrec == NULL ? NULL : nicklist_find(chanrec, nick); + nickmode = !settings_get_bool("toggle_show_nickmode") || nickrec == NULL ? "" : + nickrec->op ? "@" : nickrec->voice ? "+" : " "; + + window = chanrec == NULL ? NULL : window_item_window((WI_ITEM_REC *) chanrec); + if (window != NULL && window->active == (WI_ITEM_REC *) chanrec) + { + /* message to active channel in window */ + if (color != NULL) + { + /* highlighted nick */ + printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT, + IRCTXT_PUBMSG_HILIGHT, color, nick, msg, nickmode); + } + else + { + printformat(server, target, MSGLEVEL_PUBLIC | (toyou ? MSGLEVEL_NOHILIGHT : 0), + toyou ? IRCTXT_PUBMSG_ME : IRCTXT_PUBMSG, nick, msg, nickmode); + } + } + else + { + /* message to not existing/active channel */ + if (color != NULL) + { + /* highlighted nick */ + printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT, + IRCTXT_PUBMSG_HILIGHT_CHANNEL, color, nick, target, msg, nickmode); + } + else + { + printformat(server, target, MSGLEVEL_PUBLIC | (toyou ? MSGLEVEL_NOHILIGHT : 0), + toyou ? IRCTXT_PUBMSG_ME_CHANNEL : IRCTXT_PUBMSG_CHANNEL, + nick, target, msg, nickmode); + } + } + + g_free_not_null(color); + level = MSGLEVEL_PUBLIC; + } + else + { + /* private message */ + if (settings_get_bool("toggle_autocreate_query") && query_find(server, nick) == NULL) + item = (WI_ITEM_REC *) query_create(server, nick, TRUE); + else + item = (WI_ITEM_REC *) query_find(server, nick); + + printformat(server, nick, MSGLEVEL_MSGS, + item == NULL ? IRCTXT_MSG_PRIVATE : IRCTXT_MSG_PRIVATE_QUERY, nick, addr == NULL ? "" : addr, msg); + level = MSGLEVEL_MSGS; + } + + msg_beep_check(server, level); + + g_free(params); +} + +/* we use "ctcp msg" here because "ctcp msg action" can be ignored with + /IGNORE * CTCPS */ +static void ctcp_action_msg(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr, gchar *target) +{ + WINDOW_REC *window; + CHANNEL_REC *channel; + WI_ITEM_REC *item; + int level; + + g_return_if_fail(data != NULL); + + if (g_strncasecmp(data, "ACTION ", 7) != 0) + return; + data += 7; + + level = 0; + if (ignore_check(server, nick, addr, target, data, MSGLEVEL_ACTIONS)) + { + /* ignored */ + } + else if (ischannel(*target)) + { + /* channel action */ + channel = channel_find(server, target); + + window = channel == NULL ? NULL : window_item_window((WI_ITEM_REC *) channel); + if (window != NULL && window->active == (WI_ITEM_REC *) channel) + { + /* message to active channel in window */ + printformat(server, target, MSGLEVEL_ACTIONS, + IRCTXT_ACTION_PUBLIC, nick, data); + } + else + { + /* message to not existing/active channel */ + printformat(server, target, MSGLEVEL_ACTIONS, + IRCTXT_ACTION_PUBLIC_CHANNEL, nick, target, data); + } + level = MSGLEVEL_PUBLIC; + } + else + { + /* private action */ + if (settings_get_bool("toggle_autocreate_query") && query_find(server, nick) == NULL) + item = (WI_ITEM_REC *) query_create(server, nick, TRUE); + else + item = (WI_ITEM_REC *) channel_find(server, nick); + + printformat(server, nick, MSGLEVEL_ACTIONS, + item == NULL ? IRCTXT_ACTION_PRIVATE : IRCTXT_ACTION_PRIVATE_QUERY, nick, addr == NULL ? "" : addr, data); + level = MSGLEVEL_MSGS; + } + + msg_beep_check(server, level); +} + +static void event_notice(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + char *params, *target, *msg; + int level; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (nick == NULL) nick = server->real_address; + + level = 0; + if (*msg == 1) + { + /* ctcp reply */ + } + else if (addr == NULL) + { + /* notice from server */ + if (nick == NULL || !ignore_check(server, nick, "", target, msg, MSGLEVEL_SNOTES)) + printformat(server, target, MSGLEVEL_SNOTES, IRCTXT_NOTICE_SERVER, nick == NULL ? "" : nick, msg); + } + else if (ischannel(*target) || (*target == '@' && ischannel(target[1]))) + { + /* notice in some channel */ + if (!ignore_check(server, nick, addr, target, msg, MSGLEVEL_NOTICES)) + printformat(server, target, MSGLEVEL_NOTICES, + *target == '@' ? IRCTXT_NOTICE_PUBLIC_OPS : IRCTXT_NOTICE_PUBLIC, + nick, *target == '@' ? target+1 : target, msg); + level = MSGLEVEL_NOTICES; + } + else + { + /* private notice */ + if (!ignore_check(server, nick, addr, NULL, msg, MSGLEVEL_NOTICES)) + printformat(server, nick, MSGLEVEL_NOTICES, IRCTXT_NOTICE_PRIVATE, nick, addr, msg); + level = MSGLEVEL_NOTICES; + } + + msg_beep_check(server, level); + + g_free(params); +} + +static void event_join(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + gchar *params, *channel, *tmp; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 1, &channel); + tmp = strchr(channel, 7); /* ^G does something weird.. */ + if (tmp != NULL) *tmp = '\0'; + + if (!ignore_check(server, nick, addr, channel, NULL, MSGLEVEL_JOINS)) + printformat(server, channel, MSGLEVEL_JOINS, IRCTXT_JOIN, nick, addr, channel); + g_free(params); +} + +static void event_part(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + gchar *params, *channel, *reason; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &reason); + + if (!ignore_check(server, nick, addr, channel, NULL, MSGLEVEL_PARTS)) + printformat(server, channel, MSGLEVEL_PARTS, IRCTXT_PART, nick, addr, channel, reason); + g_free(params); +} + +static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +{ + GString *chans; + GSList *tmp; + int once; + + g_return_if_fail(data != NULL); + + if (ignore_check(server, nick, addr, NULL, NULL, MSGLEVEL_QUITS)) + return; + + if (*data == ':') data++; /* quit message */ + + once = settings_get_bool("show_quit_once"); + chans = !once ? NULL : g_string_new(NULL); + for (tmp = channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *rec = tmp->data; + + if (rec->server == server && nicklist_find(rec, nick) && + !ignore_check(server, nick, addr, rec->name, data, MSGLEVEL_QUITS)) { + if (once) + g_string_sprintfa(chans, "%s,", rec->name); + else + printformat(server, rec->name, MSGLEVEL_QUITS, IRCTXT_QUIT, nick, addr, data); + } + } + + if (once) { + g_string_truncate(chans, chans->len-1); + printformat(server, NULL, MSGLEVEL_QUITS, + chans->len == 0 ? IRCTXT_QUIT : IRCTXT_QUIT_ONCE, + nick, addr, data, chans->str); + g_string_free(chans, TRUE); + } +} + +static void event_kick(gchar *data, IRC_SERVER_REC *server, gchar *kicker, gchar *addr) +{ + gchar *params, *channel, *nick, *reason; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 3 | PARAM_FLAG_GETREST, &channel, &nick, &reason); + if (!ignore_check(server, kicker, addr, channel, reason, MSGLEVEL_KICKS)) + { + printformat(server, channel, MSGLEVEL_KICKS, + IRCTXT_KICK, nick, channel, kicker, reason); + } + g_free(params); +} + +static void print_nick_change(IRC_SERVER_REC *server, const char *target, const char *newnick, const char *oldnick, const char *addr, int ownnick) +{ + if (ignore_check(server, oldnick, addr, target, newnick, MSGLEVEL_NICKS)) + return; + + if (ownnick) + printformat(server, target, MSGLEVEL_NICKS, IRCTXT_YOUR_NICK_CHANGED, newnick); + else + printformat(server, target, MSGLEVEL_NICKS, IRCTXT_NICK_CHANGED, oldnick, newnick); +} + +static void event_nick(gchar *data, IRC_SERVER_REC *server, gchar *sender, gchar *addr) +{ + GSList *tmp; + char *params, *newnick; + int ownnick, msgprint; + + g_return_if_fail(data != NULL); + + if (ignore_check(server, sender, addr, NULL, NULL, MSGLEVEL_NICKS)) + return; + + params = event_get_params(data, 1, &newnick); + + msgprint = FALSE; + ownnick = g_strcasecmp(sender, server->nick) == 0; + + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *channel = tmp->data; + + if (nicklist_find(channel, sender)) { + print_nick_change(server, channel->name, newnick, sender, addr, ownnick); + msgprint = TRUE; + } + } + + for (tmp = server->queries; tmp != NULL; tmp = tmp->next) { + QUERY_REC *query = tmp->data; + + if (g_strcasecmp(query->nick, sender) == 0) { + print_nick_change(server, query->nick, newnick, sender, addr, ownnick); + msgprint = TRUE; + } + } + + if (!msgprint && ownnick) + printformat(server, NULL, MSGLEVEL_NICKS, IRCTXT_YOUR_NICK_CHANGED, newnick); + g_free(params); +} + +static void event_mode(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +{ + char *params, *channel, *mode; + + g_return_if_fail(data != NULL); + if (nick == NULL) nick = server->real_address; + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &mode); + if (ignore_check(server, nick, addr, channel, mode, MSGLEVEL_MODES)) { + g_free(params); + return; + } + + if (!ischannel(*channel)) { + /* user mode change */ + printformat(server, NULL, MSGLEVEL_MODES, IRCTXT_USERMODE_CHANGE, mode, channel); + } else if (addr == NULL) { + /* channel mode changed by server */ + printformat(server, channel, MSGLEVEL_MODES, + IRCTXT_SERVER_CHANMODE_CHANGE, channel, mode, nick); + } else { + /* channel mode changed by normal user */ + printformat(server, channel, MSGLEVEL_MODES, + IRCTXT_CHANMODE_CHANGE, channel, mode, nick); + } + + g_free(params); +} + +static void event_pong(const char *data, IRC_SERVER_REC *server, const char *nick) +{ + char *params, *host, *reply; + + g_return_if_fail(data != NULL); + if (nick == NULL) nick = server->real_address; + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &host, &reply); + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_PONG, host, reply); + g_free(params); +} + +static void event_invite(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + gchar *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + if (*channel != '\0' && !ignore_check(server, nick, addr, channel, NULL, MSGLEVEL_INVITES)) + printformat(server, NULL, MSGLEVEL_INVITES, IRCTXT_INVITE, nick, channel); + g_free(params); +} + +static void event_topic(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + gchar *params, *channel, *topic; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &topic); + + if (!ignore_check(server, nick, addr, channel, topic, MSGLEVEL_TOPICS)) + printformat(server, channel, MSGLEVEL_TOPICS, + *topic != '\0' ? IRCTXT_NEW_TOPIC : IRCTXT_TOPIC_UNSET, + nick, channel, topic); + g_free(params); +} + +static void event_error(gchar *data, IRC_SERVER_REC *server) +{ + g_return_if_fail(data != NULL); + + if (*data == ':') data++; + printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_ERROR, data); +} + +static void event_wallops(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + g_return_if_fail(data != NULL); + + if (*data == ':') data++; + if (!ignore_check(server, nick, addr, NULL, data, MSGLEVEL_WALLOPS)) + { + if (g_strncasecmp(data, "\001ACTION", 7) != 0) + printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_WALLOPS, nick, data); + else + { + /* Action in WALLOP */ + gint len; + + data = g_strdup(data); + len = strlen(data); + if (data[len-1] == 1) data[len-1] = '\0'; + printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_ACTION_WALLOPS, nick, data); + g_free(data); + } + msg_beep_check(server, MSGLEVEL_WALLOPS); + } +} + +static void channel_sync(CHANNEL_REC *channel) +{ + g_return_if_fail(channel != NULL); + + printformat(channel->server, channel->name, MSGLEVEL_CLIENTNOTICE|MSGLEVEL_NO_ACT, IRCTXT_CHANNEL_SYNCED, + channel->name, (glong) (time(NULL)-channel->createtime)); +} + +static void event_connected(IRC_SERVER_REC *server) +{ + gchar *str; + + g_return_if_fail(server != NULL); + + if (*settings_get_str("default_nick") == '\0' || + g_strcasecmp(server->nick, settings_get_str("default_nick")) == 0) + return; + + /* someone has our nick, find out who. */ + str = g_strdup_printf("WHOIS %s", settings_get_str("default_nick")); + irc_send_cmd(server, str); + g_free(str); + + server_redirect_event((SERVER_REC *) server, settings_get_str("default_nick"), 1, + "event 318", "event empty", 1, + "event 401", "event empty", 1, + "event 311", "nickfind event whois", 1, + "event 301", "event empty", 1, + "event 312", "event empty", 1, + "event 313", "event empty", 1, + "event 317", "event empty", 1, + "event 319", "event empty", 1, NULL); + +} + +static void event_nickfind_whois(gchar *data, IRC_SERVER_REC *server) +{ + gchar *params, *nick, *user, *host, *realname; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname); + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_YOUR_NICK_OWNED, nick, user, host, realname); + g_free(params); +} + +static void event_ban_type_changed(gchar *bantype) +{ + GString *str; + + g_return_if_fail(bantype != NULL); + + if (strcmp(bantype, "UD") == 0) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, "Normal"); + else if (strcmp(bantype, "HD") == 0 || strcmp(bantype, "H") == 0) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, "Host"); + else if (strcmp(bantype, "D") == 0) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, "Domain"); + else + { + str = g_string_new("Custom:"); + if (*bantype == 'N') + { + g_string_append(str, " Nick"); + bantype++; + } + if (*bantype == 'U') + { + g_string_append(str, " User"); + bantype++; + } + if (*bantype == 'H') + { + g_string_append(str, " Host"); + bantype++; + } + if (*bantype == 'D') + g_string_append(str, " Domain"); + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, str->str); + g_string_free(str, TRUE); + } +} + +/*FIXME: move to core +static void event_perl_error(gchar *text) +{ + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_PERL_ERROR, text); +}*/ + +static void sig_server_lag_disconnected(IRC_SERVER_REC *server) +{ + g_return_if_fail(server != NULL); + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_LAG_DISCONNECTED, server->connrec->address, time(NULL)-server->lag_sent); +} + +static void sig_server_reconnect_removed(RECONNECT_REC *reconnect) +{ + g_return_if_fail(reconnect != NULL); + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_RECONNECT_REMOVED, reconnect->conn->address, reconnect->conn->port, + reconnect->conn->ircnet == NULL ? "" : reconnect->conn->ircnet); +} + +static void sig_server_reconnect_not_found(gchar *tag) +{ + g_return_if_fail(tag != NULL); + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_RECONNECT_NOT_FOUND, tag); +} + +static void event_received(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr) +{ + g_return_if_fail(data != NULL); + + if (!isdigit((gint) *data)) + printtext(server, NULL, MSGLEVEL_CRAP, "%s", data); + else + { + /* numeric event. */ + gchar *params, *cmd, *args, *ptr; + + params = event_get_params(data, 3 | PARAM_FLAG_GETREST, &cmd, NULL, &args); + ptr = strstr(args, " :"); + if (ptr != NULL) *(ptr+1) = ' '; + printtext(server, NULL, MSGLEVEL_CRAP, "%s", args); + g_free(params); + } +} + +static void sig_empty(void) +{ +} + +static void read_settings(void) +{ + beep_msg_level = level2bits(settings_get_str("beep_on_msg")); + beep_when_away = settings_get_bool("beep_when_away"); +} + +void fe_events_init(void) +{ + beep_msg_level = 0; + + read_settings(); + signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_add("ctcp msg", (SIGNAL_FUNC) ctcp_action_msg); + signal_add("ctcp msg action", (SIGNAL_FUNC) sig_empty); + signal_add("event notice", (SIGNAL_FUNC) event_notice); + signal_add("event join", (SIGNAL_FUNC) event_join); + signal_add("event part", (SIGNAL_FUNC) event_part); + signal_add("event quit", (SIGNAL_FUNC) event_quit); + signal_add("event kick", (SIGNAL_FUNC) event_kick); + signal_add("event nick", (SIGNAL_FUNC) event_nick); + signal_add("event mode", (SIGNAL_FUNC) event_mode); + signal_add("event pong", (SIGNAL_FUNC) event_pong); + signal_add("event invite", (SIGNAL_FUNC) event_invite); + signal_add("event topic", (SIGNAL_FUNC) event_topic); + signal_add("event error", (SIGNAL_FUNC) event_error); + signal_add("event wallops", (SIGNAL_FUNC) event_wallops); + + signal_add("default event", (SIGNAL_FUNC) event_received); + + signal_add("channel sync", (SIGNAL_FUNC) channel_sync); + signal_add("event connected", (SIGNAL_FUNC) event_connected); + signal_add("nickfind event whois", (SIGNAL_FUNC) event_nickfind_whois); + signal_add("ban type changed", (SIGNAL_FUNC) event_ban_type_changed); + //signal_add("perl error", (SIGNAL_FUNC) event_perl_error); + + signal_add("server lag disconnect", (SIGNAL_FUNC) sig_server_lag_disconnected); + signal_add("server reconnect remove", (SIGNAL_FUNC) sig_server_reconnect_removed); + signal_add("server reconnect not found", (SIGNAL_FUNC) sig_server_reconnect_not_found); + + signal_add("setup changed", (SIGNAL_FUNC) read_settings); +} + +void fe_events_deinit(void) +{ + signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_remove("ctcp msg", (SIGNAL_FUNC) ctcp_action_msg); + signal_remove("ctcp msg action", (SIGNAL_FUNC) sig_empty); + signal_remove("event notice", (SIGNAL_FUNC) event_notice); + signal_remove("event join", (SIGNAL_FUNC) event_join); + signal_remove("event part", (SIGNAL_FUNC) event_part); + signal_remove("event quit", (SIGNAL_FUNC) event_quit); + signal_remove("event kick", (SIGNAL_FUNC) event_kick); + signal_remove("event nick", (SIGNAL_FUNC) event_nick); + signal_remove("event mode", (SIGNAL_FUNC) event_mode); + signal_remove("event pong", (SIGNAL_FUNC) event_pong); + signal_remove("event invite", (SIGNAL_FUNC) event_invite); + signal_remove("event topic", (SIGNAL_FUNC) event_topic); + signal_remove("event error", (SIGNAL_FUNC) event_error); + signal_remove("event wallops", (SIGNAL_FUNC) event_wallops); + + signal_remove("default event", (SIGNAL_FUNC) event_received); + + signal_remove("channel sync", (SIGNAL_FUNC) channel_sync); + signal_remove("event connected", (SIGNAL_FUNC) event_connected); + signal_remove("nickfind event whois", (SIGNAL_FUNC) event_nickfind_whois); + signal_remove("ban type changed", (SIGNAL_FUNC) event_ban_type_changed); + //signal_remove("perl error", (SIGNAL_FUNC) event_perl_error); + + signal_remove("server lag disconnect", (SIGNAL_FUNC) sig_server_lag_disconnected); + signal_remove("server reconnect remove", (SIGNAL_FUNC) sig_server_reconnect_removed); + signal_remove("server reconnect not found", (SIGNAL_FUNC) sig_server_reconnect_not_found); + + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); +} diff --git a/src/fe-common/irc/fe-ignore.c b/src/fe-common/irc/fe-ignore.c new file mode 100644 index 00000000..35da7c84 --- /dev/null +++ b/src/fe-common/irc/fe-ignore.c @@ -0,0 +1,248 @@ +/* + fe-ignore.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "commands.h" +#include "levels.h" +#include "misc.h" + +#include "irc.h" +#include "irc-server.h" +#include "ignore.h" + +static char *ignore_get_key(IGNORE_REC *rec) +{ + char *chans, *ret; + + if (rec->channels == NULL) + return rec->mask != NULL ? g_strdup(rec->mask) : NULL; + + chans = g_strjoinv(",", rec->channels); + if (rec->mask == NULL) return chans; + + ret = g_strdup_printf("%s %s", rec->mask, chans); + g_free(chans); + return ret; +} + +static char *ignore_get_levels(int level, int xlevel) +{ + GString *str; + char *levelstr, *p, *ret; + + str = g_string_new(NULL); + if (level != 0) { + levelstr = bits2level(level); + g_string_append(str, levelstr); + g_free(levelstr); + } + + if (xlevel != 0) { + if (str->len > 0) g_string_append_c(str, ' '); + + levelstr = bits2level(xlevel); + for (p = levelstr; *p != '\0'; p++) { + if (!isspace(*p) && (p == levelstr || isspace(p[-1]))) + g_string_append_c(str, '^'); + g_string_append_c(str, *p); + } + g_free(levelstr); + } + + ret = str->str; + g_string_free(str, FALSE); + return ret; +} + +/* msgs ^notices : level=msgs, xlevel=notices */ +static void ignore_split_levels(const char *levels, int *level, int *xlevel) +{ + GString *slevel, *sxlevel; + char **levellist, **tmp; + + if (*levels == '\0') return; + + slevel = g_string_new(NULL); + sxlevel = g_string_new(NULL); + + levellist = g_strsplit(levels, " ", -1); + for (tmp = levellist; *tmp != NULL; tmp++) { + if (**tmp == '^') + g_string_sprintfa(sxlevel, "%s ", (*tmp)+1); + else if (**tmp == '-' && (*tmp)[1] == '^') + g_string_sprintfa(sxlevel, "-%s ", (*tmp)+2); + else + g_string_sprintfa(slevel, "%s ", *tmp); + } + g_strfreev(levellist); + + *level = combine_level(*level, slevel->str); + *xlevel = combine_level(*xlevel, sxlevel->str); + + g_string_free(slevel, TRUE); + g_string_free(sxlevel, TRUE); +} + +static void ignore_print(int index, IGNORE_REC *rec) +{ + char *key, *levels; + + key = ignore_get_key(rec); + levels = ignore_get_levels(rec->level, rec->except_level); + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, + IRCTXT_IGNORE_LINE, index, + key != NULL ? key : "", + levels != NULL ? levels : "", + rec->fullword ? " -word" : "", + rec->regexp ? " -regexp" : ""); + g_free(key); + g_free(levels); +} + +static void cmd_ignore_show(void) +{ + GSList *tmp; + int index; + + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_IGNORE_HEADER); + index = 1; + for (tmp = ignores; tmp != NULL; tmp = tmp->next, index++) { + IGNORE_REC *rec = tmp->data; + + ignore_print(index, rec); + } + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_IGNORE_FOOTER); +} + +static void cmd_ignore(const char *data) +{ + /* /IGNORE [-regexp | -word] [-pattern <pattern>] [-except] + [-channels <channel>] <mask> <levels> + OR + + /IGNORE [-regexp | -word] [-pattern <pattern>] [-except] + <channels> <levels> */ + char *params, *args, *patternarg, *chanarg, *mask, *levels, *key; + char **channels; + IGNORE_REC *rec; + int new_ignore; + + if (*data == '\0') { + cmd_ignore_show(); + return; + } + + args = "pattern channels"; + params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, + &args, &patternarg, &chanarg, &mask, &levels); + if (levels == 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + if (ischannel(*mask)) { + chanarg = mask; + mask = ""; + } + channels = *chanarg == '\0' ? NULL : + g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1); + + rec = ignore_find(NULL, mask, channels); + new_ignore = rec == NULL; + + if (rec == NULL) { + rec = g_new0(IGNORE_REC, 1); + + rec->mask = *mask == '\0' ? NULL : g_strdup(mask); + rec->channels = channels; + } else { + g_free_and_null(rec->pattern); + g_strfreev(channels); + } + + if (stristr(args, "-except") != NULL) { + rec->except_level = combine_level(rec->except_level, levels); + } else { + ignore_split_levels(levels, &rec->level, &rec->except_level); + } + + rec->pattern = *patternarg == '\0' ? NULL : g_strdup(patternarg); + rec->fullword = stristr(args, "-word") != NULL; + rec->regexp = stristr(args, "-regexp") != NULL; + + if (rec->level == 0 && rec->except_level == 0) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNIGNORED, rec->mask); + else { + key = ignore_get_key(rec); + levels = ignore_get_levels(rec->level, rec->except_level); + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_IGNORED, key, levels); + g_free(key); + g_free(levels); + } + + if (new_ignore) + ignore_add_rec(rec); + else + ignore_update_rec(rec); + + g_free(params); +} + +static void cmd_unignore(const char *data) +{ + IGNORE_REC *rec; + GSList *tmp; + char *key; + + if (is_numeric(data, ' ')) { + /* with index number */ + tmp = g_slist_nth(ignores, atol(data)-1); + rec = tmp == NULL ? NULL : tmp->data; + } else { + /* with mask */ + char *chans[2] = { "*", NULL }; + + if (ischannel(*data)) chans[0] = (char *) data; + rec = ignore_find("*", ischannel(*data) ? NULL : data, chans); + } + + if (rec == NULL) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_IGNORE_NOT_FOUND, data); + else { + key = ignore_get_key(rec); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNIGNORED, key); + g_free(key); + + rec->level = 0; + rec->except_level = 0; + ignore_update_rec(rec); + } +} + +void fe_ignore_init(void) +{ + command_bind("ignore", NULL, (SIGNAL_FUNC) cmd_ignore); + command_bind("unignore", NULL, (SIGNAL_FUNC) cmd_unignore); +} + +void fe_ignore_deinit(void) +{ + command_unbind("ignore", (SIGNAL_FUNC) cmd_ignore); + command_unbind("unignore", (SIGNAL_FUNC) cmd_unignore); +} diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c new file mode 100644 index 00000000..bdaa1376 --- /dev/null +++ b/src/fe-common/irc/fe-irc-commands.c @@ -0,0 +1,541 @@ +/* + fe-irc-commands.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "commands.h" +#include "special-vars.h" +#include "settings.h" + +#include "levels.h" +#include "irc.h" +#include "server.h" +#include "server-reconnect.h" +#include "mode-lists.h" +#include "nicklist.h" +#include "channels.h" +#include "query.h" + +#include "windows.h" +#include "window-items.h" + +static void cmd_server(const char *data) +{ + if (*data == '+' && data[1] != '\0') + window_create(NULL, FALSE); +} + +static void print_servers(void) +{ + GSList *tmp; + + for (tmp = servers; tmp != NULL; tmp = tmp->next) { + IRC_SERVER_REC *rec = tmp->data; + + printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_LIST, + rec->tag, rec->connrec->address, rec->connrec->port, + rec->connrec->ircnet == NULL ? "" : rec->connrec->ircnet, rec->connrec->nick); + } +} + +static void print_lookup_servers(void) +{ + GSList *tmp; + for (tmp = lookup_servers; tmp != NULL; tmp = tmp->next) { + IRC_SERVER_REC *rec = tmp->data; + + printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_LOOKUP_LIST, + rec->tag, rec->connrec->address, rec->connrec->port, + rec->connrec->ircnet == NULL ? "" : rec->connrec->ircnet, rec->connrec->nick); + } +} + +static void print_reconnects(void) +{ + GSList *tmp; + char *tag, *next_connect; + int left; + + for (tmp = reconnects; tmp != NULL; tmp = tmp->next) { + RECONNECT_REC *rec = tmp->data; + IRC_SERVER_CONNECT_REC *conn = rec->conn; + + tag = g_strdup_printf("RECON-%d", rec->tag); + left = rec->next_connect-time(NULL); + next_connect = g_strdup_printf("%02d:%02d", left/60, left%60); + printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_RECONNECT_LIST, + tag, conn->address, conn->port, + conn->ircnet == NULL ? "" : conn->ircnet, + conn->nick, next_connect); + g_free(next_connect); + g_free(tag); + } +} + +static void cmd_servers(void) +{ + print_servers(); + print_lookup_servers(); + print_reconnects(); +} + +static void cmd_unquery(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +{ + QUERY_REC *query; + + g_return_if_fail(data != NULL); + + if (*data == '\0') { + /* remove current query */ + query = irc_item_query(item); + if (query == NULL) return; + } else { + query = query_find(server, data); + if (query == NULL) { + printformat(server, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_NO_QUERY, data); + return; + } + } + + query_destroy(query); +} + +static void cmd_query(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +{ + WINDOW_REC *window; + QUERY_REC *query; + + g_return_if_fail(data != NULL); + + if (*data == '\0') { + /* remove current query */ + cmd_unquery("", server, item); + return; + } + + if (*data != '=' && (server == NULL || !server->connected)) + cmd_return_error(CMDERR_NOT_CONNECTED); + + query = query_find(server, data); + if (query != NULL) { + /* query already existed - change to query window */ + window = window_item_window((WI_ITEM_REC *) query); + g_return_if_fail(window != NULL); + + window_set_active(window); + window_item_set_active(window, (WI_ITEM_REC *) query); + return; + } + + query_create(server, data, FALSE); +} + +static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) +{ + WINDOW_REC *window; + CHANNEL_REC *channel; + NICK_REC *nickrec; + char *params, *target, *msg, *nickmode, *freestr, *newtarget; + int free_ret; + + g_return_if_fail(data != NULL); + + params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + if (*target == '=') + { + /* dcc msg - handled in fe-dcc.c */ + g_free(params); + return; + } + + free_ret = FALSE; + if (strcmp(target, ",") == 0 || strcmp(target, ".") == 0) + newtarget = parse_special(&target, server, item, NULL, &free_ret, NULL); + else if (strcmp(target, "*") == 0 && + (irc_item_channel(item) || irc_item_query(item))) + newtarget = item->name; + else newtarget = target; + + if (newtarget == NULL) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, *target == ',' ? + IRCTXT_NO_MSGS_GOT : IRCTXT_NO_MSGS_SENT); + g_free(params); + signal_stop(); + return; + } + target = newtarget; + + if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); + channel = channel_find(server, target); + + freestr = !free_ret ? NULL : target; + if (*target == '@' && ischannel(target[1])) + target++; /* Hybrid 6 feature, send msg to all ops in channel */ + + if (ischannel(*target)) + { + /* msg to channel */ + nickrec = channel == NULL ? NULL : nicklist_find(channel, server->nick); + nickmode = !settings_get_bool("toggle_show_nickmode") || nickrec == NULL ? "" : + nickrec->op ? "@" : nickrec->voice ? "+" : " "; + + window = channel == NULL ? NULL : window_item_window((WI_ITEM_REC *) channel); + if (window != NULL && window->active == (WI_ITEM_REC *) channel) + { + printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT, + IRCTXT_OWN_MSG, server->nick, msg, nickmode); + } + else + { + printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT, + IRCTXT_OWN_MSG_CHANNEL, server->nick, target, msg, nickmode); + } + } + else + { + /* private message */ + printformat(server, target, MSGLEVEL_MSGS | MSGLEVEL_NOHILIGHT, + channel == NULL ? IRCTXT_OWN_MSG_PRIVATE : IRCTXT_OWN_MSG_PRIVATE_QUERY, target, msg, server->nick); + } + g_free_not_null(freestr); + + g_free(params); +} + +static void cmd_notice(gchar *data, IRC_SERVER_REC *server) +{ + char *params, *target, *msg; + + g_return_if_fail(data != NULL); + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + + params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + if (*target == '@' && ischannel(target[1])) + target++; /* Hybrid 6 feature, send notice to all ops in channel */ + + printformat(server, target, MSGLEVEL_NOTICES | MSGLEVEL_NOHILIGHT, + IRCTXT_OWN_NOTICE, target, msg); + + g_free(params); +} + +static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +{ + g_return_if_fail(data != NULL); + + if (!irc_item_check(item)) + return; + + if (irc_item_dcc_chat(item)) { + /* DCC action - handled by fe-dcc.c */ + return; + } + + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + + printformat(server, item->name, MSGLEVEL_ACTIONS, + IRCTXT_OWN_ME, server->nick, data); + + irc_send_cmdv(server, "PRIVMSG %s :\001ACTION %s\001", item->name, data); +} + +static void cmd_action(const char *data, IRC_SERVER_REC *server) +{ + char *params, *target, *text; + + g_return_if_fail(data != NULL); + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + if (*data == '=') { + /* DCC action - handled by fe-dcc.c */ + return; + } + + params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text); + if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + printformat(server, target, MSGLEVEL_ACTIONS, IRCTXT_OWN_ME, server->nick, text); + irc_send_cmdv(server, "PRIVMSG %s :\001ACTION %s\001", target, text); + g_free(params); +} + +static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) +{ + char *params, *target, *ctcpcmd, *ctcpdata; + + g_return_if_fail(data != NULL); + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + + params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + if (*target == '=') { + /* send CTCP via DCC CHAT */ + g_free(params); + return; + } + if (*target == '@' && ischannel(target[1])) + target++; /* Hybrid 6 feature, send ctcp to all ops in channel */ + + g_strup(ctcpcmd); + printformat(server, target, MSGLEVEL_CTCPS, IRCTXT_OWN_CTCP, target, ctcpcmd, ctcpdata); + + g_free(params); +} + +static void cmd_nctcp(const char *data, IRC_SERVER_REC *server) +{ + gchar *params, *target, *ctcpcmd, *ctcpdata; + + g_return_if_fail(data != NULL); + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + + params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + if (*target == '@' && ischannel(target[1])) + target++; /* Hybrid 6 feature, send notice to all ops in channel */ + + g_strup(ctcpcmd); + printformat(server, target, MSGLEVEL_NOTICES, IRCTXT_OWN_NOTICE, target, ctcpcmd, ctcpdata); + + g_free(params); +} + +static void cmd_banstat(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +{ + CHANNEL_REC *cur_channel, *channel; + GSList *tmp; + + g_return_if_fail(data != NULL); + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + + cur_channel = irc_item_channel(item); + if (cur_channel == NULL) cmd_return_error(CMDERR_NOT_JOINED); + + if (strcmp(data, "*") == 0 || *data == '\0') + channel = cur_channel; + else { + channel = channel_find(server, data); + if (channel == NULL) { + /* not joined to such channel, but ask ban lists from server */ + GString *str; + + str = g_string_new(NULL); + g_string_sprintf(str, "%s b", data); + signal_emit("command mode", 3, str->str, server, cur_channel); + g_string_sprintf(str, "%s e", data); + signal_emit("command mode", 3, str->str, server, cur_channel); + g_string_free(str, TRUE); + return; + } + } + + if (channel == NULL) cmd_return_error(CMDERR_CHAN_NOT_FOUND); + + /* show bans.. */ + for (tmp = channel->banlist; tmp != NULL; tmp = tmp->next) { + BAN_REC *rec; + + rec = (BAN_REC *) tmp->data; + if (*rec->setby == '\0') + printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_BANLIST, channel->name, rec->ban); + else + printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_BANLIST, + channel->name, rec->ban, rec->setby, (gint) (time(NULL)-rec->time)); + } + + /* ..and show ban exceptions.. */ + for (tmp = channel->ebanlist; tmp != NULL; tmp = tmp->next) { + BAN_REC *rec; + + rec = (BAN_REC *) tmp->data; + if (*rec->setby == '\0') + printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_EBANLIST, channel->name, rec->ban); + else + printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_EBANLIST, + channel->name, rec->ban, rec->setby, (gint) (time(NULL)-rec->time)); + } +} + +static void cmd_invitelist(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +{ + CHANNEL_REC *channel, *cur_channel; + GSList *tmp; + + g_return_if_fail(data != NULL); + if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); + + cur_channel = irc_item_channel(item); + if (cur_channel == NULL) cmd_return_error(CMDERR_NOT_JOINED); + + if (strcmp(data, "*") == 0 || *data == '\0') + channel = cur_channel; + else + channel = channel_find(server, data); + if (channel == NULL) cmd_return_error(CMDERR_CHAN_NOT_FOUND); + + for (tmp = channel->invitelist; tmp != NULL; tmp = tmp->next) + printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_INVITELIST, channel->name, tmp->data); +} + +static void cmd_join(const char *data, IRC_SERVER_REC *server) +{ + if ((*data == '\0' || g_strncasecmp(data, "-invite", 7) == 0) && + server->last_invite == NULL) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOT_INVITED); + signal_stop(); + } +} + +static void cmd_channel(const char *data, IRC_SERVER_REC *server) +{ + CHANNEL_REC *channel; + GString *nicks; + GSList *nicklist, *tmp, *ntmp; + char *mode; + + if (*data != '\0') { + cmd_join(data, server); + return; + } + + if (channels == NULL) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOT_IN_CHANNELS); + return; + } + + /* print active channel */ + channel = irc_item_channel(active_win->active); + if (channel != NULL) + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CURRENT_CHANNEL, channel->name); + + /* print list of all channels, their modes, server tags and nicks */ + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANLIST_HEADER); + for (tmp = channels; tmp != NULL; tmp = tmp->next) { + channel = tmp->data; + + nicklist = nicklist_getnicks(channel); + mode = channel_get_mode(channel); + nicks = g_string_new(NULL); + for (ntmp = nicklist; ntmp != NULL; ntmp = ntmp->next) { + NICK_REC *rec = ntmp->data; + + g_string_sprintfa(nicks, "%s ", rec->nick); + } + + g_string_truncate(nicks, nicks->len-1); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANLIST_LINE, + channel->name, mode, channel->server->tag, nicks->str); + + g_free(mode); + g_slist_free(nicklist); + g_string_free(nicks, TRUE); + } +} + +static void cmd_nick(const char *data, IRC_SERVER_REC *server) +{ + g_return_if_fail(data != NULL); + + if (*data != '\0') return; + if (server == NULL || !server->connected) + cmd_return_error(CMDERR_NOT_CONNECTED); + + /* display current nick */ + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_YOUR_NICK, server->nick); + signal_stop(); +} + +static void cmd_ver(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +{ + char *str; + + g_return_if_fail(data != NULL); + + if (!irc_server_check(server)) + cmd_return_error(CMDERR_NOT_CONNECTED); + if (*data == '\0' && !irc_item_check(item)) + cmd_return_error(CMDERR_NOT_JOINED); + + str = g_strdup_printf("%s VERSION", *data == '\0' ? item->name : data); + signal_emit("command ctcp", 3, str, server, item); + g_free(str); +} + +static void cmd_ts(const char *data) +{ + GSList *tmp; + + g_return_if_fail(data != NULL); + + for (tmp = channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *rec = tmp->data; + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_TOPIC, + rec->name, rec->topic == NULL ? "" : rec->topic); + } +} + +void fe_irc_commands_init(void) +{ + command_bind("server", NULL, (SIGNAL_FUNC) cmd_server); + command_bind("servers", NULL, (SIGNAL_FUNC) cmd_servers); + command_bind("query", NULL, (SIGNAL_FUNC) cmd_query); + command_bind("unquery", NULL, (SIGNAL_FUNC) cmd_unquery); + command_bind("msg", NULL, (SIGNAL_FUNC) cmd_msg); + command_bind("notice", NULL, (SIGNAL_FUNC) cmd_notice); + command_bind("me", NULL, (SIGNAL_FUNC) cmd_me); + command_bind("action", NULL, (SIGNAL_FUNC) cmd_action); + command_bind("ctcp", NULL, (SIGNAL_FUNC) cmd_ctcp); + command_bind("nctcp", NULL, (SIGNAL_FUNC) cmd_nctcp); + command_bind("banstat", NULL, (SIGNAL_FUNC) cmd_banstat); + command_bind("invitelist", NULL, (SIGNAL_FUNC) cmd_invitelist); + command_bind("join", NULL, (SIGNAL_FUNC) cmd_join); + command_bind("channel", NULL, (SIGNAL_FUNC) cmd_channel); + command_bind("nick", NULL, (SIGNAL_FUNC) cmd_nick); + command_bind("ver", NULL, (SIGNAL_FUNC) cmd_ver); + command_bind("ts", NULL, (SIGNAL_FUNC) cmd_ts); +} + +void fe_irc_commands_deinit(void) +{ + command_unbind("server", (SIGNAL_FUNC) cmd_server); + command_unbind("servers", (SIGNAL_FUNC) cmd_servers); + command_unbind("query", (SIGNAL_FUNC) cmd_query); + command_unbind("unquery", (SIGNAL_FUNC) cmd_unquery); + command_unbind("msg", (SIGNAL_FUNC) cmd_msg); + command_unbind("notice", (SIGNAL_FUNC) cmd_notice); + command_unbind("me", (SIGNAL_FUNC) cmd_me); + command_unbind("action", (SIGNAL_FUNC) cmd_action); + command_unbind("ctcp", (SIGNAL_FUNC) cmd_ctcp); + command_unbind("nctcp", (SIGNAL_FUNC) cmd_nctcp); + command_unbind("banstat", (SIGNAL_FUNC) cmd_banstat); + command_unbind("invitelist", (SIGNAL_FUNC) cmd_invitelist); + command_unbind("join", (SIGNAL_FUNC) cmd_join); + command_unbind("channel", (SIGNAL_FUNC) cmd_channel); + command_unbind("nick", (SIGNAL_FUNC) cmd_nick); + command_unbind("ver", (SIGNAL_FUNC) cmd_ver); + command_unbind("ts", (SIGNAL_FUNC) cmd_ts); +} diff --git a/src/fe-common/irc/fe-query.c b/src/fe-common/irc/fe-query.c new file mode 100644 index 00000000..be46ea0b --- /dev/null +++ b/src/fe-common/irc/fe-query.c @@ -0,0 +1,133 @@ +/* + fe-query.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "modules.h" +#include "signals.h" +#include "commands.h" + +#include "irc.h" +#include "levels.h" +#include "query.h" + +#include "windows.h" +#include "window-items.h" + +static void signal_query_created(QUERY_REC *query, gpointer automatic) +{ + window_item_create((WI_ITEM_REC *) query, GPOINTER_TO_INT(automatic)); +} + +static void signal_query_created_curwin(QUERY_REC *query) +{ + g_return_if_fail(query != NULL); + + window_add_item(active_win, (WI_ITEM_REC *) query, FALSE); + signal_stop(); +} + +static void signal_query_destroyed(QUERY_REC *query) +{ + WINDOW_REC *window; + + g_return_if_fail(query != NULL); + + window = window_item_window((WI_ITEM_REC *) query); + if (window != NULL) window_remove_item(window, (WI_ITEM_REC *) query); +} + +static void signal_window_item_removed(WINDOW_REC *window, WI_ITEM_REC *item) +{ + QUERY_REC *query; + + g_return_if_fail(window != NULL); + + query = irc_item_query(item); + if (query != NULL) query_destroy(query); +} + +static void sig_server_connected(IRC_SERVER_REC *server) +{ + GSList *tmp; + + if (!irc_server_check(server)) + return; + + /* check if there's any queries without server */ + for (tmp = queries; tmp != NULL; tmp = tmp->next) { + QUERY_REC *rec = tmp->data; + + if (rec->server == NULL && + g_strcasecmp(rec->server_tag, server->tag) == 0) { + window_item_change_server((WI_ITEM_REC *) rec, server); + server->queries = g_slist_append(server->queries, rec); + } + } +} + +static void cmd_window_server(const char *data) +{ + SERVER_REC *server; + + g_return_if_fail(data != NULL); + + server = server_find_tag(data); + if (irc_server_check(server) && irc_item_query(active_win->active)) { + /* /WINDOW SERVER used in a query window */ + query_change_server((QUERY_REC *) active_win->active, + (IRC_SERVER_REC *) server); + window_change_server(active_win, server); + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_QUERY_SERVER_CHANGED, server->tag, server->connrec->address, + server->connrec->ircnet == NULL ? "" : server->connrec->ircnet); + + signal_stop(); + } +} + +static void cmd_wquery(const char *data, void *server, WI_ITEM_REC *item) +{ + signal_add("query created", (SIGNAL_FUNC) signal_query_created_curwin); + signal_emit("command query", 3, data, server, item); + signal_remove("query created", (SIGNAL_FUNC) signal_query_created_curwin); +} + +void fe_query_init(void) +{ + signal_add("query created", (SIGNAL_FUNC) signal_query_created); + signal_add("query destroyed", (SIGNAL_FUNC) signal_query_destroyed); + signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_removed); + signal_add("server connected", (SIGNAL_FUNC) sig_server_connected); + + command_bind("wquery", NULL, (SIGNAL_FUNC) cmd_wquery); + command_bind("window server", NULL, (SIGNAL_FUNC) cmd_window_server); +} + +void fe_query_deinit(void) +{ + signal_remove("query created", (SIGNAL_FUNC) signal_query_created); + signal_remove("query destroyed", (SIGNAL_FUNC) signal_query_destroyed); + signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_removed); + signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected); + + command_unbind("wquery", (SIGNAL_FUNC) cmd_wquery); + command_unbind("window server", (SIGNAL_FUNC) cmd_window_server); +} diff --git a/src/fe-common/irc/flood/Makefile.am b/src/fe-common/irc/flood/Makefile.am new file mode 100644 index 00000000..c802dfd9 --- /dev/null +++ b/src/fe-common/irc/flood/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libfe_common_irc_flood.la + +INCLUDES = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/core/ \ + -I$(top_srcdir)/src/irc/core/ \ + -I$(top_srcdir)/src/fe-common/core/ \ + -DHELPDIR=\""$(datadir)/irssi/help"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" + +libfe_common_irc_flood_la_SOURCES = \ + fe-flood.c \ + module-formats.c + +noinst_headers = \ + module-formats.h diff --git a/src/fe-common/irc/flood/fe-flood.c b/src/fe-common/irc/flood/fe-flood.c new file mode 100644 index 00000000..d21d6952 --- /dev/null +++ b/src/fe-common/irc/flood/fe-flood.c @@ -0,0 +1,54 @@ +/* + fe-flood.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "levels.h" + +#include "irc-server.h" +#include "irc/flood/autoignore.h" + +static void event_autoignore_new(IRC_SERVER_REC *server, AUTOIGNORE_REC *ignore) +{ + g_return_if_fail(ignore != NULL); + + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_AUTOIGNORE, + ignore->nick, (ignore->timeleft+59)/60); +} + +static void event_autoignore_remove(IRC_SERVER_REC *server, AUTOIGNORE_REC *ignore) +{ + g_return_if_fail(ignore != NULL); + + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_AUTOUNIGNORE, ignore->nick); +} + +void fe_flood_init(void) +{ + signal_add("autoignore new", (SIGNAL_FUNC) event_autoignore_new); + signal_add("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove); +} + +void fe_flood_deinit(void) +{ + signal_remove("autoignore new", (SIGNAL_FUNC) event_autoignore_new); + signal_remove("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove); +} diff --git a/src/fe-common/irc/flood/module-formats.c b/src/fe-common/irc/flood/module-formats.c new file mode 100644 index 00000000..942c13d6 --- /dev/null +++ b/src/fe-common/irc/flood/module-formats.c @@ -0,0 +1,33 @@ +/* + module-formats.c : irssi + + Copyright (C) 2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "printtext.h" + +FORMAT_REC fecommon_irc_flood_formats[] = +{ + { MODULE_NAME, N_("Flood"), 0 }, + + /* ---- */ + { NULL, N_("Autoignore"), 0 }, + + { "autoignore", N_("Flood detected from %_$0%_, autoignoring for %_$1%_ minutes"), 2, { 0, 1 } }, + { "autounignore", N_("Unignoring %_$0"), 1, { 0 } } +}; diff --git a/src/fe-common/irc/flood/module-formats.h b/src/fe-common/irc/flood/module-formats.h new file mode 100644 index 00000000..b435a752 --- /dev/null +++ b/src/fe-common/irc/flood/module-formats.h @@ -0,0 +1,13 @@ +#include "printtext.h" + +enum { + IRCTXT_MODULE_NAME, + + IRCTXT_FILL_1, + + IRCTXT_AUTOIGNORE, + IRCTXT_AUTOUNIGNORE +}; + +extern FORMAT_REC fecommon_irc_flood_formats[]; +#define MODULE_FORMATS fecommon_irc_flood_formats diff --git a/src/fe-common/irc/irc-hilight-text.c b/src/fe-common/irc/irc-hilight-text.c new file mode 100644 index 00000000..da9bb258 --- /dev/null +++ b/src/fe-common/irc/irc-hilight-text.c @@ -0,0 +1,54 @@ +/* + irc-hilight-text.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" + +#include "hilight-text.h" + +char *irc_hilight_find_nick(const char *channel, const char *nick, const char *address) +{ + GSList *tmp; + char *color; + int len, best_match; + + g_return_val_if_fail(channel != NULL, NULL); + g_return_val_if_fail(nick != NULL, NULL); + g_return_val_if_fail(address != NULL, NULL); + + color = NULL; best_match = 0; + for (tmp = hilights; tmp != NULL; tmp = tmp->next) { + HILIGHT_REC *rec = tmp->data; + + if (!rec->nickmask) + continue; + + len = strlen(rec->text); + if (best_match < len) { + best_match = len; + color = rec->color; + } + } + + if (best_match == 0) + return NULL; + + if (color == NULL) color = "\00316"; + return g_strconcat(isdigit(*color) ? "\003" : "", color, NULL); +} diff --git a/src/fe-common/irc/irc-hilight-text.h b/src/fe-common/irc/irc-hilight-text.h new file mode 100644 index 00000000..6acf8a8b --- /dev/null +++ b/src/fe-common/irc/irc-hilight-text.h @@ -0,0 +1,6 @@ +#ifndef __IRC_HILIGHT_TEXT_H +#define __IRC_HILIGHT_TEXT_H + +char *irc_hilight_find_nick(const char *channel, const char *nick, const char *address); + +#endif diff --git a/src/fe-common/irc/irc-nick-hilight.c b/src/fe-common/irc/irc-nick-hilight.c new file mode 100644 index 00000000..0d790822 --- /dev/null +++ b/src/fe-common/irc/irc-nick-hilight.c @@ -0,0 +1,89 @@ +/* + irc-nick-hilight.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "signals.h" +#include "levels.h" + +#include "irc.h" +#include "ignore.h" +#include "irc-server.h" + +#include "completion.h" +#include "windows.h" +#include "window-items.h" + +static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +{ + WINDOW_REC *window; + WI_ITEM_REC *item; + char *params, *target, *msg; + int level; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + + if (*msg == 1) { + /* don't hilight CTCPs */ + g_free(params); + return; + } + + /* get window and window item */ + level = ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS; + item = window_item_find(server, ischannel(*target) ? target : nick); + window = item == NULL ? + window_find_closest(server, target, GPOINTER_TO_INT(level)) : + window_item_window(item); + + /* check that msg wasn't send to current window and + that it didn't get ignored */ + if (window != active_win && !ignore_check(server, nick, addr, target, msg, level)) { + /* hilight */ + level = !ischannel(*target) || + completion_msgtoyou((SERVER_REC *) server, msg) ? + NEWDATA_MSG_FORYOU : NEWDATA_MSG; + if (item != NULL && item->new_data < level) { + item->new_data = level; + signal_emit("window item hilight", 1, item); + } else { + int oldlevel = window->new_data; + + if (window->new_data < level) { + window->new_data = level; + signal_emit("window hilight", 2, window, GINT_TO_POINTER(oldlevel)); + } + signal_emit("window activity", 2, window, GINT_TO_POINTER(oldlevel)); + } + } + + g_free(params); +} + +void irc_nick_hilight_init(void) +{ + signal_add_last("event privmsg", (SIGNAL_FUNC) event_privmsg); +} + +void irc_nick_hilight_deinit(void) +{ + signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); +} diff --git a/src/fe-common/irc/module-formats.c b/src/fe-common/irc/module-formats.c new file mode 100644 index 00000000..5097e2aa --- /dev/null +++ b/src/fe-common/irc/module-formats.c @@ -0,0 +1,174 @@ +/* + module-formats.c : irssi + + Copyright (C) 2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "printtext.h" + +FORMAT_REC fecommon_irc_formats[] = +{ + { MODULE_NAME, N_("IRC"), 0 }, + + /* ---- */ + { NULL, N_("Server"), 0 }, + + { "lag_disconnected", N_("No PONG reply from server %_$0%_ in $1 seconds, disconnecting"), 2, { 0, 1 } }, + { "disconnected", N_("Disconnected from %_$0%_ %K[%n$1%K]"), 2, { 0, 0 } }, + { "server_list", N_("%_$0%_: $1:$2 ($3)"), 5, { 0, 0, 1, 0, 0 } }, + { "server_lookup_list", N_("%_$0%_: $1:$2 ($3) (connecting...)"), 5, { 0, 0, 1, 0, 0 } }, + { "server_reconnect_list", N_("%_$0%_: $1:$2 ($3) ($5 left before reconnecting)"), 6, { 0, 0, 1, 0, 0, 0 } }, + { "server_reconnect_removed", N_("Removed reconnection to server %_$0%_ port %_$1%_"), 3, { 0, 1, 0 } }, + { "server_reconnect_not_found", N_("Reconnection tag %_$0%_ not found"), 1, { 0 } }, + { "query_server_changed", N_("Query with %_$2%_ changed to server %_$1%_"), 3, { 0, 0, 0 } }, + + /* ---- */ + { NULL, N_("Channels"), 0 }, + + { "join", N_("%c%_$0%_ %K[%c$1%K]%n has joined %_$2"), 3, { 0, 0, 0 } }, + { "part", N_("%c$0 %K[%n$1%K]%n has left %_$2%_ %K[%n$3%K]"), 4, { 0, 0, 0, 0 } }, + { "joinerror_toomany", N_("Cannot join to channel %_$0%_ %K(%nYou have joined to too many channels%K)"), 1, { 0 } }, + { "joinerror_full", N_("Cannot join to channel %_$0%_ %K(%nChannel is full%K)"), 1, { 0 } }, + { "joinerror_invite", N_("Cannot join to channel %_$0%_ %K(%nYou must be invited%K)"), 1, { 0 } }, + { "joinerror_banned", N_("Cannot join to channel %_$0%_ %K(%nYou are banned%K)"), 1, { 0 } }, + { "joinerror_bad_key", N_("Cannot join to channel %_$0%_ %K(%nBad channel key%K)"), 1, { 0 } }, + { "joinerror_bad_mask", N_("Cannot join to channel %_$0%_ %K(%nBad channel mask%K)"), 1, { 0 } }, + { "joinerror_unavail", N_("Cannot join to channel %_$0%_ %K(%nChannel is temporarily unavailable%K)"), 1, { 0 } }, + { "kick", N_("%c$0%n was kicked from %_$1%_ by %_$2%_ %K[%n$3%K]"), 4, { 0, 0, 0, 0 } }, + { "quit", N_("%c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]"), 3, { 0, 0, 0 } }, + { "quit_once", N_("%_$3%_ %c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]"), 4, { 0, 0, 0, 0 } }, + { "invite", N_("%_$0%_ invites you to %_$1"), 2, { 0, 0 } }, + { "not_invited", N_("You have not been invited to a channel!"), 0 }, + { "names", N_("%K[%g%_Users%_%K(%g$0%K)]%n $1"), 2, { 0, 0 } }, + { "endofnames", N_("%g%_$0%_%K:%n Total of %_$1%_ nicks %K[%n%_$2%_ ops, %_$3%_ voices, %_$4%_ normal%K]"), 5, { 0, 1, 1, 1, 1 } }, + { "channel_created", N_("Channel %_$0%_ created $1"), 2, { 0, 0 } }, + { "topic", N_("Topic for %c$0%K:%n $1"), 2, { 0, 0 } }, + { "no_topic", N_("No topic set for %c$0"), 1, { 0 } }, + { "new_topic", N_("%_$0%_ changed the topic of %c$1%n to%K:%n $2"), 3, { 0, 0, 0 } }, + { "topic_unset", N_("Topic unset by %_$0%_ on %c$1"), 2, { 0, 0 } }, + { "topic_info", N_("Topic set by %_$0%_ %K[%n$1%K]"), 2, { 0, 0 } }, + { "chanmode_change", N_("mode/%c$0 %K[%n$1%K]%n by %_$2"), 3, { 0, 0, 0 } }, + { "server_chanmode_change", N_("%RServerMode/%c$0 %K[%n$1%K]%n by %_$2"), 3, { 0, 0, 0 } }, + { "channel_mode", N_("mode/%c$0 %K[%n$1%K]"), 2, { 0, 0 } }, + { "bantype", N_("Ban type changed to %_$0"), 1, { 0 } }, + { "banlist", N_("%_$0%_: ban %c$1"), 2, { 0, 0 } }, + { "banlist_long", N_("%_$0%_: ban %c$1 %K[%nby %_$2%_, $3 secs ago%K]"), 4, { 0, 0, 0, 1 } }, + { "ebanlist", N_("%_$0%_: ban exception %c$1"), 2, { 0, 0 } }, + { "ebanlist_long", N_("%_$0%_: ban exception %c$1 %K[%nby %_$2%_, $3 secs ago%K]"), 4, { 0, 0, 0, 1 } }, + { "invitelist", N_("%_$0%_: invite %c$1"), 2, { 0, 0 } }, + { "no_such_channel", N_("$0: No such channel"), 1, { 0 } }, + { "not_in_channels", N_("You are not on any channels"), 0 }, + { "current_channel", N_("Current channel $0"), 1, { 0 } }, + { "chanlist_header", N_("You are on the following channels:"), 0 }, + { "chanlist_line", N_("$[-10]0 %|+$1 ($2): $3"), 4, { 0, 0, 0, 0 } }, + { "channel_synced", N_("Join to %_$0%_ was synced in %_$1%_ secs"), 2, { 0, 2 } }, + + /* ---- */ + { NULL, N_("Nick"), 0 }, + + { "usermode_change", N_("Mode change %K[%n%_$0%_%K]%n for user %c$1"), 2, { 0, 0 } }, + { "user_mode", N_("Your user mode is %K[%n%_$0%_%K]"), 1, { 0 } }, + { "away", N_("You have been marked as being away"), 0 }, + { "unaway", N_("You are no longer marked as being away"), 0 }, + { "nick_away", N_("$0 is away: $1"), 2, { 0, 0 } }, + { "no_such_nick", N_("$0: No such nick/channel"), 1, { 0 } }, + { "your_nick", N_("Your nickname is $0"), 1, { 0 } }, + { "your_nick_changed", N_("You're now known as %c$0"), 1, { 0 } }, + { "nick_changed", N_("%_$0%_ is now known as %c$1"), 2, { 0, 0 } }, + { "nick_in_use", N_("Nick %_$0%_ is already in use"), 1, { 0 } }, + { "nick_unavailable", N_("Nick %_$0%_ is temporarily unavailable"), 1, { 0 } }, + { "your_nick_owned", N_("Your nick is owned by %_$3%_ %K[%n$1@$2%K]"), 4, { 0, 0, 0, 0 } }, + + /* ---- */ + { NULL, N_("Who queries"), 0 }, + + { "whois", N_("%_$0%_ %K[%n$1@$2%K]%n%: ircname : $3"), 4, { 0, 0, 0, 0 } }, + { "whois_idle", N_(" idle : $1 hours $2 mins $3 secs"), 4, { 0, 1, 1, 1 } }, + { "whois_idle_signon", N_(" idle : $1 hours $2 mins $3 secs %K[%nsignon: $4%K]"), 5, { 0, 1, 1, 1, 0 } }, + { "whois_server", N_(" server : $1 %K[%n$2%K]"), 3, { 0, 0, 0 } }, + { "whois_oper", N_(" : %_IRC operator%_"), 1, { 0 } }, + { "whois_channels", N_(" channels : $1"), 2, { 0, 0 } }, + { "whois_away", N_(" away : $1"), 2, { 0, 0 } }, + { "end_of_whois", N_("End of WHOIS"), 1, { 0 } }, + { "who", N_("$[-10]0 %|%_$[!9]1%_ $[!3]2 $[!2]3 $4@$5 %K(%W$6%K)"), 7, { 0, 0, 0, 0, 0, 0, 0 } }, + { "end_of_who", N_("End of /WHO list"), 1, { 0 } }, + + /* ---- */ + { NULL, N_("Your messages"), 0 }, + + { "own_msg", N_("%K<%n$2%W$0%K>%n %|$1"), 3, { 0, 0, 0 } }, + { "own_msg_channel", N_("%K<%n$3%W$0%K:%c$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } }, + { "own_msg_private", N_("%K[%rmsg%K(%R$0%K)]%n $1"), 2, { 0, 0 } }, + { "own_msg_private_query", N_("%K<%W$2%K>%n %|$1"), 3, { 0, 0, 0 } }, + { "own_notice", N_("%K[%rnotice%K(%R$0%K)]%n $1"), 2, { 0, 0 } }, + { "own_me", N_("%W * $0%n $1"), 2, { 0, 0 } }, + { "own_ctcp", N_("%K[%rctcp%K(%R$0%K)]%n $1 $2"), 3, { 0, 0, 0 } }, + + /* ---- */ + { NULL, N_("Received messages"), 0 }, + + { "pubmsg_me", N_("%K<%n$2%Y$0%K>%n %|$1"), 3, { 0, 0, 0 } }, + { "pubmsg_me_channel", N_("%K<%n$3%Y$0%K:%c$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } }, + { "pubmsg_hilight", N_("%K<%n$3$0$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } }, + { "pubmsg_hilight_channel", N_("%K<%n$4$0$1%K:%c$2%K>%n %|$3"), 5, { 0, 0, 0, 0, 0 } }, + { "pubmsg", N_("%K<%n$2$0%K>%n %|$1"), 3, { 0, 0, 0 } }, + { "pubmsg_channel", N_("%K<%n$3$0%K:%c$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } }, + { "msg_private", N_("%K[%R$0%K(%r$1%K)]%n $2"), 3, { 0, 0, 0 } }, + { "msg_private_query", N_("%K<%R$0%K>%n %|$2"), 3, { 0, 0, 0 } }, + { "notice_server", N_("%g!$0%n $1"), 2, { 0, 0 } }, + { "notice_public", N_("%K-%M$0%K:%m$1%K-%n $2"), 3, { 0, 0, 0 } }, + { "notice_public_ops", N_("%K-%M$0%K:%m@$1%K-%n $2"), 3, { 0, 0, 0 } }, + { "notice_private", N_("%K-%M$0%K(%m$1%K)-%n $2"), 3, { 0, 0, 0 } }, + { "action_private", N_("%W (*) $0%n $2"), 3, { 0, 0, 0 } }, + { "action_private_query", N_("%W * $0%n $2"), 3, { 0, 0, 0 } }, + { "action_public", N_("%W * $0%n $1"), 2, { 0, 0 } }, + { "action_public_channel", N_("%W * $0%K:%c$1%n $2"), 3, { 0, 0, 0 } }, + + /* ---- */ + { NULL, N_("CTCPs"), 0 }, + + { "ctcp_reply", N_("CTCP %_$0%_ reply from %_$1%_%K:%n $2"), 3, { 0, 0, 0 } }, + { "ctcp_ping_reply", N_("CTCP %_PING%_ reply from %_$0%_: $1.$2 seconds"), 3, { 0, 2, 2 } }, + { "ctcp_requested", N_("%g>>> %_$0%_ %K[%g$1%K] %grequested %_$2%_ from %_$3"), 4, { 0, 0, 0, 0 } }, + + /* ---- */ + { NULL, N_("Other server events"), 0 }, + + { "online", N_("Users online: %_$0"), 1, { 0 } }, + { "pong", N_("PONG received from $0: $1"), 2, { 0, 0 } }, + { "wallops", N_("%WWALLOP%n $0: $1"), 2, { 0, 0 } }, + { "action_wallops", N_("%WWALLOP * $0%n $1"), 2, { 0, 0 } }, + { "error", N_("%_ERROR%_ $0"), 1, { 0 } }, + { "unknown_mode", N_("Unknown mode character $0"), 1, { 0 } }, + { "not_chanop", N_("You're not channel operator in $0"), 1, { 0 } }, + + /* ---- */ + { NULL, N_("Misc"), 0 }, + + { "ignored", N_("Ignoring %_$1%_ from %_$0%_"), 2, { 0, 0 } }, + { "unignored", N_("Unignored %_$0%_"), 1, { 0 } }, + { "ignore_not_found", N_("%_$0%_ is not being ignored"), 1, { 0 } }, + { "ignore_no_ignores", N_("There are no ignores"), 0 }, + { "ignore_header", N_("Ignorance List:"), 0 }, + { "ignore_line", N_("$[-4]0 $1: $2 $3 $4"), 5, { 1, 0, 0, 0, 0 } }, + { "ignore_footer", N_(""), 0 }, + { "talking_in", N_("You are now talking in %_$0%_"), 1, { 0 } }, + { "no_query", N_("No query with %_$0%_"), 1, { 0 } }, + { "no_msgs_got", N_("You have not received a message from anyone yet"), 0 }, + { "no_msgs_sent", N_("You have not sent a message to anyone yet"), 0 } +}; diff --git a/src/fe-common/irc/module-formats.h b/src/fe-common/irc/module-formats.h new file mode 100644 index 00000000..004e6008 --- /dev/null +++ b/src/fe-common/irc/module-formats.h @@ -0,0 +1,146 @@ +#include "printtext.h" + +enum { + IRCTXT_MODULE_NAME, + + IRCTXT_FILL_1, + + IRCTXT_LAG_DISCONNECTED, + IRCTXT_DISCONNECTED, + IRCTXT_SERVER_LIST, + IRCTXT_SERVER_LOOKUP_LIST, + IRCTXT_SERVER_RECONNECT_LIST, + IRCTXT_RECONNECT_REMOVED, + IRCTXT_RECONNECT_NOT_FOUND, + IRCTXT_QUERY_SERVER_CHANGED, + + IRCTXT_FILL_2, + + IRCTXT_JOIN, + IRCTXT_PART, + IRCTXT_JOINERROR_TOOMANY, + IRCTXT_JOINERROR_FULL, + IRCTXT_JOINERROR_INVITE, + IRCTXT_JOINERROR_BANNED, + IRCTXT_JOINERROR_BAD_KEY, + IRCTXT_JOINERROR_BAD_MASK, + IRCTXT_JOINERROR_UNAVAIL, + IRCTXT_KICK, + IRCTXT_QUIT, + IRCTXT_QUIT_ONCE, + IRCTXT_INVITE, + IRCTXT_NOT_INVITED, + IRCTXT_NAMES, + IRCTXT_ENDOFNAMES, + IRCTXT_CHANNEL_CREATED, + IRCTXT_TOPIC, + IRCTXT_NO_TOPIC, + IRCTXT_NEW_TOPIC, + IRCTXT_TOPIC_UNSET, + IRCTXT_TOPIC_INFO, + IRCTXT_CHANMODE_CHANGE, + IRCTXT_SERVER_CHANMODE_CHANGE, + IRCTXT_CHANNEL_MODE, + IRCTXT_BANTYPE, + IRCTXT_BANLIST, + IRCTXT_BANLIST_LONG, + IRCTXT_EBANLIST, + IRCTXT_EBANLIST_LONG, + IRCTXT_INVITELIST, + IRCTXT_NO_SUCH_CHANNEL, + IRCTXT_NOT_IN_CHANNELS, + IRCTXT_CURRENT_CHANNEL, + IRCTXT_CHANLIST_HEADER, + IRCTXT_CHANLIST_LINE, + IRCTXT_CHANNEL_SYNCED, + + IRCTXT_FILL_4, + + IRCTXT_USERMODE_CHANGE, + IRCTXT_USER_MODE, + IRCTXT_AWAY, + IRCTXT_UNAWAY, + IRCTXT_NICK_AWAY, + IRCTXT_NO_SUCH_NICK, + IRCTXT_YOUR_NICK, + IRCTXT_YOUR_NICK_CHANGED, + IRCTXT_NICK_CHANGED, + IRCTXT_NICK_IN_USE, + IRCTXT_NICK_UNAVAILABLE, + IRCTXT_YOUR_NICK_OWNED, + + IRCTXT_FILL_5, + + IRCTXT_WHOIS, + IRCTXT_WHOIS_IDLE, + IRCTXT_WHOIS_IDLE_SIGNON, + IRCTXT_WHOIS_SERVER, + IRCTXT_WHOIS_OPER, + IRCTXT_WHOIS_CHANNELS, + IRCTXT_WHOIS_AWAY, + IRCTXT_END_OF_WHOIS, + IRCTXT_WHO, + IRCTXT_END_OF_WHO, + + IRCTXT_FILL_6, + + IRCTXT_OWN_MSG, + IRCTXT_OWN_MSG_CHANNEL, + IRCTXT_OWN_MSG_PRIVATE, + IRCTXT_OWN_MSG_PRIVATE_QUERY, + IRCTXT_OWN_NOTICE, + IRCTXT_OWN_ME, + IRCTXT_OWN_CTCP, + + IRCTXT_FILL_7, + + IRCTXT_PUBMSG_ME, + IRCTXT_PUBMSG_ME_CHANNEL, + IRCTXT_PUBMSG_HILIGHT, + IRCTXT_PUBMSG_HILIGHT_CHANNEL, + IRCTXT_PUBMSG, + IRCTXT_PUBMSG_CHANNEL, + IRCTXT_MSG_PRIVATE, + IRCTXT_MSG_PRIVATE_QUERY, + IRCTXT_NOTICE_SERVER, + IRCTXT_NOTICE_PUBLIC, + IRCTXT_NOTICE_PUBLIC_OPS, + IRCTXT_NOTICE_PRIVATE, + IRCTXT_ACTION_PRIVATE, + IRCTXT_ACTION_PRIVATE_QUERY, + IRCTXT_ACTION_PUBLIC, + IRCTXT_ACTION_PUBLIC_CHANNEL, + + IRCTXT_FILL_8, + + IRCTXT_CTCP_REPLY, + IRCTXT_CTCP_PING_REPLY, + IRCTXT_CTCP_REQUESTED, + + IRCTXT_FILL_10, + + IRCTXT_ONLINE, + IRCTXT_PONG, + IRCTXT_WALLOPS, + IRCTXT_ACTION_WALLOPS, + IRCTXT_ERROR, + IRCTXT_UNKNOWN_MODE, + IRCTXT_NOT_CHANOP, + + IRCTXT_FILL_11, + + IRCTXT_IGNORED, + IRCTXT_UNIGNORED, + IRCTXT_IGNORE_NOT_FOUND, + IRCTXT_IGNORE_NO_IGNORES, + IRCTXT_IGNORE_HEADER, + IRCTXT_IGNORE_LINE, + IRCTXT_IGNORE_FOOTER, + IRCTXT_TALKING_IN, + IRCTXT_NO_QUERY, + IRCTXT_NO_MSGS_GOT, + IRCTXT_NO_MSGS_SENT +}; + +extern FORMAT_REC fecommon_irc_formats[]; +#define MODULE_FORMATS fecommon_irc_formats diff --git a/src/fe-common/irc/module.h b/src/fe-common/irc/module.h new file mode 100644 index 00000000..e1cc2773 --- /dev/null +++ b/src/fe-common/irc/module.h @@ -0,0 +1,3 @@ +#include "common.h" + +#define MODULE_NAME "fe-common/irc" diff --git a/src/fe-common/irc/notifylist/Makefile.am b/src/fe-common/irc/notifylist/Makefile.am new file mode 100644 index 00000000..c44da278 --- /dev/null +++ b/src/fe-common/irc/notifylist/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libfe_common_irc_notifylist.la + +INCLUDES = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/core/ \ + -I$(top_srcdir)/src/irc/core/ \ + -I$(top_srcdir)/src/fe-common/core/ \ + -DHELPDIR=\""$(datadir)/irssi/help"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" + +libfe_common_irc_notifylist_la_SOURCES = \ + fe-notifylist.c \ + module-formats.c + +noinst_headers = \ + module-formats.h diff --git a/src/fe-common/irc/notifylist/fe-notifylist.c b/src/fe-common/irc/notifylist/fe-notifylist.c new file mode 100644 index 00000000..7520cdb8 --- /dev/null +++ b/src/fe-common/irc/notifylist/fe-notifylist.c @@ -0,0 +1,241 @@ +/* + fe-notifylist.c : irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "commands.h" +#include "misc.h" +#include "lib-config/iconfig.h" +#include "settings.h" + +#include "levels.h" +#include "irc-server.h" +#include "ircnet-setup.h" +#include "irc/notifylist/notifylist.h" + +/* add the nick of a hostmask to list if it isn't there already */ +static GSList *mask_add_once(GSList *list, const char *mask) +{ + char *str, *ptr; + + g_return_val_if_fail(mask != NULL, NULL); + + ptr = strchr(mask, '!'); + str = ptr == NULL ? g_strdup(mask) : + g_strndup(mask, (int) (ptr-mask)+1); + + if (gslist_find_icase_string(list, str) == NULL) + return g_slist_append(list, str); + + g_free(str); + return list; +} + +/* search for online people, print them and update offline list */ +static void print_notify_onserver(IRC_SERVER_REC *server, GSList *nicks, + GSList **offline, const char *desc) +{ + GSList *tmp; + GString *str; + + g_return_if_fail(server != NULL); + g_return_if_fail(offline != NULL); + g_return_if_fail(desc != NULL); + + str = g_string_new(NULL); + for (tmp = nicks; tmp != NULL; tmp = tmp->next) { + char *nick = tmp->data; + + if (!notifylist_ison_server(server, nick)) + continue; + + g_string_sprintfa(str, "%s, ", nick); + *offline = g_slist_remove(*offline, nick); + } + + if (str->len > 0) { + g_string_truncate(str, str->len-2); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_ONLINE, desc, str->str); + } + + g_string_free(str, TRUE); +} + +/* show the notify list, displaying who is on which net */ +static void cmd_notify_show(void) +{ + GSList *nicks, *offline, *tmp; + IRC_SERVER_REC *server; + + if (notifies == NULL) + return; + + /* build a list containing only the nicks */ + nicks = NULL; + for (tmp = notifies; tmp != NULL; tmp = tmp->next) { + NOTIFYLIST_REC *rec = tmp->data; + + nicks = mask_add_once(nicks, rec->mask); + } + offline = g_slist_copy(nicks); + + /* print the notifies on specific ircnets */ + for (tmp = ircnets; tmp != NULL; tmp = tmp->next) { + IRCNET_REC *rec = tmp->data; + + server = (IRC_SERVER_REC *) server_find_ircnet(rec->name); + if (server == NULL) continue; + + print_notify_onserver(server, nicks, &offline, rec->name); + } + + /* print the notifies on servers without a specified ircnet */ + for (tmp = servers; tmp != NULL; tmp = tmp->next) { + server = tmp->data; + + if (server->connrec->ircnet != NULL) + continue; + print_notify_onserver(server, nicks, &offline, server->tag); + } + + /* print offline people */ + if (offline != NULL) { + GString *str; + + str = g_string_new(NULL); + for (tmp = offline; tmp != NULL; tmp = tmp->next) + g_string_sprintfa(str, "%s, ", (char *) tmp->data); + + g_string_truncate(str, str->len-2); + printformat(NULL,NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_OFFLINE, str->str); + g_string_free(str, TRUE); + + g_slist_free(offline); + } + + g_slist_foreach(nicks, (GFunc) g_free, NULL); + g_slist_free(nicks); +} + +static void notifylist_print(NOTIFYLIST_REC *rec) +{ + char idle[MAX_INT_STRLEN], *ircnets; + + if (rec->idle_check_time <= 0) + idle[0] = '\0'; + else + g_snprintf(idle, sizeof(idle), "%d", rec->idle_check_time); + + ircnets = rec->ircnets == NULL ? NULL : + g_strjoinv(",", rec->ircnets); + + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NOTIFY_LIST, + rec->mask, ircnets != NULL ? ircnets : "", + rec->away_check ? "-away" : "", idle); + + g_free_not_null(ircnets); +} + +static void cmd_notifylist_show(void) +{ + g_slist_foreach(notifies, (GFunc) notifylist_print, NULL); +} + +static void cmd_notify(const char *data) +{ + if (*data == '\0') { + cmd_notify_show(); + signal_stop(); + } + + if (g_strcasecmp(data, "-list") == 0) { + cmd_notifylist_show(); + signal_stop(); + } +} + +static void notifylist_joined(IRC_SERVER_REC *server, const char *nick, + const char *username, const char *host, + const char *realname, const char *awaymsg) +{ + g_return_if_fail(nick != NULL); + + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_JOIN, + nick, username, host, realname, + server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); +} + +static void notifylist_left(IRC_SERVER_REC *server, const char *nick, + const char *username, const char *host, + const char *realname, const char *awaymsg) +{ + g_return_if_fail(nick != NULL); + + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_PART, + nick, username, host, realname, + server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); +} + +static void notifylist_away(IRC_SERVER_REC *server, const char *nick, + const char *username, const char *host, + const char *realname, const char *awaymsg) +{ + g_return_if_fail(nick != NULL); + + if (awaymsg != NULL) { + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_AWAY, + nick, username, host, realname, awaymsg, + server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); + } else { + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_UNAWAY, + nick, username, host, realname, + server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); + } +} + +static void notifylist_unidle(IRC_SERVER_REC *server, const char *nick, + const char *username, const char *host, + const char *realname, const char *awaymsg) +{ + g_return_if_fail(nick != NULL); + + printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_UNIDLE, + nick, username, host, realname, awaymsg != NULL ? awaymsg : "", + server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); +} + +void fe_notifylist_init(void) +{ + command_bind("notify", NULL, (SIGNAL_FUNC) cmd_notify); + signal_add("notifylist joined", (SIGNAL_FUNC) notifylist_joined); + signal_add("notifylist left", (SIGNAL_FUNC) notifylist_left); + signal_add("notifylist away changed", (SIGNAL_FUNC) notifylist_away); + signal_add("notifylist unidle", (SIGNAL_FUNC) notifylist_unidle); +} + +void fe_notifylist_deinit(void) +{ + command_unbind("notify", (SIGNAL_FUNC) cmd_notify); + signal_remove("notifylist joined", (SIGNAL_FUNC) notifylist_joined); + signal_remove("notifylist left", (SIGNAL_FUNC) notifylist_left); + signal_remove("notifylist away changed", (SIGNAL_FUNC) notifylist_away); + signal_remove("notifylist unidle", (SIGNAL_FUNC) notifylist_unidle); +} diff --git a/src/fe-common/irc/notifylist/module-formats.c b/src/fe-common/irc/notifylist/module-formats.c new file mode 100644 index 00000000..ad1d3f1e --- /dev/null +++ b/src/fe-common/irc/notifylist/module-formats.c @@ -0,0 +1,39 @@ +/* + module-formats.c : irssi + + Copyright (C) 2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "printtext.h" + +FORMAT_REC fecommon_irc_notifylist_formats[] = +{ + { MODULE_NAME, N_("Notifylist"), 0 }, + + /* ---- */ + { NULL, N_("Notifylist"), 0 }, + + { "notify_join", N_("%_$0%_ %K[%n$1@$2%K] [%n%_$3%_%K]%n has joined to $4"), 5, { 0, 0, 0, 0, 0 } }, + { "notify_part", N_("%_$0%_ has left $4"), 5, { 0, 0, 0, 0, 0 } }, + { "notify_away", N_("%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now away: $4"), 6, { 0, 0, 0, 0, 0, 0 } }, + { "notify_unaway", N_("%_$0%_ %K[%n$4%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now unaway"), 5, { 0, 0, 0, 0, 0 } }, + { "notify_unidle", N_("%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n just stopped idling"), 6, { 0, 0, 0, 0, 0, 0 } }, + { "notify_online", N_("On $0: %_$1%_"), 2, { 0, 0 } }, + { "notify_offline", N_("Offline: $0"), 1, { 0 } }, + { "notify_list", N_("$0: $1 $2 $3"), 4, { 0, 0, 0, 0 } } +}; diff --git a/src/fe-common/irc/notifylist/module-formats.h b/src/fe-common/irc/notifylist/module-formats.h new file mode 100644 index 00000000..77b40cc2 --- /dev/null +++ b/src/fe-common/irc/notifylist/module-formats.h @@ -0,0 +1,19 @@ +#include "printtext.h" + +enum { + IRCTXT_MODULE_NAME, + + IRCTXT_FILL_1, + + IRCTXT_NOTIFY_JOIN, + IRCTXT_NOTIFY_PART, + IRCTXT_NOTIFY_AWAY, + IRCTXT_NOTIFY_UNAWAY, + IRCTXT_NOTIFY_UNIDLE, + IRCTXT_NOTIFY_ONLINE, + IRCTXT_NOTIFY_OFFLINE, + IRCTXT_NOTIFY_LIST +}; + +extern FORMAT_REC fecommon_irc_notifylist_formats[]; +#define MODULE_FORMATS fecommon_irc_notifylist_formats |