From d14690767c2dc8a8a42e292d350fbe0fb36f3c21 Mon Sep 17 00:00:00 2001 From: Xavier G Date: Mon, 18 Apr 2016 01:39:27 +0200 Subject: [PATCH] Improve UTF-8 handling in display_sorted_nicks(). This commit aims at improving the way irssi generates the output of /names with UTF-8 nicks. However, it is only a partial fix: instead of counting bytes, irssi now counts characters; but it should ideally count columns, since Unicode characters are liable to spread accross several columns. Alas, as this message is being written, the whole ecosystem is far from being able to deal with that: some terminals handle multi-columns characters, some others don't; various ncurses programs (vim, tmux, etc.) suffer from bugs on terminals who do handle them. --- src/fe-common/core/fe-channels.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/fe-common/core/fe-channels.c b/src/fe-common/core/fe-channels.c index fd44be11..a1bc5d75 100644 --- a/src/fe-common/core/fe-channels.c +++ b/src/fe-common/core/fe-channels.c @@ -26,6 +26,7 @@ #include "levels.h" #include "misc.h" #include "settings.h" +#include "special-vars.h" #include "chat-protocols.h" #include "chatnets.h" @@ -323,7 +324,7 @@ static void cmd_channel_remove(const char *data) static int get_nick_length(void *data) { - return strlen(((NICK_REC *) data)->nick); + return g_utf8_strlen(((NICK_REC *) data)->nick, 1024); } static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) @@ -333,9 +334,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) GString *str; GSList *tmp; char *format, *stripped, *prefix_format; - char *linebuf, nickmode[2] = { 0, 0 }; + char *aligned_nick, nickmode[2] = { 0, 0 }; int *columns, cols, rows, last_col_rows, col, row, max_width; - int item_extra, linebuf_size, formatnum; + int item_extra, formatnum; window = window_find_closest(channel->server, channel->visible_name, MSGLEVEL_CLIENTCRAP); @@ -394,7 +395,6 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) last_col_rows = rows; str = g_string_new(prefix_format); - linebuf_size = max_width+1; linebuf = g_malloc(linebuf_size); col = 0; row = 0; for (tmp = nicklist; tmp != NULL; tmp = tmp->next) { @@ -405,13 +405,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) else nickmode[0] = ' '; - if (linebuf_size < columns[col]-item_extra+1) { - linebuf_size = (columns[col]-item_extra+1)*2; - linebuf = g_realloc(linebuf, linebuf_size); - } - memset(linebuf, ' ', columns[col]-item_extra); - linebuf[columns[col]-item_extra] = '\0'; - memcpy(linebuf, rec->nick, strlen(rec->nick)); + aligned_nick = get_alignment(rec->nick, + columns[col]-item_extra, + ALIGN_PAD, ' '); formatnum = rec->op ? TXT_NAMES_NICK_OP : rec->halfop ? TXT_NAMES_NICK_HALFOP : @@ -420,8 +416,9 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) format = format_get_text(MODULE_NAME, NULL, channel->server, channel->visible_name, - formatnum, nickmode, linebuf); + formatnum, nickmode, aligned_nick); g_string_append(str, format); + g_free(aligned_nick); g_free(format); if (++col == cols) { @@ -446,7 +443,6 @@ static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist) g_string_free(str, TRUE); g_free_not_null(columns); g_free_not_null(prefix_format); - g_free(linebuf); } void fe_channels_nicklist(CHANNEL_REC *channel, int flags)