diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | src/plugins/irc/irc-bar-item.c | 11 | ||||
-rw-r--r-- | src/plugins/irc/irc-channel.c | 31 | ||||
-rw-r--r-- | src/plugins/irc/irc-command.c | 2 | ||||
-rw-r--r-- | src/plugins/irc/irc-info.c | 2 | ||||
-rw-r--r-- | src/plugins/irc/irc-mode.c | 230 | ||||
-rw-r--r-- | src/plugins/irc/irc-mode.h | 6 | ||||
-rw-r--r-- | src/plugins/irc/irc-nick.c | 456 | ||||
-rw-r--r-- | src/plugins/irc/irc-nick.h | 67 | ||||
-rw-r--r-- | src/plugins/irc/irc-protocol.c | 100 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 206 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.h | 15 | ||||
-rw-r--r-- | src/plugins/irc/irc-upgrade.c | 109 |
14 files changed, 648 insertions, 595 deletions
@@ -1,7 +1,7 @@ WeeChat ChangeLog ================= Sébastien Helleu <flashcode@flashtux.org> -v0.3.4-dev, 2010-10-26 +v0.3.4-dev, 2010-10-28 Version 0.3.4 (under dev!) @@ -26,6 +26,8 @@ Version 0.3.4 (under dev!) * api: add priority for hooks (task #10550) * api: add new functions: hashtable_get_string, hook_info_hashtable, info_get_hashtable, hook_hsignal, hook_hsignal_send +* irc: improve nick prefixes, all modes (even unknown) are used with PREFIX + value from message 005 * irc: add command redirection (task #6703) * irc: add new options irc.color.nick_prefix and irc.color.nick_suffix * irc: add new option irc.look.item_away_message @@ -1,7 +1,7 @@ WeeChat News ============ Sébastien Helleu <flashcode@flashtux.org> -v0.3.4-dev, 2010-10-12 +v0.3.4-dev, 2010-10-28 Version 0.3.4 (under dev!) @@ -9,6 +9,8 @@ Version 0.3.4 (under dev!) Important release notes: +* if you are using `/upgrade` from a previous release, some nick prefixes can + be wrong, so it is recommended to do `/allchan names`. * some IRC options have been renamed, before upgrading to this version, note value for old options, and set them again with new name: ** options moved from 'network' section to servers (with global value, and server diff --git a/src/plugins/irc/irc-bar-item.c b/src/plugins/irc/irc-bar-item.c index 1deec1b6f..a2c4047e0 100644 --- a/src/plugins/irc/irc-bar-item.c +++ b/src/plugins/irc/irc-bar-item.c @@ -422,7 +422,7 @@ irc_bar_item_input_prompt (void *data, struct t_gui_bar_item *item, struct t_irc_server *server; struct t_irc_channel *channel; struct t_irc_nick *ptr_nick; - char *buf, prefix[2], str_prefix[64]; + char *buf, str_prefix[64]; int length, prefix_color; /* make C compiler happy */ @@ -449,15 +449,12 @@ irc_bar_item_input_prompt (void *data, struct t_gui_bar_item *item, ptr_nick = irc_nick_search (channel, server->nick); if (ptr_nick) { - prefix[0] = '\0'; - prefix[1] = '\0'; - irc_nick_get_gui_infos (server, ptr_nick, - &prefix[0], &prefix_color, NULL, NULL); - if (prefix[0] != ' ') + if (ptr_nick->prefix[0] != ' ') { + prefix_color = irc_nick_get_prefix_color (server, ptr_nick); snprintf (str_prefix, sizeof (str_prefix), "%s%s", weechat_color (weechat_config_string (weechat_config_get (irc_nick_get_prefix_color_name (prefix_color)))), - prefix); + ptr_nick->prefix); } } } diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c index 6ffed14e0..ac9ad55db 100644 --- a/src/plugins/irc/irc-channel.c +++ b/src/plugins/irc/irc-channel.c @@ -150,8 +150,9 @@ irc_channel_new (struct t_irc_server *server, int channel_type, { struct t_irc_channel *new_channel; struct t_gui_buffer *new_buffer; - int buffer_created, current_buffer_number, buffer_position; - char *buffer_name, str_number[32];; + int i, buffer_created, current_buffer_number, buffer_position; + char *buffer_name, str_number[32], str_group[32]; + const char *prefix_modes; /* alloc memory for new channel */ if ((new_channel = malloc (sizeof (*new_channel))) == NULL) @@ -234,21 +235,15 @@ irc_channel_new (struct t_irc_server *server, int channel_type, if (channel_type == IRC_CHANNEL_TYPE_CHANNEL) { - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_CHANOWNER, - "weechat.color.nicklist_group", 1); - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_CHANADMIN, - "weechat.color.nicklist_group", 1); - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_CHANADMIN2, - "weechat.color.nicklist_group", 1); - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_OP, - "weechat.color.nicklist_group", 1); - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_HALFOP, - "weechat.color.nicklist_group", 1); - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_VOICE, - "weechat.color.nicklist_group", 1); - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_CHANUSER, - "weechat.color.nicklist_group", 1); - weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_NORMAL, + prefix_modes = irc_server_get_prefix_modes (server); + for (i = 0; prefix_modes[i]; i++) + { + snprintf (str_group, sizeof (str_group), + "%03d|%c", i, prefix_modes[i]); + weechat_nicklist_add_group (new_buffer, NULL, str_group, + "weechat.color.nicklist_group", 1); + } + weechat_nicklist_add_group (new_buffer, NULL, IRC_NICK_GROUP_OTHER, "weechat.color.nicklist_group", 1); } @@ -367,7 +362,7 @@ irc_channel_remove_away (struct t_irc_server *server, { for (ptr_nick = channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick) { - irc_nick_set (server, channel, ptr_nick, 0, IRC_NICK_AWAY); + irc_nick_set_away (server, channel, ptr_nick, 0); } } } diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c index 9ff26ef7c..e2fe5baa1 100644 --- a/src/plugins/irc/irc-command.c +++ b/src/plugins/irc/irc-command.c @@ -4212,7 +4212,7 @@ irc_command_wallchops (void *data, struct t_gui_buffer *buffer, int argc, for (ptr_nick = ptr_channel->nicks; ptr_nick; ptr_nick = ptr_nick->next_nick) { - if (IRC_NICK_IS_OP(ptr_nick) + if (irc_nick_is_op (ptr_server, ptr_nick) && (strcmp (ptr_nick->name, ptr_server->nick) != 0)) { irc_server_sendf (ptr_server, diff --git a/src/plugins/irc/irc-info.c b/src/plugins/irc/irc-info.c index 9efe59419..5d9562f34 100644 --- a/src/plugins/irc/irc-info.c +++ b/src/plugins/irc/irc-info.c @@ -434,7 +434,6 @@ irc_info_get_infolist_cb (void *data, const char *infolist_name, { /* build list with only one nick */ if (!irc_nick_add_to_infolist (ptr_infolist, - ptr_server, pointer)) { weechat_infolist_free (ptr_infolist); @@ -449,7 +448,6 @@ irc_info_get_infolist_cb (void *data, const char *infolist_name, ptr_nick = ptr_nick->next_nick) { if (!irc_nick_add_to_infolist (ptr_infolist, - ptr_server, ptr_nick)) { weechat_infolist_free (ptr_infolist); diff --git a/src/plugins/irc/irc-mode.c b/src/plugins/irc/irc-mode.c index 24664e9d0..ee02e2c3a 100644 --- a/src/plugins/irc/irc-mode.c +++ b/src/plugins/irc/irc-mode.c @@ -33,25 +33,6 @@ /* - * irc_mode_channel_set_nick: set a mode for a nick on a channel - */ - -void -irc_mode_channel_set_nick (struct t_irc_server *server, - struct t_irc_channel *channel, const char *nick, - char set_flag, int flag) -{ - struct t_irc_nick *ptr_nick; - - if (nick) - { - ptr_nick = irc_nick_search (channel, nick); - if (ptr_nick) - irc_nick_set (server, channel, ptr_nick, (set_flag == '+'), flag); - } -} - -/* * irc_mode_channel_set: set channel modes * return: 1 if channel modes are updated * 0 if channel modes are NOT updated @@ -63,7 +44,8 @@ irc_mode_channel_set (struct t_irc_server *server, struct t_irc_channel *channel, const char *modes) { char *pos_args, *str_modes, set_flag, **argv, *pos, *ptr_arg; - int mode, modes_count, channel_modes_updated, argc, current_arg; + int modes_count, channel_modes_updated, argc, current_arg; + struct t_irc_nick *ptr_nick; if (!server || !channel || !modes) return 0; @@ -121,33 +103,11 @@ irc_mode_channel_set (struct t_irc_server *server, case '-': set_flag = '-'; break; - case 'a': /* channel admin (unrealircd specific flag) */ - ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? - argv[current_arg] : NULL; - mode = irc_mode_get_nick_attr (server, "a", '~'); - if (mode >= 0) - { - irc_mode_channel_set_nick (server, channel, ptr_arg, - set_flag, mode); - } - current_arg++; - break; case 'b': /* ban (ignored) */ ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? argv[current_arg] : NULL; current_arg++; break; - case 'h': /* half-op */ - ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? - argv[current_arg] : NULL; - mode = irc_mode_get_nick_attr (server, "h", '%'); - if (mode >= 0) - { - irc_mode_channel_set_nick (server, channel, ptr_arg, - set_flag, mode); - } - current_arg++; - break; case 'k': /* channel key */ if (channel->key) { @@ -177,54 +137,25 @@ irc_mode_channel_set (struct t_irc_server *server, channel_modes_updated = 1; current_arg++; break; - case 'o': /* op */ - ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? - argv[current_arg] : NULL; - mode = irc_mode_get_nick_attr (server, "o", '@'); - if (mode >= 0) - { - irc_mode_channel_set_nick (server, channel, ptr_arg, - set_flag, mode); - } - current_arg++; - break; - case 'q': /* channel owner (unrealircd specific flag) */ - ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? - argv[current_arg] : NULL; - mode = irc_mode_get_nick_attr (server, "q", '~'); - if (mode >= 0) - { - irc_mode_channel_set_nick (server, channel, ptr_arg, - set_flag, mode); - } - current_arg++; - break; - case 'u': /* channel user */ - ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? - argv[current_arg] : NULL; - mode = irc_mode_get_nick_attr (server, "u", '-'); - if (mode >= 0) - { - irc_mode_channel_set_nick (server, channel, ptr_arg, - set_flag, mode); - } - current_arg++; - break; - case 'v': /* voice */ - ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? - argv[current_arg] : NULL; - mode = irc_mode_get_nick_attr (server, "v", '+'); - if (mode >= 0) + default: + if (irc_server_get_prefix_mode_index (server, pos[0]) >= 0) { - irc_mode_channel_set_nick (server, channel, ptr_arg, - set_flag, mode); + ptr_arg = ((current_arg >= 0) && (current_arg < argc)) ? + argv[current_arg] : NULL; + if (ptr_arg) + { + ptr_nick = irc_nick_search (channel, ptr_arg); + if (ptr_nick) + { + irc_nick_set_mode (server, channel, ptr_nick, + (set_flag == '+'), pos[0]); + } + } } + else + channel_modes_updated = 1; current_arg++; break; - default: - current_arg++; - channel_modes_updated = 1; - break; } pos++; } @@ -326,130 +257,3 @@ irc_mode_user_set (struct t_irc_server *server, const char *modes) modes++; } } - -/* - * irc_mode_prefix_to_nick_attr: get nick attribute for prefix - * return -1 if prefix is unknown - */ - -int -irc_mode_prefix_to_nick_attr (char prefix) -{ - switch (prefix) - { - case '@': /* op */ - return IRC_NICK_OP; - case '~': /* channel owner */ - return IRC_NICK_CHANOWNER; - case '*': /* channel owner */ - return IRC_NICK_CHANOWNER; - case '&': /* channel admin */ - return IRC_NICK_CHANADMIN; - case '!': /* channel admin (2) */ - return IRC_NICK_CHANADMIN2; - case '%': /* half-op */ - return IRC_NICK_HALFOP; - case '+': /* voice */ - return IRC_NICK_VOICE; - case '-': /* channel user */ - return IRC_NICK_CHANUSER; - } - - return -1; -} - -/* - * irc_mode_get_nick_attr: return nick attribute for mode, if allowed by server - * return -1 if not allowed - * for example : - * IRC: 005 (...) PREFIX=(ohv)@%+ - * => allowed modes: ohv - */ - -int -irc_mode_get_nick_attr (struct t_irc_server *server, char *mode, - char prefix) -{ - char str[2], *pos, *ptr_prefixes, *pos_mode; - int index; - - /* if server did not send any prefix info, then use default prefixes */ - if (!server->prefix) - { - str[0] = prefix; - str[1] = '\0'; - pos = strpbrk (str, IRC_MODE_NICK_DEFAULT_PREFIXES_LIST); - if (!pos) - return -1; - return irc_mode_prefix_to_nick_attr (pos[0]); - } - - /* find start of prefixes, after "(...)" */ - ptr_prefixes = strchr (server->prefix, ')'); - if (ptr_prefixes) - ptr_prefixes++; - - /* we check if mode is in list and return prefix found */ - if (mode && ptr_prefixes) - { - pos_mode = strchr (server->prefix + 1, mode[0]); - if (pos_mode && (pos_mode < ptr_prefixes)) - { - index = pos_mode - server->prefix - 1; - if (pos_mode && (index < (int)strlen (ptr_prefixes))) - { - return irc_mode_prefix_to_nick_attr (ptr_prefixes[index]); - } - } - } - - if (!ptr_prefixes) - ptr_prefixes = server->prefix; - - pos = strchr (ptr_prefixes, prefix); - if (!pos) - return -1; - - return irc_mode_prefix_to_nick_attr (pos[0]); -} - -/* - * irc_mode_get_prefix: return prefix for mode - * for example if prefixes are: - * IRC: 005 (...) PREFIX=(ohv)@%+ - * 'o' will return '@' - * 'h' will return '%' - * 'v' will return '+' - */ - -char -irc_mode_get_prefix (struct t_irc_server *server, char mode, - char default_prefix) -{ - char *ptr_prefixes, *pos_mode; - int index; - - if (!server->prefix) - return default_prefix; - - /* find start of prefixes, after "(...)" */ - ptr_prefixes = strchr (server->prefix, ')'); - if (ptr_prefixes) - ptr_prefixes++; - - if (!ptr_prefixes || !ptr_prefixes[0]) - return default_prefix; - - /* search prefix for mode */ - pos_mode = strchr (server->prefix + 1, mode); - if (pos_mode && (pos_mode < ptr_prefixes)) - { - index = pos_mode - server->prefix - 1; - if (pos_mode && (index < (int)strlen (ptr_prefixes))) - { - return ptr_prefixes[index]; - } - } - - return default_prefix; -} diff --git a/src/plugins/irc/irc-mode.h b/src/plugins/irc/irc-mode.h index 358ba5b77..1bd7b3aef 100644 --- a/src/plugins/irc/irc-mode.h +++ b/src/plugins/irc/irc-mode.h @@ -20,8 +20,6 @@ #ifndef __WEECHAT_IRC_MODE_H #define __WEECHAT_IRC_MODE_H 1 -#define IRC_MODE_NICK_DEFAULT_PREFIXES_LIST "@%+~*&!-" - struct t_irc_server; struct t_irc_channel; @@ -29,9 +27,5 @@ extern int irc_mode_channel_set (struct t_irc_server *server, struct t_irc_channel *channel, const char *modes); extern void irc_mode_user_set (struct t_irc_server *server, const char *modes); -extern int irc_mode_get_nick_attr (struct t_irc_server *server, char *mode, - char prefix); -extern char irc_mode_get_prefix (struct t_irc_server *server, char mode, - char default_prefix); #endif /* __WEECHAT_IRC_MODE_H */ diff --git a/src/plugins/irc/irc-nick.c b/src/plugins/irc/irc-nick.c index b88b986ef..ae6ee1faf 100644 --- a/src/plugins/irc/irc-nick.c +++ b/src/plugins/irc/irc-nick.c @@ -197,97 +197,213 @@ irc_nick_find_color_name (const char *nickname) } /* - * irc_nick_get_gui_infos: get GUI infos for a nick (sort_index, prefix, - * prefix color) + * irc_nick_set_current_prefix: set current prefix, using higher prefix set in + * prefixes */ void -irc_nick_get_gui_infos (struct t_irc_server *server, - struct t_irc_nick *nick, - char *prefix, int *prefix_color, - struct t_gui_buffer *buffer, - struct t_gui_nick_group **group) +irc_nick_set_current_prefix (struct t_irc_nick *nick) { - if (nick->flags & IRC_NICK_CHANOWNER) - { - if (prefix) - prefix[0] = irc_mode_get_prefix (server, 'q', '~'); - if (prefix_color) - *prefix_color = 1; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_CHANOWNER); - } - else if (nick->flags & IRC_NICK_CHANADMIN) - { - if (prefix) - prefix[0] = irc_mode_get_prefix (server, 'a', '&'); - if (prefix_color) - *prefix_color = 1; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_CHANADMIN); - } - else if (nick->flags & IRC_NICK_CHANADMIN2) + char *ptr_prefixes; + + nick->prefix[0] = ' '; + for (ptr_prefixes = nick->prefixes; ptr_prefixes[0]; ptr_prefixes++) { - if (prefix) - prefix[0] = irc_mode_get_prefix (server, 'a', '!'); - if (prefix_color) - *prefix_color = 1; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_CHANADMIN2); + if (ptr_prefixes[0] != ' ') + { + nick->prefix[0] = ptr_prefixes[0]; + break; + } } - else if (nick->flags & IRC_NICK_OP) +} + +/* + * irc_nick_set_prefix: set or unset a prefix in prefixes + * if set == 1, prefix is set (prefix is used) + * 0, prefix is unset (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) { - if (prefix) - prefix[0] = irc_mode_get_prefix (server, 'o', '@'); - if (prefix_color) - *prefix_color = 1; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_OP); + nick->prefixes[index] = (set) ? prefix : ' '; + irc_nick_set_current_prefix (nick); } - else if (nick->flags & IRC_NICK_HALFOP) +} + +/* + * irc_nick_set_prefixes: set 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) { - if (prefix) - prefix[0] = irc_mode_get_prefix (server, 'h', '%'); - if (prefix_color) - *prefix_color = 2; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_HALFOP); + for (ptr_prefixes = prefixes; ptr_prefixes[0]; ptr_prefixes++) + { + irc_nick_set_prefix (server, nick, 1, ptr_prefixes[0]); + } } - else if (nick->flags & IRC_NICK_VOICE) + + /* set current prefix */ + irc_nick_set_current_prefix (nick); +} + +/* + * irc_nick_is_op: return 1 is nick is "op" (or better than "op", for example + * channel admin or channel owner) + */ + +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; +} + +/* + * irc_nick_has_prefix_mode: return 1 if nick prefixes contains prefix + * for a mode given + * for example if mode is 'o', we'll search for '@' + * in nick prefixes + */ + +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; +} + +/* + * irc_nick_get_nicklist_group: get 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[32]; + 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) { - if (prefix) - prefix[0] = irc_mode_get_prefix (server, 'v', '+'); - if (prefix_color) - *prefix_color = 3; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_VOICE); + ptr_group = weechat_nicklist_search_group (buffer, NULL, + IRC_NICK_GROUP_OTHER); } - else if (nick->flags & IRC_NICK_CHANUSER) + else { - if (prefix) - prefix[0] = irc_mode_get_prefix (server, 'u', '-'); - if (prefix_color) - *prefix_color = 4; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_CHANUSER); + prefix_modes = irc_server_get_prefix_modes (server); + snprintf (str_group, sizeof (str_group), + "%03d|%c", index, prefix_modes[index]); + ptr_group = weechat_nicklist_search_group (buffer, NULL, str_group); } - else + + return ptr_group; +} + +/* + * irc_nick_get_prefix_color: get prefix color index for a nick + */ + +int +irc_nick_get_prefix_color (struct t_irc_server *server, + struct t_irc_nick *nick) +{ + int index, prefix_color; + + prefix_color = 0; + index = irc_server_get_prefix_char_index (server, nick->prefix[0]); + if (index >= 0) { - if (prefix) - prefix[0] = ' '; - if (prefix_color) - *prefix_color = 0; - if (buffer && group) - *group = weechat_nicklist_search_group (buffer, NULL, - IRC_NICK_GROUP_NORMAL); + if (index <= irc_server_get_prefix_mode_index (server, 'o')) + prefix_color = 1; /* color for op (or better than op) */ + else if (index == irc_server_get_prefix_mode_index (server, 'h')) + prefix_color = 2; /* color for halh-op */ + else if (index == irc_server_get_prefix_mode_index (server, 'v')) + prefix_color = 3; /* color for voice */ + else if (index == irc_server_get_prefix_mode_index (server, 'u')) + prefix_color = 4; /* color for chan user */ } + + return prefix_color; +} + +/* + * irc_nick_nicklist_add: add nick to buffer nicklist + */ + +void +irc_nick_nicklist_add (struct t_irc_server *server, + struct t_irc_channel *channel, + struct t_irc_nick *nick) +{ + int prefix_color; + struct t_gui_nick_group *ptr_group; + + ptr_group = irc_nick_get_nicklist_group (server, channel->buffer, nick); + prefix_color = irc_nick_get_prefix_color (server, nick); + weechat_nicklist_add_nick (channel->buffer, ptr_group, + nick->name, + (nick->away) ? + "weechat.color.nicklist_away" : "bar_fg", + nick->prefix, + irc_nick_get_prefix_color_name (prefix_color), + 1); +} + +/* + * irc_nick_nicklist_remove: remove 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)); } /* @@ -318,49 +434,24 @@ irc_nick_get_prefix_color_name (int prefix_color) struct t_irc_nick * irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, - const char *nickname, int is_chanowner, int is_chanadmin, - int is_chanadmin2, int is_op, int is_halfop, int has_voice, - int is_chanuser, int is_away) + const char *nickname, const char *prefixes, int away) { struct t_irc_nick *new_nick, *ptr_nick; - char prefix[2]; - int prefix_color; - struct t_gui_nick_group *ptr_group; + int length; /* nick already exists on this channel? */ ptr_nick = irc_nick_search (channel, nickname); if (ptr_nick) { /* remove old nick from nicklist */ - irc_nick_get_gui_infos (server, ptr_nick, prefix, - &prefix_color, channel->buffer, &ptr_group); - weechat_nicklist_remove_nick (channel->buffer, - weechat_nicklist_search_nick (channel->buffer, - ptr_group, - ptr_nick->name)); + irc_nick_nicklist_remove (server, channel, ptr_nick); /* update nick */ - IRC_NICK_SET_FLAG(ptr_nick, is_chanowner, IRC_NICK_CHANOWNER); - IRC_NICK_SET_FLAG(ptr_nick, is_chanadmin, IRC_NICK_CHANADMIN); - IRC_NICK_SET_FLAG(ptr_nick, is_chanadmin2, IRC_NICK_CHANADMIN2); - IRC_NICK_SET_FLAG(ptr_nick, is_op, IRC_NICK_OP); - IRC_NICK_SET_FLAG(ptr_nick, is_halfop, IRC_NICK_HALFOP); - IRC_NICK_SET_FLAG(ptr_nick, has_voice, IRC_NICK_VOICE); - IRC_NICK_SET_FLAG(ptr_nick, is_chanuser, IRC_NICK_CHANUSER); - IRC_NICK_SET_FLAG(ptr_nick, is_away, IRC_NICK_AWAY); + irc_nick_set_prefixes (server, ptr_nick, prefixes); + ptr_nick->away = away; /* add new nick in nicklist */ - prefix[0] = ' '; - prefix[1] = '\0'; - irc_nick_get_gui_infos (server, ptr_nick, prefix, - &prefix_color, channel->buffer, &ptr_group); - weechat_nicklist_add_nick (channel->buffer, ptr_group, - ptr_nick->name, - (is_away) ? - "weechat.color.nicklist_away" : "bar_fg", - prefix, - irc_nick_get_prefix_color_name (prefix_color), - 1); + irc_nick_nicklist_add (server, channel, ptr_nick); return ptr_nick; } @@ -372,15 +463,17 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, /* initialize new nick */ new_nick->name = strdup (nickname); new_nick->host = NULL; - new_nick->flags = 0; - IRC_NICK_SET_FLAG(new_nick, is_chanowner, IRC_NICK_CHANOWNER); - IRC_NICK_SET_FLAG(new_nick, is_chanadmin, IRC_NICK_CHANADMIN); - IRC_NICK_SET_FLAG(new_nick, is_chanadmin2, IRC_NICK_CHANADMIN2); - IRC_NICK_SET_FLAG(new_nick, is_op, IRC_NICK_OP); - IRC_NICK_SET_FLAG(new_nick, is_halfop, IRC_NICK_HALFOP); - IRC_NICK_SET_FLAG(new_nick, has_voice, IRC_NICK_VOICE); - IRC_NICK_SET_FLAG(new_nick, is_chanuser, IRC_NICK_CHANUSER); - IRC_NICK_SET_FLAG(new_nick, is_away, IRC_NICK_AWAY); + length = strlen (irc_server_get_prefix_chars (server)); + new_nick->prefixes = malloc (length + 1); + 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 (weechat_strcasecmp (new_nick->name, server->nick) == 0) new_nick->color = IRC_COLOR_CHAT_NICK_SELF; else @@ -400,17 +493,7 @@ irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, channel->nick_completion_reset = 1; /* add nick to buffer nicklist */ - prefix[0] = ' '; - prefix[1] = '\0'; - irc_nick_get_gui_infos (server, new_nick, prefix, &prefix_color, - channel->buffer, &ptr_group); - weechat_nicklist_add_nick (channel->buffer, ptr_group, - new_nick->name, - (is_away) ? - "weechat.color.nicklist_away" : "bar_fg", - prefix, - irc_nick_get_prefix_color_name (prefix_color), - 1); + irc_nick_nicklist_add (server, channel, new_nick); /* all is ok, return address of new nick */ return new_nick; @@ -424,17 +507,10 @@ 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, prefix_color; - struct t_gui_nick_group *ptr_group; - char prefix[2]; + int nick_is_me; /* remove nick from nicklist */ - irc_nick_get_gui_infos (server, nick, prefix, &prefix_color, - channel->buffer, &ptr_group); - weechat_nicklist_remove_nick (channel->buffer, - weechat_nicklist_search_nick (channel->buffer, - ptr_group, - nick->name)); + irc_nick_nicklist_remove (server, channel, nick); /* update nicks speaking */ nick_is_me = (strcmp (nick->name, server->nick) == 0) ? 1 : 0; @@ -451,54 +527,33 @@ irc_nick_change (struct t_irc_server *server, struct t_irc_channel *channel, nick->color = irc_nick_find_color (nick->name); /* add nick in nicklist */ - prefix[0] = ' '; - prefix[1] = '\0'; - irc_nick_get_gui_infos (server, nick, prefix, &prefix_color, - channel->buffer, &ptr_group); - weechat_nicklist_add_nick (channel->buffer, ptr_group, - nick->name, - (nick->flags & IRC_NICK_AWAY) ? - "weechat.color.nicklist_away" : "bar_fg", - prefix, - irc_nick_get_prefix_color_name (prefix_color), - 1); + irc_nick_nicklist_add (server, channel, nick); } /* - * irc_nick_set: set a flag for a nick + * irc_nick_set_mode: set a mode for a nick */ void -irc_nick_set (struct t_irc_server *server, struct t_irc_channel *channel, - struct t_irc_nick *nick, int set, int flag) +irc_nick_set_mode (struct t_irc_server *server, struct t_irc_channel *channel, + struct t_irc_nick *nick, int set, char mode) { - char prefix[2]; - int prefix_color; - struct t_gui_nick_group *ptr_group; + 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_get_gui_infos (server, nick, prefix, &prefix_color, - channel->buffer, &ptr_group); - weechat_nicklist_remove_nick (channel->buffer, - weechat_nicklist_search_nick (channel->buffer, - ptr_group, - nick->name)); + irc_nick_nicklist_remove (server, channel, nick); /* set flag */ - IRC_NICK_SET_FLAG(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 */ - prefix[0] = ' '; - prefix[1] = '\0'; - irc_nick_get_gui_infos (server, nick, prefix, &prefix_color, - channel->buffer, &ptr_group); - weechat_nicklist_add_nick (channel->buffer, ptr_group, - nick->name, - (nick->flags & IRC_NICK_AWAY) ? - "weechat.color.nicklist_away" : "bar_fg", - prefix, - irc_nick_get_prefix_color_name (prefix_color), - 1); + irc_nick_nicklist_add (server, channel, nick); if (strcmp (nick->name, server->nick) == 0) weechat_bar_item_update ("input_prompt"); @@ -513,20 +568,12 @@ irc_nick_free (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick) { struct t_irc_nick *new_nicks; - char prefix; - int prefix_color; - struct t_gui_nick_group *ptr_group; if (!channel || !nick) return; /* remove nick from nicklist */ - irc_nick_get_gui_infos (server, nick, &prefix, &prefix_color, - channel->buffer, &ptr_group); - weechat_nicklist_remove_nick (channel->buffer, - weechat_nicklist_search_nick (channel->buffer, - ptr_group, - nick->name)); + irc_nick_nicklist_remove (server, channel, nick); /* remove nick */ if (channel->last_nick == nick) @@ -549,6 +596,8 @@ irc_nick_free (struct t_irc_server *server, struct t_irc_channel *channel, free (nick->name); if (nick->host) free (nick->host); + if (nick->prefixes) + free (nick->prefixes); free (nick); @@ -604,8 +653,9 @@ irc_nick_search (struct t_irc_channel *channel, const char *nickname) */ void -irc_nick_count (struct t_irc_channel *channel, int *total, int *count_op, - int *count_halfop, int *count_voice, int *count_normal) +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; @@ -618,15 +668,15 @@ irc_nick_count (struct t_irc_channel *channel, int *total, int *count_op, ptr_nick = ptr_nick->next_nick) { (*total)++; - if (IRC_NICK_IS_OP(ptr_nick)) + if (irc_nick_is_op (server, ptr_nick)) (*count_op)++; else { - if (ptr_nick->flags & IRC_NICK_HALFOP) + if (irc_nick_has_prefix_mode (server, ptr_nick, 'h')) (*count_halfop)++; else { - if (ptr_nick->flags & IRC_NICK_VOICE) + if (irc_nick_has_prefix_mode (server, ptr_nick, 'v')) (*count_voice)++; else (*count_normal)++; @@ -643,14 +693,16 @@ void irc_nick_set_away (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick, int is_away) { - if ((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 + || ((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->flags & IRC_NICK_AWAY))) || - ((!is_away) && (nick->flags & IRC_NICK_AWAY))) + if ((is_away && !nick->away) || (!is_away && nick->away)) { - irc_nick_set (server, channel, nick, is_away, IRC_NICK_AWAY); + irc_nick_nicklist_remove (server, channel, nick); + nick->away = is_away; + irc_nick_nicklist_add (server, channel, nick); } } } @@ -669,14 +721,13 @@ irc_nick_as_prefix (struct t_irc_server *server, struct t_irc_nick *nick, const char *str_prefix_color; int prefix_color; - prefix[0] = '\0'; + prefix[0] = (nick) ? nick->prefix[0] : '\0'; prefix[1] = '\0'; if (weechat_config_boolean (weechat_config_get ("weechat.look.nickmode"))) { if (nick) { - irc_nick_get_gui_infos (server, nick, &prefix[0], &prefix_color, - NULL, NULL); + prefix_color = irc_nick_get_prefix_color (server, nick); if ((prefix[0] == ' ') && !weechat_config_boolean (weechat_config_get ("weechat.look.nickmode_empty"))) prefix[0] = '\0'; @@ -741,11 +792,9 @@ irc_nick_color_for_pv (struct t_irc_channel *channel, const char *nickname) int irc_nick_add_to_infolist (struct t_infolist *infolist, - struct t_irc_server *server, struct t_irc_nick *nick) { struct t_infolist_item *ptr_item; - char prefix[2]; if (!infolist || !nick) return 0; @@ -758,14 +807,13 @@ irc_nick_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_string (ptr_item, "host", nick->host)) return 0; - if (!weechat_infolist_new_var_integer (ptr_item, "flags", nick->flags)) + if (!weechat_infolist_new_var_string (ptr_item, "prefixes", nick->prefixes)) return 0; - if (!weechat_infolist_new_var_string (ptr_item, "color", nick->color)) + if (!weechat_infolist_new_var_string (ptr_item, "prefix", nick->prefix)) return 0; - prefix[0] = ' '; - prefix[1] = '\0'; - irc_nick_get_gui_infos (server, nick, prefix, NULL, NULL, NULL); - if (!weechat_infolist_new_var_string (ptr_item, "prefix", prefix)) + if (!weechat_infolist_new_var_integer (ptr_item, "away", nick->away)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "color", nick->color)) return 0; return 1; @@ -780,8 +828,10 @@ 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 (" flags. . . . . : %d", nick->flags); + 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 (" color. . . . . : '%s'", nick->color); weechat_log_printf (" prev_nick. . . : 0x%lx", nick->prev_nick); weechat_log_printf (" next_nick. . . : 0x%lx", nick->next_nick); diff --git a/src/plugins/irc/irc-nick.h b/src/plugins/irc/irc-nick.h index 9dffce6ea..d1d787652 100644 --- a/src/plugins/irc/irc-nick.h +++ b/src/plugins/irc/irc-nick.h @@ -23,34 +23,7 @@ #define IRC_NICK_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHI" \ "JKLMNOPQRSTUVWXYZ0123456789-[]\\`_^{|}" -#define IRC_NICK_CHANOWNER 1 -#define IRC_NICK_CHANADMIN 2 -#define IRC_NICK_CHANADMIN2 4 -#define IRC_NICK_OP 8 -#define IRC_NICK_HALFOP 16 -#define IRC_NICK_VOICE 32 -#define IRC_NICK_AWAY 64 -#define IRC_NICK_CHANUSER 128 -#define IRC_NICK_SET_FLAG(nick, set, flag) \ - if (set) \ - nick->flags |= flag; \ - else \ - nick->flags &= 0xFFFF - flag; - -#define IRC_NICK_IS_OP(__nick) \ - ((__nick->flags & IRC_NICK_CHANOWNER) || \ - (__nick->flags & IRC_NICK_CHANADMIN) || \ - (__nick->flags & IRC_NICK_CHANADMIN2) || \ - (__nick->flags & IRC_NICK_OP)) - -#define IRC_NICK_GROUP_CHANOWNER "01|chanowner" -#define IRC_NICK_GROUP_CHANADMIN "02|chanadmin" -#define IRC_NICK_GROUP_CHANADMIN2 "03|chanadmin2" -#define IRC_NICK_GROUP_OP "04|op" -#define IRC_NICK_GROUP_HALFOP "05|halfop" -#define IRC_NICK_GROUP_VOICE "06|voice" -#define IRC_NICK_GROUP_CHANUSER "07|chanuser" -#define IRC_NICK_GROUP_NORMAL "08|normal" +#define IRC_NICK_GROUP_OTHER "999|..." struct t_irc_server; struct t_irc_channel; @@ -59,8 +32,10 @@ struct t_irc_nick { char *name; /* nickname */ char *host; /* full hostname */ - int flags; /* chanowner/chanadmin (unrealircd), */ - /* op, halfop, voice, away */ + char *prefixes; /* string with prefixes enabled for nick */ + char prefix[2]; /* current prefix (higher prefix set in */ + /* prefixes) */ + int away; /* 1 if nick is away */ const char *color; /* color for nickname in chat window */ struct t_irc_nick *prev_nick; /* link to previous nick on channel */ struct t_irc_nick *next_nick; /* link to next nick on channel */ @@ -71,29 +46,25 @@ extern int irc_nick_valid (struct t_irc_channel *channel, extern int irc_nick_is_nick (const char *string); extern const char *irc_nick_find_color (const char *nickname); extern const char *irc_nick_find_color_name (const char *nickname); -extern void irc_nick_get_gui_infos (struct t_irc_server *server, - struct t_irc_nick *nick, - char *prefix, int *prefix_color, - struct t_gui_buffer *buffer, - struct t_gui_nick_group **group); +extern int irc_nick_is_op (struct t_irc_server *server, + struct t_irc_nick *nick); +extern int irc_nick_has_prefix_mode (struct t_irc_server *server, + struct t_irc_nick *nick, + char prefix_mode); +extern int irc_nick_get_prefix_color (struct t_irc_server *server, + struct t_irc_nick *nick); extern const char *irc_nick_get_prefix_color_name (int prefix_color); extern struct t_irc_nick *irc_nick_new (struct t_irc_server *server, struct t_irc_channel *channel, const char *nickname, - int is_chanowner, - int is_chanadmin, - int is_chanadmin2, - int is_op, - int is_halfop, - int has_voice, - int is_chanuser, - int is_away); + const char *prefixes, + int away); extern void irc_nick_change (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick, const char *new_nick); -extern void irc_nick_set (struct t_irc_server *server, - struct t_irc_channel *channel, - struct t_irc_nick *nick, int set, int flag); +extern void irc_nick_set_mode (struct t_irc_server *server, + struct t_irc_channel *channel, + struct t_irc_nick *nick, int set, char mode); extern void irc_nick_free (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick); @@ -101,7 +72,8 @@ extern void irc_nick_free_all (struct t_irc_server *server, struct t_irc_channel *channel); extern struct t_irc_nick *irc_nick_search (struct t_irc_channel *channel, const char *nickname); -extern void irc_nick_count (struct t_irc_channel *channel, int *total, +extern 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); extern void irc_nick_set_away (struct t_irc_server *server, @@ -114,7 +86,6 @@ extern char *irc_nick_as_prefix (struct t_irc_server *server, extern const char * irc_nick_color_for_pv (struct t_irc_channel *channel, const char *nickname); extern int irc_nick_add_to_infolist (struct t_infolist *infolist, - struct t_irc_server *server, struct t_irc_nick *nick); extern void irc_nick_print_log (struct t_irc_nick *nick); diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c index 118b9e6ab..17f709afe 100644 --- a/src/plugins/irc/irc-protocol.c +++ b/src/plugins/irc/irc-protocol.c @@ -604,7 +604,7 @@ IRC_PROTOCOL_CALLBACK(join) } /* add nick in channel */ - ptr_nick = irc_nick_new (server, ptr_channel, nick, 0, 0, 0, 0, 0, 0, 0, 0); + ptr_nick = irc_nick_new (server, ptr_channel, nick, NULL, 0); if (ptr_nick) ptr_nick->host = strdup (address); @@ -2007,9 +2007,7 @@ IRC_PROTOCOL_CALLBACK(005) pos2 = strchr (pos, ' '); if (pos2) pos2[0] = '\0'; - if (server->prefix) - free (server->prefix); - server->prefix = strdup (pos); + irc_server_set_prefix_modes_chars (server, pos); if (pos2) pos2[0] = ' '; } @@ -3497,11 +3495,9 @@ IRC_PROTOCOL_CALLBACK(352) IRC_PROTOCOL_CALLBACK(353) { - char *pos_channel, *pos_nick, *pos_host, *nickname; - const char *color; - int args, i, prefix_found; - int is_chanowner, is_chanadmin, is_chanadmin2, is_op, is_halfop; - int has_voice, is_chanuser, is_away; + char *pos_channel, *pos_nick, *pos_nick_orig, *pos_host, *nickname; + char *prefixes; + int args, i, away; struct t_irc_channel *ptr_channel; struct t_irc_nick *ptr_nick; @@ -3527,84 +3523,36 @@ IRC_PROTOCOL_CALLBACK(353) ptr_channel = irc_channel_search (server, pos_channel); - for (i = args; i < argc; i++) + if (ptr_channel && ptr_channel->nicks) { - pos_nick = (argv[i][0] == ':') ? argv[i] + 1 : argv[i]; - - is_chanowner = 0; - is_chanadmin = 0; - is_chanadmin2 = 0; - is_op = 0; - is_halfop = 0; - has_voice = 0; - is_chanuser = 0; - is_away = 0; - prefix_found = 1; - - while (prefix_found) + for (i = args; i < argc; i++) { - prefix_found = 0; + pos_nick = (argv[i][0] == ':') ? argv[i] + 1 : argv[i]; + pos_nick_orig = pos_nick; - if (irc_mode_get_nick_attr (server, NULL, pos_nick[0]) >= 0) + /* skip prefix(es) */ + while (pos_nick[0] + && (irc_server_get_prefix_char_index (server, pos_nick[0]) >= 0)) { - prefix_found = 1; - switch (pos_nick[0]) - { - case '@': /* op */ - is_op = 1; - color = IRC_COLOR_NICK_PREFIX_OP; - break; - case '~': /* channel owner */ - is_chanowner = 1; - color = IRC_COLOR_NICK_PREFIX_OP; - break; - case '*': /* channel owner */ - is_chanowner = 1; - color = IRC_COLOR_NICK_PREFIX_OP; - break; - case '&': /* channel admin */ - is_chanadmin = 1; - color = IRC_COLOR_NICK_PREFIX_OP; - break; - case '!': /* channel admin (2) */ - is_chanadmin2 = 1; - color = IRC_COLOR_NICK_PREFIX_OP; - break; - case '%': /* half-op */ - is_halfop = 1; - color = IRC_COLOR_NICK_PREFIX_HALFOP; - break; - case '+': /* voice */ - has_voice = 1; - color = IRC_COLOR_NICK_PREFIX_VOICE; - break; - case '-': /* channel user */ - is_chanuser = 1; - color = IRC_COLOR_NICK_PREFIX_USER; - break; - default: - color = IRC_COLOR_CHAT; - break; - } - } - if (prefix_found) pos_nick++; - } - if (ptr_channel && ptr_channel->nicks) - { + } + + /* extract nick from host */ pos_host = strchr (pos_nick, '!'); if (pos_host) nickname = weechat_strndup (pos_nick, pos_host - pos_nick); else nickname = strdup (pos_nick); + + /* add or update nick on channel */ if (nickname) { ptr_nick = irc_nick_search (ptr_channel, nickname); - is_away = (ptr_nick && (ptr_nick->flags & IRC_NICK_AWAY)) ? 1 : 0; - if (!irc_nick_new (server, ptr_channel, nickname, - is_chanowner, is_chanadmin, is_chanadmin2, - is_op, is_halfop, has_voice, is_chanuser, - is_away)) + away = (ptr_nick && ptr_nick->away) ? 1 : 0; + prefixes = (pos_nick > pos_nick_orig) ? + weechat_strndup (pos_nick_orig, pos_nick - pos_nick_orig) : NULL; + if (!irc_nick_new (server, ptr_channel, nickname, prefixes, + away)) { weechat_printf (server->buffer, _("%s%s: cannot create nick \"%s\" " @@ -3613,6 +3561,8 @@ IRC_PROTOCOL_CALLBACK(353) IRC_PLUGIN_NAME, nickname, ptr_channel->name); } free (nickname); + if (prefixes) + free (prefixes); } } } @@ -3724,7 +3674,7 @@ IRC_PROTOCOL_CALLBACK(366) } /* display number of nicks, ops, halfops & voices on the channel */ - irc_nick_count (ptr_channel, &num_nicks, &num_op, &num_halfop, + irc_nick_count (server, ptr_channel, &num_nicks, &num_op, &num_halfop, &num_voice, &num_normal); weechat_printf_tags (ptr_channel->buffer, irc_protocol_tags (command, "irc_numeric", NULL), diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index 74f274d1b..b1c04983a 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -88,6 +88,9 @@ char *irc_server_option_default[IRC_SERVER_NUM_OPTIONS] = "WeeChat %v", "WeeChat %v", }; +char *irc_server_prefix_modes_default = "qaohvu"; +char *irc_server_prefix_chars_default = "~&@%+-"; + const char *irc_server_send_default_tags = NULL; /* default tags when */ /* sending a message */ @@ -385,6 +388,182 @@ irc_server_get_isupport_value (struct t_irc_server *server, const char *feature) } /* + * irc_server_set_prefix_modes_chars: set "prefix_modes" and "prefix_chars" in + * server using value of PREFIX in IRC + * message 005 + * for example, if prefix is "(aohv)&@%+", + * prefix_modes = "aohv" + * prefix_chars = "&@%+" + */ + +void +irc_server_set_prefix_modes_chars (struct t_irc_server *server, + const char *prefix) +{ + char *pos; + int i, length_modes, length_chars; + + if (!server || !prefix) + return; + + /* free previous values */ + if (server->prefix_modes) + { + free (server->prefix_modes); + server->prefix_modes = NULL; + } + if (server->prefix_chars) + { + free (server->prefix_chars); + server->prefix_chars = NULL; + } + + /* assign new values */ + pos = strchr (prefix, ')'); + if (pos) + { + server->prefix_modes = weechat_strndup (prefix + 1, + pos - prefix - 1); + if (server->prefix_modes) + { + pos++; + length_modes = strlen (server->prefix_modes); + length_chars = strlen (pos); + server->prefix_chars = malloc (length_modes + 1); + if (server->prefix_chars) + { + for (i = 0; i < length_modes; i++) + { + server->prefix_chars[i] = (i < length_chars) ? pos[i] : ' '; + } + server->prefix_chars[length_modes] = '\0'; + } + else + { + free (server->prefix_modes); + server->prefix_modes = NULL; + } + } + } +} + +/* + * irc_server_get_prefix_modes: get prefix_modes for server (return default + * modes if prefix_modes is not set) + */ + +const char * +irc_server_get_prefix_modes (struct t_irc_server *server) +{ + return (server && server->prefix_modes) ? + server->prefix_modes : irc_server_prefix_modes_default; +} + +/* + * irc_server_get_prefix_chars: get prefix_chars for server (return default + * chars if prefix_chars is not set) + */ + +const char * +irc_server_get_prefix_chars (struct t_irc_server *server) +{ + return (server && server->prefix_chars) ? + server->prefix_chars : irc_server_prefix_chars_default; +} + +/* + * irc_server_get_prefix_mode_index: get index of mode in prefix_modes + * return -1 if mode does not exist in server + */ + +int +irc_server_get_prefix_mode_index (struct t_irc_server *server, char mode) +{ + const char *prefix_modes; + char *pos; + + if (server) + { + prefix_modes = irc_server_get_prefix_modes (server); + pos = strchr (prefix_modes, mode); + if (pos) + return pos - prefix_modes; + } + + return -1; +} + +/* + * irc_server_get_prefix_char_index: get index of prefix_char in prefix_chars + * return -1 if prefix_char does not exist in + * server + */ + +int +irc_server_get_prefix_char_index (struct t_irc_server *server, + char prefix_char) +{ + const char *prefix_chars; + char *pos; + + if (server) + { + prefix_chars = irc_server_get_prefix_chars (server); + pos = strchr (prefix_chars, prefix_char); + if (pos) + return pos - prefix_chars; + } + + return -1; +} + +/* + * irc_server_get_prefix_mode_for_char: get mode for prefix char + * return ' ' (space) if prefix char is + * not found + */ + +char +irc_server_get_prefix_mode_for_char (struct t_irc_server *server, + char prefix_char) +{ + const char *prefix_modes; + int index; + + if (server) + { + prefix_modes = irc_server_get_prefix_modes (server); + index = irc_server_get_prefix_char_index (server, prefix_char); + if (index >= 0) + return prefix_modes[index]; + } + + return ' '; +} + +/* + * irc_server_get_prefix_mode_for_char: get prefix char for mode + * return ' ' (space) if mode is not found + */ + +char +irc_server_get_prefix_char_for_mode (struct t_irc_server *server, char mode) +{ + const char *prefix_chars; + int index; + + if (server) + { + prefix_chars = irc_server_get_prefix_chars (server); + index = irc_server_get_prefix_mode_index (server, mode); + if (index >= 0) + return prefix_chars[index]; + } + + return ' '; +} + +/* * irc_server_alloc: allocate a new server and add it to the servers queue */ @@ -445,7 +624,8 @@ irc_server_alloc (const char *name) new_server->nick = NULL; new_server->nick_modes = NULL; new_server->isupport = NULL; - new_server->prefix = NULL; + new_server->prefix_modes = NULL; + new_server->prefix_chars = NULL; new_server->reconnect_delay = 0; new_server->reconnect_start = 0; new_server->command_time = 0; @@ -894,8 +1074,10 @@ irc_server_free_data (struct t_irc_server *server) free (server->nick_modes); if (server->isupport) free (server->isupport); - if (server->prefix) - free (server->prefix); + if (server->prefix_modes) + free (server->prefix_modes); + if (server->prefix_chars) + free (server->prefix_chars); if (server->away_message) free (server->away_message); if (server->cmd_list_regexp) @@ -3350,10 +3532,15 @@ irc_server_disconnect (struct t_irc_server *server, int switch_address, free (server->isupport); server->isupport = NULL; } - if (server->prefix) + if (server->prefix_modes) { - free (server->prefix); - server->prefix = NULL; + free (server->prefix_modes); + server->prefix_modes = NULL; + } + if (server->prefix_chars) + { + free (server->prefix_chars); + server->prefix_chars = NULL; } server->is_away = 0; server->away_time = 0; @@ -3972,7 +4159,9 @@ irc_server_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_string (ptr_item, "isupport", server->isupport)) return 0; - if (!weechat_infolist_new_var_string (ptr_item, "prefix", server->prefix)) + if (!weechat_infolist_new_var_string (ptr_item, "prefix_modes", server->prefix_modes)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "prefix_chars", server->prefix_chars)) return 0; if (!weechat_infolist_new_var_integer (ptr_item, "reconnect_delay", server->reconnect_delay)) return 0; @@ -4266,7 +4455,8 @@ irc_server_print_log () weechat_log_printf (" nick . . . . . . . . : '%s'", ptr_server->nick); weechat_log_printf (" nick_modes . . . . . : '%s'", ptr_server->nick_modes); weechat_log_printf (" isupport . . . . . . : '%s'", ptr_server->isupport); - weechat_log_printf (" prefix . . . . . . . : '%s'", ptr_server->prefix); + weechat_log_printf (" prefix_modes . . . . : '%s'", ptr_server->prefix_modes); + weechat_log_printf (" prefix_chars . . . . : '%s'", ptr_server->prefix_chars); weechat_log_printf (" reconnect_delay. . . : %d", ptr_server->reconnect_delay); weechat_log_printf (" reconnect_start. . . : %ld", ptr_server->reconnect_start); weechat_log_printf (" command_time . . . . : %ld", ptr_server->command_time); diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index 251afb337..b8e728d3c 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -150,7 +150,8 @@ struct t_irc_server char *nick; /* current nickname */ char *nick_modes; /* nick modes */ char *isupport; /* copy of message 005 (ISUPPORT) */ - char *prefix; /* nick prefix allowed (from msg 005) */ + char *prefix_modes; /* prefix modes from msg 005 (eg "aohv") */ + char *prefix_chars; /* prefix chars from msg 005 (eg "&@%+") */ int reconnect_delay; /* current reconnect delay (growing) */ time_t reconnect_start; /* this time + delay = reconnect time */ time_t command_time; /* this time + command_delay = time to */ @@ -209,6 +210,18 @@ extern void irc_server_set_nick (struct t_irc_server *server, const char *nick); extern int irc_server_get_nick_index (struct t_irc_server *server); extern const char *irc_server_get_isupport_value (struct t_irc_server *server, const char *feature); +extern void irc_server_set_prefix_modes_chars (struct t_irc_server *server, + const char *prefix); +extern const char *irc_server_get_prefix_modes (struct t_irc_server *server); +extern const char *irc_server_get_prefix_chars (struct t_irc_server *server); +extern int irc_server_get_prefix_mode_index (struct t_irc_server *server, + char mode); +extern int irc_server_get_prefix_char_index (struct t_irc_server *server, + char prefix_char); +extern char irc_server_get_prefix_mode_for_char (struct t_irc_server *server, + char prefix_char); +extern char irc_server_get_prefix_char_for_mode (struct t_irc_server *server, + char mode); extern struct t_irc_server *irc_server_alloc (const char *name); extern int irc_server_alloc_with_url (const char *irc_url); extern void irc_server_apply_command_line_options (struct t_irc_server *server, diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c index 1e5d48c29..d4c5d0522 100644 --- a/src/plugins/irc/irc-upgrade.c +++ b/src/plugins/irc/irc-upgrade.c @@ -21,6 +21,7 @@ * irc-upgrade.c: save/restore IRC plugin data when upgrading WeeChat */ +#include <stdlib.h> #include <stdio.h> #include <string.h> @@ -103,7 +104,7 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) infolist = weechat_infolist_new (); if (!infolist) return 0; - if (!irc_nick_add_to_infolist (infolist, ptr_server, ptr_nick)) + if (!irc_nick_add_to_infolist (infolist, ptr_nick)) { weechat_infolist_free (infolist); return 0; @@ -324,9 +325,30 @@ irc_upgrade_read_cb (void *data, str = weechat_infolist_string (infolist, "isupport"); if (str) irc_upgrade_current_server->isupport = strdup (str); + /* + * "prefix" is not any more in this infolist (since + * WeeChat 0.3.4), but we read it to keep compatibility + * with old WeeChat versions, on /upgrade) + */ str = weechat_infolist_string (infolist, "prefix"); if (str) - irc_upgrade_current_server->prefix = strdup (str); + irc_server_set_prefix_modes_chars (irc_upgrade_current_server, str); + /* "prefix_modes" is new in WeeChat 0.3.4 */ + str = weechat_infolist_string (infolist, "prefix_modes"); + if (str) + { + if (irc_upgrade_current_server->prefix_modes) + free (irc_upgrade_current_server->prefix_modes); + irc_upgrade_current_server->prefix_modes = strdup (str); + } + /* "prefix_chars" is new in WeeChat 0.3.4 */ + str = weechat_infolist_string (infolist, "prefix_chars"); + if (str) + { + if (irc_upgrade_current_server->prefix_chars) + free (irc_upgrade_current_server->prefix_chars); + irc_upgrade_current_server->prefix_chars = strdup (str); + } irc_upgrade_current_server->reconnect_delay = weechat_infolist_integer (infolist, "reconnect_delay"); irc_upgrade_current_server->reconnect_start = weechat_infolist_time (infolist, "reconnect_start"); irc_upgrade_current_server->command_time = weechat_infolist_time (infolist, "command_time"); @@ -412,23 +434,88 @@ irc_upgrade_read_cb (void *data, case IRC_UPGRADE_TYPE_NICK: if (irc_upgrade_current_server && irc_upgrade_current_channel) { - flags = weechat_infolist_integer (infolist, "flags"); ptr_nick = irc_nick_new (irc_upgrade_current_server, irc_upgrade_current_channel, weechat_infolist_string (infolist, "name"), - flags & IRC_NICK_CHANOWNER, - flags & IRC_NICK_CHANADMIN, - flags & IRC_NICK_CHANADMIN2, - flags & IRC_NICK_OP, - flags & IRC_NICK_HALFOP, - flags & IRC_NICK_VOICE, - flags & IRC_NICK_CHANUSER, - flags & IRC_NICK_AWAY); + weechat_infolist_string (infolist, "prefixes"), + weechat_infolist_integer (infolist, "away")); if (ptr_nick) { str = weechat_infolist_string (infolist, "host"); if (str) ptr_nick->host = strdup (str); + + /* + * "flags" is not any more in this infolist (since + * WeeChat 0.3.4), but we read it to keep compatibility + * with old WeeChat versions, on /upgrade) + * We try to restore prefixes with old flags, but + * this is approximation, it's not sure we will + * restore good prefixes here (a /names on channel + * will fix problem if prefixes are wrong). + * Flags were defined in irc-nick.h: + * #define IRC_NICK_CHANOWNER 1 + * #define IRC_NICK_CHANADMIN 2 + * #define IRC_NICK_CHANADMIN2 4 + * #define IRC_NICK_OP 8 + * #define IRC_NICK_HALFOP 16 + * #define IRC_NICK_VOICE 32 + * #define IRC_NICK_AWAY 64 + * #define IRC_NICK_CHANUSER 128 + */ + flags = weechat_infolist_integer (infolist, "flags"); + if (flags > 0) + { + /* channel owner */ + if (flags & 1) + { + irc_nick_set_mode (irc_upgrade_current_server, + irc_upgrade_current_channel, + ptr_nick, 1, 'q'); + } + /* channel admin */ + if ((flags & 2) || (flags & 4)) + { + irc_nick_set_mode (irc_upgrade_current_server, + irc_upgrade_current_channel, + ptr_nick, 1, 'a'); + } + /* op */ + if (flags & 8) + { + irc_nick_set_mode (irc_upgrade_current_server, + irc_upgrade_current_channel, + ptr_nick, 1, 'o'); + } + /* half-op */ + if (flags & 16) + { + irc_nick_set_mode (irc_upgrade_current_server, + irc_upgrade_current_channel, + ptr_nick, 1, 'h'); + } + /* voice */ + if (flags & 32) + { + irc_nick_set_mode (irc_upgrade_current_server, + irc_upgrade_current_channel, + ptr_nick, 1, 'v'); + } + /* away */ + if (flags & 64) + { + irc_nick_set_away (irc_upgrade_current_server, + irc_upgrade_current_channel, + ptr_nick, 1); + } + /* channel user */ + if (flags & 128) + { + irc_nick_set_mode (irc_upgrade_current_server, + irc_upgrade_current_channel, + ptr_nick, 1, 'u'); + } + } } } break; |