summaryrefslogtreecommitdiff
path: root/src/irc
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2003-09-27 10:01:11 +0000
committerSebastien Helleu <flashcode@flashtux.org>2003-09-27 10:01:11 +0000
commit109101faebaa56cc93916803898608328016bf46 (patch)
tree476e7ab1951995c0a980954d7a271cf272e4a835 /src/irc
downloadweechat-109101faebaa56cc93916803898608328016bf46.zip
First CVS upload.
Diffstat (limited to 'src/irc')
-rw-r--r--src/irc/Makefile44
-rw-r--r--src/irc/irc-channel.c153
-rw-r--r--src/irc/irc-commands.c3064
-rw-r--r--src/irc/irc-display.c127
-rw-r--r--src/irc/irc-nick.c357
-rw-r--r--src/irc/irc-server.c615
-rw-r--r--src/irc/irc.h247
7 files changed, 4607 insertions, 0 deletions
diff --git a/src/irc/Makefile b/src/irc/Makefile
new file mode 100644
index 000000000..d22617bda
--- /dev/null
+++ b/src/irc/Makefile
@@ -0,0 +1,44 @@
+# Copyright (c) 2003 FlashCode <flashcode@flashtux.org>
+#
+# 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
+#
+
+CC=gcc
+
+OPTIONS=-Wall -W -pipe -O2
+
+OUTPUT=irc.a
+OBJS=irc-commands.o irc-display.o irc-server.o irc-channel.o irc-nick.o
+DEFINES=WEE_CURSES
+
+all: $(OBJS)
+ ar r $(OUTPUT) $(OBJS)
+
+$(OBJS):
+ $(CC) $(OPTIONS) -o $@ -c $< $(INCLUDES) -D$(DEFINES)
+
+clean:
+ rm -f *.o *.a *~ core
+
+irc-channel.o: irc-channel.c ../weechat.h irc.h ../gui/gui.h \
+ ../completion.h ../history.h
+irc-commands.o: irc-commands.c ../weechat.h irc.h ../gui/gui.h \
+ ../completion.h ../history.h ../command.h ../irc/irc.h ../config.h
+irc-display.o: irc-display.c ../weechat.h irc.h ../gui/gui.h \
+ ../completion.h ../history.h
+irc-nick.o: irc-nick.c ../weechat.h irc.h ../gui/gui.h ../completion.h \
+ ../history.h
+irc-server.o: irc-server.c ../weechat.h irc.h ../gui/gui.h \
+ ../completion.h ../history.h
diff --git a/src/irc/irc-channel.c b/src/irc/irc-channel.c
new file mode 100644
index 000000000..bdad12265
--- /dev/null
+++ b/src/irc/irc-channel.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2003 by FlashCode <flashcode@flashtux.org>
+ * Bounga <bounga@altern.org>
+ * Xahlexx <xahlexx@tuxisland.org>
+ * See README for License detail.
+ *
+ * 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
+ */
+
+
+/* irc-channel.c: manages a chat (channel or private chat) */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../weechat.h"
+#include "irc.h"
+
+
+t_irc_channel *current_channel = NULL;
+
+
+/*
+ * channel_new: allocate a new channel for a server and add it to the server queue
+ */
+
+t_irc_channel *
+channel_new (t_irc_server *server, int channel_type, char *channel_name)
+{
+ t_irc_channel *new_channel;
+
+ #if DEBUG >= 1
+ log_printf ("joining channel %s\n", channel_name);
+ #endif
+
+ /* alloc memory for new channel */
+ if ((new_channel = (t_irc_channel *) malloc (sizeof (t_irc_channel))) == NULL)
+ {
+ fprintf (stderr, _("%s cannot allocate new channel"), WEECHAT_ERROR);
+ return NULL;
+ }
+
+ /* initialize new channel */
+ new_channel->type = channel_type;
+ new_channel->name = strdup (channel_name);
+ new_channel->topic = NULL;
+ new_channel->nicks = NULL;
+ new_channel->last_nick = NULL;
+
+ /* add new channel to queue */
+ new_channel->prev_channel = server->last_channel;
+ new_channel->next_channel = NULL;
+ if (server->channels)
+ server->last_channel->next_channel = new_channel;
+ else
+ server->channels = new_channel;
+ server->last_channel = new_channel;
+
+ gui_window_new (server, new_channel);
+
+ /* all is ok, return address of new channel */
+ return new_channel;
+}
+
+/*
+ * channel_free: free a channel and remove it from channels queue
+ */
+
+void
+channel_free (t_irc_server *server, t_irc_channel *channel)
+{
+ t_irc_channel *new_channels;
+
+ /* remove channel from queue */
+ if (server->last_channel == channel)
+ server->last_channel = channel->prev_channel;
+ if (channel->prev_channel)
+ {
+ (channel->prev_channel)->next_channel = channel->next_channel;
+ new_channels = server->channels;
+ }
+ else
+ new_channels = channel->next_channel;
+
+ if (channel->next_channel)
+ (channel->next_channel)->prev_channel = channel->prev_channel;
+
+ /* free data */
+ if (channel->name)
+ free (channel->name);
+ if (channel->topic)
+ free (channel->topic);
+ nick_free_all (channel);
+ free (channel);
+ server->channels = new_channels;
+}
+
+/*
+ * channel_free_all: free all allocated channels
+ */
+
+void
+channel_free_all (t_irc_server *server)
+{
+ /* remove all channels for the server */
+ while (server->channels)
+ channel_free (server, server->channels);
+}
+
+/*
+ * channel_search: returns pointer on a channel with name
+ */
+
+t_irc_channel *
+channel_search (t_irc_server *server, char *channel_name)
+{
+ t_irc_channel *ptr_channel;
+
+ for (ptr_channel = server->channels; ptr_channel;
+ ptr_channel = ptr_channel->next_channel)
+ {
+ if (strcasecmp (ptr_channel->name, channel_name) == 0)
+ return ptr_channel;
+ }
+ return NULL;
+}
+
+/*
+ * string_is_channel: returns 1 if string is channel
+ */
+
+int
+string_is_channel (char *string)
+{
+ char first_char[2];
+
+ first_char[0] = string[0];
+ first_char[1] = '\0';
+ return (strpbrk (first_char, CHANNEL_PREFIX)) ? 1 : 0;
+}
diff --git a/src/irc/irc-commands.c b/src/irc/irc-commands.c
new file mode 100644
index 000000000..2b4cf33ec
--- /dev/null
+++ b/src/irc/irc-commands.c
@@ -0,0 +1,3064 @@
+/*
+ * Copyright (c) 2003 by FlashCode <flashcode@flashtux.org>
+ * Bounga <bounga@altern.org>
+ * Xahlexx <xahlexx@tuxisland.org>
+ * See README for License detail.
+ *
+ * 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
+ */
+
+
+/* irc-commands.c: implementation of IRC commands, according to
+ RFC 1459,2810,2811,2812 */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "../weechat.h"
+#include "irc.h"
+#include "../command.h"
+#include "../config.h"
+#include "../gui/gui.h"
+
+
+t_irc_command irc_commands[] =
+{ { "away", N_("toggle away status"),
+ N_("[-all] [message]"),
+ N_("-all: toggle away status on all connected servers\n"
+ "message: message for away (if no message is given, away status is removed)"),
+ 0, MAX_ARGS, 1, NULL, irc_cmd_send_away, NULL },
+ { "ctcp", N_("send a ctcp message"),
+ N_("nickname type"),
+ N_("nickname: user to send ctcp to\ntype: \"action\" or \"version\""),
+ 2, MAX_ARGS, 1, NULL, irc_cmd_send_ctcp, NULL },
+ { "deop", N_("removes channel operator status from nickname(s)"),
+ N_("nickname [nickname]"), "",
+ 1, 1, 1, irc_cmd_send_deop, NULL, NULL },
+ { "devoice", N_("removes voice from nickname(s)"),
+ N_("nickname [nickname]"), "",
+ 1, 1, 1, irc_cmd_send_devoice, NULL, NULL },
+ { "error", N_("error received from IRC server"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_error },
+ { "invite", N_("invite a nick on a channel"),
+ N_("nickname channel"),
+ N_("nickname: nick to invite\nchannel: channel to invite"),
+ 2, 2, 1, NULL, irc_cmd_send_invite, NULL },
+ { "join", N_("join a channel"),
+ N_("channel[,channel] [key[,key]]"),
+ N_("channel: channel name to join\nkey: key to join the channel"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_join, irc_cmd_recv_join },
+ { "kick", N_("forcibly remove a user from a channel"),
+ N_("[channel] nickname [comment]"),
+ N_("channel: channel where user is\nnickname: nickname to kick\ncomment: comment for kick"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_kick, irc_cmd_recv_kick },
+ { "kill", N_("close client-server connection"),
+ N_("nickname comment"),
+ N_("nickname: nickname\ncomment: comment for kill"),
+ 2, MAX_ARGS, 1, NULL, irc_cmd_send_kill, NULL },
+ { "list", N_("list channels and their topic"),
+ N_("[channel[,channel] [server]]"),
+ N_("channel: channel to list\nserver: server name"),
+ 0, MAX_ARGS, 1, NULL, irc_cmd_send_list, NULL },
+ { "me", N_("send a ctcp action to the current channel"),
+ N_("message"),
+ N_("message: message to send"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_me, NULL },
+ { "mode", N_("change channel or user mode"),
+ N_("{ channel {[+|-]|o|p|s|i|t|n|b|v} [limit] [user] [ban mask] } | "
+ "{ nickname {[+|-]|i|w|s|o}"),
+ N_("channel modes:\n"
+ " channel: channel name to modify\n"
+ " o: give/take channel operator privileges\n"
+ " p: private channel flag\n"
+ " s: secret channel flag\n"
+ " i: invite-only channel flag\n"
+ " t: topic settable by channel operator only flag\n"
+ " n: no messages to channel from clients on the outside\n"
+ " m: moderated channel\n"
+ " l: set the user limit to channel\n"
+ " b: set a ban mask to keep users out\n"
+ " v: give/take the ability to speak on a moderated channel\n"
+ " k: set a channel key (password)\n"
+ "user modes:\n"
+ " nickname: nickname to modify\n"
+ " i: mark a user as invisible\n"
+ " s: mark a user for receive server notices\n"
+ " w: user receives wallops\n"
+ " o: operator flag\n"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_mode, irc_cmd_recv_mode },
+ { "msg", N_("send message to a nick or channel"),
+ N_("receiver[,receiver] text"), N_("receiver: nick or channel (may be mask)"
+ "\ntext: text to send"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_msg, NULL },
+ { "names", N_("list nicknames on channels"),
+ N_("[channel[,channel]]"), N_("channel: channel name"),
+ 0, MAX_ARGS, 1, NULL, irc_cmd_send_names, NULL },
+ { "nick", N_("change current nickname"),
+ N_("nickname"), N_("nickname: new nickname for current IRC server"),
+ 1, 1, 1, irc_cmd_send_nick, NULL, irc_cmd_recv_nick },
+ { "notice", N_("send notice message to user"),
+ N_("nickname text"), N_("nickname: user to send notice to\ntext: text to send"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_notice, irc_cmd_recv_notice },
+ { "op", N_("gives channel operator status to nickname(s)"),
+ N_("nickname [nickname]"), "",
+ 1, 1, 1, irc_cmd_send_op, NULL, NULL },
+ { "oper", N_("get operator privileges"),
+ N_("user password"),
+ N_("user/password: used to get privileges on current IRC server"),
+ 2, 2, 1, irc_cmd_send_oper, NULL, NULL },
+ { "part", N_("leave a channel"),
+ N_("[channel[,channel]]"), N_("channel: channel name to join"),
+ 0, MAX_ARGS, 1, NULL, irc_cmd_send_part, irc_cmd_recv_part },
+ { "ping", N_("ping server"),
+ N_("server1 [server2]"),
+ N_("server1: server to ping\nserver2: forward ping to this server"),
+ 1, 2, 1, irc_cmd_send_ping, NULL, irc_cmd_recv_ping },
+ { "pong", N_("answer to a ping message"),
+ N_("daemon [daemon2]"), N_("daemon: daemon who has responded to Ping message\n"
+ "daemon2: forward message to this daemon"),
+ 1, 2, 1, irc_cmd_send_pong, NULL, NULL },
+ { "privmsg", N_("message received"),
+ "", "",
+ 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_privmsg },
+ { "quit", N_("close all connections & quit " WEECHAT_NAME),
+ N_("[quit_message]"),
+ N_("quit_message: quit message (displayed to other users)"),
+ 0, MAX_ARGS, 0, NULL, irc_cmd_send_quit, irc_cmd_recv_quit },
+ { "quote", N_("send raw data to server without parsing"),
+ N_("data"),
+ N_("data: raw data to send"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_quote, NULL },
+ { "topic", N_("get/set channel topic"),
+ N_("[channel] [topic]"), N_("channel: channel name\ntopic: new topic for channel "
+ "(if topic is \"-delete\" then topic is deleted)"),
+ 0, MAX_ARGS, 1, NULL, irc_cmd_send_topic, irc_cmd_recv_topic },
+ { "version", N_("gives the version info of nick or server (current or specified)"),
+ N_("[server | nickname]"), N_("server: server name\nnickname: nickname"),
+ 0, 1, 1, NULL, irc_cmd_send_version, NULL },
+ { "voice", N_("gives voice to nickname(s)"),
+ N_("nickname [nickname]"), "",
+ 1, 1, 1, irc_cmd_send_voice, NULL, NULL },
+ { "whois", N_("query information about user(s)"),
+ N_("[server] nickname[,nickname]"), N_("server: server name\n"
+ "nickname: nickname (may be a mask)"),
+ 1, MAX_ARGS, 1, NULL, irc_cmd_send_whois, NULL },
+ { "001", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "002", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "003", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "004", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_004 },
+ { "005", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "250", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "251", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "252", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "253", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "254", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "255", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "256", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "257", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "258", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "259", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "260", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "261", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "262", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "263", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "264", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "265", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "266", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "267", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "268", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "269", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "301", N_("away message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_301 },
+ { "305", N_("unaway"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_reply },
+ { "306", N_("now away"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_reply },
+ { "311", N_("whois (user)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_311 },
+ { "312", N_("whois (server)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_312 },
+ { "313", N_("whois (operator)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_313 },
+ { "317", N_("whois (idle)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_317 },
+ { "318", N_("whois (end)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_318 },
+ { "319", N_("whois (channels)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_319 },
+ { "320", N_("whois (identified user)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_320 },
+ { "321", N_("/list start"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_321 },
+ { "322", N_("channel (for /list)"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_322 },
+ { "323", N_("/list end"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_323 },
+ { "331", N_("no topic for channel"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_331 },
+ { "332", N_("topic of channel"),
+ N_("channel :topic"),
+ N_("channel: name of channel\ntopic: topic of the channel"),
+ 2, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_332 },
+ { "333", N_("infos about topic (nick & date changed)"),
+ "", "",
+ 0, 0, 1, NULL, NULL, irc_cmd_recv_333 },
+ { "351", N_("server version"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_351 },
+ { "353", N_("list of nicks on channel"),
+ N_("channel :[[@|+]nick ...]"),
+ N_("channel: name of channel\nnick: nick on the channel"),
+ 2, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_353 },
+ { "366", N_("end of /names list"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_366 },
+ { "371", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "372", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "373", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "374", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "375", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "376", N_("a server message"), "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_server_msg },
+ { "401", N_("no such nick/channel"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "402", N_("no such server"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "403", N_("no such channel"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "404", N_("cannot send to channel"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "405", N_("too many channels"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "406", N_("was no such nick"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "406", N_("was no such nick"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "407", N_("was no such nick"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "409", N_("no origin"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "411", N_("no recipient"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "412", N_("no text to send"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "413", N_("no toplevel"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "414", N_("wilcard in toplevel domain"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "421", N_("unknown command"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "422", N_("MOTD is missing"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "423", N_("no administrative info"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "424", N_("file error"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "431", N_("no nickname given"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "432", N_("erroneus nickname"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "433", N_("nickname already in use"),
+ "", "", 0, 0, 1, NULL, NULL, irc_cmd_recv_433 },
+ { "436", N_("nickname collision"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "441", N_("user not in channel"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "442", N_("not on channel"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "443", N_("user already on channel"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "444", N_("user not logged in"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "445", N_("summon has been disabled"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "446", N_("users has been disabled"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "451", N_("you are not registered"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "461", N_("not enough parameters"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "462", N_("you may not register"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "463", N_("your host isn't among the privileged"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "464", N_("password incorrect"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "465", N_("you are banned from this server"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "467", N_("channel key already set"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "471", N_("channel is already full"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "472", N_("unknown mode char to me"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "473", N_("cannot join channel (invite only)"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "474", N_("cannot join channel (banned from channel)"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "475", N_("cannot join channel (bad channel key)"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "481", N_("you're not an IRC operator"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "482", N_("you're not channel operator"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "483", N_("you can't kill a server!"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "491", N_("no O-lines for your host"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "501", N_("unknown mode flag"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { "502", N_("can't change mode for other users"),
+ "", "", 0, MAX_ARGS, 1, NULL, NULL, irc_cmd_recv_error },
+ { NULL, NULL, NULL, NULL, 0, 0, 1, NULL, NULL, NULL }
+};
+
+
+/*
+ * irc_recv_command: executes action when receiving IRC command
+ * returns: 0 = all ok, command executed
+ * -1 = command failed
+ * -2 = no command to execute
+ * -3 = command not found
+ */
+
+int
+irc_recv_command (t_irc_server *server,
+ char *host, char *command, char *arguments)
+{
+ int i, cmd_found;
+
+ #if DEBUG >= 2
+ gui_printf (server->window, "recv_irc_command: cmd=%s args=%s\n",
+ command, arguments);
+ #endif
+
+ if (command == NULL)
+ return -2;
+
+ /* looks for irc command */
+ cmd_found = -1;
+ for (i = 0; irc_commands[i].command_name; i++)
+ if (strcasecmp (irc_commands[i].command_name, command) == 0)
+ {
+ cmd_found = i;
+ break;
+ }
+
+ /* command not found */
+ if (cmd_found < 0)
+ return -3;
+
+ if (irc_commands[i].recv_function != NULL)
+ return (int) (irc_commands[i].recv_function) (server, host, arguments);
+
+ return 0;
+}
+
+/*
+ * irc_login: login to irc server
+ */
+
+void
+irc_login (t_irc_server *server)
+{
+ char hostname[128];
+
+ if ((server->password) && (server->password[0]))
+ server_sendf (server, "PASS %s\r\n", server->password);
+
+ gethostname (hostname, sizeof (hostname) - 1);
+ hostname[sizeof (hostname) - 1] = '\0';
+ if (!hostname[0])
+ strcpy (hostname, _("unknown"));
+ gui_printf (server->window,
+ _(WEECHAT_NAME ": using local hostname \"%s\"\n"),
+ hostname);
+ server_sendf (server,
+ "NICK %s\r\n"
+ "USER %s %s %s :%s\r\n",
+ server->nick, server->username, hostname, "servername",
+ server->realname);
+}
+
+/*
+ * irc_cmd_send_away: toggle away status
+ */
+
+int
+irc_cmd_send_away (t_irc_server *server, char *arguments)
+{
+ char *pos;
+ t_irc_server *ptr_server;
+
+ if (arguments && (strncmp (arguments, "-all", 4) == 0))
+ {
+ pos = arguments + 4;
+ while (pos[0] == ' ')
+ pos++;
+ if (!pos[0])
+ pos = NULL;
+
+ for (ptr_server = irc_servers; ptr_server;
+ ptr_server = ptr_server->next_server)
+ {
+ if (server->is_connected)
+ {
+ if (pos)
+ server_sendf (ptr_server, "AWAY :%s\r\n", pos);
+ else
+ server_sendf (ptr_server, "AWAY\r\n");
+ }
+ }
+ }
+ else
+ {
+ if (arguments)
+ server_sendf (server, "AWAY :%s\r\n", arguments);
+ else
+ server_sendf (server, "AWAY\r\n");
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_ctcp: send a ctcp message
+ */
+
+int
+irc_cmd_send_ctcp (t_irc_server *server, char *arguments)
+{
+ char *pos, *pos2;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ pos2 = strchr (pos, ' ');
+ if (pos2)
+ {
+ pos2[0] = '\0';
+ pos2++;
+ while (pos2[0] == ' ')
+ pos2++;
+ }
+ else
+ pos2 = NULL;
+
+ if (strcasecmp (pos, "version") == 0)
+ {
+ if (pos2)
+ server_sendf (server, "PRIVMSG %s :\01VERSION %s\01\r\n",
+ arguments, pos2);
+ else
+ server_sendf (server, "PRIVMSG %s :\01VERSION\01\r\n",
+ arguments);
+ }
+ if (strcasecmp (pos, "action") == 0)
+ {
+ if (pos2)
+ server_sendf (server, "PRIVMSG %s :\01ACTION %s\01\r\n",
+ arguments, pos2);
+ else
+ server_sendf (server, "PRIVMSG %s :\01ACTION\01\r\n",
+ arguments);
+ }
+
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_deop: remove operator privileges from nickname(s)
+ */
+
+int
+irc_cmd_send_deop (t_irc_server *server, int argc, char **argv)
+{
+ int i;
+
+ if (WIN_IS_CHANNEL(gui_current_window))
+ {
+ for (i = 0; i < argc; i++)
+ server_sendf (server, "MODE %s -o %s\r\n",
+ CHANNEL(gui_current_window)->name,
+ argv[i]);
+ }
+ else
+ gui_printf (server->window,
+ _("%s \"deop\" command can only be executed in a channel window\n"),
+ WEECHAT_ERROR);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_devoice: remove voice from nickname(s)
+ */
+
+int
+irc_cmd_send_devoice (t_irc_server *server, int argc, char **argv)
+{
+ int i;
+
+ if (WIN_IS_CHANNEL(gui_current_window))
+ {
+ for (i = 0; i < argc; i++)
+ server_sendf (server, "MODE %s -v %s\r\n",
+ CHANNEL(gui_current_window)->name,
+ argv[i]);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s \"devoice\" command can only be executed in a channel window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_invite: invite a nick on a channel
+ */
+
+int
+irc_cmd_send_invite (t_irc_server *server, char *arguments)
+{
+ server_sendf (server, "INVITE %s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_join: join a new channel
+ */
+
+int
+irc_cmd_send_join (t_irc_server *server, char *arguments)
+{
+ server_sendf (server, "JOIN %s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_kick: forcibly remove a user from a channel
+ */
+
+int
+irc_cmd_send_kick (t_irc_server *server, char *arguments)
+{
+ if (string_is_channel (arguments))
+ server_sendf (server, "KICK %s\r\n", arguments);
+ else
+ {
+ if (WIN_IS_CHANNEL (gui_current_window))
+ {
+ server_sendf (server,
+ "KICK %s %s\r\n",
+ CHANNEL(gui_current_window)->name, arguments);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s \"kick\" command can only be executed in a channel window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_kill: close client-server connection
+ */
+
+int
+irc_cmd_send_kill (t_irc_server *server, char *arguments)
+{
+ server_sendf (server, "KILL %s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_list: close client-server connection
+ */
+
+int
+irc_cmd_send_list (t_irc_server *server, char *arguments)
+{
+ if (arguments)
+ server_sendf (server, "LIST %s\r\n", arguments);
+ else
+ server_sendf (server, "LIST\r\n");
+ return 0;
+}
+
+/*
+ * irc_cmd_send_me: send a ctcp action to the current channel
+ */
+
+int
+irc_cmd_send_me (t_irc_server *server, char *arguments)
+{
+ if (WIN_IS_SERVER(gui_current_window))
+ {
+ gui_printf (server->window,
+ _("%s \"me\" command can not be executed on a server window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ server_sendf (server, "PRIVMSG %s :\01ACTION %s\01\r\n",
+ CHANNEL(gui_current_window)->name, arguments);
+ irc_display_prefix (gui_current_window, PREFIX_ACTION_ME);
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT_NICK, "%s", server->nick);
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT, " %s\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_mode: change mode for channel/nickname
+ */
+
+int
+irc_cmd_send_mode (t_irc_server *server, char *arguments)
+{
+ server_sendf (server, "MODE %s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_msg: send a message to a nick or channel
+ */
+
+int
+irc_cmd_send_msg (t_irc_server *server, char *arguments)
+{
+ char *pos, *pos_comma;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+
+ while (arguments && arguments[0])
+ {
+ pos_comma = strchr (arguments, ',');
+ if (pos_comma)
+ {
+ pos_comma[0] = '\0';
+ pos_comma++;
+ }
+ if (string_is_channel (arguments))
+ {
+ ptr_channel = channel_search (server, arguments);
+ if (ptr_channel)
+ {
+ ptr_nick = nick_search (ptr_channel, server->nick);
+ if (ptr_nick)
+ {
+ irc_display_nick (ptr_channel->window, ptr_nick,
+ MSG_TYPE_NICK, 1, 1, 0);
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_MSG,
+ COLOR_WIN_CHAT, "%s\n", pos);
+ }
+ else
+ gui_printf (server->window,
+ _("%s nick not found for \"privmsg\" command\n"),
+ WEECHAT_ERROR);
+ }
+ server_sendf (server, "PRIVMSG %s :%s\r\n", arguments, pos);
+ }
+ else
+ {
+ ptr_channel = channel_search (server, arguments);
+ if (!ptr_channel)
+ {
+ ptr_channel = channel_new (server, CHAT_PRIVATE, arguments);
+ if (!ptr_channel)
+ {
+ gui_printf (server->window,
+ _("%s cannot create new private window \"%s\"\n"),
+ WEECHAT_ERROR,
+ arguments);
+ return -1;
+ }
+ gui_redraw_window_title (ptr_channel->window);
+ }
+
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_NICK,
+ COLOR_WIN_CHAT_DARK, "<");
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_NICK,
+ COLOR_WIN_NICK_SELF,
+ "%s", server->nick);
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_NICK,
+ COLOR_WIN_CHAT_DARK, "> ");
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_MSG,
+ COLOR_WIN_CHAT, "%s\n", pos);
+ server_sendf (server, "PRIVMSG %s :%s\r\n", arguments, pos);
+ }
+ arguments = pos_comma;
+ }
+ }
+ else
+ gui_printf (server->window,
+ _("%s wrong number of args for \"privmsg\" command\n"),
+ WEECHAT_ERROR);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_names: list nicknames on channels
+ */
+
+int
+irc_cmd_send_names (t_irc_server *server, char *arguments)
+{
+ if (arguments)
+ server_sendf (server, "NAMES %s\r\n", arguments);
+ else
+ {
+ if (!WIN_IS_CHANNEL(gui_current_window))
+ {
+ gui_printf (server->window,
+ _("%s \"names\" command can only be executed in a channel window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ else
+ server_sendf (server, "NAMES %s\r\n",
+ CHANNEL(gui_current_window)->name);
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_nick: change nickname
+ */
+
+int
+irc_cmd_send_nick (t_irc_server *server, int argc, char **argv)
+{
+ if (argc != 1)
+ return -1;
+ server_sendf (server, "NICK %s\r\n", argv[0]);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_notice: send notice message
+ */
+
+int
+irc_cmd_send_notice (t_irc_server *server, char *arguments)
+{
+ server_sendf (server, "NOTICE %s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_op: give operator privileges to nickname(s)
+ */
+
+int
+irc_cmd_send_op (t_irc_server *server, int argc, char **argv)
+{
+ int i;
+
+ if (WIN_IS_CHANNEL(gui_current_window))
+ {
+ for (i = 0; i < argc; i++)
+ server_sendf (server, "MODE %s +o %s\r\n",
+ CHANNEL(gui_current_window)->name,
+ argv[i]);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s \"op\" command can only be executed in a channel window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_oper: get oper privileges
+ */
+
+int
+irc_cmd_send_oper (t_irc_server *server, int argc, char **argv)
+{
+ if (argc != 2)
+ return -1;
+ server_sendf (server, "OPER %s %s\r\n", argv[0], argv[1]);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_part: leave a channel or close a private window
+ */
+
+int
+irc_cmd_send_part (t_irc_server *server, char *arguments)
+{
+ char *channel_name, *pos_args;
+ t_irc_channel *ptr_channel;
+
+ if (arguments)
+ {
+ if (string_is_channel (arguments))
+ {
+ channel_name = arguments;
+ pos_args = strchr (arguments, ' ');
+ if (pos_args)
+ {
+ pos_args[0] = '\0';
+ pos_args++;
+ while (pos_args[0] == ' ')
+ pos_args++;
+ }
+ }
+ else
+ {
+ if (WIN_IS_SERVER(gui_current_window))
+ {
+ gui_printf (server->window,
+ _("%s \"part\" command can not be executed on a server window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ channel_name = CHANNEL(gui_current_window)->name;
+ pos_args = arguments;
+ }
+ }
+ else
+ {
+ if (WIN_IS_SERVER(gui_current_window))
+ {
+ gui_printf (server->window,
+ _("%s \"part\" command can not be executed on a server window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ if (WIN_IS_PRIVATE(gui_current_window))
+ {
+ ptr_channel = CHANNEL(gui_current_window);
+ gui_window_free (ptr_channel->window);
+ channel_free (server, ptr_channel);
+ gui_redraw_window_status (gui_current_window);
+ gui_redraw_window_input (gui_current_window);
+ return 0;
+ }
+ channel_name = CHANNEL(gui_current_window)->name;
+ pos_args = NULL;
+ }
+
+ if (pos_args)
+ server_sendf (server, "PART %s :%s\r\n", channel_name, pos_args);
+ else
+ server_sendf (server, "PART %s\r\n", channel_name);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_ping: ping a server
+ */
+
+int
+irc_cmd_send_ping (t_irc_server *server, int argc, char **argv)
+{
+ if (argc == 1)
+ server_sendf (server, "PING %s\r\n", argv[0]);
+ if (argc == 2)
+ server_sendf (server, "PING %s %s\r\n", argv[0],
+ argv[1]);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_pong: send pong answer to a daemon
+ */
+
+int
+irc_cmd_send_pong (t_irc_server *server, int argc, char **argv)
+{
+ if (argc == 1)
+ server_sendf (server, "PONG %s\r\n", argv[0]);
+ if (argc == 2)
+ server_sendf (server, "PONG %s %s\r\n", argv[0],
+ argv[1]);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_quit: disconnect from all servers and quit WeeChat
+ */
+
+int
+irc_cmd_send_quit (t_irc_server *server, char *arguments)
+{
+ if (server && server->is_connected)
+ {
+ if (arguments)
+ server_sendf (server, "QUIT :%s\r\n", arguments);
+ else
+ server_sendf (server, "QUIT\r\n");
+ }
+ quit_weechat = 1;
+ return 0;
+}
+
+/*
+ * irc_cmd_send_quote: send raw data to server
+ */
+
+int
+irc_cmd_send_quote (t_irc_server *server, char *arguments)
+{
+ server_sendf (server, "%s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_topic: get/set topic for a channel
+ */
+
+int
+irc_cmd_send_topic (t_irc_server *server, char *arguments)
+{
+ char *channel_name, *new_topic, *pos;
+
+ channel_name = NULL;
+ new_topic = NULL;
+
+ if (arguments)
+ {
+ if (string_is_channel (arguments))
+ {
+ channel_name = arguments;
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ new_topic = (pos[0]) ? pos : NULL;
+ }
+ }
+ else
+ new_topic = arguments;
+ }
+
+ /* look for current channel if not specified */
+ if (!channel_name)
+ {
+ if (WIN_IS_SERVER(gui_current_window))
+ {
+ gui_printf (server->window,
+ _("%s \"topic\" command can not be executed on a server window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ channel_name = CHANNEL(gui_current_window)->name;
+ }
+
+ if (new_topic)
+ {
+ if (strcmp (new_topic, "-delete") == 0)
+ server_sendf (server, "TOPIC %s :\r\n", channel_name);
+ else
+ server_sendf (server, "TOPIC %s :%s\r\n", channel_name, new_topic);
+ }
+ else
+ server_sendf (server, "TOPIC %s\r\n", channel_name);
+ return 0;
+}
+
+/*
+ * irc_cmd_send_version: gives the version info of nick or server (current or specified)
+ */
+
+int
+irc_cmd_send_version (t_irc_server *server, char *arguments)
+{
+ if (arguments)
+ {
+ if (WIN_IS_CHANNEL(gui_current_window) &&
+ nick_search (CHANNEL(gui_current_window), arguments))
+ server_sendf (server, "PRIVMSG %s :\01VERSION\01\r\n",
+ arguments);
+ else
+ server_sendf (server, "VERSION %s\r\n",
+ arguments);
+ }
+ else
+ {
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf (server->window, "%s, compiled on %s %s\n",
+ WEECHAT_NAME_AND_VERSION,
+ __DATE__, __TIME__);
+ server_sendf (server, "VERSION\r\n");
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_voice: give voice to nickname(s)
+ */
+
+int
+irc_cmd_send_voice (t_irc_server *server, int argc, char **argv)
+{
+ int i;
+
+ if (WIN_IS_CHANNEL(gui_current_window))
+ {
+ for (i = 0; i < argc; i++)
+ server_sendf (server, "MODE %s +v %s\r\n",
+ CHANNEL(gui_current_window)->name,
+ argv[i]);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s \"voice\" command can only be executed in a channel window\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_send_whois: query information about user(s)
+ */
+
+int
+irc_cmd_send_whois (t_irc_server *server, char *arguments)
+{
+ server_sendf (server, "WHOIS %s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_error: error received from server
+ */
+
+int
+irc_cmd_recv_error (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2;
+ int first;
+
+ /* make gcc happy */
+ (void) server;
+ (void) host;
+
+ if (strncmp (arguments, "Closing Link", 12) == 0)
+ {
+ server_disconnect (server);
+ return 0;
+ }
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ }
+ else
+ pos = arguments;
+
+ irc_display_prefix (server->window, PREFIX_ERROR);
+ first = 1;
+
+ while (pos && pos[0])
+ {
+ pos2 = strchr (pos, ' ');
+ if ((pos[0] == ':') || (!pos2))
+ {
+ if (pos[0] == ':')
+ pos++;
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ "%s%s\n", (first) ? "" : ": ", pos);
+ pos = NULL;
+ }
+ else
+ {
+ pos2[0] = '\0';
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%s%s",
+ (first) ? "" : " ", pos);
+ first = 0;
+ pos = pos2 + 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_join: 'join' message received
+ */
+
+int
+irc_cmd_recv_join (t_irc_server *server, char *host, char *arguments)
+{
+ t_irc_channel *ptr_channel;
+ char *pos;
+
+ ptr_channel = channel_search (server, arguments);
+ if (!ptr_channel)
+ {
+ ptr_channel = channel_new (server, CHAT_CHANNEL, arguments);
+ if (!ptr_channel)
+ {
+ gui_printf (server->window,
+ _("%s cannot create new channel \"%s\"\n"),
+ WEECHAT_ERROR, arguments);
+ return -1;
+ }
+ }
+
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ irc_display_prefix (ptr_channel->window, PREFIX_JOIN);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_NICK,
+ "%s ", host);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_DARK,
+ "(");
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_HOST,
+ "%s", pos + 1);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_DARK,
+ ")");
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT,
+ _(" has joined "));
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_CHANNEL,
+ "%s\n", arguments);
+ nick_new (ptr_channel, host, 0, 0, 0);
+ gui_redraw_window_nick (gui_current_window);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_kick: 'kick' message received
+ */
+
+int
+irc_cmd_recv_kick (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos_nick, *pos_comment;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ pos_nick[0] = '\0';
+ pos_nick++;
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+
+ pos_comment = strchr (pos_nick, ' ');
+ if (pos_comment)
+ {
+ pos_comment[0] = '\0';
+ pos_comment++;
+ while (pos_comment[0] == ' ')
+ pos_comment++;
+ if (pos_comment[0] == ':')
+ pos_comment++;
+ }
+
+ ptr_channel = channel_search (server, arguments);
+ if (!ptr_channel)
+ {
+ gui_printf (server->window,
+ _("%s channel not found for \"kick\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ irc_display_prefix (ptr_channel->window, PREFIX_PART);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_NICK,
+ "%s", host);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT,
+ _(" has kicked "));
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_NICK,
+ "%s", pos_nick);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT,
+ _(" from "));
+ if (pos_comment)
+ {
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_CHANNEL,
+ "%s ", arguments);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_DARK,
+ "(");
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT,
+ "%s", pos_comment);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_DARK,
+ ")\n");
+ }
+ else
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_CHANNEL,
+ "%s\n", arguments);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s nick not found for \"kick\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ ptr_nick = nick_search (ptr_channel, pos_nick);
+ if (ptr_nick)
+ {
+ nick_free (ptr_channel, ptr_nick);
+ gui_redraw_window_nick (gui_current_window);
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_mode: 'mode' message received
+ */
+
+int
+irc_cmd_recv_mode (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2, *pos_parm;
+ char set_flag;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+
+ /* no host => we can't identify sender of message! */
+ if (host == NULL)
+ {
+ gui_printf (server->window,
+ _("%s \"mode\" command received without host\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ /* keep only nick name from host */
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ pos = strchr (arguments, ' ');
+ if (!pos)
+ {
+ gui_printf (server->window,
+ _("%s \"mode\" command received without channel or nickname\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+
+ pos_parm = strchr (pos, ' ');
+ if (pos_parm)
+ {
+ pos_parm[0] = '\0';
+ pos_parm++;
+ while (pos_parm[0] == ' ')
+ pos_parm++;
+ pos2 = strchr (pos_parm, ' ');
+ if (pos2)
+ pos2[0] = '\0';
+ }
+
+ set_flag = '+';
+
+ if (string_is_channel (arguments))
+ {
+ ptr_channel = channel_search (server, arguments);
+ if (ptr_channel)
+ {
+ /* channel modes */
+ while (pos && pos[0])
+ {
+ switch (pos[0])
+ {
+ case '+':
+ set_flag = '+';
+ break;
+ case '-':
+ set_flag = '-';
+ break;
+ case 'b':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "b", host,
+ (set_flag == '+') ?
+ _("sets ban on") :
+ _("removes ban on"),
+ pos_parm);
+ /* TODO: change & redraw channel modes */
+ break;
+ case 'i':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "i", host,
+ (set_flag == '+') ?
+ _("sets invite-only channel flag") :
+ _("removes invite-only channel flag"),
+ NULL);
+ /* TODO: change & redraw channel modes */
+ break;
+ case 'l':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "l", host,
+ (set_flag == '+') ?
+ _("sets the user limit to") :
+ _("removes user limit"),
+ (set_flag == '+') ? pos_parm : NULL);
+ /* TODO: change & redraw channel modes */
+ break;
+ case 'm':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "m", host,
+ (set_flag == '+') ?
+ _("sets moderated channel flag") :
+ _("removes moderated channel flag"),
+ NULL);
+ /* TODO: change & redraw channel modes */
+ break;
+ case 'o':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "o", host,
+ (set_flag == '+') ?
+ _("gives channel operator status to") :
+ _("removes channel operator status from"),
+ pos_parm);
+ ptr_nick = nick_search (ptr_channel, pos_parm);
+ if (ptr_nick)
+ {
+ ptr_nick->is_op = (set_flag == '+') ? 1 : 0;
+ nick_resort (ptr_channel, ptr_nick);
+ gui_redraw_window_nick (ptr_channel->window);
+ }
+ break;
+ /* TODO: remove this obsolete (?) channel flag? */
+ case 'p':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "p", host,
+ (set_flag == '+') ?
+ _("sets private channel flag") :
+ _("removes private channel flag"),
+ NULL);
+ /* TODO: change & redraw channel modes */
+ break;
+ case 's':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "s", host,
+ (set_flag == '+') ?
+ _("sets secret channel flag") :
+ _("removes secret channel flag"),
+ NULL);
+ /* TODO: change & redraw channel modes */
+ break;
+ case 't':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "t", host,
+ (set_flag == '+') ?
+ _("sets topic protection") :
+ _("removes topic protection"),
+ NULL);
+ /* TODO: change & redraw channel modes */
+ break;
+ case 'v':
+ irc_display_mode (ptr_channel->window,
+ arguments, set_flag, "v", host,
+ (set_flag == '+') ?
+ _("gives voice to") :
+ _("removes voice from"),
+ pos_parm);
+
+ ptr_nick = nick_search (ptr_channel, pos_parm);
+ if (ptr_nick)
+ {
+ ptr_nick->has_voice = (set_flag == '+') ? 1 : 0;
+ nick_resort (ptr_channel, ptr_nick);
+ gui_redraw_window_nick (ptr_channel->window);
+ }
+ break;
+ }
+ pos++;
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s channel not found for \"mode\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ else
+ {
+ /* nickname modes */
+ gui_printf (server->window, "(TODO!) nickname modes: channel=%s, args=%s\n", arguments, pos);
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_nick: 'nick' message received
+ */
+
+int
+irc_cmd_recv_nick (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+ int nick_is_me;
+
+ /* no host => we can't identify sender of message! */
+ if (host == NULL)
+ {
+ gui_printf (server->window,
+ _("%s \"nick\" command received without host\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ /* keep only nick name from host */
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ for (ptr_channel = server->channels; ptr_channel;
+ ptr_channel = ptr_channel->next_channel)
+ {
+ ptr_nick = nick_search (ptr_channel, host);
+ if (ptr_nick)
+ {
+ nick_is_me = (strcmp (ptr_nick->nick, server->nick) == 0);
+ nick_change (ptr_channel, ptr_nick, arguments);
+ irc_display_prefix (ptr_channel->window, PREFIX_INFO);
+ if (nick_is_me)
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ _("You are "));
+ else
+ {
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_NICK,
+ "%s", host);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, " is ");
+ }
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ _("now known as "));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_NICK,
+ "%s\n",
+ arguments);
+ if (ptr_channel->window->win_nick)
+ gui_redraw_window_nick (ptr_channel->window);
+ }
+ }
+
+ if (strcmp (server->nick, host) == 0)
+ {
+ free (server->nick);
+ server->nick = strdup (arguments);
+ }
+ gui_redraw_window_input (gui_current_window);
+
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_notice: 'notice' message received
+ */
+
+int
+irc_cmd_recv_notice (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2;
+
+ if (host)
+ {
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+ }
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ if (pos[0] == ':')
+ pos++;
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s nickname not found for \"notice\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ irc_display_prefix (server->window, PREFIX_SERVER);
+ if (strncmp (pos, "\01VERSION", 8) == 0)
+ {
+ pos += 9;
+ pos2 = strchr (pos, '\01');
+ if (pos2)
+ pos2[0] = '\0';
+ gui_printf_color (server->window, COLOR_WIN_CHAT, "CTCP ");
+ gui_printf_color (server->window, COLOR_WIN_CHAT_CHANNEL, "VERSION");
+ gui_printf_color (server->window, COLOR_WIN_CHAT, " reply from ");
+ gui_printf_color (server->window, COLOR_WIN_CHAT_NICK, "%s", host);
+ gui_printf_color (server->window, COLOR_WIN_CHAT, ": %s\n", pos);
+ }
+ else
+ gui_printf_color (server->window, COLOR_WIN_CHAT, "%s\n", pos);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_part: 'part' message received
+ */
+
+int
+irc_cmd_recv_part (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos_args;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+
+ /* no host => we can't identify sender of message! */
+ if (!host || !arguments)
+ {
+ gui_printf (server->window,
+ _("%s \"part\" command received without host or channel\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ pos_args = strchr (arguments, ' ');
+ if (pos_args)
+ {
+ pos_args[0] = '\0';
+ pos_args++;
+ while (pos_args[0] == ' ')
+ pos_args++;
+ if (pos_args[0] == ':')
+ pos_args++;
+ }
+
+ /* keep only nick name from host */
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ ptr_channel = channel_search (server, arguments);
+ if (ptr_channel)
+ {
+ ptr_nick = nick_search (ptr_channel, host);
+ if (ptr_nick)
+ {
+ if (strcmp (ptr_nick->nick, server->nick) == 0)
+ {
+ /* part request was issued by local client */
+ gui_window_free (ptr_channel->window);
+ channel_free (server, ptr_channel);
+ gui_redraw_window_status (gui_current_window);
+ gui_redraw_window_input (gui_current_window);
+ }
+ else
+ {
+
+ /* remove nick from nick list and display message */
+ nick_free (ptr_channel, ptr_nick);
+ irc_display_prefix (ptr_channel->window, PREFIX_PART);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_NICK, "%s ", host);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, "(");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_HOST, "%s", pos+1);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, ")");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, _(" has left "));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%s", ptr_channel->name);
+ if (pos_args && pos_args[0])
+ {
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, " (");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, "%s", pos_args);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, ")");
+ }
+ gui_printf (ptr_channel->window, "\n");
+
+ /* redraw nick list if this is current window */
+ if (ptr_channel->window->win_nick)
+ gui_redraw_window_nick (ptr_channel->window);
+ }
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s channel not found for \"part\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_ping: 'ping' command received
+ */
+
+int
+irc_cmd_recv_ping (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+
+ (void)host;
+ pos = strrchr (arguments, ' ');
+ if (pos)
+ pos[0] = '\0';
+ server_sendf (server, "PONG :%s\r\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_privmsg: 'privmsg' command received
+ */
+
+int
+irc_cmd_recv_privmsg (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2, *host2;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+
+ /* no host => we can't identify sender of message! */
+ if (host == NULL)
+ {
+ gui_printf (server->window,
+ _("%s \"privmsg\" command received without host\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ /* keep only nick name from host */
+ pos = strchr (host, '!');
+ if (pos)
+ {
+ pos[0] = '\0';
+ host2 = pos+1;
+ }
+ else
+ host2 = host;
+
+ /* receiver is a channel ? */
+ if (string_is_channel (arguments))
+ {
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ if (pos[0] == ':')
+ pos++;
+
+ ptr_channel = channel_search (server, arguments);
+ if (ptr_channel)
+ {
+ if (strncmp (pos, "\01ACTION ", 8) == 0)
+ {
+ pos += 8;
+ pos2 = strchr (pos, '\01');
+ if (pos2)
+ pos2[0] = '\0';
+ irc_display_prefix (ptr_channel->window, PREFIX_ACTION_ME);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_NICK, "%s", host);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, " %s\n", pos);
+ }
+ else
+ {
+ ptr_nick = nick_search (ptr_channel, host);
+ if (ptr_nick)
+ {
+ irc_display_nick (ptr_channel->window, ptr_nick,
+ MSG_TYPE_NICK, 1, 1, 0);
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_MSG,
+ COLOR_WIN_CHAT, "%s\n", pos);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s nick not found for \"privmsg\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s channel not found for \"privmsg\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ if (pos[0] == ':')
+ pos++;
+
+ if (strcmp (pos, "\01VERSION\01") == 0)
+ server_sendf (server,
+ "NOTICE %s :\01VERSION "
+ WEECHAT_NAME " v"
+ WEECHAT_VERSION ", compiled on " __DATE__ "\01\r\n",
+ host);
+ else
+ {
+ /* private message received */
+ ptr_channel = channel_search (server, host);
+ if (!ptr_channel)
+ {
+ ptr_channel = channel_new (server, CHAT_PRIVATE, host);
+ if (!ptr_channel)
+ {
+ gui_printf (server->window,
+ _("%s cannot create new private window \"%s\"\n"),
+ WEECHAT_ERROR, host);
+ return -1;
+ }
+ }
+ if (!ptr_channel->topic)
+ {
+ ptr_channel->topic = strdup (host2);
+ gui_redraw_window_title (ptr_channel->window);
+ }
+
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_NICK,
+ COLOR_WIN_CHAT_DARK, "<");
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_NICK,
+ COLOR_WIN_NICK_PRIVATE,
+ "%s", host);
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_NICK,
+ COLOR_WIN_CHAT_DARK, "> ");
+ gui_printf_color_type (ptr_channel->window,
+ MSG_TYPE_MSG,
+ COLOR_WIN_CHAT, "%s\n", pos);
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s cannot parse \"privmsg\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_quit: 'quit' command received
+ */
+
+int
+irc_cmd_recv_quit (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+
+ /* no host => we can't identify sender of message! */
+ if (host == NULL)
+ {
+ gui_printf (server->window,
+ _("%s \"quit\" command received without host\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ /* keep only nick name from host */
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ for (ptr_channel = server->channels; ptr_channel;
+ ptr_channel = ptr_channel->next_channel)
+ {
+ if (ptr_channel->type == CHAT_PRIVATE)
+ ptr_nick = NULL;
+ else
+ ptr_nick = nick_search (ptr_channel, host);
+
+ if (ptr_nick || (strcmp (ptr_channel->name, host) == 0))
+ {
+ if (ptr_nick)
+ nick_free (ptr_channel, ptr_nick);
+ irc_display_prefix (ptr_channel->window, PREFIX_QUIT);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_NICK, "%s ", host);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, "(");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_HOST, "%s", pos + 1);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, ")");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, _(" has quit "));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, "(");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, "%s",
+ arguments);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, ")\n");
+ if ((ptr_channel->window == gui_current_window) &&
+ (ptr_channel->window->win_nick))
+ gui_redraw_window_nick (ptr_channel->window);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_server_msg: command received from server (numeric)
+ */
+
+int
+irc_cmd_recv_server_msg (t_irc_server *server, char *host, char *arguments)
+{
+ /* make gcc happy */
+ (void) host;
+
+ /* skip nickname if at beginning of server message */
+ if (strncmp (server->nick, arguments, strlen (server->nick)) == 0)
+ {
+ arguments += strlen (server->nick) + 1;
+ while (arguments[0] == ' ')
+ arguments++;
+ }
+
+ if (arguments[0] == ':')
+ arguments++;
+
+ /* display server message */
+ irc_display_prefix (server->window, PREFIX_SERVER);
+ gui_printf_color (server->window, COLOR_WIN_CHAT, "%s\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_server_reply: server reply
+ */
+
+int
+irc_cmd_recv_server_reply (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2;
+ int first;
+
+ /* make gcc happy */
+ (void) server;
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ }
+ else
+ pos = arguments;
+
+ irc_display_prefix (server->window, PREFIX_ERROR);
+ first = 1;
+
+ while (pos && pos[0])
+ {
+ pos2 = strchr (pos, ' ');
+ if ((pos[0] == ':') || (!pos2))
+ {
+ if (pos[0] == ':')
+ pos++;
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ "%s%s\n", (first) ? "" : ": ", pos);
+ pos = NULL;
+ }
+ else
+ {
+ pos2[0] = '\0';
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%s%s",
+ (first) ? "" : " ", pos);
+ first = 0;
+ pos = pos2 + 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_topic: 'topic' command received
+ */
+
+int
+irc_cmd_recv_topic (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+ t_irc_channel *ptr_channel;
+ t_gui_window *window;
+
+ /* make gcc happy */
+ (void) host;
+
+ /* keep only nick name from host */
+ pos = strchr (host, '!');
+ if (pos)
+ pos[0] = '\0';
+
+ if (string_is_channel (arguments))
+ {
+ gui_printf (server->window,
+ _("%s \"topic\" command received without channel\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ if (pos[0] == ':')
+ pos++;
+ if (!pos[0])
+ pos = NULL;
+ }
+
+ ptr_channel = channel_search (server, arguments);
+ window = (ptr_channel) ? ptr_channel->window : server->window;
+
+ irc_display_prefix (window, PREFIX_INFO);
+ gui_printf_color (window,
+ COLOR_WIN_CHAT_NICK, "%s",
+ host);
+ if (pos)
+ {
+ gui_printf_color (window,
+ COLOR_WIN_CHAT, _(" has changed topic for "));
+ gui_printf_color (window,
+ COLOR_WIN_CHAT_CHANNEL, "%s",
+ arguments);
+ gui_printf_color (window,
+ COLOR_WIN_CHAT, _(" to: \"%s\"\n"),
+ pos);
+ }
+ else
+ {
+ gui_printf_color (window,
+ COLOR_WIN_CHAT, _(" has unset topic for "));
+ gui_printf_color (window,
+ COLOR_WIN_CHAT_CHANNEL, "%s\n",
+ arguments);
+ }
+
+ if (ptr_channel)
+ {
+ if (ptr_channel->topic)
+ free (ptr_channel->topic);
+ if (pos)
+ ptr_channel->topic = strdup (pos);
+ else
+ ptr_channel->topic = strdup ("");
+ gui_redraw_window_title (ptr_channel->window);
+ }
+
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_004: '004' command (connected to irc server ?????)
+ */
+
+int
+irc_cmd_recv_004 (t_irc_server *server, char *host, char *arguments)
+{
+ /* make gcc happy */
+ (void) host;
+ (void) arguments;
+
+ irc_cmd_recv_server_msg (server, host, arguments);
+
+ /* connection to IRC server is ok! */
+ server->is_connected = 1;
+ gui_redraw_window_status (server->window);
+ gui_redraw_window_input (server->window);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_311: '311' command (away message)
+ */
+
+int
+irc_cmd_recv_301 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_message;
+
+ /* make gcc happy */
+ (void) server;
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_message = strchr (pos_nick, ' ');
+ if (pos_message)
+ {
+ pos_message[0] = '\0';
+ pos_message++;
+ while (pos_message[0] == ' ')
+ pos_message++;
+ if (pos_message[0] == ':')
+ pos_message++;
+
+ irc_display_prefix (gui_current_window, PREFIX_INFO);
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT, _(" is away: %s\n"), pos_message);
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_311: '311' command (whois, user)
+ */
+
+int
+irc_cmd_recv_311 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_user, *pos_host, *pos_realname;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_user = strchr (pos_nick, ' ');
+ if (pos_user)
+ {
+ pos_user[0] = '\0';
+ pos_user++;
+ while (pos_user[0] == ' ')
+ pos_user++;
+ pos_host = strchr (pos_user, ' ');
+ if (pos_host)
+ {
+ pos_host[0] = '\0';
+ pos_host++;
+ while (pos_host[0] == ' ')
+ pos_host++;
+ pos_realname = strchr (pos_host, ' ');
+ if (pos_realname)
+ {
+ pos_realname[0] = '\0';
+ pos_realname++;
+ while (pos_realname[0] == ' ')
+ pos_realname++;
+ if (pos_realname[0] == '*')
+ pos_realname++;
+ while (pos_realname[0] == ' ')
+ pos_realname++;
+ if (pos_realname[0] == ':')
+ pos_realname++;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "] (");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_HOST, "%s@%s",
+ pos_user, pos_host);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, ")");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, ": %s\n", pos_realname);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_312: '312' command (whois, server)
+ */
+
+int
+irc_cmd_recv_312 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_server, *pos_serverinfo;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_server = strchr (pos_nick, ' ');
+ if (pos_server)
+ {
+ pos_server[0] = '\0';
+ pos_server++;
+ while (pos_server[0] == ' ')
+ pos_server++;
+ pos_serverinfo = strchr (pos_server, ' ');
+ if (pos_serverinfo)
+ {
+ pos_serverinfo[0] = '\0';
+ pos_serverinfo++;
+ while (pos_serverinfo[0] == ' ')
+ pos_serverinfo++;
+ if (pos_serverinfo[0] == ':')
+ pos_serverinfo++;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "] ");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, "%s ", pos_server);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "(");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, "%s", pos_serverinfo);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, ")\n");
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_313: '313' command (whois, operator)
+ */
+
+int
+irc_cmd_recv_313 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_message;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_message = strchr (pos_nick, ' ');
+ if (pos_message)
+ {
+ pos_message[0] = '\0';
+ pos_message++;
+ while (pos_message[0] == ' ')
+ pos_message++;
+ if (pos_message[0] == ':')
+ pos_message++;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "] ");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, "%s\n", pos_message);
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_317: '317' command (whois, idle)
+ */
+
+int
+irc_cmd_recv_317 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_idle, *pos_signon, *pos_message;
+ int idle_time, day, hour, min, sec;
+ time_t datetime;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_idle = strchr (pos_nick, ' ');
+ if (pos_idle)
+ {
+ pos_idle[0] = '\0';
+ pos_idle++;
+ while (pos_idle[0] == ' ')
+ pos_idle++;
+ pos_signon = strchr (pos_idle, ' ');
+ if (pos_signon)
+ {
+ pos_signon[0] = '\0';
+ pos_signon++;
+ while (pos_signon[0] == ' ')
+ pos_signon++;
+ pos_message = strchr (pos_signon, ' ');
+ if (pos_message)
+ {
+ pos_message[0] = '\0';
+
+ idle_time = atoi (pos_idle);
+ day = idle_time / (60 * 60 * 24);
+ hour = (idle_time % (60 * 60 * 24)) / (60 * 60);
+ min = ((idle_time % (60 * 60 * 24)) % (60 * 60)) / 60;
+ sec = ((idle_time % (60 * 60 * 24)) % (60 * 60)) % 60;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "] ");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, _("idle: "));
+ if (day > 0)
+ {
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%d ", day);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ (day > 1) ? _("days") : _("day"));
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ ", ");
+ }
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%02d ", hour);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ (hour > 1) ? _("hours") : _("hour"));
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ " %02d ", min);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ (min > 1) ? _("minutes") : _("minute"));
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ " %02d ", sec);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ (sec > 1) ? _("seconds") : _("second"));
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT,
+ ", ");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, _("signon at: "));
+ datetime = (time_t)(atol (pos_signon));
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%s", ctime (&datetime));
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_318: '318' command (whois, end)
+ */
+
+int
+irc_cmd_recv_318 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_message;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_message = strchr (pos_nick, ' ');
+ if (pos_message)
+ {
+ pos_message[0] = '\0';
+ pos_message++;
+ while (pos_message[0] == ' ')
+ pos_message++;
+ if (pos_message[0] == ':')
+ pos_message++;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "] ");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, "%s\n", pos_message);
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_319: '319' command (whois, end)
+ */
+
+int
+irc_cmd_recv_319 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_channel, *pos;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_channel = strchr (pos_nick, ' ');
+ if (pos_channel)
+ {
+ pos_channel[0] = '\0';
+ pos_channel++;
+ while (pos_channel[0] == ' ')
+ pos_channel++;
+ if (pos_channel[0] == ':')
+ pos_channel++;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "] ");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, _("Channels: "));
+
+ while (pos_channel && pos_channel[0])
+ {
+ if (pos_channel[0] == '@')
+ {
+ gui_printf_color (server->window,
+ COLOR_WIN_NICK_OP, "@");
+ pos_channel++;
+ }
+ else
+ {
+ if (pos_channel[0] == '%')
+ {
+ gui_printf_color (server->window,
+ COLOR_WIN_NICK_HALFOP, "%");
+ pos_channel++;
+ }
+ else
+ if (pos_channel[0] == '+')
+ {
+ gui_printf_color (server->window,
+ COLOR_WIN_NICK_VOICE, "+");
+ pos_channel++;
+ }
+ }
+ pos = strchr (pos_channel, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ }
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%s%s",
+ pos_channel,
+ (pos && pos[0]) ? " " : "\n");
+ pos_channel = pos;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_320: '320' command (whois, identified user)
+ */
+
+int
+irc_cmd_recv_320 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_nick, *pos_message;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_nick = strchr (arguments, ' ');
+ if (pos_nick)
+ {
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_message = strchr (pos_nick, ' ');
+ if (pos_message)
+ {
+ pos_message[0] = '\0';
+ pos_message++;
+ while (pos_message[0] == ' ')
+ pos_message++;
+ if (pos_message[0] == ':')
+ pos_message++;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT_DARK, "] ");
+ gui_printf_color (server->window,
+ COLOR_WIN_CHAT, "%s\n", pos_message);
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_321: '321' command (/list start)
+ */
+
+int
+irc_cmd_recv_321 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ }
+ else
+ pos = arguments;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf (server->window, "%s\n", pos);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_322: '322' command (channel for /list)
+ */
+
+int
+irc_cmd_recv_322 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ }
+ else
+ pos = arguments;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf (server->window, "%s\n", pos);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_323: '323' command (/list end)
+ */
+
+int
+irc_cmd_recv_323 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ }
+ else
+ pos = arguments;
+
+ irc_display_prefix (server->window, PREFIX_INFO);
+ gui_printf (server->window, "%s\n", pos);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_331: '331' command received (no topic for channel)
+ */
+
+int
+irc_cmd_recv_331 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos;
+
+ /* make gcc happy */
+ (void) server;
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ pos[0] = '\0';
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT, _("No topic set for "));
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT_CHANNEL, "%s\n", arguments);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_332: '332' command received (topic of channel)
+ */
+
+int
+irc_cmd_recv_332 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2;
+ t_irc_channel *ptr_channel;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ while (pos[0] == ' ')
+ pos++;
+ pos2 = strchr (pos, ' ');
+ if (pos2)
+ {
+ pos2[0] = '\0';
+ ptr_channel = channel_search (server, pos);
+ if (ptr_channel)
+ {
+ pos2++;
+ while (pos2[0] == ' ')
+ pos2++;
+ if (pos2[0] == ':')
+ pos2++;
+ if (ptr_channel->topic)
+ free (ptr_channel->topic);
+ ptr_channel->topic = strdup (pos2);
+
+ irc_display_prefix (ptr_channel->window, PREFIX_INFO);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, _("Topic for "));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL, "%s", pos);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, _(" is: \"%s\"\n"), pos2);
+
+ gui_redraw_window_title (ptr_channel->window);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s channel not found for \"332\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s cannot identify channel for \"332\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_333: '333' command received (infos about topic (nick / date)
+ */
+
+int
+irc_cmd_recv_333 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos_channel, *pos_nick, *pos_date;
+ t_irc_channel *ptr_channel;
+ time_t datetime;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos_channel = strchr (arguments, ' ');
+ if (pos_channel)
+ {
+ while (pos_channel[0] == ' ')
+ pos_channel++;
+ pos_nick = strchr (pos_channel, ' ');
+ if (pos_nick)
+ {
+ pos_nick[0] = '\0';
+ pos_nick++;
+ while (pos_nick[0] == ' ')
+ pos_nick++;
+ pos_date = strchr (pos_nick, ' ');
+ if (pos_date)
+ {
+ pos_date[0] = '\0';
+ pos_date++;
+ while (pos_date[0] == ' ')
+ pos_date++;
+
+ ptr_channel = channel_search (server, pos_channel);
+ if (ptr_channel)
+ {
+ irc_display_prefix (ptr_channel->window, PREFIX_INFO);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, _("Topic set by "));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_NICK, "%s", pos_nick);
+ datetime = (time_t)(atol (pos_date));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, ", %s", ctime (&datetime));
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s channel not found for \"333\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s cannot identify date/time for \"333\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s cannot identify nickname for \"333\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s cannot identify channel for \"333\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_351: '351' command received (server version)
+ */
+
+int
+irc_cmd_recv_351 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2;
+
+ /* make gcc happy */
+ (void) server;
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ }
+ else
+ pos = arguments;
+
+ pos2 = strstr (pos, " :");
+ if (pos2)
+ {
+ pos2[0] = '\0';
+ pos2 += 2;
+ }
+
+ irc_display_prefix (server->window, PREFIX_SERVER);
+ if (pos2)
+ gui_printf (server->window, "%s %s\n", pos, pos2);
+ else
+ gui_printf (server->window, "%s\n", pos);
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_353: '353' command received (list of users on a channel)
+ */
+
+int
+irc_cmd_recv_353 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos_nick;
+ int is_op, is_halfop, has_voice;
+ t_irc_channel *ptr_channel;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos = strstr (arguments, " = ");
+ if (pos)
+ arguments = pos + 3;
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+
+ ptr_channel = channel_search (server, arguments);
+ if (!ptr_channel)
+ return 0;
+
+ pos++;
+ while (pos[0] == ' ')
+ pos++;
+ if (pos[0] != ':')
+ {
+ gui_printf (server->window,
+ _("%s cannot parse \"353\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ pos++;
+ if (pos[0])
+ {
+ while (pos && pos[0])
+ {
+ is_op = 0;
+ is_halfop = 0;
+ has_voice = 0;
+ while ((pos[0] == '@') || (pos[0] == '%') || (pos[0] == '+'))
+ {
+ if (pos[0] == '@')
+ is_op = 1;
+ if (pos[0] == '%')
+ is_halfop = 1;
+ if (pos[0] == '+')
+ has_voice = 1;
+ pos++;
+ }
+ pos_nick = pos;
+ pos = strchr (pos, ' ');
+ if (pos)
+ {
+ pos[0] = '\0';
+ pos++;
+ }
+ if (!nick_new (ptr_channel, pos_nick, is_op, is_halfop, has_voice))
+ gui_printf (server->window,
+ _("%s cannot create nick \"%s\" for channel \"%s\"\n"),
+ WEECHAT_ERROR, pos_nick, ptr_channel->name);
+ }
+ }
+ gui_redraw_window_nick (ptr_channel->window);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _("%s cannot parse \"353\" command\n"),
+ WEECHAT_ERROR);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_366: '366' command received (end of /names list)
+ */
+
+int
+irc_cmd_recv_366 (t_irc_server *server, char *host, char *arguments)
+{
+ char *pos, *pos2;
+ t_irc_channel *ptr_channel;
+ t_irc_nick *ptr_nick;
+ int num_nicks, num_op, num_halfop, num_voice, num_normal;
+
+ /* make gcc happy */
+ (void) host;
+
+ pos = strchr (arguments, ' ');
+ if (pos)
+ {
+ while (pos[0] == ' ')
+ pos++;
+ pos2 = strchr (pos, ' ');
+ if (pos2)
+ {
+ pos2[0] = '\0';
+ pos2++;
+ while (pos2[0] == ' ')
+ pos2++;
+ if (pos2[0] == ':')
+ pos2++;
+
+ ptr_channel = channel_search (server, pos);
+ if (ptr_channel)
+ {
+
+ /* display users on channel */
+ irc_display_prefix (ptr_channel->window, PREFIX_INFO);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT,
+ _("Nicks "));
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_CHANNEL,
+ "%s", ptr_channel->name);
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT, ": ");
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_DARK, "[");
+
+ for (ptr_nick = ptr_channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick)
+ {
+ irc_display_nick (ptr_channel->window, ptr_nick,
+ MSG_TYPE_INFO, 0, 0, 1);
+ if (ptr_nick != ptr_channel->last_nick)
+ gui_printf (ptr_channel->window, " ");
+ }
+ gui_printf_color (ptr_channel->window, COLOR_WIN_CHAT_DARK, "]\n");
+
+ /* display number of nicks, ops, halfops & voices on the channel */
+ nick_count (ptr_channel, &num_nicks, &num_op, &num_halfop, &num_voice,
+ &num_normal);
+ irc_display_prefix (ptr_channel->window, PREFIX_INFO);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, _("Channel "));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%s", ptr_channel->name);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT, ": ");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%d ", num_nicks);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ (num_nicks > 1) ? _("nicks") : _("nick"));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, " (");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%d ", num_op);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ (num_op > 1) ? _("ops") : _("op"));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ ", ");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%d ", num_halfop);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ (num_halfop > 1) ? _("halfops") : _("halfop"));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ ", ");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%d ", num_voice);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ (num_voice > 1) ? _("voices") : _("voice"));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ ", ");
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_CHANNEL,
+ "%d ", num_normal);
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT,
+ _("normal"));
+ gui_printf_color (ptr_channel->window,
+ COLOR_WIN_CHAT_DARK, ")\n");
+ }
+ else
+ {
+ irc_display_prefix (gui_current_window, PREFIX_INFO);
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT_CHANNEL, pos);
+ gui_printf_color (gui_current_window,
+ COLOR_WIN_CHAT, ": %s\n", pos2);
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * irc_cmd_recv_433: '433' command received (nickname already in use)
+ */
+
+int
+irc_cmd_recv_433 (t_irc_server *server, char *host, char *arguments)
+{
+ char hostname[128];
+
+ if (!server->is_connected)
+ {
+ if (strcmp (server->nick, server->nick1) == 0)
+ {
+ gui_printf (server->window,
+ _(WEECHAT_NAME
+ ": nickname \"%s\" is already in use, "
+ "trying 2nd nickname \"%s\"\n"),
+ server->nick, server->nick2);
+ free (server->nick);
+ server->nick = strdup (server->nick2);
+ }
+ else
+ {
+ if (strcmp (server->nick, server->nick2) == 0)
+ {
+ gui_printf (server->window,
+ _(WEECHAT_NAME
+ ": nickname \"%s\" is already in use, "
+ "trying 3rd nickname \"%s\"\n"),
+ server->nick, server->nick3);
+ free (server->nick);
+ server->nick = strdup (server->nick3);
+ }
+ else
+ {
+ gui_printf (server->window,
+ _(WEECHAT_NAME
+ ": all declared nicknames are already in use, "
+ "closing connection with server!\n"));
+ server_disconnect (server);
+ return 0;
+ }
+ }
+
+ gethostname (hostname, sizeof (hostname) - 1);
+ hostname[sizeof (hostname) - 1] = '\0';
+ if (!hostname[0])
+ strcpy (hostname, _("unknown"));
+ server_sendf (server,
+ "NICK %s\r\n",
+ server->nick);
+ }
+ else
+ return irc_cmd_recv_error (server, host, arguments);
+ return 0;
+}
diff --git a/src/irc/irc-display.c b/src/irc/irc-display.c
new file mode 100644
index 000000000..2f2f9931b
--- /dev/null
+++ b/src/irc/irc-display.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2003 by FlashCode <flashcode@flashtux.org>
+ * Bounga <bounga@altern.org>
+ * Xahlexx <xahlexx@tuxisland.org>
+ * See README for License detail.
+ *
+ * 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
+ */
+
+
+/* irc-display.c: display functions for IRC */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../weechat.h"
+#include "irc.h"
+#include "../config.h"
+#include "../gui/gui.h"
+
+
+/*
+ * irc_display_prefix: display prefix for action or info message
+ * prefix must be 3 chars length
+ */
+
+void
+irc_display_prefix (t_gui_window *window, char *prefix)
+{
+ if (prefix[0] == prefix[2])
+ {
+ gui_printf_color (window, COLOR_WIN_CHAT_PREFIX1, "%c", prefix[0]);
+ gui_printf_color (window, COLOR_WIN_CHAT_PREFIX2, "%c", prefix[1]);
+ gui_printf_color (window, COLOR_WIN_CHAT_PREFIX1, "%c ", prefix[2]);
+ }
+ else
+ gui_printf_color (window, COLOR_WIN_CHAT_PREFIX1, "%s ", prefix);
+}
+
+/*
+ * irc_display_nick: display nick in chat window
+ */
+
+void
+irc_display_nick (t_gui_window *window, t_irc_nick *nick, int message_type,
+ int display_around, int color_nick, int no_nickmode)
+{
+ if (display_around)
+ gui_printf_color_type (window,
+ message_type, COLOR_WIN_CHAT_DARK, "<");
+ if (cfg_look_nickmode)
+ {
+ if (nick->is_op)
+ gui_printf_color_type (window,
+ message_type,
+ COLOR_WIN_NICK_OP, "@");
+ else
+ {
+ if (nick->is_halfop)
+ gui_printf_color_type (window,
+ message_type,
+ COLOR_WIN_NICK_HALFOP, "%%");
+ else
+ {
+ if (nick->has_voice)
+ gui_printf_color_type (window,
+ message_type,
+ COLOR_WIN_NICK_VOICE, "+");
+ else
+ if (cfg_look_nickmode_empty && !no_nickmode)
+ gui_printf_color_type (window,
+ message_type,
+ COLOR_WIN_CHAT, " ");
+ }
+ }
+ }
+ gui_printf_color_type (window,
+ message_type,
+ (color_nick) ?
+ ((cfg_look_color_nicks) ?
+ nick->color : COLOR_WIN_CHAT) :
+ COLOR_WIN_CHAT,
+ "%s", nick->nick);
+
+ if (display_around)
+ gui_printf_color_type (window,
+ message_type, COLOR_WIN_CHAT_DARK, "> ");
+}
+
+/*
+ * irc_display_mode: display IRC message for mode change
+ */
+
+void
+irc_display_mode (t_gui_window *window, char *channel_name, char set_flag,
+ char *symbol, char *nick_host, char *message, char *param)
+{
+ irc_display_prefix (window, PREFIX_INFO);
+ gui_printf_color (window, COLOR_WIN_CHAT_DARK, "[");
+ gui_printf_color (window, COLOR_WIN_CHAT_CHANNEL, "%s", channel_name);
+ gui_printf_color (window, COLOR_WIN_CHAT, "/");
+ gui_printf_color (window, COLOR_WIN_CHAT_CHANNEL, "%c%s", set_flag, symbol);
+ gui_printf_color (window, COLOR_WIN_CHAT_DARK, "] ");
+ gui_printf_color (window, COLOR_WIN_CHAT_NICK, "%s", nick_host);
+ if (param)
+ {
+ gui_printf_color (window, COLOR_WIN_CHAT, " %s ", message);
+ gui_printf_color (window, COLOR_WIN_CHAT_NICK, "%s\n", param);
+ }
+ else
+ gui_printf_color (window, COLOR_WIN_CHAT, " %s\n", message);
+}
diff --git a/src/irc/irc-nick.c b/src/irc/irc-nick.c
new file mode 100644
index 000000000..1f9faf3b3
--- /dev/null
+++ b/src/irc/irc-nick.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2003 by FlashCode <flashcode@flashtux.org>
+ * Bounga <bounga@altern.org>
+ * Xahlexx <xahlexx@tuxisland.org>
+ * See README for License detail.
+ *
+ * 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
+ */
+
+
+/* irc-nick.c: manages nick list for channels */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "../weechat.h"
+#include "irc.h"
+
+
+/*
+ * nick_find_color: find a color for a nick (less used will be better!)
+ */
+
+int
+nick_find_color (t_irc_channel *channel)
+{
+ int i, color_less_used, min_used;
+ int count_used[COLOR_WIN_NICK_NUMBER];
+ t_irc_nick *ptr_nick;
+
+ /* initialize array for counting usage of color */
+ for (i = 0; i < COLOR_WIN_NICK_NUMBER; i++)
+ count_used[i] = 0;
+
+ /* summarize each color usage */
+ for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick)
+ count_used[ptr_nick->color - COLOR_WIN_NICK_FIRST]++;
+
+ /* look for color less used on channel */
+ color_less_used = -1;
+ min_used = INT_MAX;
+ for (i = 0; i < COLOR_WIN_NICK_NUMBER; i++)
+ {
+ if (count_used[i] < min_used)
+ {
+ color_less_used = i;
+ min_used = count_used[i];
+ }
+ }
+
+ return (color_less_used < 0) ?
+ COLOR_WIN_NICK_FIRST : COLOR_WIN_NICK_FIRST + color_less_used;
+}
+
+/*
+ * nick_compare: compare two nicks
+ * return: -1 is nick1 < nick2
+ * 0 if nick1 = nick2
+ * +1 if nick1 > nick2
+ * status sort: operator > voice > normal nick
+ */
+
+int
+nick_compare (t_irc_nick *nick1, t_irc_nick *nick2)
+{
+ int score1, score2, comp;
+
+ score1 = - ( (nick1->is_op * 3) + (nick1->is_halfop * 2) + nick1->has_voice );
+ score2 = - ( (nick2->is_op * 3) + (nick2->is_halfop * 2) + nick2->has_voice );
+
+ comp = strcasecmp(nick1->nick, nick2->nick);
+ if (comp > 0)
+ score1++;
+ else
+ if (comp < 0)
+ score2++;
+
+ /* nick1 > nick2 */
+ if (score1 > score2)
+ return 1;
+ /* nick1 < nick2 */
+ if (score1 < score2)
+ return -1;
+ /* nick1 == nick2 */
+ return 0;
+}
+
+/*
+ * nick_find_pos: find position for a nick (for sorting nick list)
+ */
+
+t_irc_nick *
+nick_find_pos (t_irc_channel *channel, t_irc_nick *nick)
+{
+ t_irc_nick *ptr_nick;
+
+ for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick)
+ {
+ if (nick_compare (nick, ptr_nick) < 0)
+ return ptr_nick;
+ }
+ return NULL;
+}
+
+/*
+ * nick_insert_sorted: insert nick into sorted list
+ */
+
+void
+nick_insert_sorted (t_irc_channel *channel, t_irc_nick *nick)
+{
+ t_irc_nick *pos_nick;
+
+ if (channel->nicks)
+ {
+ pos_nick = nick_find_pos (channel, nick);
+
+ if (pos_nick)
+ {
+ /* insert nick into the list (before nick found) */
+ nick->prev_nick = pos_nick->prev_nick;
+ nick->next_nick = pos_nick;
+ if (pos_nick->prev_nick)
+ pos_nick->prev_nick->next_nick = nick;
+ else
+ channel->nicks = nick;
+ pos_nick->prev_nick = nick;
+ }
+ else
+ {
+ /* add nick to the end */
+ nick->prev_nick = channel->last_nick;
+ nick->next_nick = NULL;
+ channel->last_nick->next_nick = nick;
+ channel->last_nick = nick;
+ }
+ }
+ else
+ {
+ nick->prev_nick = NULL;
+ nick->next_nick = NULL;
+ channel->nicks = nick;
+ channel->last_nick = nick;
+ }
+}
+
+/*
+ * nick_new: allocate a new nick for a channel and add it to the nick list
+ */
+
+t_irc_nick *
+nick_new (t_irc_channel *channel, char *nick_name,
+ int is_op, int is_halfop, int has_voice)
+{
+ t_irc_nick *new_nick;
+
+ /* nick already exists on this channel? */
+ if ((new_nick = nick_search (channel, nick_name)))
+ {
+ /* update nick */
+ new_nick->is_op = is_op;
+ new_nick->is_halfop = is_halfop;
+ new_nick->has_voice = has_voice;
+ return new_nick;
+ }
+
+ /* alloc memory for new nick */
+ if ((new_nick = (t_irc_nick *) malloc (sizeof (t_irc_nick))) == NULL)
+ {
+ gui_printf (channel->window,
+ _("%s cannot allocate new nick\n"), WEECHAT_ERROR);
+ return NULL;
+ }
+
+ /* initialize new nick */
+ new_nick->nick = strdup (nick_name);
+ new_nick->is_op = is_op;
+ new_nick->is_halfop = is_halfop;
+ new_nick->has_voice = has_voice;
+ if (strcasecmp (new_nick->nick, SERVER(channel->window)->nick) == 0)
+ new_nick->color = COLOR_WIN_NICK_SELF;
+ else
+ new_nick->color = nick_find_color (channel);
+
+ nick_insert_sorted (channel, new_nick);
+
+ /* all is ok, return address of new nick */
+ return new_nick;
+}
+
+/*
+ * nick_resort: resort nick in the list
+ */
+
+void
+nick_resort (t_irc_channel *channel, t_irc_nick *nick)
+{
+ /* temporarly remove nick from list */
+ if (nick == channel->nicks)
+ channel->nicks = nick->next_nick;
+ else
+ nick->prev_nick->next_nick = nick->next_nick;
+ if (nick->next_nick)
+ nick->next_nick->prev_nick = nick->prev_nick;
+ if (nick == channel->last_nick)
+ channel->last_nick = nick->prev_nick;
+
+ /* insert again nick into sorted list */
+ nick_insert_sorted (channel, nick);
+}
+
+/*
+ * nick_change: change nickname and move it if necessary (list is sorted)
+ */
+
+void
+nick_change (t_irc_channel *channel, t_irc_nick *nick, char *new_nick)
+{
+ /* change nickname */
+ if (nick->nick)
+ free (nick->nick);
+ nick->nick = strdup (new_nick);
+
+ /* insert again nick into sorted list */
+ nick_resort (channel, nick);
+}
+
+/*
+ * nick_free: free a nick and remove it from nicks queue
+ */
+
+void
+nick_free (t_irc_channel *channel, t_irc_nick *nick)
+{
+ t_irc_nick *new_nicks;
+
+ /* remove nick from queue */
+ if (channel->last_nick == nick)
+ channel->last_nick = nick->prev_nick;
+ if (nick->prev_nick)
+ {
+ (nick->prev_nick)->next_nick = nick->next_nick;
+ new_nicks = channel->nicks;
+ }
+ else
+ new_nicks = nick->next_nick;
+
+ if (nick->next_nick)
+ (nick->next_nick)->prev_nick = nick->prev_nick;
+
+ /* free data */
+ if (nick->nick)
+ free (nick->nick);
+ free (nick);
+ channel->nicks = new_nicks;
+}
+
+/*
+ * nick_free_all: free all allocated nicks for a channel
+ */
+
+void
+nick_free_all (t_irc_channel *channel)
+{
+ /* remove all nicks for the channel */
+ while (channel->nicks)
+ nick_free (channel, channel->nicks);
+}
+
+/*
+ * nick_search: returns pointer on a nick
+ */
+
+t_irc_nick *
+nick_search (t_irc_channel *channel, char *nickname)
+{
+ t_irc_nick *ptr_nick;
+
+ for (ptr_nick = channel->nicks; ptr_nick;
+ ptr_nick = ptr_nick->next_nick)
+ {
+ if (strcasecmp (ptr_nick->nick, nickname) == 0)
+ return ptr_nick;
+ }
+ return NULL;
+}
+
+/*
+ * nick_count: returns number of nicks (total, op, halfop, voice) on a channel
+ */
+
+void
+nick_count (t_irc_channel *channel, int *total, int *count_op,
+ int *count_halfop, int *count_voice, int *count_normal)
+{
+ t_irc_nick *ptr_nick;
+
+ (*total) = 0;
+ (*count_op) = 0;
+ (*count_halfop) = 0;
+ (*count_voice) = 0;
+ (*count_normal) = 0;
+ for (ptr_nick = channel->nicks; ptr_nick;
+ ptr_nick = ptr_nick->next_nick)
+ {
+ (*total)++;
+ if (ptr_nick->is_op)
+ (*count_op)++;
+ else
+ {
+ if (ptr_nick->is_halfop)
+ (*count_halfop)++;
+ else
+ {
+ if (ptr_nick->has_voice)
+ (*count_voice)++;
+ else
+ (*count_normal)++;
+ }
+ }
+ }
+}
+
+/*
+ * nick_get_max_length: returns longer nickname on a channel
+ */
+
+int
+nick_get_max_length (t_irc_channel *channel)
+{
+ int length, max_length;
+ t_irc_nick *ptr_nick;
+
+ max_length = 0;
+ for (ptr_nick = channel->nicks; ptr_nick;
+ ptr_nick = ptr_nick->next_nick)
+ {
+ length = strlen (ptr_nick->nick);
+ if (length > max_length)
+ max_length = length;
+ }
+ return max_length;
+}
diff --git a/src/irc/irc-server.c b/src/irc/irc-server.c
new file mode 100644
index 000000000..b8bacc303
--- /dev/null
+++ b/src/irc/irc-server.c
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2003 by FlashCode <flashcode@flashtux.org>
+ * Bounga <bounga@altern.org>
+ * Xahlexx <xahlexx@tuxisland.org>
+ * See README for License detail.
+ *
+ * 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
+ */
+
+
+/* irc-server.c: (dis)connection and communication with irc server */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "../weechat.h"
+#include "irc.h"
+#include "../gui/gui.h"
+
+
+t_irc_server *irc_servers = NULL;
+t_irc_server *last_irc_server = NULL;
+t_irc_server *current_irc_server = NULL;
+
+t_irc_message *recv_msgq, *msgq_last_msg;
+
+/* buffer containing beginning of message if not ending with \r\n */
+char *unterminated_message = NULL;
+
+
+/*
+ * server_alloc: allocate a new server and add it to the servers queue
+ */
+
+t_irc_server *
+server_alloc ()
+{
+ t_irc_server *new_server;
+
+ #if DEBUG >= 1
+ log_printf ("allocating new server\n");
+ #endif
+
+ /* alloc memory for new server */
+ if ((new_server = (t_irc_server *) malloc (sizeof (t_irc_server))) == NULL)
+ {
+ fprintf (stderr, _("%s cannot allocate new server"), WEECHAT_ERROR);
+ return NULL;
+ }
+
+ /* initialize new server */
+ new_server->name = NULL;
+ new_server->address = NULL;
+ new_server->password = NULL;
+ new_server->nick1 = NULL;
+ new_server->nick2 = NULL;
+ new_server->nick3 = NULL;
+ new_server->username = NULL;
+ new_server->realname = NULL;
+ new_server->nick = NULL;
+ new_server->is_connected = 0;
+ new_server->sock4 = -1;
+ new_server->is_away = 0;
+ new_server->server_read = -1;
+ new_server->server_write = -1;
+ new_server->window = NULL;
+ new_server->channels = NULL;
+ new_server->last_channel = NULL;
+
+ /* add new server to queue */
+ new_server->prev_server = last_irc_server;
+ new_server->next_server = NULL;
+ if (irc_servers)
+ last_irc_server->next_server = new_server;
+ else
+ irc_servers = new_server;
+ last_irc_server = new_server;
+
+ /* all is ok, return address of new server */
+ return new_server;
+}
+
+/*
+ * server_create_window: create windows for a server
+ */
+
+void
+server_create_window (t_irc_server *server)
+{
+ if (!SERVER(gui_windows))
+ {
+ server->window = gui_windows;
+ SERVER(gui_windows) = server;
+ }
+ else
+ gui_window_new (server, NULL);
+}
+
+/*
+ * server_free: free a server and remove it from servers queue
+ */
+
+void
+server_free (t_irc_server *server)
+{
+ t_irc_server *new_irc_servers;
+
+ /* remove server from queue */
+ if (server->prev_server)
+ {
+ (server->prev_server)->next_server = server->next_server;
+ new_irc_servers = irc_servers;
+ }
+ else
+ new_irc_servers = server->next_server;
+
+ if (server->next_server)
+ (server->next_server)->prev_server = server->prev_server;
+
+ /* free data */
+ if (server->name)
+ free (server->name);
+ if (server->address)
+ free (server->address);
+ if (server->password)
+ free (server->password);
+ if (server->nick1)
+ free (server->nick1);
+ if (server->nick2)
+ free (server->nick2);
+ if (server->nick3)
+ free (server->nick3);
+ if (server->username)
+ free (server->username);
+ if (server->realname)
+ free (server->realname);
+ if (server->nick)
+ free (server->nick);
+ if (server->channels)
+ channel_free_all (server);
+ /* TODO: free weechat window (???) */
+ /* (...) */
+ free (server);
+ irc_servers = new_irc_servers;
+}
+
+/*
+ * server_free_all: free all allocated servers
+ */
+
+void
+server_free_all ()
+{
+ /* for each server in memory, remove it */
+ while (irc_servers)
+ server_free (irc_servers);
+}
+
+/*
+ * server_new: creates a new server, and initialize it
+ */
+
+t_irc_server *
+server_new (char *name, char *address, int port, char *password,
+ char *nick1, char *nick2, char *nick3,
+ char *username, char *realname)
+{
+ t_irc_server *new_server;
+
+ if (!name || !address || (port < 0) || !nick1 || !nick2 || !nick3
+ || !username || !realname)
+ return NULL;
+
+ #if DEBUG >= 1
+ log_printf ("creating new server (name:%s, address:%s, port:%d, pwd:%s, "
+ "nick1:%s, nick2:%s, nick3:%s, username:%s, realname:%s)\n",
+ name, address, port, password, nick1, nick2, nick3,
+ username, realname);
+ #endif
+
+ if ((new_server = server_alloc ()))
+ {
+ new_server->name = strdup (name);
+ new_server->address = strdup (address);
+ new_server->port = port;
+ new_server->password = (password) ? strdup (password) : strdup ("");
+ new_server->nick1 = (nick1) ? strdup (nick1) : strdup ("weechat_user");
+ new_server->nick2 = (nick2) ? strdup (nick2) : strdup ("weechat2");
+ new_server->nick3 = (nick3) ? strdup (nick3) : strdup ("weechat3");
+ new_server->username =
+ (username) ? strdup (username) : strdup ("weechat");
+ new_server->realname =
+ (realname) ? strdup (realname) : strdup ("realname");
+ new_server->nick = strdup (new_server->nick1);
+ }
+ else
+ return NULL;
+ return new_server;
+}
+
+/*
+ * server_send: send data to irc server
+ */
+
+int
+server_send (t_irc_server * server, char *buffer, int size_buf)
+{
+ if (!server)
+ return -1;
+
+ return send (server->sock4, buffer, size_buf, 0);
+}
+
+/*
+ * server_sendf: send formatted data to irc server
+ */
+
+int
+server_sendf (t_irc_server * server, char *fmt, ...)
+{
+ va_list args;
+ static char buffer[1024];
+ int size_buf;
+
+ if (!server)
+ return -1;
+
+ va_start (args, fmt);
+ size_buf = vsnprintf (buffer, sizeof (buffer) - 1, fmt, args);
+ va_end (args);
+
+ if ((size_buf == 0) || (strcmp (buffer, "\r\n") == 0))
+ return 0;
+
+ buffer[sizeof (buffer) - 1] = '\0';
+ if ((size_buf < 0) || (size_buf > (int) (sizeof (buffer) - 1)))
+ size_buf = strlen (buffer);
+ buffer[size_buf - 2] = '\0';
+ #if DEBUG >= 2
+ gui_printf (server->window, "[DEBUG] Sending to server >>> %s\n", buffer);
+ #endif
+ buffer[size_buf - 2] = '\r';
+ return server_send (server, buffer, size_buf);
+}
+
+/*
+ * server_msgq_add_msg: add a message to received messages queue (at the end)
+ */
+
+void
+server_msgq_add_msg (t_irc_server * server, char *msg)
+{
+ t_irc_message *message;
+
+ message = (t_irc_message *) malloc (sizeof (t_irc_message));
+ message->server = server;
+ if (unterminated_message)
+ {
+ message->data = (char *) malloc (strlen (unterminated_message) +
+ strlen (msg) + 1);
+ strcpy (message->data, unterminated_message);
+ strcat (message->data, msg);
+ free (unterminated_message);
+ unterminated_message = NULL;
+ }
+ else
+ message->data = strdup (msg);
+ message->next_message = NULL;
+
+ if (msgq_last_msg)
+ {
+ msgq_last_msg->next_message = message;
+ msgq_last_msg = message;
+ }
+ else
+ {
+ recv_msgq = message;
+ msgq_last_msg = message;
+ }
+}
+
+/*
+ * server_msgq_add_buffer: explode received buffer, creating queued messages
+ */
+
+void
+server_msgq_add_buffer (t_irc_server * server, char *buffer)
+{
+ char *pos;
+
+ while (buffer[0])
+ {
+ pos = strstr (buffer, "\r\n");
+ if (pos)
+ {
+ pos[0] = '\0';
+ server_msgq_add_msg (server, buffer);
+ buffer = pos + 2;
+ }
+ else
+ {
+ pos = strchr (buffer, '\0');
+ if (pos)
+ {
+ unterminated_message =
+ (char *) realloc (unterminated_message,
+ strlen (buffer) + 1);
+ strcpy (unterminated_message, buffer);
+ return;
+ }
+ gui_printf (server->window,
+ _("%s unable to explode received buffer\n"),
+ WEECHAT_ERROR);
+ }
+ }
+}
+
+/*
+ * server_msgq_flush: flush message queue
+ */
+
+void
+server_msgq_flush ()
+{
+ t_irc_message *next;
+ /*char **argv;
+ int argc;*/
+ char *ptr_data, *pos, *pos2;
+ char *host, *command, *args;
+
+ /* TODO: optimize this function, parse only a few messages (for low CPU time!) */
+ while (recv_msgq)
+ {
+ #if DEBUG >= 2
+ gui_printf (gui_current_window, "[DEBUG] %s\n", recv_msgq->data);
+ #endif
+
+ ptr_data = recv_msgq->data;
+
+ while (ptr_data[0] == ' ')
+ ptr_data++;
+
+ if (ptr_data)
+ {
+ #if DEBUG >= 2
+ gui_printf (NULL, "[DEBUG] data received from server: %s\n", ptr_data);
+ #endif
+
+ host = NULL;
+ command = NULL;
+ args = ptr_data;
+
+ if (ptr_data[0] == ':')
+ {
+ pos = strchr(ptr_data, ' ');
+ pos[0] = '\0';
+ host = ptr_data+1;
+ pos++;
+ }
+ else
+ pos = ptr_data;
+
+ if (pos != NULL)
+ {
+ while (pos[0] == ' ')
+ pos++;
+ pos2 = strchr(pos, ' ');
+ if (pos2 != NULL)
+ {
+ pos2[0] = '\0';
+ command = strdup(pos);
+ pos2++;
+ while (pos2[0] == ' ')
+ pos2++;
+ args = (pos2[0] == ':') ? pos2+1 : pos2;
+ }
+ }
+
+ switch (irc_recv_command (recv_msgq->server, host, command, args))
+ {
+ case -1:
+ gui_printf (recv_msgq->server->window,
+ _("Command '%s' failed!\n"), command);
+ break;
+ case -2:
+ gui_printf (recv_msgq->server->window,
+ _("No command to execute!\n"));
+ break;
+ case -3:
+ gui_printf (recv_msgq->server->window,
+ _("Unknown command: cmd=%s, args=%s\n"),
+ command, args);
+ break;
+ }
+ }
+
+ free (recv_msgq->data);
+ next = recv_msgq->next_message;
+ free (recv_msgq);
+ recv_msgq = next;
+ if (recv_msgq == NULL)
+ msgq_last_msg = NULL;
+ }
+}
+
+/*
+ * server_recv: receive data from an irc server
+ */
+
+void
+server_recv (t_irc_server *server)
+{
+ static char buffer[4096 + 2];
+ int num_read;
+
+ num_read = recv (server->sock4, buffer, sizeof (buffer) - 2, 0);
+ if (num_read > 0)
+ {
+ buffer[num_read] = '\0';
+ server_msgq_add_buffer (server, buffer);
+ server_msgq_flush ();
+ }
+}
+
+/*
+ * server_connect: connect to an irc server
+ */
+
+int
+server_connect (t_irc_server *server)
+{
+ int set;
+ struct hostent *ip4_hostent;
+ struct sockaddr_in addr;
+ char *ip_address;
+ int error;
+ int server_pipe[2];
+
+ gui_printf (server->window,
+ _(WEECHAT_NAME ": connecting to %s:%d...\n"),
+ server->address, server->port);
+ log_printf ("connecting to server %s:%d...\n",
+ server->address, server->port);
+ server->is_connected = 0;
+
+ /* create pipe */
+ if (pipe (server_pipe) < 0)
+ {
+ gui_printf (server->window,
+ _("%s cannot create pipe\n"), WEECHAT_ERROR);
+ server_free (server);
+ return 0;
+ }
+ server->server_read = server_pipe[0];
+ server->server_write = server_pipe[1];
+
+ /* create socket and set options */
+ server->sock4 = socket (AF_INET, SOCK_STREAM, 0);
+ set = 1;
+ if (setsockopt
+ (server->sock4, SOL_SOCKET, SO_REUSEADDR, (char *) &set,
+ sizeof (set)) == -1)
+ gui_printf (server->window,
+ _("%s cannot set socket option 'SO_REUSEADDR'\n"),
+ WEECHAT_ERROR);
+ set = 1;
+ if (setsockopt
+ (server->sock4, SOL_SOCKET, SO_KEEPALIVE, (char *) &set,
+ sizeof (set)) == -1)
+ gui_printf (server->window,
+ _("%s cannot set socket option \"SO_KEEPALIVE\"\n"),
+ WEECHAT_ERROR);
+
+ /* bind to hostname */
+ ip4_hostent = gethostbyname (server->address);
+ if (!ip4_hostent)
+ {
+ gui_printf (server->window,
+ _("%s address \"%s\" not found\n"),
+ WEECHAT_ERROR, server->address);
+ close (server->server_read);
+ close (server->server_write);
+ close (server->sock4);
+ server->sock4 = -1;
+ return 0;
+ }
+ memset (&addr, 0, sizeof (addr));
+ memcpy (&addr.sin_addr, ip4_hostent->h_addr, ip4_hostent->h_length);
+ addr.sin_port = htons (server->port);
+ addr.sin_family = AF_INET;
+ /*error = bind(server->sock4, (struct sockaddr *)(&addr), sizeof(addr));
+ if (error != 0)
+ {
+ gui_printf (server->window,
+ WEECHAT_ERORR "server_connect: can't bind to hostname\n");
+ return 0;
+ } */
+ ip_address = inet_ntoa (addr.sin_addr);
+ if (!ip_address)
+ {
+ gui_printf (server->window,
+ _("%s IP address not found\n"), WEECHAT_ERROR);
+ close (server->server_read);
+ close (server->server_write);
+ close (server->sock4);
+ server->sock4 = -1;
+ return 0;
+ }
+
+ /* connection to server */
+ gui_printf (server->window,
+ _(WEECHAT_NAME ": server IP is: %s\n"), ip_address);
+
+ error = connect (server->sock4, (struct sockaddr *) &addr, sizeof (addr));
+ if (error != 0)
+ {
+ gui_printf (server->window,
+ _("%s cannot connect to irc server\n"), WEECHAT_ERROR);
+ close (server->server_read);
+ close (server->server_write);
+ close (server->sock4);
+ server->sock4 = -1;
+ return 0;
+ }
+
+ current_irc_server = server;
+ return 1;
+}
+
+/*
+ * server_disconnect: disconnect from an irc server
+ */
+
+void
+server_disconnect (t_irc_server *server)
+{
+ if (server->is_connected)
+ {
+ close (server->server_read);
+ close (server->server_write);
+ close (server->sock4);
+ server->is_connected = 0;
+ }
+}
+
+/*
+ * server_disconnect_all: disconnect from all irc servers
+ */
+
+void
+server_disconnect_all ()
+{
+ t_irc_server *ptr_server;
+
+ for (ptr_server = irc_servers; ptr_server; ptr_server = ptr_server->next_server)
+ server_disconnect (ptr_server);
+}
+
+/*
+ * server_get_number_connected: returns number of connected server
+ */
+
+int
+server_get_number_connected ()
+{
+ t_irc_server *ptr_server;
+ int number;
+
+ number = 0;
+ for (ptr_server = irc_servers; ptr_server; ptr_server = ptr_server->next_server)
+ {
+ if (ptr_server->is_connected)
+ number++;
+ }
+ return number;
+}
+
+/*
+ * server_name_already_exists: return 1 if server name already exists
+ * otherwise return 0
+ */
+
+int
+server_name_already_exists (char *name)
+{
+ t_irc_server *ptr_server;
+
+ for (ptr_server = irc_servers; ptr_server; ptr_server = ptr_server->next_server)
+ {
+ if (strcmp (ptr_server->name, name) == 0)
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/irc/irc.h b/src/irc/irc.h
new file mode 100644
index 000000000..f1f3698be
--- /dev/null
+++ b/src/irc/irc.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2003 by FlashCode <flashcode@flashtux.org>
+ * Bounga <bounga@altern.org>
+ * Xahlexx <xahlexx@tuxisland.org>
+ * See README for License detail.
+ *
+ * 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
+ */
+
+
+#ifndef __WEECHAT_IRC_H
+#define __WEECHAT_IRC_H 1
+
+#include "../gui/gui.h"
+
+#define PREFIX_SERVER "-@-"
+#define PREFIX_INFO "-=-"
+#define PREFIX_ACTION_ME "-*-"
+#define PREFIX_JOIN "-->"
+#define PREFIX_PART "<--"
+#define PREFIX_QUIT "<--"
+#define PREFIX_ERROR "=!="
+
+#define CHANNEL_PREFIX "#&+!"
+
+/* nick types */
+
+typedef struct t_irc_nick t_irc_nick;
+
+struct t_irc_nick
+{
+ char *nick; /* nickname */
+ int is_op; /* operator privileges? */
+ int is_halfop; /* half operaor privileges? */
+ int has_voice; /* nick has voice? */
+ int color; /* color for nickname */
+ t_irc_nick *prev_nick; /* link to previous nick on the channel */
+ t_irc_nick *next_nick; /* link to next nick on the channel */
+};
+
+/* channel types */
+
+typedef struct t_irc_channel t_irc_channel;
+
+#define CHAT_UNKNOWN -1
+#define CHAT_CHANNEL 0
+#define CHAT_PRIVATE 1
+
+struct t_irc_channel
+{
+ int type; /* channel type */
+ char *name; /* name of channel (exemple: "#abc") */
+ char *topic; /* topic of channel (host for private) */
+ t_irc_nick *nicks; /* nicks on the channel */
+ t_irc_nick *last_nick; /* last nick on the channel */
+ t_gui_window *window; /* GUI window allocated for channel */
+ t_irc_channel *prev_channel; /* link to previous channel */
+ t_irc_channel *next_channel; /* link to next channel */
+};
+
+/* server types */
+
+typedef struct t_irc_server t_irc_server;
+
+struct t_irc_server
+{
+ /* user choices */
+ char *name; /* name of server (only for display) */
+ char *address; /* address of server (IP or name) */
+ int port; /* port for server (6667 by default) */
+ char *password; /* password for server */
+ char *nick1; /* first nickname for the server */
+ char *nick2; /* alternate nickname */
+ char *nick3; /* 2nd alternate nickname */
+ char *username; /* user name */
+ char *realname; /* real name */
+
+ /* internal vars */
+ char *nick; /* current nickname */
+ int is_connected; /* 1 if WeeChat is connected to server */
+ int sock4; /* socket for server */
+ int is_away; /* 1 is user is marker as away */
+ int server_read; /* pipe for reading server data */
+ int server_write; /* pipe for sending data to server */
+ t_gui_window *window; /* GUI window allocated for server */
+ t_irc_channel *channels; /* opened channels on server */
+ t_irc_channel *last_channel; /* last opened channal on server */
+ t_irc_server *prev_server; /* link to previous server */
+ t_irc_server *next_server; /* link to next server */
+};
+
+/* irc commands */
+
+typedef struct t_irc_command t_irc_command;
+
+struct t_irc_command
+{
+ char *command_name; /* command name (internal or IRC cmd) */
+ char *command_description; /* command description */
+ char *arguments; /* command parameters */
+ char *arguments_description; /* parameters description */
+ int min_arg, max_arg; /* min & max number of parameters */
+ int need_connection; /* = 1 if cmd needs server connection */
+ int (*cmd_function_args)(t_irc_server *, int, char **);
+ /* function called when user enters cmd */
+ int (*cmd_function_1arg)(t_irc_server *, char *);
+ /* function called when user enters cmd */
+ int (*recv_function)(t_irc_server *, char *, char *);
+ /* function called when cmd is received */
+};
+
+typedef struct t_irc_message t_irc_message;
+
+struct t_irc_message
+{
+ t_irc_server *server; /* server pointer for received msg */
+ char *data; /* message content */
+ t_irc_message *next_message; /* link to next message */
+};
+
+extern t_irc_command irc_commands[];
+extern t_irc_server *irc_servers, *current_irc_server;
+extern t_irc_message *recv_msgq, *msgq_last_msg;
+extern t_irc_channel *current_channel;
+
+/* server functions (irc-server.c) */
+
+extern t_irc_server *server_alloc ();
+extern void server_create_window (t_irc_server *);
+extern void server_free (t_irc_server *);
+extern void server_free_all ();
+extern t_irc_server *server_new (char *, char *, int, char *, char *, char *,
+ char *, char *, char *);
+extern int server_send (t_irc_server *, char *, int);
+extern int server_sendf (t_irc_server *, char *, ...);
+extern void server_recv (t_irc_server *);
+extern int server_connect ();
+extern void server_disconnect (t_irc_server *);
+extern void server_disconnect_all ();
+extern int server_get_number_connected ();
+extern int server_name_already_exists (char *);
+
+/* channel functions (irc-channel.c) */
+
+extern t_irc_channel *channel_new (t_irc_server *, int, char *);
+extern void channel_free (t_irc_server *, t_irc_channel *);
+extern void channel_free_all (t_irc_server *);
+extern t_irc_channel *channel_search (t_irc_server *, char *);
+extern int string_is_channel (char *);
+
+/* nick functions (irc-nick.c) */
+
+extern t_irc_nick *nick_new (t_irc_channel *, char *, int, int, int);
+extern void nick_resort (t_irc_channel *, t_irc_nick *);
+extern void nick_change (t_irc_channel *, t_irc_nick *, char *);
+extern void nick_free (t_irc_channel *, t_irc_nick *);
+extern void nick_free_all (t_irc_channel *);
+extern t_irc_nick *nick_search (t_irc_channel *, char *);
+extern void nick_count (t_irc_channel *, int *, int *, int *, int *, int *);
+extern int nick_get_max_length (t_irc_channel *);
+
+/* IRC display (irc-diplay.c) */
+
+extern void irc_display_prefix (t_gui_window *, char *);
+extern void irc_display_nick (t_gui_window *, t_irc_nick *, int, int, int, int);
+extern void irc_display_mode (t_gui_window *, char *, char, char *, char *,
+ char *, char *);
+
+/* IRC protocol (irc-commands.c) */
+
+extern int irc_recv_command (t_irc_server *, char *, char *, char *);
+extern void irc_login (t_irc_server *);
+/* IRC commands issued by user */
+extern int irc_cmd_send_away (t_irc_server *, char *);
+extern int irc_cmd_send_ctcp (t_irc_server *, char *);
+extern int irc_cmd_send_deop (t_irc_server *, int, char **);
+extern int irc_cmd_send_devoice (t_irc_server *, int, char **);
+extern int irc_cmd_send_invite (t_irc_server *, char *);
+extern int irc_cmd_send_join (t_irc_server *, char *);
+extern int irc_cmd_send_kick (t_irc_server *, char *);
+extern int irc_cmd_send_kill (t_irc_server *, char *);
+extern int irc_cmd_send_list (t_irc_server *, char *);
+extern int irc_cmd_send_me (t_irc_server *, char *);
+extern int irc_cmd_send_mode (t_irc_server *, char *);
+extern int irc_cmd_send_msg (t_irc_server *, char *);
+extern int irc_cmd_send_names (t_irc_server *, char *);
+extern int irc_cmd_send_nick (t_irc_server *, int, char **);
+extern int irc_cmd_send_notice (t_irc_server *, char *);
+extern int irc_cmd_send_op (t_irc_server *, int, char **);
+extern int irc_cmd_send_oper (t_irc_server *, int, char **);
+extern int irc_cmd_send_part (t_irc_server *, char *);
+extern int irc_cmd_send_ping (t_irc_server *, int, char **);
+extern int irc_cmd_send_pong (t_irc_server *, int, char **);
+extern int irc_cmd_send_quit (t_irc_server *, char *);
+extern int irc_cmd_send_quote (t_irc_server *, char *);
+extern int irc_cmd_send_topic (t_irc_server *, char *);
+extern int irc_cmd_send_version (t_irc_server *, char *);
+extern int irc_cmd_send_voice (t_irc_server *, int, char **);
+extern int irc_cmd_send_whois (t_irc_server *, char *);
+/* IRC commands executed when received from server */
+extern int irc_cmd_recv_error (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_join (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_kick (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_mode (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_nick (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_notice (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_part (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_ping (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_privmsg (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_quit (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_server_msg (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_server_reply (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_topic (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_001 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_004 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_301 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_311 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_312 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_313 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_317 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_318 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_319 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_320 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_321 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_322 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_323 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_331 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_332 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_333 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_351 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_353 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_366 (t_irc_server *, char *, char *);
+extern int irc_cmd_recv_433 (t_irc_server *, char *, char *);
+
+#endif /* irc.h */