Am 28.08.07 21:39 schrieb(en) Albrecht Dreß:
I am using this patch here, and could re-post it...
... and it seems 2b limited to one single source file. The gui clearly needs some polish, but would this meets your intentions?
Cheers, Albrecht. --Albrecht Dreß - Johanna-Kirchner-Straße 13 - D-53123 Bonn (Germany)
Phone (+49) 228 6199571 - mailto:albrecht dress arcor de
GnuPG public key: http://www.mynetcologne.de/~nc-dreszal/pubkey.asc
Index: src/sendmsg-window.c
===================================================================
--- src/sendmsg-window.c (Revision 7684)
+++ src/sendmsg-window.c (Arbeitskopie)
@@ -54,6 +54,7 @@
#include "libbalsa.h"
#include "misc.h"
#include "send.h"
+#include "html.h"
#include "balsa-app.h"
#include "balsa-message.h"
@@ -2782,7 +2783,6 @@
g_free(sstr);
}
-
/* create_info_pane
creates upper panel with the message headers: From, To, ... and
returns it.
@@ -3277,6 +3277,291 @@
return subject;
}
+/* --- stuff for collecting parts for a reply --- */
+
+static GList *
+scan_bodies(GList * list, LibBalsaMessageBody * body, gboolean ignore_html,
+ gboolean container_mp_alt)
+{
+ gchar * mime_type;
+
+ while (body) {
+ switch (libbalsa_message_body_type(body)) {
+ case LIBBALSA_MESSAGE_BODY_TYPE_TEXT:
+ {
+ gchar *mime_type;
+ LibBalsaHTMLType html_type;
+
+ mime_type = libbalsa_message_body_get_mime_type(body);
+ html_type = libbalsa_html_type(mime_type);
+ g_free(mime_type);
+
+ /* On a multipart/alternative, ignore_html defines if html or
+ * non-html parts will be added. Eject from the container when
+ * the first part has been found.
+ * Otherwise, select all text parts. */
+ if (container_mp_alt) {
+ if ((ignore_html && html_type == LIBBALSA_HTML_TYPE_NONE) ||
+ (!ignore_html && html_type != LIBBALSA_HTML_TYPE_NONE)) {
+ list = g_list_append(list, body);
+ return list;
+ }
+ } else
+ list = g_list_append(list, body);
+ break;
+ }
+
+ case LIBBALSA_MESSAGE_BODY_TYPE_MULTIPART:
+ case LIBBALSA_MESSAGE_BODY_TYPE_MESSAGE:
+ mime_type = libbalsa_message_body_get_mime_type(body);
+ list = scan_bodies(list, body->parts, ignore_html,
+ !g_ascii_strcasecmp(mime_type, "multipart/alternative"));
+ g_free(mime_type);
+ break;
+
+ default:
+ break;
+ }
+
+ body = body->next;
+ }
+
+ return list;
+}
+
+enum {
+ QUOTE_INCLUDE,
+ QUOTE_MIME_TYPE,
+ QUOTE_DISP_TYPE,
+ QUOTE_FILENAME,
+ QUOTE_BODY,
+ QOUTE_NUM_ELEMS
+};
+
+static void
+list_add_quote_body(LibBalsaMessageBody * body, GtkListStore * store)
+{
+ GtkTreeIter iter;
+ gchar * mime_type = libbalsa_message_body_get_mime_type(body);
+ const gchar * disp_type;
+ static gboolean preselect;
+
+ gtk_list_store_append(store, &iter);
+ if (body->mime_part)
+ disp_type = g_mime_part_get_content_disposition(GMIME_PART(body->mime_part));
+ else
+ disp_type = NULL;
+ preselect = !disp_type || *disp_type == '\0' ||
+ !g_ascii_strcasecmp(disp_type, "inline");
+ gtk_list_store_set(store, &iter,
+ QUOTE_INCLUDE, preselect,
+ QUOTE_MIME_TYPE, mime_type,
+ QUOTE_DISP_TYPE, disp_type,
+ QUOTE_FILENAME, body->filename,
+ QUOTE_BODY, body,
+ -1);
+ g_free(mime_type);
+}
+
+static void
+cell_toggled_cb(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeView *treeview)
+{
+ GtkTreeModel *model = NULL;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean active;
+
+ g_return_if_fail (GTK_IS_TREE_VIEW (treeview));
+ if (!(model = gtk_tree_view_get_model(treeview)))
+ return;
+
+ path = gtk_tree_path_new_from_string(path_str);
+ if (!gtk_tree_model_get_iter(model, &iter, path))
+ return;
+ gtk_tree_path_free(path);
+
+ gtk_tree_model_get(GTK_TREE_MODEL (model),
+ &iter,
+ QUOTE_INCLUDE, &active,
+ -1);
+ gtk_list_store_set(GTK_LIST_STORE (model),
+ &iter,
+ QUOTE_INCLUDE, !active,
+ -1);
+}
+
+static GList *
+quote_parts_select_dlg(GList * body_list, GtkWindow * parent)
+{
+ GtkWidget *dialog;
+ GtkWidget *label;
+ GtkWidget *image;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkListStore *list_store;
+ GtkWidget *list_view;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GList *result = NULL;
+
+ dialog = gtk_dialog_new_with_buttons(_("Select parts for quotation"),
+ parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ label = gtk_label_new(_("Select the parts of the message which shall be quoted in the reply"));
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+
+ image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0);
+
+ /* stolen form gtk/gtkmessagedialog.c */
+ hbox = gtk_hbox_new (FALSE, 12);
+ vbox = gtk_vbox_new (FALSE, 12);
+
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
+ FALSE, 0);
+
+ gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
+ gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 14);
+
+ /* add the table */
+ list_store = gtk_list_store_new(QOUTE_NUM_ELEMS,
+ G_TYPE_BOOLEAN, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER);
+ g_list_foreach(body_list, (GFunc) list_add_quote_body, list_store);
+ list_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
+ renderer = gtk_cell_renderer_toggle_new();
+ g_signal_connect(renderer, "toggled", G_CALLBACK(cell_toggled_cb),
+ list_view);
+ column = gtk_tree_view_column_new_with_attributes(_("Add"),
+ renderer,
+ "active", QUOTE_INCLUDE,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+ column = gtk_tree_view_column_new_with_attributes(_("Type"),
+ gtk_cell_renderer_text_new(),
+ "text", QUOTE_MIME_TYPE,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+ column = gtk_tree_view_column_new_with_attributes(_("Mode"),
+ gtk_cell_renderer_text_new(),
+ "text", QUOTE_DISP_TYPE,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+ column = gtk_tree_view_column_new_with_attributes(_("File name"),
+ gtk_cell_renderer_text_new(),
+ "text", QUOTE_FILENAME,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+
+ /* add, show & run */
+ gtk_box_pack_start(GTK_BOX(vbox), list_view, FALSE, FALSE, 0);
+ gtk_widget_show_all(hbox);
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
+ GtkTreeIter iter;
+
+ /* build & return a new list with the selected parts */
+ gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list_store), &iter);
+ do {
+ gboolean use_in_quote;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(list_store),
+ &iter,
+ QUOTE_INCLUDE,
+ &use_in_quote,
+ -1);
+ if (use_in_quote) {
+ LibBalsaMessageBody *this_body;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(list_store),
+ &iter,
+ QUOTE_BODY,
+ &this_body,
+ -1);
+ result = g_list_append(result, this_body);
+ }
+ } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store), &iter));
+ }
+
+ /* clean up */
+ g_object_unref(G_OBJECT(list_store));
+ gtk_widget_destroy(dialog);
+ return result;
+}
+
+static GString *
+collect_for_quote(LibBalsaMessageBody *root, gchar * reply_prefix_str,
+ gint llen, gboolean ignore_html, gboolean flow,
+ LibBalsaCharsetFunc charset_cb, gpointer charset_cb_data)
+{
+ GList *body_list;
+ LibBalsaMessage *message = root->message;
+ GString *q_body;
+ GList *quote_list;
+
+ libbalsa_message_body_ref(message, FALSE, FALSE);
+
+ /* scan the message and collect text parts which might be included
+ * in the reply, and if there is only one return this part */
+ if (!(body_list = scan_bodies(NULL, root, ignore_html, FALSE))) {
+ libbalsa_message_body_unref(message);
+ return NULL;
+ } else if (body_list->next == NULL) {
+ q_body = process_mime_part(message,
+ (LibBalsaMessageBody *) body_list->data,
+ reply_prefix_str, llen, FALSE, flow,
+ charset_cb, charset_cb_data);
+ g_list_free(body_list);
+ libbalsa_message_body_unref(message);
+ return q_body;
+ }
+
+ /* if there is more than one part ask the user if all should be added */
+ quote_list = quote_parts_select_dlg(body_list, NULL);
+ g_list_free(body_list);
+
+ /* quote selected parts... */
+ q_body = NULL;
+ for (body_list = quote_list; body_list; body_list = g_list_next(body_list)) {
+ LibBalsaMessageBody *this_body = (LibBalsaMessageBody *) body_list->data;
+ GString * this_part;
+
+ this_part = process_mime_part(message, this_body,
+ reply_prefix_str, llen, FALSE, flow,
+ charset_cb, charset_cb_data);
+ if (!q_body)
+ q_body = this_part;
+ else {
+ if (q_body->str[q_body->len - 1] != '\n')
+ g_string_append_c(q_body, '\n');
+ if (this_body->filename)
+ g_string_append_printf(q_body, "\n------%s \"%s\"------\n",
+ _("quoted attachment"), this_body->filename);
+ else
+ g_string_append_printf(q_body, "\n------%s------\n",
+ _("quoted attachment"));
+ g_string_append(q_body, this_part->str);
+ g_string_free(this_part, TRUE);
+ }
+ }
+
+ /* clean up */
+ g_list_free(quote_list);
+ libbalsa_message_body_unref(message);
+ return q_body;
+}
+
+
/* quote_body -----------------------------------------------------------
quotes properly the body of the message.
Use GString to optimize memory usage.
@@ -3369,11 +3654,14 @@
str = g_strdup_printf(_("On %s, %s wrote:\n"), date, personStr);
else
str = g_strdup_printf(_("%s wrote:\n"), personStr);
- body = content2reply(root,
- qtype == QUOTE_ALL ? balsa_app.quote_str : NULL,
- bsmsg->flow ? -1 : balsa_app.wraplength,
- balsa_app.reply_strip_html, bsmsg->flow,
- sw_charset_cb, bsmsg);
+
+ /* scan the message and collect text parts which might be included
+ * in the reply */
+ body = collect_for_quote(root,
+ qtype == QUOTE_ALL ? balsa_app.quote_str : NULL,
+ bsmsg->flow ? -1 : balsa_app.wraplength,
+ balsa_app.reply_strip_html, bsmsg->flow,
+ sw_charset_cb, bsmsg);
if (body) {
gchar *buf;
@@ -5285,7 +5573,7 @@
gtk_box_pack_start (GTK_BOX (dialog_vbox), hbox, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
- image = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG);
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
@@ -5316,7 +5604,7 @@
dialog_action_area = GTK_DIALOG (no_subj_dialog)->action_area;
gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
- cnclbutton = gtk_button_new_from_stock ("gtk-cancel");
+ cnclbutton = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
gtk_dialog_add_action_widget (GTK_DIALOG (no_subj_dialog), cnclbutton, GTK_RESPONSE_CANCEL);
GTK_WIDGET_SET_FLAGS (cnclbutton, GTK_CAN_DEFAULT);
@@ -5332,7 +5620,7 @@
hbox = gtk_hbox_new (FALSE, 2);
gtk_container_add (GTK_CONTAINER (alignment), hbox);
- image = gtk_image_new_from_stock ("balsa_send", GTK_ICON_SIZE_BUTTON);
+ image = gtk_image_new_from_stock (BALSA_PIXMAP_SEND, GTK_ICON_SIZE_BUTTON);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
label = gtk_label_new_with_mnemonic (_("_Send"));
Attachment:
pgpYkieRPcTsH.pgp
Description: PGP signature