From 2633eda69a964f51fda03f6c829834e4fdc82308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Wed, 22 Apr 2015 23:08:01 +0200 Subject: [PATCH] degesch: better message autosplit --- degesch.c | 56 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/degesch.c b/degesch.c index 5b10c7b..e561173 100644 --- a/degesch.c +++ b/degesch.c @@ -2722,27 +2722,57 @@ send_message_to_target (struct app_context *ctx, return; } - int one_message = 0; + // We don't always have the full info for message splitting + int space_in_one_message = 0; if (ctx->irc_user_host) // :!@ PRIVMSG : - one_message = 510 - 1 - (int) strlen (ctx->irc_user->nickname) + space_in_one_message = 510 + - 1 - (int) strlen (ctx->irc_user->nickname) - 1 - (int) strlen (ctx->irc_user_host) - 1 - 7 - 1 - strlen (target) - 1 - 1; - // FIXME: UTF-8 sequences - int left = strlen (message); - while (left) + // Attempt to split the message if it doesn't completely fit into + // a single IRC protocol message while trying not to break UTF-8. + // Unicode can still end up being wrong, though. + // TODO: at least try to word-wrap if nothing else + for (int message_left = strlen (message); message_left; ) { - int part = MIN (one_message, left); - if (!one_message) - part = left; + struct str m; + str_init (&m); - irc_send (ctx, "PRIVMSG %s :%.*s", target, part, message); + int part_left = MIN (space_in_one_message, message_left); + if (!space_in_one_message) + part_left = message_left; + + bool empty = true; + while (true) + { + const char *next = utf8_next (message, message_left); + hard_assert (next); + + int char_len = message - next; + if (char_len > part_left) + break; + + str_append_data (&m, message, char_len); + + message += char_len; + message_left -= char_len; + empty = false; + } + if (empty) + { + // Well, that's just weird + buffer_send_error (ctx, buffer, "%s", + "Message splitting was unsuccessful as there was " + "too little room for UTF-8 characters"); + message_left = 0; + } + + irc_send (ctx, "PRIVMSG %s :%s", target, m.str); buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0, - ctx->irc_user->nickname, NULL, "%.*s", part, message); - - left -= part; - message += part; + ctx->irc_user->nickname, NULL, "%s", m.str); + str_free (&m); } }