[balsa: 1/2] Implement and use libbalsa_wrap_quoted_string()




commit 1ef095dc35b0f2e735a677a8b7d4cacfe50225fd
Author: Peter Bloomfield <peterbloomfield bellsouth net>
Date:   Sun May 15 14:15:31 2022 +0000

    Implement and use libbalsa_wrap_quoted_string()

 libbalsa/mime.c              | 94 ++++++++++++++++++++++++++++++++++++++++++++
 libbalsa/misc.h              |  3 ++
 src/balsa-mime-widget-text.c |  9 ++++-
 src/sendmsg-window.c         | 12 ++++--
 4 files changed, 113 insertions(+), 5 deletions(-)
---
diff --git a/libbalsa/mime.c b/libbalsa/mime.c
index fae3d3918..1329b3a4e 100644
--- a/libbalsa/mime.c
+++ b/libbalsa/mime.c
@@ -1153,3 +1153,97 @@ libbalsa_text_to_html(const gchar * title, const gchar * body, const gchar * lan
     /* return the utf-8 encoded text/html */
     return g_string_free(html_body, FALSE);
 }
+
+/*
+ * libbalsa_wrap_quoted string
+ * Wraps the string, prefixing wrapped lines with any quote string
+ * Uses the same wrapping strategy as libbalsa_wrap_string()
+ * Returns a newly allocated string--deallocate with g_free() when done
+*/
+char *
+libbalsa_wrap_quoted_string(const char *str,
+                            unsigned    width,
+                            GRegex     *quote_regex)
+{
+    char **lines;
+    char **line;
+    GString *wrapped;
+    PangoLogAttr *log_attrs = NULL;
+
+    g_return_val_if_fail(str != NULL, NULL);
+    g_return_val_if_fail(quote_regex != NULL, NULL);
+
+    lines = g_strsplit(str, "\n", -1);
+    wrapped = g_string_new(NULL);
+
+    for (line = lines; *line != NULL; line++) {
+        unsigned quote_len, quote_len_utf8;
+        const char *start_ptr, *break_ptr, *ptr;
+        const unsigned minl = width / 2;
+        unsigned ptr_offset, start_offset, break_offset;
+        int num_chars;
+        int attrs_len;
+        unsigned cursor;
+
+        num_chars = g_utf8_strlen(*line, -1);
+        attrs_len = num_chars + 1;
+        log_attrs = g_renew(PangoLogAttr, log_attrs, attrs_len);
+        pango_get_log_attrs(*line, -1, -1, pango_language_get_default(), log_attrs, attrs_len);
+
+        libbalsa_match_regex(*line, quote_regex, NULL, &quote_len);
+
+        g_string_append_len(wrapped, *line, quote_len);
+        ptr = *line + quote_len;
+
+        ptr_offset = g_utf8_pointer_to_offset(*line, ptr);
+        cursor = quote_len_utf8 = ptr_offset;
+
+        start_ptr = break_ptr = ptr;
+        start_offset = break_offset = ptr_offset;
+
+        while (*ptr != '\0') {
+            gunichar c = g_utf8_get_char(ptr);
+
+            if (c == '\t')
+                cursor += 8 - cursor % 8;
+            else
+                cursor++;
+
+            if (log_attrs[ptr_offset].is_line_break) {
+                break_ptr = ptr;
+                break_offset = ptr_offset;
+            }
+
+            if (cursor >= width && break_offset >= start_offset + minl && !g_unichar_isspace(c)) {
+                const char *end_ptr, *test_ptr;
+                gunichar test_char;
+
+                /* Back up over whitespace */
+                test_ptr = break_ptr;
+                do {
+                    end_ptr = test_ptr;
+                    test_ptr = g_utf8_prev_char(test_ptr);
+                    test_char = g_utf8_get_char(test_ptr);
+                } while (test_ptr > start_ptr && g_unichar_isspace(test_char));
+
+                g_string_append_len(wrapped, start_ptr, end_ptr - start_ptr);
+                g_string_append_c(wrapped, '\n');
+                g_string_append_len(wrapped, *line, quote_len);
+
+                start_ptr = break_ptr;
+                start_offset = break_offset;
+                cursor = quote_len_utf8 + ptr_offset - start_offset;
+            }
+            ptr = g_utf8_next_char(ptr);
+            ptr_offset++;
+        }
+
+        g_string_append(wrapped, start_ptr);
+        g_string_append_c(wrapped, '\n');
+    }
+
+    g_free(log_attrs);
+    g_strfreev(lines);
+
+    return (char *) g_string_free(wrapped, FALSE);
+}
diff --git a/libbalsa/misc.h b/libbalsa/misc.h
index 7ef58b576..f0e8eca9a 100644
--- a/libbalsa/misc.h
+++ b/libbalsa/misc.h
@@ -97,6 +97,9 @@ gchar *libbalsa_get_domainname(void);
 
 gboolean libbalsa_find_word(const gchar * word, const gchar * str);
 void libbalsa_wrap_string(gchar * str, int width);
