diff --git a/ChangeLog b/ChangeLog index 500a19f7a..4f85f3eae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ WeeChat ChangeLog ================= Sébastien Helleu -v0.4.1-dev, 2013-03-08 +v0.4.1-dev, 2013-03-09 This document lists all changes for each version. @@ -52,6 +52,8 @@ Version 0.4.1 (under dev!) * irc: add color in output of /names when result is on server buffer (channel not joined) (bug #38070) * perl: simplify code to load scripts +* relay: add message "_nicklist_diff" (differences between old and current + nicklist) * relay: add support of multiple servers on same port for irc protocol (the client must send the server in the "PASS" command) * relay: add websocket server support (RFC 6455) for irc and weechat protocols, diff --git a/doc/en/weechat_dev.en.txt b/doc/en/weechat_dev.en.txt index f07833dd1..9af1cb0b7 100644 --- a/doc/en/weechat_dev.en.txt +++ b/doc/en/weechat_dev.en.txt @@ -241,6 +241,7 @@ Plugins | weechat/ | Relay for remote interface | relay-weechat.c | Relay for remote interface (main functions) | relay-weechat-msg.c | Send binary messages to clients +| relay-weechat-nicklist.c | Nicklist functions | relay-weechat-protocol.c | Read commands from clients | rmodifier/ | Rmodifier plugin | rmodifier.c | Main rmodifier functions diff --git a/po/POTFILES.in b/po/POTFILES.in index a53cd2ed7..00f21c3d7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -215,6 +215,8 @@ ./src/plugins/relay/weechat/relay-weechat.h ./src/plugins/relay/weechat/relay-weechat-msg.c ./src/plugins/relay/weechat/relay-weechat-msg.h +./src/plugins/relay/weechat/relay-weechat-nicklist.c +./src/plugins/relay/weechat/relay-weechat-nicklist.h ./src/plugins/relay/weechat/relay-weechat-protocol.c ./src/plugins/relay/weechat/relay-weechat-protocol.h ./src/plugins/rmodifier/rmodifier.c diff --git a/po/srcfiles.cmake b/po/srcfiles.cmake index 2a1bbc27a..980c01df6 100644 --- a/po/srcfiles.cmake +++ b/po/srcfiles.cmake @@ -208,6 +208,8 @@ SET(WEECHAT_SOURCES ./src/plugins/relay/weechat/relay-weechat.h ./src/plugins/relay/weechat/relay-weechat-msg.c ./src/plugins/relay/weechat/relay-weechat-msg.h +./src/plugins/relay/weechat/relay-weechat-nicklist.c +./src/plugins/relay/weechat/relay-weechat-nicklist.h ./src/plugins/relay/weechat/relay-weechat-protocol.c ./src/plugins/relay/weechat/relay-weechat-protocol.h ./src/plugins/rmodifier/rmodifier.c diff --git a/src/plugins/relay/CMakeLists.txt b/src/plugins/relay/CMakeLists.txt index 9f4ffca96..b96230547 100644 --- a/src/plugins/relay/CMakeLists.txt +++ b/src/plugins/relay/CMakeLists.txt @@ -24,6 +24,7 @@ relay-client.c relay-client.h irc/relay-irc.c irc/relay-irc.h weechat/relay-weechat.c weechat/relay-weechat.h weechat/relay-weechat-msg.c weechat/relay-weechat-msg.h +weechat/relay-weechat-nicklist.c weechat/relay-weechat-nicklist.h weechat/relay-weechat-protocol.c weechat/relay-weechat-protocol.h relay-command.c relay-command.h relay-completion.c relay-completion.h diff --git a/src/plugins/relay/Makefile.am b/src/plugins/relay/Makefile.am index 1bdba98c7..a23678ed6 100644 --- a/src/plugins/relay/Makefile.am +++ b/src/plugins/relay/Makefile.am @@ -35,6 +35,8 @@ relay_la_SOURCES = relay.c \ weechat/relay-weechat.h \ weechat/relay-weechat-msg.c \ weechat/relay-weechat-msg.h \ + weechat/relay-weechat-nicklist.c \ + weechat/relay-weechat-nicklist.h \ weechat/relay-weechat-protocol.c \ weechat/relay-weechat-protocol.h \ relay-command.c \ diff --git a/src/plugins/relay/weechat/relay-weechat-msg.c b/src/plugins/relay/weechat/relay-weechat-msg.c index 0430c746f..c0b1d8f4e 100644 --- a/src/plugins/relay/weechat/relay-weechat-msg.c +++ b/src/plugins/relay/weechat/relay-weechat-msg.c @@ -34,6 +34,7 @@ #include "../relay.h" #include "relay-weechat.h" #include "relay-weechat-msg.h" +#include "relay-weechat-nicklist.h" #include "../relay-buffer.h" #include "../relay-client.h" #include "../relay-config.h" @@ -823,85 +824,108 @@ relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg, /* * Adds nicklist for a buffer, as hdata object. * + * Argument "nicklist" contains nicklist diffs. If it is NULL or don't have + * items inside, full nicklist is sent. + * * Returns the number of nicks+groups added to message. */ int relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg, - struct t_gui_buffer *buffer) + struct t_gui_buffer *buffer, + struct t_relay_weechat_nicklist *nicklist) { - int count; + int count, i; struct t_hdata *ptr_hdata_group, *ptr_hdata_nick; struct t_gui_nick_group *ptr_group; struct t_gui_nick *ptr_nick; count = 0; - ptr_hdata_group = weechat_hdata_get ("nick_group"); - ptr_hdata_nick = weechat_hdata_get ("nick"); - - ptr_group = NULL; - ptr_nick = NULL; - weechat_nicklist_get_next_item (buffer, &ptr_group, &ptr_nick); - while (ptr_group || ptr_nick) + if (nicklist) { - if (ptr_nick) + /* send nicklist diffs */ + for (i = 0; i < nicklist->items_count; i++) { relay_weechat_msg_add_pointer (msg, buffer); - relay_weechat_msg_add_pointer (msg, ptr_nick); - relay_weechat_msg_add_char (msg, 0); /* group */ - relay_weechat_msg_add_char (msg, - (char)weechat_hdata_integer(ptr_hdata_nick, - ptr_nick, - "visible")); - relay_weechat_msg_add_int (msg, - weechat_hdata_integer (ptr_hdata_nick, - ptr_nick, - "level")); - relay_weechat_msg_add_string (msg, - weechat_hdata_string (ptr_hdata_nick, - ptr_nick, - "name")); - relay_weechat_msg_add_string (msg, - weechat_hdata_string (ptr_hdata_nick, - ptr_nick, - "color")); - relay_weechat_msg_add_string (msg, - weechat_hdata_string (ptr_hdata_nick, - ptr_nick, - "prefix")); - relay_weechat_msg_add_string (msg, - weechat_hdata_string (ptr_hdata_nick, - ptr_nick, - "prefix_color")); - count++; - } - else - { - relay_weechat_msg_add_pointer (msg, buffer); - relay_weechat_msg_add_pointer (msg, ptr_group); - relay_weechat_msg_add_char (msg, 1); /* group */ - relay_weechat_msg_add_char (msg, - (char)weechat_hdata_integer(ptr_hdata_group, - ptr_group, - "visible")); - relay_weechat_msg_add_int (msg, - weechat_hdata_integer (ptr_hdata_group, - ptr_group, - "level")); - relay_weechat_msg_add_string (msg, - weechat_hdata_string (ptr_hdata_group, - ptr_group, - "name")); - relay_weechat_msg_add_string (msg, - weechat_hdata_string (ptr_hdata_group, - ptr_group, - "color")); - relay_weechat_msg_add_string (msg, NULL); /* prefix */ - relay_weechat_msg_add_string (msg, NULL); /* prefix_color */ + relay_weechat_msg_add_pointer (msg, nicklist->items[i].pointer); + relay_weechat_msg_add_char (msg, nicklist->items[i].diff); + relay_weechat_msg_add_char (msg, nicklist->items[i].group); + relay_weechat_msg_add_char (msg, nicklist->items[i].visible); + relay_weechat_msg_add_int (msg, nicklist->items[i].level); + relay_weechat_msg_add_string (msg, nicklist->items[i].name); + relay_weechat_msg_add_string (msg, nicklist->items[i].color); + relay_weechat_msg_add_string (msg, nicklist->items[i].prefix); + relay_weechat_msg_add_string (msg, nicklist->items[i].prefix_color); count++; } + } + else + { + /* send full nicklist */ + ptr_hdata_group = weechat_hdata_get ("nick_group"); + ptr_hdata_nick = weechat_hdata_get ("nick"); + + ptr_group = NULL; + ptr_nick = NULL; weechat_nicklist_get_next_item (buffer, &ptr_group, &ptr_nick); + while (ptr_group || ptr_nick) + { + if (ptr_nick) + { + relay_weechat_msg_add_pointer (msg, buffer); + relay_weechat_msg_add_pointer (msg, ptr_nick); + relay_weechat_msg_add_char (msg, 0); /* group */ + relay_weechat_msg_add_char (msg, + (char)weechat_hdata_integer(ptr_hdata_nick, + ptr_nick, + "visible")); + relay_weechat_msg_add_int (msg, 0); /* level */ + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "name")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "color")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "prefix")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_nick, + ptr_nick, + "prefix_color")); + count++; + } + else + { + relay_weechat_msg_add_pointer (msg, buffer); + relay_weechat_msg_add_pointer (msg, ptr_group); + relay_weechat_msg_add_char (msg, 1); /* group */ + relay_weechat_msg_add_char (msg, + (char)weechat_hdata_integer(ptr_hdata_group, + ptr_group, + "visible")); + relay_weechat_msg_add_int (msg, + weechat_hdata_integer (ptr_hdata_group, + ptr_group, + "level")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_group, + ptr_group, + "name")); + relay_weechat_msg_add_string (msg, + weechat_hdata_string (ptr_hdata_group, + ptr_group, + "color")); + relay_weechat_msg_add_string (msg, NULL); /* prefix */ + relay_weechat_msg_add_string (msg, NULL); /* prefix_color */ + count++; + } + weechat_nicklist_get_next_item (buffer, &ptr_group, &ptr_nick); + } } return count; @@ -909,23 +933,31 @@ relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg, /* * Adds nicklist for one or all buffers, as hdata object. + * + * Argument "nicklist" contains nicklist diffs. If it is NULL or don't have + * items inside, full nicklist is sent. */ void relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg, - struct t_gui_buffer *buffer) + struct t_gui_buffer *buffer, + struct t_relay_weechat_nicklist *nicklist) { + char str_vars[512]; struct t_hdata *ptr_hdata; struct t_gui_buffer *ptr_buffer; int pos_count, count; uint32_t count32; + snprintf (str_vars, sizeof (str_vars), + "%sgroup:chr,visible:chr,level:int," + "name:str,color:str," + "prefix:str,prefix_color:str", + (nicklist) ? "_diff:chr," : ""); + relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HDATA); relay_weechat_msg_add_string (msg, "buffer/nicklist_item"); - relay_weechat_msg_add_string (msg, - "group:chr,visible:chr,level:int," - "name:str,color:str," - "prefix:str,prefix_color:str"); + relay_weechat_msg_add_string (msg, str_vars); /* "count" will be set later, with number of objects in hdata */ pos_count = msg->data_size; @@ -933,14 +965,16 @@ relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg, relay_weechat_msg_add_int (msg, 0); if (buffer) - count += relay_weechat_msg_add_nicklist_buffer (msg, buffer); + { + count += relay_weechat_msg_add_nicklist_buffer (msg, buffer, nicklist); + } else { ptr_hdata = weechat_hdata_get ("buffer"); ptr_buffer = weechat_hdata_get_list (ptr_hdata, "gui_buffers"); while (ptr_buffer) { - count += relay_weechat_msg_add_nicklist_buffer (msg, ptr_buffer); + count += relay_weechat_msg_add_nicklist_buffer (msg, ptr_buffer, NULL); ptr_buffer = weechat_hdata_move (ptr_hdata, ptr_buffer, 1); } } diff --git a/src/plugins/relay/weechat/relay-weechat-msg.h b/src/plugins/relay/weechat/relay-weechat-msg.h index a498e4777..534f66bd6 100644 --- a/src/plugins/relay/weechat/relay-weechat-msg.h +++ b/src/plugins/relay/weechat/relay-weechat-msg.h @@ -20,6 +20,8 @@ #ifndef __WEECHAT_RELAY_WEECHAT_MSG_H #define __WEECHAT_RELAY_WEECHAT_MSG_H 1 +struct t_relay_weechat_nicklist; + #define RELAY_WEECHAT_MSG_INITIAL_ALLOC 4096 /* object ids in binary messages */ @@ -73,7 +75,8 @@ extern void relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg, void *pointer, const char *arguments); extern void relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg, - struct t_gui_buffer *buffer); + struct t_gui_buffer *buffer, + struct t_relay_weechat_nicklist *nicklist); extern void relay_weechat_msg_send (struct t_relay_client *client, struct t_relay_weechat_msg *msg); extern void relay_weechat_msg_free (struct t_relay_weechat_msg *msg); diff --git a/src/plugins/relay/weechat/relay-weechat-nicklist.c b/src/plugins/relay/weechat/relay-weechat-nicklist.c new file mode 100644 index 000000000..355f1d4f8 --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat-nicklist.c @@ -0,0 +1,155 @@ +/* + * relay-weechat-nicklist.c - nicklist functions for WeeChat protocol + * + * Copyright (C) 2003-2013 Sebastien Helleu + * + * 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 . + */ + +#include +#include + +#include "../../weechat-plugin.h" +#include "../relay.h" +#include "relay-weechat.h" +#include "relay-weechat-nicklist.h" + + +/* + * Builds a new nicklist structure (to store nicklist diffs). + * + * Returns pointer to new nicklist structure, NULL if error. + */ + +struct t_relay_weechat_nicklist * +relay_weechat_nicklist_new () +{ + struct t_relay_weechat_nicklist *new_nicklist; + + new_nicklist = malloc (sizeof (*new_nicklist)); + if (!new_nicklist) + return NULL; + + new_nicklist->nicklist_count = 0; + new_nicklist->items_count = 0; + new_nicklist->items = NULL; + + return new_nicklist; +} + +/* + * Adds a nicklist item in nicklist structure. + */ + +void +relay_weechat_nicklist_add_item (struct t_relay_weechat_nicklist *nicklist, + char diff, struct t_gui_nick_group *group, + struct t_gui_nick *nick) +{ + struct t_relay_weechat_nicklist_item *new_items, *ptr_item; + struct t_hdata *hdata; + const char *str; + int i; + + /* + * check if the last "parent_group" (with diff = '^') of items is the same + * as this one: if yes, don't add this parent group + */ + if ((diff == RELAY_WEECHAT_NICKLIST_DIFF_PARENT) + && (nicklist->items_count > 0)) + { + for (i = nicklist->items_count - 1; i >= 0; i--) + { + if (nicklist->items[i].diff == RELAY_WEECHAT_NICKLIST_DIFF_PARENT) + { + if (nicklist->items[i].pointer == group) + return; + break; + } + } + } + + new_items = realloc (nicklist->items, + (nicklist->items_count + 1) * sizeof (new_items[0])); + if (!new_items) + return; + + nicklist->items = new_items; + ptr_item = &(nicklist->items[nicklist->items_count]); + if (group) + { + hdata = weechat_hdata_get ("nick_group"); + ptr_item->pointer = group; + } + else + { + hdata = weechat_hdata_get ("nick"); + ptr_item->pointer = nick; + } + ptr_item->diff = diff; + ptr_item->group = (group) ? 1 : 0; + ptr_item->visible = weechat_hdata_integer (hdata, ptr_item->pointer, "visible"); + ptr_item->level = (group) ? weechat_hdata_integer (hdata, ptr_item->pointer, "level") : 0; + str = weechat_hdata_string (hdata, ptr_item->pointer, "name"); + ptr_item->name = (str) ? strdup (str) : NULL; + str = weechat_hdata_string (hdata, ptr_item->pointer, "color"); + ptr_item->color = (str) ? strdup (str) : NULL; + str = weechat_hdata_string (hdata, ptr_item->pointer, "prefix"); + ptr_item->prefix = (str) ? strdup (str) : NULL; + str = weechat_hdata_string (hdata, ptr_item->pointer, "prefix_color"); + ptr_item->prefix_color = (str) ? strdup (str) : NULL; + + nicklist->items_count++; +} + +/* + * Frees a nicklist_item structure. + */ + +void +relay_weechat_nicklist_item_free (struct t_relay_weechat_nicklist_item *item) +{ + if (item->name) + free (item->name); + if (item->color) + free (item->color); + if (item->prefix) + free (item->prefix); + if (item->prefix_color) + free (item->prefix_color); +} + +/* + * Frees a new nicklist structure. + */ + +void +relay_weechat_nicklist_free (struct t_relay_weechat_nicklist *nicklist) +{ + int i; + + /* free items */ + if (nicklist->items_count > 0) + { + for (i = 0; i < nicklist->items_count; i++) + { + relay_weechat_nicklist_item_free (&(nicklist->items[i])); + } + free (nicklist->items); + } + + free (nicklist); +} diff --git a/src/plugins/relay/weechat/relay-weechat-nicklist.h b/src/plugins/relay/weechat/relay-weechat-nicklist.h new file mode 100644 index 000000000..143a0af1f --- /dev/null +++ b/src/plugins/relay/weechat/relay-weechat-nicklist.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2003-2013 Sebastien Helleu + * + * 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 . + */ + +#ifndef __WEECHAT_RELAY_WEECHAT_NICKLIST_H +#define __WEECHAT_RELAY_WEECHAT_NICKLIST_H 1 + +#define RELAY_WEECHAT_NICKLIST_DIFF_UNKNOWN ' ' +#define RELAY_WEECHAT_NICKLIST_DIFF_PARENT '^' +#define RELAY_WEECHAT_NICKLIST_DIFF_ADDED '+' +#define RELAY_WEECHAT_NICKLIST_DIFF_REMOVED '-' +#define RELAY_WEECHAT_NICKLIST_DIFF_CHANGED '*' + +struct t_relay_weechat_nicklist_item +{ + void *pointer; /* pointer on group/nick */ + char diff; /* type of diff (see constants above)*/ + char group; /* 1=group, 0=nick */ + char visible; /* 1=visible, 0=not visible */ + int level; /* level */ + char *name; /* name of group/nick */ + char *color; /* color for name */ + char *prefix; /* prefix */ + char *prefix_color; /* color for prefix */ +}; + +struct t_relay_weechat_nicklist +{ + int nicklist_count; /* number of nicks in nicklist */ + /* before receiving first diff */ + int items_count; /* number of nicklist items */ + struct t_relay_weechat_nicklist_item *items; /* nicklist items */ +}; + +extern struct t_relay_weechat_nicklist *relay_weechat_nicklist_new (); +extern void relay_weechat_nicklist_add_item (struct t_relay_weechat_nicklist *nicklist, + char diff, + struct t_gui_nick_group *group, + struct t_gui_nick *nick); +extern void relay_weechat_nicklist_free (struct t_relay_weechat_nicklist *nicklist); + +#endif /* __WEECHAT_RELAY_WEECHAT_NICKLIST_H */ diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.c b/src/plugins/relay/weechat/relay-weechat-protocol.c index 9313d4bdd..0f0f25546 100644 --- a/src/plugins/relay/weechat/relay-weechat-protocol.c +++ b/src/plugins/relay/weechat/relay-weechat-protocol.c @@ -28,6 +28,7 @@ #include "relay-weechat.h" #include "relay-weechat-protocol.h" #include "relay-weechat-msg.h" +#include "relay-weechat-nicklist.h" #include "../relay-client.h" #include "../relay-config.h" #include "../relay-raw.h" @@ -193,6 +194,10 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init) if (compression >= 0) RELAY_WEECHAT_DATA(client, compression) = compression; } + else if (strcmp (options[i], "nicklistdiff") == 0) + { + RELAY_WEECHAT_DATA(client, nicklist_diff) = 1; + } } } weechat_string_free_split (options); @@ -320,7 +325,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(nicklist) msg = relay_weechat_msg_new (id); if (msg) { - relay_weechat_msg_add_nicklist (msg, ptr_buffer); + relay_weechat_msg_add_nicklist (msg, ptr_buffer, NULL); relay_weechat_msg_send (client, msg); relay_weechat_msg_free (msg); } @@ -605,7 +610,7 @@ relay_weechat_protocol_signal_buffer_cb (void *data, const char *signal, snprintf (cmd_hdata, sizeof (cmd_hdata), "buffer:0x%lx", (long unsigned int)ptr_buffer); weechat_hashtable_remove (RELAY_WEECHAT_DATA(ptr_client, buffers_nicklist), - cmd_hdata + 7); + ptr_buffer); relay_weechat_msg_add_hdata (msg, cmd_hdata, "number,full_name"); relay_weechat_msg_send (ptr_client, msg); @@ -629,35 +634,52 @@ relay_weechat_protocol_nicklist_map_cb (void *data, const void *value) { struct t_relay_client *ptr_client; - int rc; - long unsigned int buffer; + struct t_gui_buffer *ptr_buffer; + struct t_relay_weechat_nicklist *ptr_nicklist; struct t_hdata *ptr_hdata; struct t_relay_weechat_msg *msg; /* make C compiler happy */ (void) hashtable; - (void) value; ptr_client = (struct t_relay_client *)data; + ptr_buffer = (struct t_gui_buffer *)key; + ptr_nicklist = (struct t_relay_weechat_nicklist *)value; - rc = sscanf (key, "%lx", &buffer); - if ((rc != EOF) && (rc != 0)) + ptr_hdata = weechat_hdata_get ("buffer"); + if (ptr_hdata) { - ptr_hdata = weechat_hdata_get ("buffer"); - if (ptr_hdata) + if (weechat_hdata_check_pointer (ptr_hdata, + weechat_hdata_get_list (ptr_hdata, "gui_buffers"), + ptr_buffer)) { - if (weechat_hdata_check_pointer (ptr_hdata, - weechat_hdata_get_list (ptr_hdata, "gui_buffers"), - (void *)buffer)) + if (RELAY_WEECHAT_DATA(ptr_client, nicklist_diff)) { - msg = relay_weechat_msg_new ("_nicklist"); - if (msg) + /* + * if no diff at all, or if diffs are bigger than nicklist: + * send whole nicklist + */ + if (ptr_nicklist + && ((ptr_nicklist->items_count == 0) + || (ptr_nicklist->items_count >= weechat_buffer_get_integer (ptr_buffer, "nicklist_count") + 1))) { - relay_weechat_msg_add_nicklist (msg, (struct t_gui_buffer *)buffer); - relay_weechat_msg_send (ptr_client, msg); - relay_weechat_msg_free (msg); + ptr_nicklist = NULL; } } + else + { + /* it will be removed soon (when clients will handle nicklist diff) */ + ptr_nicklist = NULL; + } + + /* send nicklist diffs or full nicklist */ + msg = relay_weechat_msg_new ((ptr_nicklist) ? "_nicklist_diff" : "_nicklist"); + if (msg) + { + relay_weechat_msg_add_nicklist (msg, ptr_buffer, ptr_nicklist); + relay_weechat_msg_send (ptr_client, msg); + relay_weechat_msg_free (msg); + } } } } @@ -690,54 +712,94 @@ relay_weechat_protocol_timer_nicklist_cb (void *data, int remaining_calls) } /* - * Callback for signals "nicklist_*". + * Callback for hsignals "nicklist_*". */ int -relay_weechat_protocol_signal_nicklist_cb (void *data, const char *signal, - const char *type_data, - void *signal_data) +relay_weechat_protocol_hsignal_nicklist_cb (void *data, const char *signal, + struct t_hashtable *hashtable) { struct t_relay_client *ptr_client; - char *pos, *str_buffer; - int rc; - long unsigned int buffer; - - /* make C compiler happy */ - (void) signal; - (void) type_data; + struct t_gui_nick_group *parent_group, *group; + struct t_gui_nick *nick; + struct t_gui_buffer *ptr_buffer; + struct t_relay_weechat_nicklist *ptr_nicklist; + char diff; ptr_client = (struct t_relay_client *)data; if (!ptr_client || !relay_client_valid (ptr_client)) return WEECHAT_RC_OK; - pos = strchr ((char *)signal_data, ','); - if (!pos) + /* check if buffer is synchronized with flag "nicklist" */ + ptr_buffer = weechat_hashtable_get (hashtable, "buffer"); + if (!relay_weechat_protocol_is_sync (ptr_client, ptr_buffer, + RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST)) return WEECHAT_RC_OK; - str_buffer = weechat_strndup (signal_data, pos - (char *)signal_data); - if (!str_buffer) + parent_group = weechat_hashtable_get (hashtable, "parent_group"); + group = weechat_hashtable_get (hashtable, "group"); + nick = weechat_hashtable_get (hashtable, "nick"); + + /* if there is no parent group (for example "root" group), ignore the signal */ + if (!parent_group) return WEECHAT_RC_OK; - rc = sscanf (str_buffer, "%lx", &buffer); - if ((rc != EOF) && (rc != 0)) + ptr_nicklist = weechat_hashtable_get (RELAY_WEECHAT_DATA(ptr_client, + buffers_nicklist), + ptr_buffer); + if (!ptr_nicklist) { - /* send nicklist only if buffer is synchronized with flag "nicklist" */ - if (relay_weechat_protocol_is_sync (ptr_client, (void *)buffer, - RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST)) - { - weechat_hashtable_set (RELAY_WEECHAT_DATA(ptr_client, buffers_nicklist), - str_buffer, "1"); - if (RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist)) - { - weechat_unhook (RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist)); - RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist) = NULL; - } - relay_weechat_hook_timer_nicklist (ptr_client); - } + ptr_nicklist = relay_weechat_nicklist_new (); + if (!ptr_nicklist) + return WEECHAT_RC_OK; + ptr_nicklist->nicklist_count = weechat_buffer_get_integer (ptr_buffer, + "nicklist_count"); + weechat_hashtable_set (RELAY_WEECHAT_DATA(ptr_client, buffers_nicklist), + ptr_buffer, + ptr_nicklist); } - free (str_buffer); + /* set diff type */ + diff = RELAY_WEECHAT_NICKLIST_DIFF_UNKNOWN; + if ((strcmp (signal, "nicklist_group_added") == 0) + || (strcmp (signal, "nicklist_nick_added") == 0)) + { + diff = RELAY_WEECHAT_NICKLIST_DIFF_ADDED; + } + else if ((strcmp (signal, "nicklist_group_removing") == 0) + || (strcmp (signal, "nicklist_nick_removing") == 0)) + { + diff = RELAY_WEECHAT_NICKLIST_DIFF_REMOVED; + } + else if ((strcmp (signal, "nicklist_group_changed") == 0) + || (strcmp (signal, "nicklist_nick_changed") == 0)) + { + diff = RELAY_WEECHAT_NICKLIST_DIFF_CHANGED; + } + + if (diff != RELAY_WEECHAT_NICKLIST_DIFF_UNKNOWN) + { + /* + * add items if nicklist was not empty or very small (otherwise we will + * send full nicklist) + */ + if (ptr_nicklist->nicklist_count > 1) + { + /* add nicklist item for parent group and group/nick */ + relay_weechat_nicklist_add_item (ptr_nicklist, + RELAY_WEECHAT_NICKLIST_DIFF_PARENT, + parent_group, NULL); + relay_weechat_nicklist_add_item (ptr_nicklist, diff, group, nick); + } + + /* add timer to send nicklist */ + if (RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist)) + { + weechat_unhook (RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist)); + RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist) = NULL; + } + relay_weechat_hook_timer_nicklist (ptr_client); + } return WEECHAT_RC_OK; } diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.h b/src/plugins/relay/weechat/relay-weechat-protocol.h index 0324da968..0637386ff 100644 --- a/src/plugins/relay/weechat/relay-weechat-protocol.h +++ b/src/plugins/relay/weechat/relay-weechat-protocol.h @@ -89,6 +89,9 @@ extern int relay_weechat_protocol_signal_nicklist_cb (void *data, const char *signal, const char *type_data, void *signal_data); +extern int relay_weechat_protocol_hsignal_nicklist_cb (void *data, + const char *signal, + struct t_hashtable *hashtable); extern int relay_weechat_protocol_signal_upgrade_cb (void *data, const char *signal, const char *type_data, diff --git a/src/plugins/relay/weechat/relay-weechat.c b/src/plugins/relay/weechat/relay-weechat.c index 8b8dc2636..9136849a8 100644 --- a/src/plugins/relay/weechat/relay-weechat.c +++ b/src/plugins/relay/weechat/relay-weechat.c @@ -33,6 +33,7 @@ #include "../../weechat-plugin.h" #include "../relay.h" #include "relay-weechat.h" +#include "relay-weechat-nicklist.h" #include "relay-weechat-protocol.h" #include "../relay-client.h" #include "../relay-config.h" @@ -76,10 +77,10 @@ relay_weechat_hook_signals (struct t_relay_client *client) weechat_hook_signal ("buffer_*", &relay_weechat_protocol_signal_buffer_cb, client); - RELAY_WEECHAT_DATA(client, hook_signal_nicklist) = - weechat_hook_signal ("nicklist_*", - &relay_weechat_protocol_signal_nicklist_cb, - client); + RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist) = + weechat_hook_hsignal ("nicklist_*", + &relay_weechat_protocol_hsignal_nicklist_cb, + client); RELAY_WEECHAT_DATA(client, hook_signal_upgrade) = weechat_hook_signal ("upgrade*", &relay_weechat_protocol_signal_upgrade_cb, @@ -98,10 +99,10 @@ relay_weechat_unhook_signals (struct t_relay_client *client) weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_buffer)); RELAY_WEECHAT_DATA(client, hook_signal_buffer) = NULL; } - if (RELAY_WEECHAT_DATA(client, hook_signal_nicklist)) + if (RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist)) { - weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_nicklist)); - RELAY_WEECHAT_DATA(client, hook_signal_nicklist) = NULL; + weechat_unhook (RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist)); + RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist) = NULL; } if (RELAY_WEECHAT_DATA(client, hook_signal_upgrade)) { @@ -143,6 +144,21 @@ relay_weechat_close_connection (struct t_relay_client *client) relay_weechat_unhook_signals (client); } +/* + * Frees a value of hashtable "buffers_nicklist". + */ + +void +relay_weechat_free_buffers_nicklist (struct t_hashtable *hashtable, + const void *key, void *value) +{ + /* make C compiler happy */ + (void) hashtable; + (void) key; + + relay_weechat_nicklist_free ((struct t_relay_weechat_nicklist *)value); +} + /* * Initializes relay data specific to WeeChat protocol. */ @@ -160,6 +176,7 @@ relay_weechat_alloc (struct t_relay_client *client) { RELAY_WEECHAT_DATA(client, password_ok) = (password && password[0]) ? 0 : 1; RELAY_WEECHAT_DATA(client, compression) = 1; + RELAY_WEECHAT_DATA(client, nicklist_diff) = 0; RELAY_WEECHAT_DATA(client, buffers_sync) = weechat_hashtable_new (32, WEECHAT_HASHTABLE_STRING, @@ -167,14 +184,17 @@ relay_weechat_alloc (struct t_relay_client *client) NULL, NULL); RELAY_WEECHAT_DATA(client, hook_signal_buffer) = NULL; - RELAY_WEECHAT_DATA(client, hook_signal_nicklist) = NULL; + RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist) = NULL; RELAY_WEECHAT_DATA(client, hook_signal_upgrade) = NULL; RELAY_WEECHAT_DATA(client, buffers_nicklist) = weechat_hashtable_new (32, - WEECHAT_HASHTABLE_STRING, - WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + WEECHAT_HASHTABLE_POINTER, NULL, NULL); + weechat_hashtable_set_pointer (RELAY_WEECHAT_DATA(client, buffers_nicklist), + "callback_free_value", + &relay_weechat_free_buffers_nicklist); RELAY_WEECHAT_DATA(client, hook_timer_nicklist) = NULL; relay_weechat_hook_signals (client); @@ -194,7 +214,7 @@ relay_weechat_alloc_with_infolist (struct t_relay_client *client, struct t_relay_weechat_data *weechat_data; int index, value; char name[64]; - const char *key, *str_value; + const char *key; client->protocol_data = malloc (sizeof (*weechat_data)); if (client->protocol_data) @@ -202,6 +222,7 @@ relay_weechat_alloc_with_infolist (struct t_relay_client *client, /* general stuff */ RELAY_WEECHAT_DATA(client, password_ok) = weechat_infolist_integer (infolist, "password_ok"); RELAY_WEECHAT_DATA(client, compression) = weechat_infolist_integer (infolist, "compression"); + RELAY_WEECHAT_DATA(client, nicklist_diff) = weechat_infolist_integer (infolist, "nicklist_diff"); /* sync of buffers */ RELAY_WEECHAT_DATA(client, buffers_sync) = weechat_hashtable_new (32, @@ -224,28 +245,17 @@ relay_weechat_alloc_with_infolist (struct t_relay_client *client, index++; } RELAY_WEECHAT_DATA(client, hook_signal_buffer) = NULL; - RELAY_WEECHAT_DATA(client, hook_signal_nicklist) = NULL; + RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist) = NULL; RELAY_WEECHAT_DATA(client, hook_signal_upgrade) = NULL; RELAY_WEECHAT_DATA(client, buffers_nicklist) = weechat_hashtable_new (32, - WEECHAT_HASHTABLE_STRING, - WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + WEECHAT_HASHTABLE_POINTER, NULL, NULL); - index = 0; - while (1) - { - snprintf (name, sizeof (name), "buffers_nicklist_name_%05d", index); - key = weechat_infolist_string (infolist, name); - if (!key) - break; - snprintf (name, sizeof (name), "buffers_nicklist_value_%05d", index); - str_value = weechat_infolist_string (infolist, name); - weechat_hashtable_set (RELAY_WEECHAT_DATA(client, buffers_nicklist), - key, - str_value); - index++; - } + weechat_hashtable_set_pointer (RELAY_WEECHAT_DATA(client, buffers_nicklist), + "callback_free_value", + &relay_weechat_free_buffers_nicklist); RELAY_WEECHAT_DATA(client, hook_timer_nicklist) = NULL; relay_weechat_hook_signals (client); @@ -265,8 +275,8 @@ relay_weechat_free (struct t_relay_client *client) weechat_hashtable_free (RELAY_WEECHAT_DATA(client, buffers_sync)); if (RELAY_WEECHAT_DATA(client, hook_signal_buffer)) weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_buffer)); - if (RELAY_WEECHAT_DATA(client, hook_signal_nicklist)) - weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_nicklist)); + if (RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist)) + weechat_unhook (RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist)); if (RELAY_WEECHAT_DATA(client, hook_signal_upgrade)) weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_upgrade)); if (RELAY_WEECHAT_DATA(client, buffers_nicklist)) @@ -297,9 +307,9 @@ relay_weechat_add_to_infolist (struct t_infolist_item *item, return 0; if (!weechat_infolist_new_var_integer (item, "compression", RELAY_WEECHAT_DATA(client, compression))) return 0; - if (!weechat_hashtable_add_to_infolist (RELAY_WEECHAT_DATA(client, buffers_sync), item, "buffers_sync")) + if (!weechat_infolist_new_var_integer (item, "nicklist_diff", RELAY_WEECHAT_DATA(client, nicklist_diff))) return 0; - if (!weechat_hashtable_add_to_infolist (RELAY_WEECHAT_DATA(client, buffers_nicklist), item, "buffers_nicklist")) + if (!weechat_hashtable_add_to_infolist (RELAY_WEECHAT_DATA(client, buffers_sync), item, "buffers_sync")) return 0; return 1; @@ -316,12 +326,13 @@ relay_weechat_print_log (struct t_relay_client *client) { weechat_log_printf (" password_ok. . . . . . : %d", RELAY_WEECHAT_DATA(client, password_ok)); weechat_log_printf (" compression. . . . . . : %d", RELAY_WEECHAT_DATA(client, compression)); + weechat_log_printf (" nicklist_diff. . . . . : %d", RELAY_WEECHAT_DATA(client, nicklist_diff)); weechat_log_printf (" buffers_sync . . . . . : 0x%lx (hashtable: '%s')", RELAY_WEECHAT_DATA(client, buffers_sync), weechat_hashtable_get_string (RELAY_WEECHAT_DATA(client, buffers_sync), "keys_values")); weechat_log_printf (" hook_signal_buffer . . : 0x%lx", RELAY_WEECHAT_DATA(client, hook_signal_buffer)); - weechat_log_printf (" hook_signal_nicklist . : 0x%lx", RELAY_WEECHAT_DATA(client, hook_signal_nicklist)); + weechat_log_printf (" hook_hsignal_nicklist. : 0x%lx", RELAY_WEECHAT_DATA(client, hook_hsignal_nicklist)); weechat_log_printf (" hook_signal_upgrade. . : 0x%lx", RELAY_WEECHAT_DATA(client, hook_signal_upgrade)); weechat_log_printf (" buffers_nicklist . . . : 0x%lx (hashtable: '%s')", RELAY_WEECHAT_DATA(client, buffers_nicklist), diff --git a/src/plugins/relay/weechat/relay-weechat.h b/src/plugins/relay/weechat/relay-weechat.h index 30c740f64..0cc98a54e 100644 --- a/src/plugins/relay/weechat/relay-weechat.h +++ b/src/plugins/relay/weechat/relay-weechat.h @@ -37,12 +37,13 @@ struct t_relay_weechat_data { int password_ok; /* password received and ok? */ int compression; /* compression type */ + int nicklist_diff; /* (TEMPORARY) nicklist diff enabled?*/ /* sync of buffers */ struct t_hashtable *buffers_sync; /* buffers synchronized (events */ /* received for these buffers) */ struct t_hook *hook_signal_buffer; /* hook for signals "buffer_*" */ - struct t_hook *hook_signal_nicklist; /* hook for signals "nicklist_*" */ + struct t_hook *hook_hsignal_nicklist; /* hook for hsignals "nicklist_*" */ struct t_hook *hook_signal_upgrade; /* hook for signals "upgrade*" */ struct t_hashtable *buffers_nicklist; /* send nicklist for these buffers*/ struct t_hook *hook_timer_nicklist; /* timer for sending nicklist */