From de019e7832cbd66b2fdbc16caf243e6fd929e40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Mon, 22 Jun 2015 21:29:42 +0200 Subject: [PATCH] degesch: fix handling of buffer collisions --- degesch.c | 105 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/degesch.c b/degesch.c index b75a1f0..f9c6288 100644 --- a/degesch.c +++ b/degesch.c @@ -2669,20 +2669,23 @@ buffer_merge (struct app_context *ctx, size_t n = 0; for (struct buffer_line *iter = start; iter; iter = iter->next) n++; + struct buffer_line *tail = merged->lines_tail; - // Append the merged part to current lines in the buffer + // Cut them from the original buffer + if (start == merged->lines) + merged->lines = NULL; + else if (start->prev) + start->prev->next = NULL; + if (start == merged->lines_tail) + merged->lines_tail = start->prev; + merged->lines_count -= n; + + // And append them to current lines in the buffer buffer->lines_tail->next = start; start->prev = buffer->lines_tail; - - buffer->lines_tail = merged->lines_tail; + buffer->lines_tail = tail; buffer->lines_count += n; - // And remove it from the original buffer - if (start == merged->lines_tail) - if (!(merged->lines_tail = start->prev)) - merged->lines = NULL; - merged->lines_count -= n; - // XXX: we don't want to log this entry to a file buffer_send_status (ctx, buffer, "End of merged content"); } @@ -2691,39 +2694,20 @@ static void buffer_rename (struct app_context *ctx, struct buffer *buffer, const char *new_name) { - hard_assert (buffer->type == BUFFER_PM); + struct buffer *collision = str_map_find (&ctx->buffers_by_name, new_name); + if (collision == buffer) + return; - // FIXME: this will never find anything as we are being sent - // the full buffer name, including the server name; - // searching in "buffers_by_name" won't do it either, - // we seem to need more information to properly handle this - struct buffer *collision = - str_map_find (&buffer->server->irc_buffer_map, new_name); - if (collision) - { - // TODO: use full weechat-style buffer names - // to prevent name collisions with the global buffer - hard_assert (collision->type == BUFFER_PM); + hard_assert (!collision); - // When there's a collision, there's not much else we can do - // other than somehow trying to merge them - buffer_merge (ctx, collision, buffer); - if (ctx->current_buffer == buffer) - buffer_activate (ctx, collision); - buffer_remove (ctx, buffer); - } - else - { - // Otherwise we just rename the buffer and that's it - str_map_set (&ctx->buffers_by_name, buffer->name, NULL); - str_map_set (&ctx->buffers_by_name, new_name, buffer); + str_map_set (&ctx->buffers_by_name, buffer->name, NULL); + str_map_set (&ctx->buffers_by_name, new_name, buffer); - free (buffer->name); - buffer->name = xstrdup (new_name); + free (buffer->name); + buffer->name = xstrdup (new_name); - // We might have renamed the current buffer - refresh_prompt (ctx); - } + // We might have renamed the current buffer + refresh_prompt (ctx); } static void @@ -4373,6 +4357,27 @@ irc_handle_mode (struct server *s, const struct irc_message *msg) refresh_prompt (s->ctx); } +static struct buffer * +irc_handle_buffer_collision (struct server *s, + struct buffer *buffer, const char *new_name) +{ + struct buffer *collision = str_map_find (&s->irc_buffer_map, new_name); + if (!collision) + return buffer; + + // TODO: use full weechat-style buffer names + // to prevent name collisions with the global buffer + hard_assert (collision->type == buffer->type); + + // When there's a collision, there's not much else we can do + // other than somehow try to merge them + buffer_merge (s->ctx, collision, buffer); + if (s->ctx->current_buffer == buffer) + buffer_activate (s->ctx, collision); + buffer_remove (s->ctx, buffer); + return collision; +} + static void irc_handle_nick (struct server *s, const struct irc_message *msg) { @@ -4402,12 +4407,6 @@ irc_handle_nick (struct server *s, const struct irc_message *msg) str_map_find (&s->irc_buffer_map, user->nickname); if (pm_buffer) { - if (!lexicographically_identical) - { - str_map_set (&s->irc_buffer_map, new_nickname, pm_buffer); - str_map_set (&s->irc_buffer_map, user->nickname, NULL); - } - char *who = irc_is_this_us (s, msg->prefix) ? irc_to_utf8 (s->ctx, msg->prefix) : NULL; @@ -4415,6 +4414,21 @@ irc_handle_nick (struct server *s, const struct irc_message *msg) .who = who, .object = irc_to_utf8 (s->ctx, new_nickname)); + if (!lexicographically_identical) + { + // XXX: this code seems a bit ugly (but also necessary) + user = user_ref (user); + + pm_buffer = irc_handle_buffer_collision + (s, pm_buffer, new_nickname); + + user_unref (pm_buffer->user); + pm_buffer->user = user; + + str_map_set (&s->irc_buffer_map, user->nickname, NULL); + str_map_set (&s->irc_buffer_map, new_nickname, pm_buffer); + } + char *x = xstrdup_printf ("%s.%s", s->name, new_nickname); buffer_rename (s->ctx, pm_buffer, x); free (x); @@ -4453,8 +4467,9 @@ irc_handle_nick (struct server *s, const struct irc_message *msg) // Finally rename the user if (!lexicographically_identical) { - str_map_set (&s->irc_users, new_nickname, user_ref (user)); + // NOTE: this doesn't dereference anything str_map_set (&s->irc_users, user->nickname, NULL); + str_map_set (&s->irc_users, new_nickname, user); } free (user->nickname);