aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c56
1 files 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)
// :<nick>!<user>@<host> PRIVMSG <target> :<message>
- 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);
- buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0,
- ctx->irc_user->nickname, NULL, "%.*s", 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);
- left -= part;
- message += part;
+ 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", m.str);
+ str_free (&m);
}
}