degesch: better & working text wrapping

Now we respect word boundaries.
This commit is contained in:
Přemysl Eric Janouch 2015-04-24 22:34:44 +02:00
parent 2a0dcc2add
commit d4413627e6
1 changed files with 49 additions and 14 deletions

View File

@ -2398,15 +2398,15 @@ irc_process_message (const struct irc_message *msg,
// --- Message autosplitting magic ---------------------------------------------
// This is the most basic acceptable algorithm; something like ICU with proper
// locale specification would be needed to make it work better.
static bool
wrap_text (const char *message,
int line_max, struct str_vector *output, struct error **e)
{
// 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. As well as any mIRC formatting.
//
// TODO: at least try to word-wrap if nothing else
// Initialize to the first word, even if it's empty
const char *word_end = message + strcspn (message, " ");
for (int message_left = strlen (message); message_left; )
{
@ -2415,12 +2415,46 @@ wrap_text (const char *message,
int part_left = MIN (line_max, message_left);
bool empty = true;
// First try going word by word
const char *word_start;
int word_len = word_end - message;
while (part_left && word_len <= part_left)
{
if (word_len)
{
str_append_data (&m, message, word_len);
message += word_len;
message_left -= word_len;
part_left -= word_len;
empty = false;
}
// Find the next word's end
word_start = message + strspn (message, " ");
word_end = word_start + strcspn (word_start, " ");
word_len = word_end - message;
}
if (!empty)
{
// Discard whitespace between words if split
message_left -= word_start - message;
message = word_start;
str_vector_add (output, m.str);
str_free (&m);
continue;
}
// And if that doesn't help, cut the longest valid block of characters.
// Note that we never get to the end of the word, so "word_end" stays.
while (true)
{
const char *next = utf8_next (message, message_left);
hard_assert (next);
int char_len = message - next;
int char_len = next - message;
if (char_len > part_left)
break;
@ -2428,6 +2462,7 @@ wrap_text (const char *message,
message += char_len;
message_left -= char_len;
part_left -= char_len;
empty = false;
}
@ -2436,14 +2471,14 @@ wrap_text (const char *message,
str_free (&m);
if (empty)
{
// Well, that's just weird
error_set (e,
"Message splitting was unsuccessful as there was "
"too little room for UTF-8 characters");
return false;
}
if (!empty)
continue;
// Well, that's just weird
error_set (e,
"Message splitting was unsuccessful as there was "
"too little room for UTF-8 characters");
return false;
}
return true;
}