degesch: refactor wrap_text()

It wasn't very readable.
This commit is contained in:
Přemysl Eric Janouch 2015-04-25 01:34:31 +02:00
parent 6ef472beb2
commit b2cfbf1501

130
degesch.c
View File

@ -2406,89 +2406,91 @@ irc_process_message (const struct irc_message *msg,
// This is the most basic acceptable algorithm; something like ICU with proper // This is the most basic acceptable algorithm; something like ICU with proper
// locale specification would be needed to make it work better. // locale specification would be needed to make it work better.
static size_t
wrap_text_for_single_line (const char *text, size_t text_len,
size_t line_len, struct str *output)
{
int eaten = 0;
// First try going word by word
const char *word_start;
const char *word_end = text + strcspn (text, " ");
size_t word_len = word_end - text;
while (line_len && word_len <= line_len)
{
if (word_len)
{
str_append_data (output, text, word_len);
text += word_len;
eaten += word_len;
line_len -= word_len;
}
// Find the next word's end
word_start = text + strspn (text, " ");
word_end = word_start + strcspn (word_start, " ");
word_len = word_end - text;
}
if (eaten)
// Discard whitespace between words if split
return eaten + (word_start - text);
// And if that doesn't help, cut the longest valid block of characters
while (true)
{
const char *next = utf8_next (text, text_len - eaten);
hard_assert (next);
size_t char_len = next - text;
if (char_len > line_len)
break;
str_append_data (output, text, char_len);
text += char_len;
eaten += char_len;
line_len -= char_len;
}
return eaten;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static bool static bool
wrap_text (const char *message, wrap_message (const char *message,
int line_max, struct str_vector *output, struct error **e) int line_max, struct str_vector *output, struct error **e)
{ {
// Initialize to the first word, even if it's empty if (line_max <= 0)
const char *word_end = message + strcspn (message, " "); goto error;
for (int message_left = strlen (message); message_left; ) for (size_t message_left = strlen (message); message_left; )
{ {
struct str m; struct str m;
str_init (&m); str_init (&m);
int part_left = MIN (line_max, message_left); size_t eaten = wrap_text_for_single_line (message,
bool empty = true; MIN ((size_t) line_max, message_left), message_left, &m);
if (!eaten)
// 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); str_free (&m);
continue; goto error;
} }
// And if that doesn't help, cut the longest valid block of characters. str_vector_add_owned (output, str_steal (&m));
// Note that we never get to the end of the word, so "word_end" stays. message += eaten;
while (true) message_left -= eaten;
{
const char *next = utf8_next (message, message_left);
hard_assert (next);
int char_len = next - message;
if (char_len > part_left)
break;
str_append_data (&m, message, char_len);
message += char_len;
message_left -= char_len;
part_left -= char_len;
empty = false;
} }
return true;
if (!empty) error:
str_vector_add (output, m.str);
str_free (&m);
if (!empty)
continue;
// Well, that's just weird // Well, that's just weird
error_set (e, error_set (e,
"Message splitting was unsuccessful as there was " "Message splitting was unsuccessful as there was "
"too little room for UTF-8 characters"); "too little room for UTF-8 characters");
return false; return false;
} }
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// Automatically splits messages that arrive at other clients with our prefix /// Automatically splits messages that arrive at other clients with our prefix
/// so that they don't arrive cut off by the server /// so that they don't arrive cut off by the server
@ -2507,7 +2509,7 @@ irc_autosplit_message (struct app_context *ctx, const char *message,
// However we don't always have the full info for message splitting // However we don't always have the full info for message splitting
if (!space_in_one_message) if (!space_in_one_message)
str_vector_add (output, message); str_vector_add (output, message);
else if (!wrap_text (message, space_in_one_message, output, e)) else if (!wrap_message (message, space_in_one_message, output, e))
return false; return false;
return true; return true;
} }