From b2cfbf1501e5649dd2cf5348aaced0e9a4231cc4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C5=99emysl=20Janouch?=
Date: Sat, 25 Apr 2015 01:34:31 +0200
Subject: [PATCH] degesch: refactor wrap_text()
It wasn't very readable.
---
degesch.c | 140 +++++++++++++++++++++++++++---------------------------
1 file changed, 71 insertions(+), 69 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 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
-wrap_text (const char *message,
+wrap_message (const char *message,
int line_max, struct str_vector *output, struct error **e)
{
- // Initialize to the first word, even if it's empty
- const char *word_end = message + strcspn (message, " ");
+ if (line_max <= 0)
+ goto error;
- for (int message_left = strlen (message); message_left; )
+ for (size_t message_left = strlen (message); message_left; )
{
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)
+ size_t eaten = wrap_text_for_single_line (message,
+ MIN ((size_t) line_max, message_left), message_left, &m);
+ if (!eaten)
{
- 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;
+ goto error;
}
- // 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 = 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;
- }
-
- if (!empty)
- str_vector_add (output, m.str);
-
- str_free (&m);
-
- 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;
+ 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;
}