1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-26 12:56:37 +02:00
Files
weechat/src/plugins/irc/irc-nick.c
T
Sébastien Helleu cf6aca1619 core: add pointer in some callbacks (closes #406)
This pointer is the first argument received by callbacks, and the
existing argument "data" is now automatically freed by WeeChat when the
object containing the callback is removed.

With this new pointer, the linked list of callbacks in scripts has been
removed. This will improve speed of scripts (using a lot of hooks),
reduce memory used by scripts and reduce time to unload scripts.

Following functions are affected in the C API:

* exec_on_files
* config_new
* config_new_section
* config_new_option
* hook_command
* hook_command_run
* hook_timer
* hook_fd
* hook_process
* hook_process_hashtable
* hook_connect
* hook_print
* hook_signal
* hook_hsignal
* hook_config
* hook_completion
* hook_modifier
* hook_info
* hook_info_hashtable
* hook_infolist
* hook_hdata
* hook_focus
* unhook_all_plugin
* buffer_new
* bar_item_new
* upgrade_new
* upgrade_read
2016-03-21 18:11:21 +01:00

1218 lines
32 KiB
C

/*
* irc-nick.c - nick management for IRC plugin
*
* Copyright (C) 2003-2016 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat 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.
*
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include "../weechat-plugin.h"
#include "irc.h"
#include "irc-nick.h"
#include "irc-color.h"
#include "irc-config.h"
#include "irc-mode.h"
#include "irc-server.h"
#include "irc-channel.h"
/*
* Checks if a nick pointer is valid.
*
* Returns:
* 1: nick exists in channel
* 0: nick does not exist in channel
*/
int
irc_nick_valid (struct t_irc_channel *channel, struct t_irc_nick *nick)
{
struct t_irc_nick *ptr_nick;
if (!channel || !nick)
return 0;
for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick)
{
if (ptr_nick == nick)
return 1;
}
/* nick not found */
return 0;
}
/*
* Checks if string is a valid nick string (RFC 1459).
*
* Returns:
* 1: string is a valid nick
* 0: string is not a valid nick
*/
int
irc_nick_is_nick (const char *string)
{
const char *ptr;
if (!string || !string[0])
return 0;
/* first char must not be a number or hyphen */
ptr = string;
if (strchr ("0123456789-", *ptr))
return 0;
while (ptr && ptr[0])
{
if (!strchr (IRC_NICK_VALID_CHARS, *ptr))
return 0;
ptr++;
}
return 1;
}
/*
* Duplicates a nick and stops at first char in list (using option
* irc.look.nick_color_stop_chars).
*
* Note: result must be freed after use.
*/
char *
irc_nick_strdup_for_color (const char *nickname)
{
int char_size, other_char_seen;
char *result, *pos, utf_char[16];
result = malloc (strlen (nickname) + 1);
pos = result;
other_char_seen = 0;
while (nickname[0])
{
char_size = weechat_utf8_char_size (nickname);
memcpy (utf_char, nickname, char_size);
utf_char[char_size] = '\0';
if (strstr (weechat_config_string (irc_config_look_nick_color_stop_chars),
utf_char))
{
if (other_char_seen)
{
pos[0] = '\0';
return result;
}
}
else
{
other_char_seen = 1;
}
memcpy (pos, utf_char, char_size);
pos += char_size;
nickname += char_size;
}
pos[0] = '\0';
return result;
}
/*
* Hashes a nickname to find color.
*
* Returns a number which is the index of color in the nicks colors of option
* "weechat.color.chat_nick_colors".
*/
int
irc_nick_hash_color (const char *nickname)
{
unsigned long color;
const char *ptr_nick;
if (!irc_config_nick_colors)
irc_config_set_nick_colors ();
if (irc_config_num_nick_colors == 0)
return 0;
ptr_nick = nickname;
color = 0;
switch (weechat_config_integer (irc_config_look_nick_color_hash))
{
case IRC_CONFIG_LOOK_NICK_COLOR_HASH_DJB2:
/* variant of djb2 hash */
color = 5381;
while (ptr_nick && ptr_nick[0])
{
color ^= (color << 5) + (color >> 2) + weechat_utf8_char_int (ptr_nick);
ptr_nick = weechat_utf8_next_char (ptr_nick);
}
break;
case IRC_CONFIG_LOOK_NICK_COLOR_HASH_SUM:
/* sum of letters */
color = 0;
while (ptr_nick && ptr_nick[0])
{
color += weechat_utf8_char_int (ptr_nick);
ptr_nick = weechat_utf8_next_char (ptr_nick);
}
break;
}
return (color % irc_config_num_nick_colors);
}
/*
* Gets forced color for a nick.
*
* Returns the name of color (for example: "green"), NULL if no color is forced
* for nick.
*/
const char *
irc_nick_get_forced_color (const char *nickname)
{
const char *forced_color;
char *nick_lower;
if (!nickname)
return NULL;
forced_color = weechat_hashtable_get (irc_config_hashtable_nick_color_force,
nickname);
if (forced_color)
return forced_color;
nick_lower = strdup (nickname);
if (nick_lower)
{
weechat_string_tolower (nick_lower);
forced_color = weechat_hashtable_get (irc_config_hashtable_nick_color_force,
nick_lower);
free (nick_lower);
}
return forced_color;
}
/*
* Finds a color code for a nick (according to nick letters).
*
* Returns a WeeChat color code (that can be used for display).
*/
const char *
irc_nick_find_color (const char *nickname)
{
int color;
char *nickname2;
const char *forced_color, *str_color;
if (!irc_config_nick_colors)
irc_config_set_nick_colors ();
if (irc_config_num_nick_colors == 0)
return weechat_color ("default");
/* look if color is forced */
forced_color = irc_nick_get_forced_color (nickname);
if (forced_color)
{
forced_color = weechat_color (forced_color);
if (forced_color && forced_color[0])
return forced_color;
}
/* hash nickname to get color */
nickname2 = irc_nick_strdup_for_color (nickname);
color = irc_nick_hash_color ((nickname2) ? nickname2 : nickname);
if (nickname2)
free (nickname2);
/* return color */
str_color = weechat_color (irc_config_nick_colors[color]);
return (str_color[0]) ? str_color : weechat_color("default");
}
/*
* Finds a color name for a nick (according to nick letters).
*
* Returns the name of a color (for example: "green").
*/
const char *
irc_nick_find_color_name (const char *nickname)
{
int color;
char *nickname2;
const char *forced_color;
static char *default_color = "default";
if (!irc_config_nick_colors)
irc_config_set_nick_colors ();
if (irc_config_num_nick_colors == 0)
return default_color;
/* look if color is forced */
forced_color = irc_nick_get_forced_color (nickname);
if (forced_color)
return forced_color;
/* hash nickname to get color */
nickname2 = irc_nick_strdup_for_color (nickname);
color = irc_nick_hash_color ((nickname2) ? nickname2 : nickname);
if (nickname2)
free (nickname2);
/* return color name */
return irc_config_nick_colors[color];
}
/*
* Sets current prefix, using higher prefix set in prefixes.
*/
void
irc_nick_set_current_prefix (struct t_irc_nick *nick)
{
char *ptr_prefixes;
nick->prefix[0] = ' ';
for (ptr_prefixes = nick->prefixes; ptr_prefixes[0]; ptr_prefixes++)
{
if (ptr_prefixes[0] != ' ')
{
nick->prefix[0] = ptr_prefixes[0];
break;
}
}
}
/*
* Sets/unsets a prefix in prefixes.
*
* If set == 1, sets prefix (prefix is used).
* If set == 0, unsets prefix (space is used).
*/
void
irc_nick_set_prefix (struct t_irc_server *server, struct t_irc_nick *nick,
int set, char prefix)
{
int index;
index = irc_server_get_prefix_char_index (server, prefix);
if (index >= 0)
{
nick->prefixes[index] = (set) ? prefix : ' ';
irc_nick_set_current_prefix (nick);
}
}
/*
* Sets prefixes for nick.
*/
void
irc_nick_set_prefixes (struct t_irc_server *server, struct t_irc_nick *nick,
const char *prefixes)
{
const char *ptr_prefixes;
/* reset all prefixes in nick */
memset (nick->prefixes, ' ', strlen (nick->prefixes));
/* add prefixes in nick */
if (prefixes)
{
for (ptr_prefixes = prefixes; ptr_prefixes[0]; ptr_prefixes++)
{
irc_nick_set_prefix (server, nick, 1, ptr_prefixes[0]);
}
}
/* set current prefix */
irc_nick_set_current_prefix (nick);
}
/*
* Checks if nick is "op" (or better than "op", for example channel admin or
* channel owner).
*
* Returns:
* 1: nick is "op" (or better)
* 0: nick is not op
*/
int
irc_nick_is_op (struct t_irc_server *server, struct t_irc_nick *nick)
{
int index;
if (nick->prefix[0] == ' ')
return 0;
index = irc_server_get_prefix_char_index (server, nick->prefix[0]);
if (index < 0)
return 0;
return (index <= irc_server_get_prefix_mode_index (server, 'o')) ? 1 : 0;
}
/*
* Checks if nick prefixes contains prefix for a given mode.
*
* For example if prefix_mode is 'o', searches for '@' in nick prefixes.
*
* Returns:
* 1: prefixes contains prefix for the given mode
* 0: prefixes does not contain prefix for the given mode.
*/
int
irc_nick_has_prefix_mode (struct t_irc_server *server, struct t_irc_nick *nick,
char prefix_mode)
{
char prefix_char;
prefix_char = irc_server_get_prefix_char_for_mode (server, prefix_mode);
if (prefix_char == ' ')
return 0;
return (strchr (nick->prefixes, prefix_char)) ? 1 : 0;
}
/*
* Gets nicklist group for a nick.
*/
struct t_gui_nick_group *
irc_nick_get_nicklist_group (struct t_irc_server *server,
struct t_gui_buffer *buffer,
struct t_irc_nick *nick)
{
int index;
char str_group[2];
const char *prefix_modes;
struct t_gui_nick_group *ptr_group;
if (!server || !buffer || !nick)
return NULL;
ptr_group = NULL;
index = irc_server_get_prefix_char_index (server, nick->prefix[0]);
if (index < 0)
{
ptr_group = weechat_nicklist_search_group (buffer, NULL,
IRC_NICK_GROUP_OTHER_NAME);
}
else
{
prefix_modes = irc_server_get_prefix_modes (server);
str_group[0] = prefix_modes[index];
str_group[1] = '\0';
ptr_group = weechat_nicklist_search_group (buffer, NULL, str_group);
}
return ptr_group;
}
/*
* Gets name of prefix color for a nick.
*/
const char *
irc_nick_get_prefix_color_name (struct t_irc_server *server, char prefix)
{
static char *default_color = "";
const char *prefix_modes, *color;
char mode[2];
int index;
if (irc_config_hashtable_nick_prefixes)
{
mode[0] = ' ';
mode[1] = '\0';
index = irc_server_get_prefix_char_index (server, prefix);
if (index >= 0)
{
prefix_modes = irc_server_get_prefix_modes (server);
mode[0] = prefix_modes[index];
color = weechat_hashtable_get (irc_config_hashtable_nick_prefixes,
mode);
if (color)
return color;
}
/* fallback to "*" if no color is found with mode */
mode[0] = '*';
color = weechat_hashtable_get (irc_config_hashtable_nick_prefixes,
mode);
if (color)
return color;
}
/* no color by default */
return default_color;
}
/*
* Gets nick color for nicklist.
*/
const char *
irc_nick_get_color_for_nicklist (struct t_irc_server *server,
struct t_irc_nick *nick)
{
static char *nick_color_bar_fg = "bar_fg";
static char *nick_color_self = "weechat.color.chat_nick_self";
static char *nick_color_away = "weechat.color.nicklist_away";
if (nick->away)
return nick_color_away;
if (weechat_config_boolean(irc_config_look_color_nicks_in_nicklist))
{
if (irc_server_strcasecmp (server, nick->name, server->nick) == 0)
return nick_color_self;
else
return irc_nick_find_color_name (nick->name);
}
return nick_color_bar_fg;
}
/*
* Adds a nick to buffer nicklist.
*/
void
irc_nick_nicklist_add (struct t_irc_server *server,
struct t_irc_channel *channel,
struct t_irc_nick *nick)
{
struct t_gui_nick_group *ptr_group;
ptr_group = irc_nick_get_nicklist_group (server, channel->buffer, nick);
weechat_nicklist_add_nick (channel->buffer, ptr_group,
nick->name,
irc_nick_get_color_for_nicklist (server, nick),
nick->prefix,
irc_nick_get_prefix_color_name (server, nick->prefix[0]),
1);
}
/*
* Removes a nick from buffer nicklist.
*/
void
irc_nick_nicklist_remove (struct t_irc_server *server,
struct t_irc_channel *channel,
struct t_irc_nick *nick)
{
struct t_gui_nick_group *ptr_group;
ptr_group = irc_nick_get_nicklist_group (server, channel->buffer, nick);
weechat_nicklist_remove_nick (channel->buffer,
weechat_nicklist_search_nick (channel->buffer,
ptr_group,
nick->name));
}
/*
* Sets a property for nick in buffer nicklist.
*/
void
irc_nick_nicklist_set (struct t_irc_channel *channel,
struct t_irc_nick *nick,
const char *property, const char *value)
{
struct t_gui_nick *ptr_nick;
ptr_nick = weechat_nicklist_search_nick (channel->buffer, NULL, nick->name);
if (ptr_nick)
{
weechat_nicklist_nick_set (channel->buffer, ptr_nick, property, value);
}
}
/*
* Sets nick prefix colors in nicklist for all servers/channels.
*/
void
irc_nick_nicklist_set_prefix_color_all ()
{
struct t_irc_server *ptr_server;
struct t_irc_channel *ptr_channel;
struct t_irc_nick *ptr_nick;
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
for (ptr_channel = ptr_server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
for (ptr_nick = ptr_channel->nicks; ptr_nick;
ptr_nick = ptr_nick->next_nick)
{
irc_nick_nicklist_set (ptr_channel, ptr_nick, "prefix_color",
irc_nick_get_prefix_color_name (ptr_server,
ptr_nick->prefix[0]));
}
}
}
}
/*
* Sets nick colors in nicklist for all servers/channels.
*/
void
irc_nick_nicklist_set_color_all ()
{
struct t_irc_server *ptr_server;
struct t_irc_channel *ptr_channel;
struct t_irc_nick *ptr_nick;
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
for (ptr_channel = ptr_server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
for (ptr_nick = ptr_channel->nicks; ptr_nick;
ptr_nick = ptr_nick->next_nick)
{
irc_nick_nicklist_set (ptr_channel, ptr_nick, "color",
irc_nick_get_color_for_nicklist (ptr_server,
ptr_nick));
}
}
}
}
/*
* Adds a new nick in channel.
*
* Returns pointer to new nick, NULL if error.
*/
struct t_irc_nick *
irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel,
const char *nickname, const char *host, const char *prefixes,
int away, const char *account, const char *realname)
{
struct t_irc_nick *new_nick, *ptr_nick;
int length;
if (!nickname || !nickname[0])
return NULL;
if (!channel->nicks)
irc_channel_add_nicklist_groups (server, channel);
/* nick already exists on this channel? */
ptr_nick = irc_nick_search (server, channel, nickname);
if (ptr_nick)
{
/* remove old nick from nicklist */
irc_nick_nicklist_remove (server, channel, ptr_nick);
/* update nick */
irc_nick_set_prefixes (server, ptr_nick, prefixes);
ptr_nick->away = away;
if (ptr_nick->account)
free (ptr_nick->account);
ptr_nick->account = (account) ? strdup (account) : NULL;
if (ptr_nick->realname)
free (ptr_nick->realname);
ptr_nick->realname = (realname) ? strdup (realname) : NULL;
/* add new nick in nicklist */
irc_nick_nicklist_add (server, channel, ptr_nick);
return ptr_nick;
}
/* alloc memory for new nick */
if ((new_nick = malloc (sizeof (*new_nick))) == NULL)
return NULL;
/* initialize new nick */
new_nick->name = strdup (nickname);
new_nick->host = (host) ? strdup (host) : NULL;
new_nick->account = (account) ? strdup (account) : NULL;
new_nick->realname = (realname) ? strdup (realname) : NULL;
length = strlen (irc_server_get_prefix_chars (server));
new_nick->prefixes = malloc (length + 1);
if (!new_nick->name || !new_nick->prefixes)
{
if (new_nick->name)
free (new_nick->name);
if (new_nick->host)
free (new_nick->host);
if (new_nick->account)
free (new_nick->account);
if (new_nick->realname)
free (new_nick->realname);
if (new_nick->prefixes)
free (new_nick->prefixes);
free (new_nick);
return NULL;
}
if (new_nick->prefixes)
{
memset (new_nick->prefixes, ' ', length);
new_nick->prefixes[length] = '\0';
}
new_nick->prefix[0] = ' ';
new_nick->prefix[1] = '\0';
irc_nick_set_prefixes (server, new_nick, prefixes);
new_nick->away = away;
if (irc_server_strcasecmp (server, new_nick->name, server->nick) == 0)
new_nick->color = strdup (IRC_COLOR_CHAT_NICK_SELF);
else
new_nick->color = strdup (irc_nick_find_color (new_nick->name));
/* add nick to end of list */
new_nick->prev_nick = channel->last_nick;
if (channel->nicks)
channel->last_nick->next_nick = new_nick;
else
channel->nicks = new_nick;
channel->last_nick = new_nick;
new_nick->next_nick = NULL;
channel->nicks_count++;
channel->nick_completion_reset = 1;
/* add nick to buffer nicklist */
irc_nick_nicklist_add (server, channel, new_nick);
/* all is OK, return address of new nick */
return new_nick;
}
/*
* Changes nickname.
*/
void
irc_nick_change (struct t_irc_server *server, struct t_irc_channel *channel,
struct t_irc_nick *nick, const char *new_nick)
{
int nick_is_me;
/* remove nick from nicklist */
irc_nick_nicklist_remove (server, channel, nick);
/* update nicks speaking */
nick_is_me = (irc_server_strcasecmp (server, new_nick, server->nick) == 0) ? 1 : 0;
if (!nick_is_me)
irc_channel_nick_speaking_rename (channel, nick->name, new_nick);
/* change nickname */
if (nick->name)
free (nick->name);
nick->name = strdup (new_nick);
if (nick->color)
free (nick->color);
if (nick_is_me)
nick->color = strdup (IRC_COLOR_CHAT_NICK_SELF);
else
nick->color = strdup (irc_nick_find_color (nick->name));
/* add nick in nicklist */
irc_nick_nicklist_add (server, channel, nick);
}
/*
* Sets a mode for a nick.
*/
void
irc_nick_set_mode (struct t_irc_server *server, struct t_irc_channel *channel,
struct t_irc_nick *nick, int set, char mode)
{
int index;
const char *prefix_chars;
index = irc_server_get_prefix_mode_index (server, mode);
if (index < 0)
return;
/* remove nick from nicklist */
irc_nick_nicklist_remove (server, channel, nick);
/* set flag */
prefix_chars = irc_server_get_prefix_chars (server);
irc_nick_set_prefix (server, nick, set, prefix_chars[index]);
/* add nick in nicklist */
irc_nick_nicklist_add (server, channel, nick);
if (irc_server_strcasecmp (server, nick->name, server->nick) == 0)
weechat_bar_item_update ("input_prompt");
}
/*
* Removes a nick from a channel.
*/
void
irc_nick_free (struct t_irc_server *server, struct t_irc_channel *channel,
struct t_irc_nick *nick)
{
struct t_irc_nick *new_nicks;
if (!channel || !nick)
return;
/* remove nick from nicklist */
irc_nick_nicklist_remove (server, channel, nick);
/* remove nick */
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;
channel->nicks_count--;
/* free data */
if (nick->name)
free (nick->name);
if (nick->host)
free (nick->host);
if (nick->prefixes)
free (nick->prefixes);
if (nick->account)
free (nick->account);
if (nick->realname)
free (nick->realname);
if (nick->color)
free (nick->color);
free (nick);
channel->nicks = new_nicks;
channel->nick_completion_reset = 1;
}
/*
* Removes all nicks from a channel.
*/
void
irc_nick_free_all (struct t_irc_server *server, struct t_irc_channel *channel)
{
if (!channel)
return;
/* remove all nicks for the channel */
while (channel->nicks)
{
irc_nick_free (server, channel, channel->nicks);
}
/* remove all groups in nicklist */
weechat_nicklist_remove_all (channel->buffer);
/* should be zero, but prevent any bug :D */
channel->nicks_count = 0;
}
/*
* Searches for a nick in a channel.
*
* Returns pointer to nick found, NULL if error.
*/
struct t_irc_nick *
irc_nick_search (struct t_irc_server *server, struct t_irc_channel *channel,
const char *nickname)
{
struct t_irc_nick *ptr_nick;
if (!channel || !nickname)
return NULL;
for (ptr_nick = channel->nicks; ptr_nick;
ptr_nick = ptr_nick->next_nick)
{
if (irc_server_strcasecmp (server, ptr_nick->name, nickname) == 0)
return ptr_nick;
}
/* nick not found */
return NULL;
}
/*
* Returns number of nicks (total, op, halfop, voice, normal) on a channel.
*/
void
irc_nick_count (struct t_irc_server *server, struct t_irc_channel *channel,
int *total, int *count_op, int *count_halfop, int *count_voice,
int *count_normal)
{
struct 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 (irc_nick_is_op (server, ptr_nick))
(*count_op)++;
else
{
if (irc_nick_has_prefix_mode (server, ptr_nick, 'h'))
(*count_halfop)++;
else
{
if (irc_nick_has_prefix_mode (server, ptr_nick, 'v'))
(*count_voice)++;
else
(*count_normal)++;
}
}
}
}
/*
* Sets/unsets away status for a nick.
*/
void
irc_nick_set_away (struct t_irc_server *server, struct t_irc_channel *channel,
struct t_irc_nick *nick, int is_away)
{
if (!is_away
|| server->cap_away_notify
|| ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK) > 0)
&& ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS) == 0)
|| (channel->nicks_count <= IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS)))))
{
if ((is_away && !nick->away) || (!is_away && nick->away))
{
nick->away = is_away;
irc_nick_nicklist_set (channel, nick, "color",
irc_nick_get_color_for_nicklist (server, nick));
}
}
}
/*
* Gets nick mode for display (color + mode).
*
* If prefix == 1, returns string for display in prefix, otherwise returns
* string for display in action message (/me).
*/
const char *
irc_nick_mode_for_display (struct t_irc_server *server, struct t_irc_nick *nick,
int prefix)
{
static char result[32];
char str_prefix[2];
int nick_mode;
const char *str_prefix_color;
str_prefix[0] = (nick) ? nick->prefix[0] : '\0';
str_prefix[1] = '\0';
nick_mode = weechat_config_integer (irc_config_look_nick_mode);
if ((nick_mode == IRC_CONFIG_LOOK_NICK_MODE_BOTH)
|| (prefix && (nick_mode == IRC_CONFIG_LOOK_NICK_MODE_PREFIX))
|| (!prefix && (nick_mode == IRC_CONFIG_LOOK_NICK_MODE_ACTION)))
{
if (nick)
{
if ((str_prefix[0] == ' ')
&& (!prefix || !weechat_config_boolean (irc_config_look_nick_mode_empty)))
{
str_prefix[0] = '\0';
}
str_prefix_color = weechat_color (
irc_nick_get_prefix_color_name (server, nick->prefix[0]));
}
else
{
str_prefix[0] = (prefix
&& weechat_config_boolean (irc_config_look_nick_mode_empty)) ?
' ' : '\0';
str_prefix_color = IRC_COLOR_RESET;
}
}
else
{
str_prefix[0] = '\0';
str_prefix_color = IRC_COLOR_RESET;
}
snprintf (result, sizeof (result), "%s%s", str_prefix_color, str_prefix);
return result;
}
/*
* Returns string with nick to display as prefix on buffer (returned string ends
* by a tab).
*/
const char *
irc_nick_as_prefix (struct t_irc_server *server, struct t_irc_nick *nick,
const char *nickname, const char *force_color)
{
static char result[256];
snprintf (result, sizeof (result), "%s%s%s\t",
irc_nick_mode_for_display (server, nick, 1),
(force_color) ? force_color : ((nick) ? nick->color : ((nickname) ? irc_nick_find_color (nickname) : IRC_COLOR_CHAT_NICK)),
(nick) ? nick->name : nickname);
return result;
}
/*
* Returns WeeChat color code for a nick.
*/
const char *
irc_nick_color_for_msg (struct t_irc_server *server, int server_message,
struct t_irc_nick *nick, const char *nickname)
{
if (server_message
&& !weechat_config_boolean (irc_config_look_color_nicks_in_server_messages))
{
return IRC_COLOR_CHAT_NICK;
}
if (nick)
return nick->color;
if (nickname)
{
if (server
&& (irc_server_strcasecmp (server, nickname, server->nick) == 0))
{
return IRC_COLOR_CHAT_NICK_SELF;
}
return irc_nick_find_color (nickname);
}
return IRC_COLOR_CHAT_NICK;
}
/*
* Returns string with color of nick for private.
*/
const char *
irc_nick_color_for_pv (struct t_irc_channel *channel, const char *nickname)
{
if (weechat_config_boolean (irc_config_look_color_pv_nick_like_channel))
{
if (!channel->pv_remote_nick_color)
channel->pv_remote_nick_color = strdup (irc_nick_find_color (nickname));
if (channel->pv_remote_nick_color)
return channel->pv_remote_nick_color;
}
return IRC_COLOR_CHAT_NICK_OTHER;
}
/*
* Returns default ban mask for the nick.
*
* Note: result must be freed after use (if not NULL).
*/
char *
irc_nick_default_ban_mask (struct t_irc_nick *nick)
{
const char *ptr_ban_mask;
char *pos_hostname, user[128], ident[128], *res, *temp;
if (!nick)
return NULL;
ptr_ban_mask = weechat_config_string (irc_config_network_ban_mask_default);
pos_hostname = (nick->host) ? strchr (nick->host, '@') : NULL;
if (!nick->host || !pos_hostname || !ptr_ban_mask || !ptr_ban_mask[0])
return NULL;
if (pos_hostname - nick->host > (int)sizeof (user) - 1)
return NULL;
strncpy (user, nick->host, pos_hostname - nick->host);
user[pos_hostname - nick->host] = '\0';
strcpy (ident, (user[0] != '~') ? user : "*");
pos_hostname++;
/* replace nick */
temp = weechat_string_replace (ptr_ban_mask, "$nick", nick->name);
if (!temp)
return NULL;
res = temp;
/* replace user */
temp = weechat_string_replace (res, "$user", user);
free (res);
if (!temp)
return NULL;
res = temp;
/* replace ident */
temp = weechat_string_replace (res, "$ident", ident);
free (res);
if (!temp)
return NULL;
res = temp;
/* replace hostname */
temp = weechat_string_replace (res, "$host", pos_hostname);
free (res);
if (!temp)
return NULL;
res = temp;
return res;
}
/*
* Returns hdata for nick.
*/
struct t_hdata *
irc_nick_hdata_nick_cb (const void *pointer, void *data,
const char *hdata_name)
{
struct t_hdata *hdata;
/* make C compiler happy */
(void) pointer;
(void) data;
hdata = weechat_hdata_new (hdata_name, "prev_nick", "next_nick",
0, 0, NULL, NULL);
if (hdata)
{
WEECHAT_HDATA_VAR(struct t_irc_nick, name, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, host, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, prefixes, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, prefix, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, away, INTEGER, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, account, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, realname, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, color, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_nick, prev_nick, POINTER, 0, NULL, hdata_name);
WEECHAT_HDATA_VAR(struct t_irc_nick, next_nick, POINTER, 0, NULL, hdata_name);
}
return hdata;
}
/*
* Adds a nick in an infolist.
*
* Returns:
* 1: OK
* 0: error
*/
int
irc_nick_add_to_infolist (struct t_infolist *infolist,
struct t_irc_nick *nick)
{
struct t_infolist_item *ptr_item;
if (!infolist || !nick)
return 0;
ptr_item = weechat_infolist_new_item (infolist);
if (!ptr_item)
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "name", nick->name))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "host", nick->host))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "prefixes", nick->prefixes))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "prefix", nick->prefix))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "away", nick->away))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "account", nick->account))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "realname", nick->realname))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "color", nick->color))
return 0;
return 1;
}
/*
* Prints nick infos in WeeChat log file (usually for crash dump).
*/
void
irc_nick_print_log (struct t_irc_nick *nick)
{
weechat_log_printf ("");
weechat_log_printf (" => nick %s (addr:0x%lx):", nick->name, nick);
weechat_log_printf (" host . . . . . : '%s'", nick->host);
weechat_log_printf (" prefixes . . . : '%s'", nick->prefixes);
weechat_log_printf (" prefix . . . . : '%s'", nick->prefix);
weechat_log_printf (" away . . . . . : %d", nick->away);
weechat_log_printf (" account. . . . : '%s'", nick->account);
weechat_log_printf (" realname . . . : '%s'", nick->realname);
weechat_log_printf (" color. . . . . : '%s'", nick->color);
weechat_log_printf (" prev_nick. . . : 0x%lx", nick->prev_nick);
weechat_log_printf (" next_nick. . . : 0x%lx", nick->next_nick);
}