1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-25 20:36:38 +02:00
Files
weechat/src/plugins/irc/irc-channel.c
T
2008-05-20 17:29:44 +02:00

464 lines
14 KiB
C

/*
* Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org>
* See README for License detail, AUTHORS for developers list.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* irc-channel.c: manages a chat (channel or private chat) */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "irc.h"
#include "irc-channel.h"
#include "irc-buffer.h"
#include "irc-config.h"
#include "irc-nick.h"
#include "irc-server.h"
#include "irc-input.h"
/*
* irc_channel_new: allocate a new channel for a server and add it to servers
* list
*/
struct t_irc_channel *
irc_channel_new (struct t_irc_server *server, int channel_type,
char *channel_name, int switch_to_channel)
{
struct t_irc_channel *new_channel;
struct t_gui_buffer *new_buffer;
/* alloc memory for new channel */
if ((new_channel = malloc (sizeof (*new_channel))) == NULL)
{
weechat_printf (NULL,
_("%s%s: cannot allocate new channel"),
weechat_prefix ("error"), "irc");
return NULL;
}
/* create buffer for channel */
new_buffer = weechat_buffer_new (server->name, channel_name,
&irc_input_data_cb, NULL,
&irc_buffer_close_cb, NULL);
if (!new_buffer)
{
free (new_channel);
return NULL;
}
if (channel_type == IRC_CHANNEL_TYPE_CHANNEL)
{
weechat_buffer_set (new_buffer, "nick", server->nick);
if (weechat_config_integer (weechat_config_get ("weechat.look.nicklist")))
weechat_buffer_set (new_buffer, "nicklist", "1");
weechat_buffer_set (new_buffer, "nicklist_display_groups", "0");
weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_OP,
"nicklist_group", 1);
weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_HALFOP,
"nicklist_group", 1);
weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_VOICE,
"nicklist_group", 1);
weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_CHANUSER,
"nicklist_group", 1);
weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_NORMAL,
"nicklist_group", 1);
}
/* initialize new channel */
new_channel->type = channel_type;
new_channel->name = strdup (channel_name);
new_channel->topic = NULL;
new_channel->modes = NULL;
new_channel->limit = 0;
new_channel->key = NULL;
new_channel->nicks_count = 0;
new_channel->checking_away = 0;
new_channel->away_message = NULL;
new_channel->cycle = 0;
new_channel->display_creation_date = 0;
new_channel->nick_completion_reset = 0;
new_channel->nicks = NULL;
new_channel->last_nick = NULL;
new_channel->buffer = new_buffer;
new_channel->nicks_speaking = NULL;
//new_buffer->notify_level = irc_channel_get_notify_level (server, new_channel);
/* add new channel to channels list */
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;
if (switch_to_channel)
weechat_buffer_set (new_buffer, "display", "1");
/* all is ok, return address of new channel */
return new_channel;
}
/*
* irc_channel_free: free a channel and remove it from channels list
*/
void
irc_channel_free (struct t_irc_server *server, struct t_irc_channel *channel)
{
struct t_irc_channel *new_channels;
if (!server || !channel)
return;
/* remove channel from channels list */
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);
if (channel->modes)
free (channel->modes);
if (channel->key)
free (channel->key);
irc_nick_free_all (channel);
if (channel->away_message)
free (channel->away_message);
if (channel->nicks_speaking)
weechat_list_free (channel->nicks_speaking);
free (channel);
server->channels = new_channels;
}
/*
* irc_channel_free_all: free all allocated channels
*/
void
irc_channel_free_all (struct t_irc_server *server)
{
/* remove all channels for the server */
while (server->channels)
irc_channel_free (server, server->channels);
}
/*
* irc_channel_search: returns pointer on a channel with name
*/
struct t_irc_channel *
irc_channel_search (struct t_irc_server *server, char *channel_name)
{
struct t_irc_channel *ptr_channel;
if (!server || !channel_name)
return NULL;
for (ptr_channel = server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
if (weechat_strcasecmp (ptr_channel->name, channel_name) == 0)
return ptr_channel;
}
return NULL;
}
/*
* irc_channel_search_any: returns pointer on a channel with name
*/
struct t_irc_channel *
irc_channel_search_any (struct t_irc_server *server, char *channel_name)
{
struct t_irc_channel *ptr_channel;
if (!server || !channel_name)
return NULL;
for (ptr_channel = server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
if (weechat_strcasecmp (ptr_channel->name, channel_name) == 0)
return ptr_channel;
}
return NULL;
}
/*
* irc_channel_search_any_without_buffer: returns pointer on a channel with name
* looks only for channels without buffer
*/
struct t_irc_channel *
irc_channel_search_any_without_buffer (struct t_irc_server *server,
char *channel_name)
{
struct t_irc_channel *ptr_channel;
if (!server || !channel_name)
return NULL;
for (ptr_channel = server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
if (!ptr_channel->buffer
&& (weechat_strcasecmp (ptr_channel->name, channel_name) == 0))
return ptr_channel;
}
return NULL;
}
/*
* irc_channel_is_channel: returns 1 if string is channel
*/
int
irc_channel_is_channel (char *string)
{
char first_char[2];
if (!string)
return 0;
first_char[0] = string[0];
first_char[1] = '\0';
return (strpbrk (first_char, IRC_CHANNEL_PREFIX)) ? 1 : 0;
}
/*
* irc_channel_remove_away: remove away for all nicks on a channel
*/
void
irc_channel_remove_away (struct t_irc_channel *channel)
{
struct t_irc_nick *ptr_nick;
if (channel->type == IRC_CHANNEL_TYPE_CHANNEL)
{
for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick)
{
irc_nick_set (channel, ptr_nick, 0, IRC_NICK_AWAY);
}
}
}
/*
* irc_channel_check_away: check for away on a channel
*/
void
irc_channel_check_away (struct t_irc_server *server,
struct t_irc_channel *channel, int force)
{
if (channel->type == IRC_CHANNEL_TYPE_CHANNEL)
{
if (force
|| (weechat_config_integer (irc_config_network_away_check_max_nicks) == 0)
|| (channel->nicks_count <= weechat_config_integer (irc_config_network_away_check_max_nicks)))
{
channel->checking_away++;
irc_server_sendf (server, "WHO %s", channel->name);
}
else
irc_channel_remove_away (channel);
}
}
/*
* irc_channel_set_away: set/unset away status for a channel
*/
void
irc_channel_set_away (struct t_irc_channel *channel, char *nick, int is_away)
{
(void) channel;
(void) nick;
(void) is_away;
/*struct t_irc_nick *ptr_nick;
if (channel->type == IRC_CHANNEL_TYPE_CHANNEL)
{
ptr_nick = irc_nick_search (channel, nick);
if (ptr_nick)
irc_nick_set_away (channel, ptr_nick, is_away);
}
*/
}
/*
* irc_channel_get_notify_level: get channel notify level
*/
int
irc_channel_get_notify_level (struct t_irc_server *server,
struct t_irc_channel *channel)
{
(void) server;
(void) channel;
/*char *name, *pos, *pos2;
int server_default_notify, notify;
if ((!server) || (!channel))
return GUI_NOTIFY_LEVEL_DEFAULT;
if ((!server->notify_levels) || (!server->notify_levels[0]))
return GUI_NOTIFY_LEVEL_DEFAULT;
server_default_notify = irc_server_get_default_notify_level (server);
if ((channel->type != IRC_CHANNEL_TYPE_CHANNEL)
&& (server_default_notify == 1))
server_default_notify = 2;
name = malloc (strlen (channel->name) + 2);
strcpy (name, channel->name);
strcat (name, ":");
pos = strstr (server->notify_levels, name);
free (name);
if (!pos)
return server_default_notify;
pos2 = pos + strlen (channel->name);
if (pos2[0] != ':')
return server_default_notify;
pos2++;
if (!pos2[0])
return server_default_notify;
notify = (int)(pos2[0] - '0');
if ((notify >= GUI_NOTIFY_LEVEL_MIN) && (notify <= GUI_NOTIFY_LEVEL_MAX))
return notify;
return server_default_notify;
*/
return 0;
}
/*
* irc_channel_set_notify_level: set channel notify level
*/
void
irc_channel_set_notify_level (struct t_irc_server *server,
struct t_irc_channel *channel, int notify)
{
(void) server;
(void) channel;
(void) notify;
/*char level_string[2];
if ((!server) || (!channel))
return;
level_string[0] = notify + '0';
level_string[1] = '\0';
config_option_list_set (&(server->notify_levels), channel->name, level_string);
*/
}
/*
* irc_channel_add_nick_speaking: add a nick speaking on a channel
*/
void
irc_channel_add_nick_speaking (struct t_irc_channel *channel, char *nick)
{
int size, to_remove, i;
if (!channel->nicks_speaking)
channel->nicks_speaking = weechat_list_new ();
weechat_list_add (channel->nicks_speaking, nick, WEECHAT_LIST_POS_END);
size = weechat_list_size (channel->nicks_speaking);
if (size > IRC_CHANNEL_NICKS_SPEAKING_LIMIT)
{
to_remove = size - IRC_CHANNEL_NICKS_SPEAKING_LIMIT;
for (i = 0; i < to_remove; i++)
{
weechat_list_remove (channel->nicks_speaking,
weechat_list_get (channel->nicks_speaking, 0));
}
}
}
/*
* irc_channel_print_log: print channel infos in log (usually for crash dump)
*/
void
irc_channel_print_log (struct t_irc_channel *channel)
{
struct t_weelist_item *ptr_item;
int i;
struct t_irc_nick *ptr_nick;
weechat_log_printf ("");
weechat_log_printf (" => channel %s (addr:0x%x)]", channel->name, channel);
weechat_log_printf (" type . . . . . . . . : %d", channel->type);
weechat_log_printf (" topic. . . . . . . . : '%s'", channel->topic);
weechat_log_printf (" modes. . . . . . . . : '%s'", channel->modes);
weechat_log_printf (" limit. . . . . . . . : %d", channel->limit);
weechat_log_printf (" key. . . . . . . . . : '%s'", channel->key);
weechat_log_printf (" checking_away. . . . : %d", channel->checking_away);
weechat_log_printf (" away_message . . . . : '%s'", channel->away_message);
weechat_log_printf (" cycle. . . . . . . . : %d", channel->cycle);
weechat_log_printf (" display_creation_date: %d", channel->display_creation_date);
weechat_log_printf (" nicks. . . . . . . . : 0x%x", channel->nicks);
weechat_log_printf (" last_nick. . . . . . : 0x%x", channel->last_nick);
weechat_log_printf (" buffer . . . . . . . : 0x%x", channel->buffer);
weechat_log_printf (" nicks_speaking . . . : 0x%x", channel->nicks_speaking);
weechat_log_printf (" prev_channel . . . . : 0x%x", channel->prev_channel);
weechat_log_printf (" next_channel . . . . : 0x%x", channel->next_channel);
if (channel->nicks_speaking)
{
weechat_log_printf ("");
i = 0;
for (ptr_item = weechat_list_get (channel->nicks_speaking, 0);
ptr_item; ptr_item = weechat_list_next (ptr_item))
{
weechat_log_printf (" nick speaking %d: '%s'",
i, weechat_list_string (ptr_item));
i++;
}
}
for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick)
{
irc_nick_print_log (ptr_nick);
}
}