summaryrefslogtreecommitdiff
path: root/degesch.c
diff options
context:
space:
mode:
Diffstat (limited to 'degesch.c')
-rw-r--r--degesch.c134
1 files changed, 68 insertions, 66 deletions
diff --git a/degesch.c b/degesch.c
index d624731..70c6ae0 100644
--- a/degesch.c
+++ b/degesch.c
@@ -2406,89 +2406,91 @@ irc_process_message (const struct irc_message *msg,
// 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)
+static size_t
+wrap_text_for_single_line (const char *text, size_t text_len,
+ size_t line_len, struct str *output)
{
- // Initialize to the first word, even if it's empty
- const char *word_end = message + strcspn (message, " ");
+ int eaten = 0;
- for (int message_left = strlen (message); message_left; )
+ // 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)
{
- struct str m;
- str_init (&m);
-
- 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)
{
- 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;
+ str_append_data (output, text, word_len);
+
+ text += word_len;
+ eaten += word_len;
+ line_len -= word_len;
}
- if (!empty)
- {
- // Discard whitespace between words if split
- message_left -= word_start - message;
- message = word_start;
+ // Find the next word's end
+ word_start = text + strspn (text, " ");
+ word_end = word_start + strcspn (word_start, " ");
+ word_len = word_end - text;
+ }
- str_vector_add (output, m.str);
- str_free (&m);
- continue;
- }
+ 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.
- // 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);
+ // 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);
- int char_len = next - message;
- if (char_len > part_left)
- break;
+ size_t char_len = next - text;
+ if (char_len > line_len)
+ break;
- str_append_data (&m, message, char_len);
+ str_append_data (output, text, char_len);
- message += char_len;
- message_left -= char_len;
- part_left -= char_len;
- empty = false;
- }
+ text += char_len;
+ eaten += char_len;
+ line_len -= char_len;
+ }
+ return eaten;
+}
- if (!empty)
- str_vector_add (output, m.str);
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- str_free (&m);
+static bool
+wrap_message (const char *message,
+ int line_max, struct str_vector *output, struct error **e)
+{
+ if (line_max <= 0)
+ goto error;
- if (!empty)
- continue;
+ for (size_t message_left = strlen (message); message_left; )
+ {
+ struct str m;
+ str_init (&m);
- // Well, that's just weird
- error_set (e,
- "Message splitting was unsuccessful as there was "
- "too little room for UTF-8 characters");
- return false;
+ size_t eaten = wrap_text_for_single_line (message,
+ MIN ((size_t) line_max, message_left), message_left, &m);
+ if (!eaten)
+ {
+ str_free (&m);
+ goto error;
+ }
+
+ str_vector_add_owned (output, str_steal (&m));
+ message += eaten;
+ message_left -= eaten;
}
return true;
-}
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+error:
+ // Well, that's just weird
+ error_set (e,
+ "Message splitting was unsuccessful as there was "
+ "too little room for UTF-8 characters");
+ return false;
+}
/// Automatically splits messages that arrive at other clients with our prefix
/// 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
if (!space_in_one_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 true;
}