/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * mail-display.c: Mail display widget * * Author: * Miguel de Icaza * Bertrand Guiheneuf (bg@aful.org) * * (C) 2000 Helix Code, Inc. */ #include <config.h> #include <gnome.h> #include "e-util/e-util.h" #include "mail-display.h" #include "html-stream.h" #include "camel/camel-formatter.h" /* corba/bonobo stuff */ #include <bonobo.h> #include <libgnorba/gnorba.h> #include <bonobo/bonobo-stream-memory.h> #define PARENT_TYPE (gtk_table_get_type ()) static GtkObjectClass *mail_display_parent_class; static gchar default_header_html_string[] = " <!doctype html public \"-//w3c//dtd html 4.0 transitional//en\"> <html> <head> <meta name=\"GENERATOR\" content=\"Evolution Mail Component (Rhon Rhon release)\"> </head> <body text=\"#000000\" bgcolor=\"#999999\"> <table CELLSPACING=0 WIDTH=\"100\%\"> <tr> <td><b>From: </b></td> <td><b>To: </b></td> </tr> <tr> <td><b>Subject: </b></td> <td><b>Cc: </b></td> </tr> </table> </body> </html> "; static gchar default_body_html_string[] = " <!doctype html public \"-//w3c//dtd html 4.0 transitional//en\"> <html> <head> <meta name=\"GENERATOR\" content=\"Evolution Mail Component (Rhon Rhon release)\"> </head> <body text=\"#000000\" bgcolor=\"#FFFFFF\"> <center> Nothing to display in this view </center> </body> </html> "; /* stuff to display Bonobo Components inside the html message * body view */ static gboolean hydrate_persist_stream_from_gstring (Bonobo_PersistStream persist_stream, GString* gstr) { CORBA_Environment ev; BonoboStream* mem_stream = bonobo_stream_mem_create (gstr->str, gstr->len, TRUE); /* * If the component doesn't support * PersistStream, then we destroy the * stream we created and bail. */ if (persist_stream == CORBA_OBJECT_NIL) { gnome_warning_dialog (_("The component now claims that it " "doesn't support PersistStream!")); bonobo_object_unref (BONOBO_OBJECT (mem_stream)); return FALSE; } CORBA_exception_init (&ev); /* * Load the file into the component using PersistStream. */ Bonobo_PersistStream_load (persist_stream, (Bonobo_Stream) bonobo_object_corba_objref (BONOBO_OBJECT (mem_stream)), &ev); bonobo_object_unref (BONOBO_OBJECT (mem_stream)); if (ev._major != CORBA_NO_EXCEPTION) { gnome_warning_dialog (_("An exception occured while trying " "to load data into the component with " "PersistStream")); CORBA_exception_free (&ev); return FALSE; } CORBA_exception_free (&ev); return TRUE; } static GString* camel_stream_to_gstring (CamelStream* stream) { gchar tmp_buffer[4097]; GString *tmp_gstring = g_string_new (""); do { /* read next chunk of text */ gint nb_bytes_read; nb_bytes_read = camel_stream_read (stream, tmp_buffer, 4096); tmp_buffer [nb_bytes_read] = '\0'; /* If there's any text, append it to the gstring */ if (nb_bytes_read > 0) { tmp_gstring = g_string_append (tmp_gstring, tmp_buffer); } } while (!camel_stream_eos (stream)); return tmp_gstring; } /* * As a page is loaded, when gtkhtml comes across <object> tags, this * callback is invoked. The GtkHTMLEmbedded param is a GtkContainer; * our job in this function is to simply add a child widget to it. */ static void on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, void *unused) { CamelStream *stream; GString *camel_stream_gstr; GtkWidget *bonobo_embeddable; BonoboObjectClient* server; Bonobo_PersistStream persist; CORBA_Environment ev; gchar *uid = gtk_html_embedded_get_parameter (eb, "uid"); printf ("Here\n"); /* Both the classid (which specifies which bonobo object to * fire up) and the uid (which tells us where to find data to * persist from) must be available; if one of them isn't, * print an error and bail. */ if (!uid || !eb->classid) { printf ("on_object_requested: couldn't find %s%s%s\n", uid?"a uid":"", (!uid && !eb->classid)?" or ":"", eb->classid?"a classid":""); return; } printf ("object requested : %s\n", eb->classid); printf ("UID = %s\n", uid); /* Try to get a server with goadid specified by eb->classid */ bonobo_embeddable = bonobo_widget_new_subdoc (eb->classid, NULL); server = bonobo_widget_get_server (BONOBO_WIDGET (bonobo_embeddable)); if (!server) { printf ("Couldn't get the server for the bonobo embeddable\n"); return; } /* The UID should be a pointer to a CamelStream */ if (sscanf (uid, "camel://%p", &stream) != 1) { printf ("Couldn't get a pointer from url \"%s\"\n", uid); gtk_object_unref (GTK_OBJECT (bonobo_embeddable)); return; } /* Try to get a PersistStream interface from the server; if it doesn't support that interface, bail. */ persist = (Bonobo_PersistStream) bonobo_object_client_query_interface ( server, "IDL:Bonobo/PersistStream:1.0", NULL); if (persist == CORBA_OBJECT_NIL) { gchar* msg = g_strdup_printf ( _("The %s component doesn't support PersistStream!\n"), uid); gnome_warning_dialog (msg); gtk_object_unref (GTK_OBJECT (bonobo_embeddable)); return; } /* Hydrate the PersistStream from the CamelStream */ camel_stream_gstr = camel_stream_to_gstring (stream); printf ("on_object_requested: The CamelStream has %d elements\n", camel_stream_gstr->len); hydrate_persist_stream_from_gstring (persist, camel_stream_gstr); /* Give our new window to the container */ gtk_widget_show (bonobo_embeddable); gtk_container_add (GTK_CONTAINER(eb), bonobo_embeddable); /* Destroy the PersistStream object.*/ CORBA_exception_init (&ev); Bonobo_Unknown_unref (persist, &ev); CORBA_Object_release (persist, &ev); CORBA_exception_free (&ev); g_string_free (camel_stream_gstr, FALSE); } void mail_display_set_message (MailDisplay *mail_display, CamelMedium *medium) { CamelFormatter *camel_formatter; /* okay, we should not create a formatter * each time we need to display a message * but I don't know how the formatter reacts * to consecutive call to *_to_html - ber */ camel_formatter = camel_formatter_new (); /* * for the moment, camel-formatter deals only with * mime messages, but in the future, it should be * able to deal with any medium. * It can work on pretty much data wrapper, but in * fact, only the medium class has the distinction * header / body */ if (CAMEL_IS_MIME_MESSAGE (medium)) { /* we were given a reference to the message in the last call * to mail_display_set_message, free it now. */ if (mail_display->current_message) gtk_object_unref (GTK_OBJECT (mail_display->current_message)); mail_display->current_message = CAMEL_MIME_MESSAGE (medium); /* * reset the html stream to clean * the gtkhtml widget */ camel_stream_reset (mail_display->body_stream); camel_stream_reset (mail_display->headers_stream); /* * convert the message into html * and stream the result to the gtkhtml * widgets */ camel_stream_write_string (mail_display->headers_stream, " <!doctype html public \"-//w3c//dtd html 4.0 transitional//en\"> <html> <head> <meta name=\"GENERATOR\" content=\"Evolution Mail Component (Rhon Rhon release)\"> </head> <body text=\"#000000\" bgcolor=\"#999999\"> <font> ");; camel_stream_write_string (mail_display->body_stream, " <!doctype html public \"-//w3c//dtd html 4.0 transitional//en\"> <html> <head> <meta name=\"GENERATOR\" content=\"Evolution Mail Component (Rhon Rhon release)\"> </head> <body text=\"#000000\" bgcolor=\"#FFFFFF\"> ");; camel_formatter_mime_message_to_html (camel_formatter, CAMEL_MIME_MESSAGE (medium), mail_display->headers_stream, mail_display->body_stream); gtk_object_unref (GTK_OBJECT (camel_formatter)); camel_stream_write_string (mail_display->headers_stream, " </font> </body> </html> ");; camel_stream_write_string (mail_display->body_stream, " </body> </html> ");; camel_stream_close (mail_display->body_stream); camel_stream_close (mail_display->headers_stream); } } /* generic class stuff */ static void mail_display_init (GtkObject *object) { MailDisplay *mail_display = MAIL_DISPLAY (object); /* create the headers html widget */ mail_display->headers_html_widget = (GtkHTML *) gtk_html_new (); mail_display->headers_stream = html_stream_new (mail_display->headers_html_widget); gtk_widget_show (GTK_WIDGET (mail_display->headers_html_widget)); /* create the body html widget */ mail_display->body_html_widget = (GtkHTML *) gtk_html_new (); gtk_signal_connect (GTK_OBJECT (mail_display->body_html_widget), "object_requested", GTK_SIGNAL_FUNC (on_object_requested), NULL); mail_display->body_stream = html_stream_new (mail_display->body_html_widget); gtk_widget_show (GTK_WIDGET (mail_display->body_html_widget)); /* various other initializations */ mail_display->current_message = NULL; } static void mail_display_destroy (GtkObject *object) { /* MailDisplay *mail_display = MAIL_DISPLAY (object); */ mail_display_parent_class->destroy (object); } static void mail_display_class_init (GtkObjectClass *object_class) { object_class->destroy = mail_display_destroy; mail_display_parent_class = gtk_type_class (PARENT_TYPE); } GtkWidget * mail_display_new (FolderBrowser *parent_folder_browser) { MailDisplay *mail_display = gtk_type_new (mail_display_get_type ()); GtkTable *table = GTK_TABLE (mail_display); GtkWidget *scroll_wnd; GtkWidget* frame_wnd = NULL; g_assert (parent_folder_browser); mail_display->parent_folder_browser = parent_folder_browser; /* the table has table with 1 column and 2 lines */ table->homogeneous = FALSE; gtk_table_resize (table, 1, 2); gtk_widget_show (GTK_WIDGET (mail_display)); /* create a scrolled window and put the headers * html widget inside */ scroll_wnd = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_wnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); frame_wnd = gtk_frame_new (NULL); gtk_frame_set_shadow_type ( GTK_FRAME (frame_wnd), GTK_SHADOW_OUT); gtk_widget_show (scroll_wnd); gtk_container_add (GTK_CONTAINER (frame_wnd), scroll_wnd); gtk_widget_show (frame_wnd); gtk_container_add (GTK_CONTAINER (scroll_wnd), GTK_WIDGET (mail_display->headers_html_widget)); gtk_widget_set_usize (GTK_WIDGET (scroll_wnd), -1, 50); /* add it on the top part of the table */ gtk_table_attach (table, GTK_WIDGET (frame_wnd), 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); /* create a scrolled window and put the body * html widget inside */ scroll_wnd = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_wnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_widget_show (scroll_wnd); gtk_container_add (GTK_CONTAINER (scroll_wnd), GTK_WIDGET (mail_display->body_html_widget)); /* add it at the bottom part of the table */ gtk_table_attach (table, GTK_WIDGET (scroll_wnd), 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); /* write the default text to the html widgets */ camel_stream_write_string (mail_display->headers_stream, default_header_html_string); camel_stream_write_string (mail_display->body_stream, default_body_html_string); return GTK_WIDGET (mail_display); } E_MAKE_TYPE (mail_display, "MailDisplay", MailDisplay, mail_display_class_init, mail_display_init, PARENT_TYPE);