+char *libbalsa_wrap_quoted_string(const char *str,
+                                  unsigned    width,
+                                  GRegex     *quote_regex);
 GString *libbalsa_process_text_rfc2646(gchar * par, gint width,
                                       gboolean from_screen,
                                       gboolean to_screen, gboolean quote,
diff --git a/src/balsa-mime-widget-text.c b/src/balsa-mime-widget-text.c
index 6788c1047..250920862 100644
--- a/src/balsa-mime-widget-text.c
+++ b/src/balsa-mime-widget-text.c
@@ -295,8 +295,13 @@ balsa_mime_widget_new_text(BalsaMessage * bm, LibBalsaMessageBody * mime_body,
 #if HAVE_GTKSOURCEVIEW
               && !GTK_SOURCE_IS_VIEW(widget)
 #endif
-              )
-       libbalsa_wrap_string(ptr, balsa_app.browse_wrap_length);
+              ) {
+        GRegex *rex = balsa_quote_regex_new();
+        char *wrapped = libbalsa_wrap_quoted_string(ptr, balsa_app.browse_wrap_length, rex);
+        g_regex_unref(rex);
+        g_free(ptr);
+        ptr = wrapped;
+    }
 
     fill_text_buf_cited(mwt, widget, ptr,
                         libbalsa_message_body_is_flowed(mime_body),
diff --git a/src/sendmsg-window.c b/src/sendmsg-window.c
index c9adcf805..ff5cc189a 100644
--- a/src/sendmsg-window.c
+++ b/src/sendmsg-window.c
@@ -4819,17 +4819,23 @@ sw_wrap_body(BalsaSendmsg * bsmsg)
         GtkTextIter now;
         gint pos;
         gchar *the_text;
+        GRegex *rex;
+        char *wrapped;
 
         gtk_text_buffer_get_iter_at_mark(buffer, &now,
                                          gtk_text_buffer_get_insert(buffer));
         pos = gtk_text_iter_get_offset(&now);
 
         the_text = gtk_text_iter_get_text(&start, &end);
-        libbalsa_wrap_string(the_text, balsa_app.wraplength);
-        gtk_text_buffer_set_text(buffer, "", 0);
-        gtk_text_buffer_insert_at_cursor(buffer, the_text, -1);
+        rex = balsa_quote_regex_new();
+        wrapped = libbalsa_wrap_quoted_string(the_text, balsa_app.browse_wrap_length, rex);
+        g_regex_unref(rex);
         g_free(the_text);
 
+        gtk_text_buffer_set_text(buffer, "", 0);
+        gtk_text_buffer_insert_at_cursor(buffer, wrapped, -1);
+        g_free(wrapped);
+
         gtk_text_buffer_get_iter_at_offset(buffer, &now, pos);
         gtk_text_buffer_place_cursor(buffer, &now);
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]