[balsa/74-quote-wrapped-lines: 3/3] Implement and use libbalsa_wrap_quoted_string()




commit 65fa7a936404f5c5dc0785be59f798e451d37bc7
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Sat Apr 9 21:05:20 2022 -0400

    Implement and use libbalsa_wrap_quoted_string()
    
    See https://gitlab.gnome.org/GNOME/balsa/-/issues/74
    When a text/plain part is not Format=Flowed and is wrapped to a
    user-specified width, each wrapped line should be quoted in the same way
    as the original line, both when displayed and when quoted in a reply.
    
    modified:   libbalsa/mime.c
    modified:   libbalsa/mime.h
    modified:   src/balsa-mime-widget-text.c
    modified:   src/sendmsg-window.c

 libbalsa/mime.c              | 74 ++++++++++++++++++++++++++++++++++++++++++++
 libbalsa/mime.h              |  3 ++
 src/balsa-mime-widget-text.c |  9 ++++--
 src/sendmsg-window.c         | 12 +++++--
 4 files changed, 93 insertions(+), 5 deletions(-)
---
diff --git a/libbalsa/mime.c b/libbalsa/mime.c
index 1abf4b18e..8d6d5f353 100644
--- a/libbalsa/mime.c
+++ b/libbalsa/mime.c
@@ -1301,3 +1301,77 @@ 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;
+
+    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_pos, *space_pos, *ptr;
+        const unsigned minl = width / 2;
+        unsigned te = 0;    /* tabs' extra space */
+        unsigned ptr_offset, line_begin_offset, space_pos_offset;
+
+        libbalsa_match_regex(*line, quote_regex, NULL, &quote_len);
+
+        g_string_append_len(wrapped, *line, quote_len);
+        ptr = *line + quote_len;
+
+        quote_len_utf8 = g_utf8_pointer_to_offset(*line, ptr);
+        ptr_offset = quote_len_utf8;
+
+        line_begin_offset = space_pos_offset = 0;
+        start_pos = space_pos = ptr;
+
+        while (*ptr != '\0') {
+            switch (*ptr) {
+            case '\t':
+                te += 7;
+                break;
+            case ' ':
+                space_pos = ptr;
+                space_pos_offset = ptr_offset;
+                break;
+            }
+
+            if (ptr_offset - line_begin_offset >= width - te &&
+                space_pos_offset >= line_begin_offset + minl) {
+                g_string_append_len(wrapped, start_pos, space_pos - start_pos);
+                g_string_append_c(wrapped, '\n');
+
+                g_string_append_len(wrapped, *line, quote_len);
+                ptr_offset += quote_len_utf8;
+
+                start_pos = space_pos + 1;
+                line_begin_offset = space_pos_offset + 1;
+                te = 0;
+            }
+            ptr = g_utf8_next_char(ptr);
+            ptr_offset++;
+        }
+        g_string_append(wrapped, start_pos);
+        g_string_append_c(wrapped, '\n');
+    }
+
+    g_strfreev(lines);
+
+    return (char *) g_string_free(wrapped, FALSE);
+}
diff --git a/libbalsa/mime.h b/libbalsa/mime.h
index 7e93d9385..c45bad5f8 100644
--- a/libbalsa/mime.h
+++ b/libbalsa/mime.h
@@ -34,5 +34,8 @@ GString *process_mime_part(LibBalsaMessage * message,
 GString *content2reply(LibBalsaMessageBody *root,
                       gchar * reply_prefix_str, gint llen,
                       gboolean ignore_html, gboolean flow);
+char *libbalsa_wrap_quoted_string(const char *str,
+                                  unsigned    width,
+                                  GRegex     *quote_regex);
 
 #endif                         /* __LIBBALSA_MIME_H__ */
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]