degesch: better & working text wrapping
Now we respect word boundaries.
This commit is contained in:
parent
2a0dcc2add
commit
d4413627e6
53
degesch.c
53
degesch.c
@ -2398,15 +2398,15 @@ irc_process_message (const struct irc_message *msg,
|
|||||||
|
|
||||||
// --- Message autosplitting magic ---------------------------------------------
|
// --- 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
|
static bool
|
||||||
wrap_text (const char *message,
|
wrap_text (const char *message,
|
||||||
int line_max, struct str_vector *output, struct error **e)
|
int line_max, struct str_vector *output, struct error **e)
|
||||||
{
|
{
|
||||||
// Attempt to split the message if it doesn't completely fit into a single
|
// Initialize to the first word, even if it's empty
|
||||||
// IRC protocol message while trying not to break UTF-8. Unicode can still
|
const char *word_end = message + strcspn (message, " ");
|
||||||
// end up being wrong, though. As well as any mIRC formatting.
|
|
||||||
//
|
|
||||||
// TODO: at least try to word-wrap if nothing else
|
|
||||||
|
|
||||||
for (int message_left = strlen (message); message_left; )
|
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);
|
int part_left = MIN (line_max, message_left);
|
||||||
bool empty = true;
|
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)
|
while (true)
|
||||||
{
|
{
|
||||||
const char *next = utf8_next (message, message_left);
|
const char *next = utf8_next (message, message_left);
|
||||||
hard_assert (next);
|
hard_assert (next);
|
||||||
|
|
||||||
int char_len = message - next;
|
int char_len = next - message;
|
||||||
if (char_len > part_left)
|
if (char_len > part_left)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2428,6 +2462,7 @@ wrap_text (const char *message,
|
|||||||
|
|
||||||
message += char_len;
|
message += char_len;
|
||||||
message_left -= char_len;
|
message_left -= char_len;
|
||||||
|
part_left -= char_len;
|
||||||
empty = false;
|
empty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2436,15 +2471,15 @@ wrap_text (const char *message,
|
|||||||
|
|
||||||
str_free (&m);
|
str_free (&m);
|
||||||
|
|
||||||
if (empty)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user