From de019e7832cbd66b2fdbc16caf243e6fd929e40a Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Mon, 22 Jun 2015 21:29:42 +0200
Subject: degesch: fix handling of buffer collisions
---
degesch.c | 109 +++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 62 insertions(+), 47 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);
-
- // 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);
-
- // 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);
+ struct buffer *collision = str_map_find (&ctx->buffers_by_name, new_name);
+ if (collision == buffer)
+ return;
- free (buffer->name);
- buffer->name = xstrdup (new_name);
+ hard_assert (!collision);
- // We might have renamed the current buffer
- refresh_prompt (ctx);
- }
+ 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);
+
+ // 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);
--
cgit v1.2.3-70-g09d2