aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog15
-rw-r--r--mail/folder-browser-factory.c43
-rw-r--r--mail/mail-format.c251
-rw-r--r--mail/mail-format.h10
-rw-r--r--mail/mail-ops.c61
-rw-r--r--mail/mail-ops.h4
6 files changed, 328 insertions, 56 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index b7afba2070..64ca3a6b9d 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,18 @@
+2000-04-22 Dan Winship <danw@helixcode.com>
+
+ * folder-browser-factory.c: move msg_composer_cb and
+ msg_composer_send_cb to mail-ops. Attach send, reply, and "reply
+ to all" buttons.
+
+ * mail-ops.c (composer_send_cb, send): moved from
+ folder-browser-factory.c.
+ (reply_to_sender, reply_to_all): new functions to do replies.
+
+ * mail-format.c (text_to_html): Add an "add_pre" flag, to make
+ it wrap the output in <pre></pre>.
+ (mail_generate_reply): New function to create a composer and build
+ a reply in it.
+
2000-04-21 Dan Winship <danw@helixcode.com>
* mail-display.c (on_url_requested): deal with cid: URLs.
diff --git a/mail/folder-browser-factory.c b/mail/folder-browser-factory.c
index db828514c7..e86fddd9e9 100644
--- a/mail/folder-browser-factory.c
+++ b/mail/folder-browser-factory.c
@@ -100,41 +100,6 @@ development_warning ()
}
static void
-msg_composer_send_cb (EMsgComposer *composer,
- gpointer data)
-{
- CamelMimeMessage *message;
- CamelStream *stream;
- gint stdout_dup;
-
- message = e_msg_composer_get_message (composer);
-
- stdout_dup = dup (1);
- stream = camel_stream_fs_new_with_fd (stdout_dup);
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message),
- stream);
- camel_stream_close (stream);
-
- gtk_object_unref (GTK_OBJECT (message));
-
-#if 0
- gtk_widget_destroy (GTK_WIDGET (composer));
- gtk_main_quit ();
-#endif
-}
-
-
-static void
-msg_composer_cb (BonoboUIHandler *uih, void *user_data, const char *path)
-{
- GtkWidget *composer;
-
- composer = e_msg_composer_new ();
- gtk_signal_connect (GTK_OBJECT (composer), "send", GTK_SIGNAL_FUNC (msg_composer_send_cb), NULL);
- gtk_widget_show (composer);
-}
-
-static void
random_cb (GtkWidget *button, gpointer user_data)
{
printf ("Yow! I am called back!\n");
@@ -142,13 +107,13 @@ random_cb (GtkWidget *button, gpointer user_data)
static GnomeUIInfo gnome_toolbar [] = {
GNOMEUIINFO_ITEM_STOCK (N_("New mail"), N_("Check for new mail"), fetch_mail, GNOME_STOCK_PIXMAP_MAIL_RCV),
- GNOMEUIINFO_ITEM_STOCK (N_("Send"), N_("Send a new message"), random_cb, GNOME_STOCK_PIXMAP_MAIL_SND),
+ GNOMEUIINFO_ITEM_STOCK (N_("Send"), N_("Send a new message"), send, GNOME_STOCK_PIXMAP_MAIL_SND),
GNOMEUIINFO_ITEM_STOCK (N_("Find"), N_("Find messages"), random_cb, GNOME_STOCK_PIXMAP_SEARCH),
GNOMEUIINFO_SEPARATOR,
- GNOMEUIINFO_ITEM_STOCK (N_("Reply"), N_("Reply to the sender of this message"), random_cb, GNOME_STOCK_PIXMAP_SEARCH),
- GNOMEUIINFO_ITEM_STOCK (N_("Reply to All"), N_("Reply to all recipients of this message"), random_cb, GNOME_STOCK_PIXMAP_MAIL_RPL),
+ GNOMEUIINFO_ITEM_STOCK (N_("Reply"), N_("Reply to the sender of this message"), reply_to_sender, GNOME_STOCK_PIXMAP_MAIL_RPL),
+ GNOMEUIINFO_ITEM_STOCK (N_("Reply to All"), N_("Reply to all recipients of this message"), reply_to_all, GNOME_STOCK_PIXMAP_MAIL_RPL),
GNOMEUIINFO_ITEM_STOCK (N_("Forward"), N_("Forward this message"), random_cb, GNOME_STOCK_PIXMAP_MAIL_FWD),
@@ -174,7 +139,7 @@ control_activate (BonoboControl *control, BonoboUIHandler *uih)
bonobo_ui_handler_menu_new_item (uih, "/File/Mail", N_("_Mail"),
NULL, -1,
BONOBO_UI_HANDLER_PIXMAP_NONE, NULL,
- 0, 0, msg_composer_cb, NULL);
+ 0, 0, send, NULL);
folder_browser = bonobo_control_get_widget (control);
diff --git a/mail/mail-format.c b/mail/mail-format.c
index 328f2af638..5fdf3b2d79 100644
--- a/mail/mail-format.c
+++ b/mail/mail-format.c
@@ -30,12 +30,6 @@
#include <ctype.h> /* for isprint */
#include <string.h> /* for strstr */
-/* We shouldn't be doing this, but I don't feel like fixing it right
- * now. (It's for gtk_html_stream_write.) When gtkhtml has nicer
- * interfaces, we can fix it.
- */
-#include <gtkhtml/gtkhtml-private.h>
-
static void handle_text_plain (CamelDataWrapper *wrapper,
GtkHTMLStreamHandle *stream,
CamelDataWrapper *root);
@@ -69,6 +63,7 @@ static void handle_unknown_type (CamelDataWrapper *wrapper,
static gchar *text_to_html (const guchar *input,
guint len,
guint *encoded_len_return,
+ gboolean add_pre,
gboolean convert_newlines_to_br);
/* writes the header info for a mime message into an html stream */
@@ -325,21 +320,21 @@ call_handler_function (CamelDataWrapper *wrapper,
/* Convert plain text in equivalent-looking valid HTML. */
static gchar *
text_to_html (const guchar *input, guint len,
- guint *encoded_len_return,
+ guint *encoded_len_return, gboolean add_pre,
gboolean convert_newlines_to_br)
{
const guchar *cur = input;
guchar *buffer = NULL;
guchar *out = NULL;
gint buffer_size = 0;
- guint count;
/* Allocate a translation buffer. */
- buffer_size = len * 2;
+ buffer_size = len * 2 + 5;
buffer = g_malloc (buffer_size);
out = buffer;
- count = 0;
+ if (add_pre)
+ out += sprintf (out, "<PRE>\n");
while (len--) {
if (out - buffer > buffer_size - 100) {
@@ -392,7 +387,10 @@ text_to_html (const guchar *input, guint len,
cur++;
}
- *out = '\0';
+ if (add_pre)
+ strcpy (out, "</PRE>");
+ else
+ *out = '\0';
if (encoded_len_return)
*encoded_len_return = out - buffer;
@@ -411,7 +409,7 @@ write_field_to_stream (const gchar *description, const gchar *value,
unsigned char *p;
encoded_value = text_to_html (value, strlen(value),
- NULL, TRUE);
+ NULL, FALSE, TRUE);
for (p = (unsigned char *)encoded_value; *p; p++) {
if (!isprint (*p))
*p = '?';
@@ -543,7 +541,7 @@ handle_text_plain (CamelDataWrapper *wrapper, GtkHTMLStreamHandle *stream,
text = text_to_html (tmp_buffer,
nb_bytes_read,
&returned_strlen,
- FALSE);
+ FALSE, FALSE);
mail_write_html (stream, text);
g_free (text);
}
@@ -835,3 +833,230 @@ mail_write_html (GtkHTMLStreamHandle *stream, const char *data)
{
gtk_html_stream_write (stream, data, strlen (data));
}
+
+static char *
+get_data_wrapper_text (CamelDataWrapper *data)
+{
+ CamelStream *memstream;
+ GByteArray *ba;
+ char *text;
+
+ ba = g_byte_array_new ();
+ memstream = camel_stream_mem_new_with_byte_array (ba, CAMEL_STREAM_MEM_WRITE);
+
+ camel_data_wrapper_write_to_stream (data, memstream);
+ text = g_malloc (ba->len + 1);
+ memcpy (text, ba->data, ba->len);
+ text[ba->len] = '\0';
+
+ camel_stream_close (memstream);
+ return text;
+}
+
+static char *
+reply_body (CamelDataWrapper *data, gboolean *html)
+{
+ CamelMultipart *mp;
+ CamelMimePart *subpart;
+ int i, nparts;
+ char *subtext, *old;
+ const char *boundary, *disp;
+ char *text = NULL;
+ GMimeContentField *mime_type;
+
+ /* We only include text, message, and multipart bodies. */
+ mime_type = camel_data_wrapper_get_mime_type_field (data);
+
+ if (strcasecmp (mime_type->type, "message") == 0)
+ return get_data_wrapper_text (data);
+
+ if (strcasecmp (mime_type->type, "text") == 0) {
+ *html = !strcasecmp (mime_type->subtype, "html");
+ return get_data_wrapper_text (data);
+ }
+
+ /* If it's not message and it's not text, and it's not
+ * multipart, we don't want to deal with it.
+ */
+ if (strcasecmp (mime_type->type, "multipart") != 0)
+ return NULL;
+
+ mp = CAMEL_MULTIPART (data);
+
+ if (strcasecmp (mime_type->subtype, "alternative") == 0) {
+ /* Pick our favorite alternative and reply to it. */
+
+ subpart = find_preferred_alternative (mp);
+ if (!subpart)
+ return NULL;
+
+ return reply_body (camel_medium_get_content_object (CAMEL_MEDIUM (subpart)), html);
+ }
+
+ nparts = camel_multipart_get_number (mp);
+
+ /* If any subpart is HTML, pull it out and reply to it by itself.
+ * (If we supported any other non-plain text types, we'd do the
+ * same for them here.)
+ */
+ for (i = 0; i < nparts; i++) {
+ subpart = CAMEL_MIME_PART (camel_multipart_get_part (mp, i));
+
+ if (strcasecmp (MIME_TYPE_SUB (subpart), "html") == 0)
+ return reply_body (camel_medium_get_content_object (CAMEL_MEDIUM (subpart)), html);
+ }
+
+ /* Otherwise, concatenate all the parts that:
+ * - are text/plain or message
+ * - are not explicitly tagged with non-inline disposition
+ */
+ boundary = camel_multipart_get_boundary (mp);
+ for (i = 0; i < nparts; i++) {
+ subpart = CAMEL_MIME_PART (camel_multipart_get_part (mp, i));
+
+ disp = camel_mime_part_get_disposition (subpart);
+ if (disp && strcasecmp (disp, "inline") != 0)
+ continue;
+
+ subtext = get_data_wrapper_text (data);
+ if (text) {
+ old = text;
+ text = g_strdup_printf ("%s\n--%s\n%s", text,
+ boundary, subtext);
+ g_free (subtext);
+ g_free (old);
+ } else
+ text = subtext;
+ }
+
+ if (!text)
+ return NULL;
+
+ old = text;
+ text = g_strdup_printf ("%s\n--%s--\n", text, boundary);
+ g_free (old);
+
+ return text;
+}
+
+EMsgComposer *
+mail_generate_reply (CamelMimeMessage *message, gboolean to_all)
+{
+ CamelDataWrapper *contents;
+ char *text, *subject;
+ EMsgComposer *composer;
+ gboolean html;
+ const char *repl_to, *message_id, *references;
+ GList *to, *cc;
+
+ contents = camel_medium_get_content_object (CAMEL_MEDIUM (message));
+ text = reply_body (contents, &html);
+
+ composer = E_MSG_COMPOSER (e_msg_composer_new ());
+
+ /* Set the quoted reply text. */
+ if (text) {
+ char *repl_text;
+
+ if (html) {
+ repl_text = g_strdup_printf ("<blockquote><i>\n%s\n"
+ "</i></blockquote>\n",
+ text);
+ } else {
+ char *s, *d, *quoted_text;
+ int lines, len;
+
+ /* Count the number of lines in the body. If
+ * the text ends with a \n, this will be one
+ * too high, but that's ok. Allocate enough
+ * space for the text and the "> "s.
+ */
+ for (s = text, lines = 0; s; s = strchr (s + 1, '\n'))
+ lines++;
+ quoted_text = g_malloc (strlen (text) + lines * 2);
+
+ s = text;
+ d = quoted_text;
+
+ /* Copy text to quoted_text line by line,
+ * prepending "> ".
+ */
+ while (1) {
+ len = strcspn (s, "\n");
+ if (len == 0 && !*s)
+ break;
+ sprintf (d, "> %.*s\n", len, s);
+ s += len;
+ if (!*s++)
+ break;
+ d += len + 3;
+ }
+
+ /* Now convert that to HTML. */
+ repl_text = text_to_html (quoted_text,
+ strlen (quoted_text),
+ &len, TRUE, FALSE);
+ g_free (quoted_text);
+ }
+ e_msg_composer_set_body_text (composer, repl_text);
+ g_free (repl_text);
+ g_free (text);
+ }
+
+ /* Set the recipients */
+ repl_to = camel_mime_message_get_reply_to (message);
+ if (!repl_to)
+ repl_to = camel_mime_message_get_from (message);
+ to = g_list_append (NULL, repl_to);
+
+ if (to_all) {
+ const GList *recip;
+
+ recip = camel_mime_message_get_recipients (message,
+ CAMEL_RECIPIENT_TYPE_TO);
+ cc = g_list_copy (recip);
+
+ recip = camel_mime_message_get_recipients (message,
+ CAMEL_RECIPIENT_TYPE_CC);
+ while (recip) {
+ cc = g_list_append (cc, recip->data);
+ recip = recip->next;
+ }
+ } else
+ cc = NULL;
+
+ /* Set the subject of the new message. */
+ subject = camel_mime_message_get_subject (message);
+ if (!subject)
+ subject = g_strdup ("");
+ else if (!strncasecmp (subject, "Re: ", 4))
+ subject = g_strdup (subject);
+ else
+ subject = g_strdup_printf ("Re: %s", subject);
+
+ e_msg_composer_set_headers (composer, to, cc, NULL, subject);
+ g_list_free (to);
+ g_list_free (cc);
+ g_free (subject);
+
+ /* Add In-Reply-To and References. */
+ message_id = camel_medium_get_header (CAMEL_MEDIUM (message),
+ "Message-Id");
+ references = camel_medium_get_header (CAMEL_MEDIUM (message),
+ "References");
+ if (message_id) {
+ e_msg_composer_add_header (composer, "In-Reply-To",
+ message_id);
+ if (references) {
+ char *reply_refs;
+ reply_refs = g_strdup_printf ("%s %s", references,
+ message_id);
+ e_msg_composer_add_header (composer, "References",
+ reply_refs);
+ g_free (reply_refs);
+ }
+ } else if (references)
+ e_msg_composer_add_header (composer, "References", references);
+
+ return composer;
+}
diff --git a/mail/mail-format.h b/mail/mail-format.h
index 87c16a2049..22c5f9deb2 100644
--- a/mail/mail-format.h
+++ b/mail/mail-format.h
@@ -32,6 +32,7 @@ extern "C" {
#include <gtkhtml/gtkhtml.h>
#include "camel/camel.h"
+#include "composer/e-msg-composer.h"
void mail_format_mime_message (CamelMimeMessage *mime_message,
GtkHTMLStreamHandle *header_stream,
@@ -39,11 +40,12 @@ void mail_format_mime_message (CamelMimeMessage *mime_message,
void mail_write_html (GtkHTMLStreamHandle *stream, const char *data);
-CamelMimeMessage *mail_generate_reply (CamelMimeMessage *mime_message);
+EMsgComposer *mail_generate_reply (CamelMimeMessage *mime_message,
+ gboolean to_all);
-CamelMimeMessage *mail_generate_forward (CamelMimeMessage *mime_message,
- gboolean forward_as_attachment,
- gboolean keep_attachments);
+EMsgComposer *mail_generate_forward (CamelMimeMessage *mime_message,
+ gboolean forward_as_attachment,
+ gboolean keep_attachments);
#ifdef __cplusplus
}
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 9a076c5856..9653b50fc6 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -31,6 +31,7 @@
#include "folder-browser.h"
#include "session.h"
#include "e-util/e-setup.h"
+#include "composer/e-msg-composer.h"
#ifndef HAVE_MKSTEMP
#include <fcntl.h>
@@ -250,3 +251,63 @@ fetch_mail (GtkWidget *button, gpointer user_data)
if (msg)
gtk_object_unref (GTK_OBJECT (msg));
}
+
+
+static void
+composer_send_cb (EMsgComposer *composer, gpointer data)
+{
+ CamelMimeMessage *message;
+ CamelStream *stream;
+ int stdout_dup;
+
+ message = e_msg_composer_get_message (composer);
+
+ stdout_dup = dup (1);
+ stream = camel_stream_fs_new_with_fd (stdout_dup);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message),
+ stream);
+ camel_stream_close (stream);
+
+ gtk_object_unref (GTK_OBJECT (message));
+ gtk_object_destroy (GTK_OBJECT (composer));
+}
+
+
+void
+send (GtkWidget *widget, gpointer user_data)
+{
+ GtkWidget *composer;
+
+ composer = e_msg_composer_new ();
+
+ gtk_signal_connect (GTK_OBJECT (composer), "send",
+ GTK_SIGNAL_FUNC (composer_send_cb), NULL);
+ gtk_widget_show (composer);
+}
+
+
+static void
+reply (FolderBrowser *fb, gboolean to_all)
+{
+ EMsgComposer *composer;
+
+ composer = mail_generate_reply (fb->mail_display->current_message,
+ to_all);
+
+ gtk_signal_connect (GTK_OBJECT (composer), "send",
+ GTK_SIGNAL_FUNC (composer_send_cb), NULL);
+
+ gtk_widget_show (GTK_WIDGET (composer));
+}
+
+void
+reply_to_sender (GtkWidget *button, gpointer user_data)
+{
+ reply (FOLDER_BROWSER (user_data), FALSE);
+}
+
+void
+reply_to_all (GtkWidget *button, gpointer user_data)
+{
+ reply (FOLDER_BROWSER (user_data), TRUE);
+}
diff --git a/mail/mail-ops.h b/mail/mail-ops.h
index ed85f4d5a0..f7f3d3e0c7 100644
--- a/mail/mail-ops.h
+++ b/mail/mail-ops.h
@@ -1 +1,5 @@
void fetch_mail (GtkWidget *button, gpointer user_data);
+void send (GtkWidget *button, gpointer user_data);
+void forward_msg (GtkWidget *button, gpointer user_data);
+void reply_to_sender (GtkWidget *button, gpointer user_data);
+void reply_to_all (GtkWidget *button, gpointer user_data);