From 590fc6cf26f585841f89052e9c9ad6fb0702ba9c Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Mon, 20 Apr 2015 22:51:30 +0200 Subject: degesch: mostly implement NICK handling Except for the corner case where two buffers merge. --- degesch.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 16 deletions(-) diff --git a/degesch.c b/degesch.c index 6d75532..329ab5d 100644 --- a/degesch.c +++ b/degesch.c @@ -403,10 +403,6 @@ struct app_context // especially for away status polling) // XXX: there can be buffers for non-existent users - // TODO: user buffers rename on nick changes - // TODO: move entries in "irc_buffer_map" and "irc_users" when that happens - // TODO: user buffers may merge when an existing user renames to match - // the name of a buffer for a non-existent user // TODO: initialize key_strxfrm according to server properties; // note that collisions may arise on reconnecting // TODO: when disconnected, get rid of all users everywhere; @@ -1156,6 +1152,49 @@ buffer_activate (struct app_context *ctx, struct buffer *buffer) refresh_prompt (ctx); } +static void +buffer_merge (struct app_context *ctx, + struct buffer *buffer, struct buffer *merged) +{ + // TODO: try to merge the buffers as best as we can +} + +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->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); + // TODO: log a status message about the merge + 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); + + free (buffer->name); + buffer->name = xstrdup (new_name); + + // We might have renamed the current buffer + refresh_prompt (ctx); + } +} + static struct buffer * buffer_at_index (struct app_context *ctx, int n) { @@ -1848,13 +1887,31 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) if (!msg->prefix || msg->params.len < 1) return; + const char *new_nickname = msg->params.vector[0]; + char *nickname = irc_cut_nickname (msg->prefix); struct user *user = str_map_find (&ctx->irc_users, nickname); free (nickname); if (!user) return; - const char *new_nickname = msg->params.vector[0]; + // What the fuck + // TODO: probably log a message and force a reconnect + if (str_map_find (&ctx->irc_users, new_nickname)) + return; + + // Log a message in any PM buffer and rename it; + // we may even have one for ourselves + struct buffer *pm_buffer = + str_map_find (&ctx->irc_buffer_map, user->nickname); + if (pm_buffer) + { + buffer_send (ctx, pm_buffer, BUFFER_LINE_NICK, 0, + msg->prefix, NULL, "%s", new_nickname); + // TODO: use a full weechat-style buffer name here + buffer_rename (ctx, pm_buffer, new_nickname); + } + if (irc_is_this_us (ctx, msg->prefix)) { // Log a message in all open buffers on this server @@ -1863,26 +1920,21 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) struct buffer *buffer; while ((buffer = str_map_iter_next (&iter))) { + // We've already done that + if (buffer == pm_buffer) + continue; + buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, NULL, NULL, "%s", new_nickname); } } else { - // Log a message in any PM buffer - struct buffer *buffer = - str_map_find (&ctx->irc_buffer_map, user->nickname); - if (buffer) - { - buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, - msg->prefix, NULL, "%s", new_nickname); - // TODO: rename the buffer, and if it collides, merge them - } - // Log a message in all channels the user is in LIST_FOR_EACH (struct user_channel, iter, user->channels) { - buffer = str_map_find (&ctx->irc_buffer_map, iter->channel->name); + struct buffer *buffer = + str_map_find (&ctx->irc_buffer_map, iter->channel->name); hard_assert (buffer != NULL); buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, msg->prefix, NULL, "%s", new_nickname); @@ -1890,6 +1942,9 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) } // Finally rename the user + str_map_set (&ctx->irc_users, new_nickname, user_ref (user)); + str_map_set (&ctx->irc_users, user->nickname, NULL); + free (user->nickname); user->nickname = xstrdup (new_nickname); @@ -2644,8 +2699,11 @@ on_irc_disconnected (struct app_context *ctx) xclose (ctx->irc_fd); ctx->irc_fd = -1; ctx->irc_ready = false; + + str_map_set (&ctx->irc_users, ctx->irc_user->nickname, NULL); user_unref (ctx->irc_user); ctx->irc_user = NULL; + free (ctx->irc_user_mode); ctx->irc_user_mode = NULL; free (ctx->irc_user_host); @@ -2815,6 +2873,8 @@ irc_connect (struct app_context *ctx, struct error **e) // XXX: maybe we should wait for the first message from the server ctx->irc_user = user_new (); ctx->irc_user->nickname = xstrdup (nickname); + str_map_set (&ctx->irc_users, nickname, user_ref (ctx->irc_user)); + ctx->irc_user_mode = xstrdup (""); ctx->irc_user_host = NULL; return true; -- cgit v1.2.3-70-g09d2