[evolution] WebKit port - port plugins



commit d97c776f24ce577dc4a24c9be2d3830faa7627e8
Author: Dan VrÃtil <dvratil redhat com>
Date:   Wed Mar 28 18:39:26 2012 +0200

    WebKit port - port plugins

 plugins/audio-inline/Makefile.am          |    7 +-
 plugins/audio-inline/audio-inline.c       |   97 +-
 plugins/dbx-import/Makefile.am            |    6 +-
 plugins/external-editor/external-editor.c |    2 +-
 plugins/itip-formatter/Makefile.am        |    7 +-
 plugins/itip-formatter/itip-formatter.c   |  975 +++++++------
 plugins/itip-formatter/itip-view.c        | 2381 ++++++++++++++++++-----------
 plugins/itip-formatter/itip-view.h        |  280 +++--
 plugins/mail-to-task/Makefile.am          |    6 +-
 plugins/mail-to-task/mail-to-task.c       |   11 +-
 plugins/mark-all-read/Makefile.am         |    6 +-
 plugins/prefer-plain/prefer-plain.c       |   94 +-
 plugins/pst-import/Makefile.am            |    2 -
 plugins/tnef-attachments/Makefile.am      |    2 -
 plugins/tnef-attachments/tnef-plugin.c    |   61 +-
 plugins/vcard-inline/Makefile.am          |    7 +-
 plugins/vcard-inline/vcard-inline.c       |  373 +++--
 17 files changed, 2582 insertions(+), 1735 deletions(-)
---
diff --git a/plugins/audio-inline/Makefile.am b/plugins/audio-inline/Makefile.am
index d5dc1a5..7afdcee 100644
--- a/plugins/audio-inline/Makefile.am
+++ b/plugins/audio-inline/Makefile.am
@@ -17,8 +17,7 @@ liborg_gnome_audio_inline_la_CPPFLAGS =			\
 	-I$(top_srcdir)/widgets				\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
 	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GSTREAMER_CFLAGS)				\
-	$(GTKHTML_CFLAGS)
+	$(GSTREAMER_CFLAGS)
 
 liborg_gnome_audio_inline_la_SOURCES = audio-inline.c
 
@@ -27,10 +26,10 @@ liborg_gnome_audio_inline_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
 liborg_gnome_audio_inline_la_LIBADD =			\
 	$(top_builddir)/mail/libevolution-mail.la	\
 	$(top_builddir)/e-util/libeutil.la		\
+	$(top_builddir)/em-format/libemformat.la	\
 	$(EVOLUTION_DATA_SERVER_LIBS)			\
 	$(GNOME_PLATFORM_LIBS)				\
-	$(GSTREAMER_LIBS)				\
-	$(GTKHTML_LIBS)
+	$(GSTREAMER_LIBS)
 
 EXTRA_DIST = org-gnome-audio-inline.eplug.xml
 
diff --git a/plugins/audio-inline/audio-inline.c b/plugins/audio-inline/audio-inline.c
index a5e7ccd..45238db 100644
--- a/plugins/audio-inline/audio-inline.c
+++ b/plugins/audio-inline/audio-inline.c
@@ -29,7 +29,6 @@
 #include "e-util/e-mktemp.h"
 #include "mail/em-format-hook.h"
 #include "mail/em-format-html.h"
-#include "gtkhtml/gtkhtml-embedded.h"
 #include "gst/gst.h"
 
 #define d(x)
@@ -45,12 +44,11 @@ e_plugin_lib_enable (EPlugin *ep,
 
 void org_gnome_audio_inline_format (gpointer ep, EMFormatHookTarget *t);
 
-static volatile gint org_gnome_audio_class_id_counter = 0;
+typedef struct _EMFormatInlineAudioPURI EMFormatInlineAudioPURI;
 
-struct _org_gnome_audio_inline_pobject {
-	EMFormatHTMLPObject object;
+struct _EMFormatInlineAudioPURI {
+	EMFormatPURI puri;
 
-	CamelMimePart *part;
 	gchar *filename;
 	GstElement *playbin;
 	gulong      bus_id;
@@ -61,9 +59,9 @@ struct _org_gnome_audio_inline_pobject {
 };
 
 static void
-org_gnome_audio_inline_pobject_free (EMFormatHTMLPObject *o)
+org_gnome_audio_inline_pobject_free (EMFormatPURI *o)
 {
-	struct _org_gnome_audio_inline_pobject *po = (struct _org_gnome_audio_inline_pobject *) o;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) o;
 
 	d(printf ("audio inline formatter: pobject free\n"));
 
@@ -82,10 +80,6 @@ org_gnome_audio_inline_pobject_free (EMFormatHTMLPObject *o)
 		po->stop_button = NULL;
 	}
 
-	if (po->part) {
-		g_object_unref (po->part);
-		po->part = NULL;
-	}
 	if (po->filename) {
 		g_unlink (po->filename);
 		g_free (po->filename);
@@ -106,9 +100,9 @@ org_gnome_audio_inline_pobject_free (EMFormatHTMLPObject *o)
 
 static void
 org_gnome_audio_inline_pause_clicked (GtkWidget *button,
-                                      EMFormatHTMLPObject *pobject)
+                                                                          EMFormatPURI *puri)
 {
-	struct _org_gnome_audio_inline_pobject *po = (struct _org_gnome_audio_inline_pobject *) pobject;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
 
 	if (po->playbin) {
 		/* pause playing */
@@ -118,9 +112,9 @@ org_gnome_audio_inline_pause_clicked (GtkWidget *button,
 
 static void
 org_gnome_audio_inline_stop_clicked (GtkWidget *button,
-                                     EMFormatHTMLPObject *pobject)
+                                                                         EMFormatPURI *puri)
 {
-	struct _org_gnome_audio_inline_pobject *po = (struct _org_gnome_audio_inline_pobject *) pobject;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
 
 	if (po->playbin) {
 		/* ready to play */
@@ -150,7 +144,7 @@ org_gnome_audio_inline_gst_callback (GstBus *bus,
                                      GstMessage *message,
                                      gpointer data)
 {
-	struct _org_gnome_audio_inline_pobject *po = (struct _org_gnome_audio_inline_pobject *) data;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) data;
 	GstMessageType msg_type;
 
 	g_return_val_if_fail (po != NULL, TRUE);
@@ -195,9 +189,9 @@ org_gnome_audio_inline_gst_callback (GstBus *bus,
 
 static void
 org_gnome_audio_inline_play_clicked (GtkWidget *button,
-                                     EMFormatHTMLPObject *pobject)
+                                                                         EMFormatPURI *puri)
 {
-	struct _org_gnome_audio_inline_pobject *po = (struct _org_gnome_audio_inline_pobject *) pobject;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
 	GstState cur_state;
 
 	d(printf ("audio inline formatter: play\n"));
@@ -215,7 +209,7 @@ org_gnome_audio_inline_play_clicked (GtkWidget *button,
 		d(printf ("audio inline formatter: write to temp file %s\n", po->filename));
 
 		stream = camel_stream_fs_new_with_name (po->filename, O_RDWR | O_CREAT | O_TRUNC, 0600, NULL);
-		data = camel_medium_get_content (CAMEL_MEDIUM (po->part));
+		data = camel_medium_get_content (CAMEL_MEDIUM (po->puri.part));
 		camel_data_wrapper_decode_to_stream_sync (
 			data, stream, NULL, NULL);
 		camel_stream_flush (stream, NULL, NULL);
@@ -281,13 +275,31 @@ org_gnome_audio_inline_add_button (GtkWidget *box,
 	return button;
 }
 
-static gboolean
-org_gnome_audio_inline_button_panel (EMFormatHTML *efh,
-                                     GtkHTMLEmbedded *eb,
-                                     EMFormatHTMLPObject *pobject)
+static void
+write_button_panel (EMFormat *emf,
+                    EMFormatPURI *puri,
+                    CamelStream *stream,
+                    EMFormatWriterInfo *info,
+                    GCancellable *cancellable)
+{
+	gchar *str;
+
+	str = g_strdup_printf (
+		"<object type=\"application/x-org-gnome-audio-inline-button-panel\" "
+			"width=\"100%%\" height=\"auto\" data=\"%s\" id=\"%s\"></object>",
+		puri->uri, puri->uri);
+	camel_stream_write_string (stream, str, cancellable, NULL);
+
+	g_free (str);
+}
+
+static GtkWidget *
+org_gnome_audio_inline_button_panel (EMFormat *emf,
+                                     EMFormatPURI *puri,
+                                     GCancellable *cancellable)
 {
 	GtkWidget *box;
-	struct _org_gnome_audio_inline_pobject *po = (struct _org_gnome_audio_inline_pobject *) pobject;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
 
 	/* it is OK to call UI functions here, since we are called from UI thread */
 
@@ -297,42 +309,39 @@ org_gnome_audio_inline_button_panel (EMFormatHTML *efh,
 	po->stop_button = g_object_ref (org_gnome_audio_inline_add_button (box, GTK_STOCK_MEDIA_STOP, G_CALLBACK (org_gnome_audio_inline_stop_clicked), po, FALSE));
 
 	gtk_widget_show (box);
-	gtk_container_add ((GtkContainer *) eb, box);
 
-	return TRUE;
+	return box;
 }
 
 void
 org_gnome_audio_inline_format (gpointer ep,
                                EMFormatHookTarget *t)
 {
-	struct _org_gnome_audio_inline_pobject *pobj;
-	gchar *classid;
-	gchar *content;
-
-	classid = g_strdup_printf (
-		"org-gnome-audio-inline-button-panel-%d",
-		org_gnome_audio_class_id_counter);
+	EMFormatInlineAudioPURI *pobj;
+	gint len;
 
-	org_gnome_audio_class_id_counter++;
+	len = t->part_id->len;
+	g_string_append (t->part_id, ".org-gnome-audio-inline-button-panel");
 
-	d(printf ("audio inline formatter: format classid %s\n", classid));
+	d(printf ("audio inline formatter: format classid %s\n", t->part_id->str));
 
-	pobj = (struct _org_gnome_audio_inline_pobject *)
-		em_format_html_add_pobject (
-			(EMFormatHTML *) t->format, sizeof (*pobj), classid,
-			t->part, org_gnome_audio_inline_button_panel);
-	pobj->part = g_object_ref (t->part);
+	pobj = (EMFormatInlineAudioPURI *) em_format_puri_new (
+			t->format, sizeof (EMFormatInlineAudioPURI),
+			t->part, t->part_id->str);
+	pobj->puri.widget_func = org_gnome_audio_inline_button_panel;
+	pobj->puri.write_func = write_button_panel;
+	pobj->puri.part = g_object_ref (t->part);
+	pobj->puri.is_attachment = TRUE;
 	pobj->filename = NULL;
 	pobj->playbin = NULL;
 	pobj->play_button = NULL;
 	pobj->stop_button = NULL;
 	pobj->pause_button = NULL;
 	pobj->bus_id = 0;
-	pobj->object.free = org_gnome_audio_inline_pobject_free;
+	pobj->puri.free = org_gnome_audio_inline_pobject_free;
 	pobj->target_state = GST_STATE_NULL;
 
-	content = g_strdup_printf ("<object classid=%s></object>\n", classid);
-	camel_stream_write_string (t->stream, content, NULL, NULL);
-	g_free (content);
+	em_format_add_puri (t->format, (EMFormatPURI *) pobj);
+
+	g_string_truncate (t->part_id, len);
 }
diff --git a/plugins/dbx-import/Makefile.am b/plugins/dbx-import/Makefile.am
index eeaf69f..5bead7d 100644
--- a/plugins/dbx-import/Makefile.am
+++ b/plugins/dbx-import/Makefile.am
@@ -16,8 +16,7 @@ liborg_gnome_dbx_import_la_CPPFLAGS =			\
 	-I$(top_srcdir)/widgets				\
 	-I$(top_builddir)				\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
-	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GTKHTML_CFLAGS)
+	$(GNOME_PLATFORM_CFLAGS)
 
 liborg_gnome_dbx_import_la_SOURCES = dbx-importer.c
 
@@ -30,8 +29,7 @@ liborg_gnome_dbx_import_la_LIBADD =			\
 	$(top_builddir)/libemail-engine/libemail-engine.la \
 	$(top_builddir)/libemail-utils/libemail-utils.la  \
 	$(EVOLUTION_DATA_SERVER_LIBS)			\
-	$(GNOME_PLATFORM_LIBS)				\
-	$(GTKHTML_LIBS)
+	$(GNOME_PLATFORM_LIBS)
 
 EXTRA_DIST = org-gnome-dbx-import.eplug.xml
 
diff --git a/plugins/external-editor/external-editor.c b/plugins/external-editor/external-editor.c
index 6b787b9..6b0d375 100644
--- a/plugins/external-editor/external-editor.c
+++ b/plugins/external-editor/external-editor.c
@@ -469,7 +469,7 @@ e_plugin_ui_init (GtkUIManager *manager,
                   EMsgComposer *composer)
 {
 	GtkhtmlEditor *editor;
-	EWebView *web_view;
+	EWebViewGtkHTML *web_view;
 
 	editor = GTKHTML_EDITOR (composer);
 
diff --git a/plugins/itip-formatter/Makefile.am b/plugins/itip-formatter/Makefile.am
index 381f99e..e0672eb 100644
--- a/plugins/itip-formatter/Makefile.am
+++ b/plugins/itip-formatter/Makefile.am
@@ -7,9 +7,9 @@ liborg_gnome_itip_formatter_la_CPPFLAGS =		\
 	$(AM_CPPFLAGS)					\
 	-I$(top_srcdir)					\
 	-I$(top_srcdir)/widgets				\
+	-DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\"	\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
-	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GTKHTML_CFLAGS)
+	$(GNOME_PLATFORM_CFLAGS)
 
 liborg_gnome_itip_formatter_la_SOURCES = itip-formatter.c itip-view.c itip-view.h
 
@@ -26,8 +26,7 @@ liborg_gnome_itip_formatter_la_LIBADD =				\
 	$(top_builddir)/libemail-engine/libemail-engine.la	\
 	$(top_builddir)/libevolution-utils/libevolution-utils.la \
 	$(EVOLUTION_DATA_SERVER_LIBS)				\
-	$(GNOME_PLATFORM_LIBS)					\
-	$(GTKHTML_LIBS)
+	$(GNOME_PLATFORM_LIBS)
 
 error_DATA = org-gnome-itip-formatter.error
 errordir = $(privdatadir)/errors
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 0b0acd4..b40a508 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -33,7 +33,6 @@
 #include <libedataserver/e-account-list.h>
 #include <libedataserverui/e-source-selector.h>
 #include <libedataserverui/e-client-utils.h>
-#include <gtkhtml/gtkhtml-embedded.h>
 
 #include <libevolution-utils/e-alert-dialog.h>
 #include <e-util/e-mktemp.h>
@@ -58,12 +57,11 @@
 
 #include "itip-view.h"
 
-#define CLASSID "itip://"
 #define CONF_KEY_DELETE "delete-processed"
 
 #define d(x)
 
-struct _itip_puri {
+struct _ItipPURI {
 	EMFormatPURI puri;
 
 	const EMFormatHandler *handle;
@@ -72,7 +70,6 @@ struct _itip_puri {
 	CamelMimePart *part;
 
 	gchar *uid;
-	GtkWidget *view;
 
 	ESourceList *source_lists[E_CAL_CLIENT_SOURCE_TYPE_LAST];
 	GHashTable *clients[E_CAL_CLIENT_SOURCE_TYPE_LAST];
@@ -146,13 +143,15 @@ struct _itip_puri {
 	GHashTable *real_comps; /* ESource's UID -> ECalComponent stored on the server */
 };
 
+typedef struct _ItipPURI ItipPURI;
+
 void format_itip (EPlugin *ep, EMFormatHookTarget *target);
 GtkWidget *itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data);
-static void itip_attachment_frame (EMFormat *emf, CamelStream *stream, EMFormatPURI *puri, GCancellable *cancellable);
 gint e_plugin_lib_enable (EPlugin *ep, gint enable);
 
 typedef struct {
-	struct _itip_puri *puri;
+	ItipPURI *puri;
+        ItipView *view;
 	GCancellable *cancellable;
 	gboolean keep_alarm_check;
 	GHashTable *conflicts;
@@ -246,7 +245,7 @@ find_attendee_if_sentby (icalcomponent *ical_comp,
 }
 
 static void
-find_to_address (struct _itip_puri *pitip,
+find_to_address (ItipPURI *pitip,
                  icalcomponent *ical_comp,
                  icalparameter_partstat *status)
 {
@@ -370,7 +369,7 @@ find_to_address (struct _itip_puri *pitip,
 }
 
 static void
-find_from_address (struct _itip_puri *pitip,
+find_from_address (ItipPURI *pitip,
                    icalcomponent *ical_comp)
 {
 	EIterator *it;
@@ -434,7 +433,7 @@ find_from_address (struct _itip_puri *pitip,
 }
 
 static ECalComponent *
-get_real_item (struct _itip_puri *pitip)
+get_real_item (ItipPURI *pitip)
 {
 	ECalComponent *comp = NULL;
 	ESource *source;
@@ -451,7 +450,7 @@ get_real_item (struct _itip_puri *pitip)
 }
 
 static void
-adjust_item (struct _itip_puri *pitip,
+adjust_item (ItipPURI *pitip,
              ECalComponent *comp)
 {
 	ECalComponent *real_comp;
@@ -479,14 +478,15 @@ adjust_item (struct _itip_puri *pitip,
 }
 
 static void
-set_buttons_sensitive (struct _itip_puri *pitip)
+set_buttons_sensitive (ItipPURI *pitip,
+                       ItipView *view)
 {
 	gboolean read_only = TRUE;
 
 	if (pitip->current_client)
 		read_only = e_client_is_readonly (E_CLIENT (pitip->current_client));
 
-	itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), pitip->current_client != NULL && !read_only);
+	itip_view_set_buttons_sensitive (view, pitip->current_client != NULL && !read_only);
 }
 
 static void
@@ -515,7 +515,8 @@ cal_opened_cb (GObject *source_object,
                gpointer user_data)
 {
 	ESource *source = E_SOURCE (source_object);
-	struct _itip_puri *pitip = user_data;
+	ItipView *view = user_data;
+	ItipPURI *pitip = itip_view_get_puri (view);
 	ECalClientSourceType source_type;
 	EClient *client = NULL;
 	ECalClient *cal_client;
@@ -533,8 +534,7 @@ cal_opened_cb (GObject *source_object,
 
 	} else if (error != NULL) {
 		g_warn_if_fail (client == NULL);
-		add_failed_to_load_msg (
-			ITIP_VIEW (pitip->view), source, error);
+		add_failed_to_load_msg (view, source, error);
 		g_error_free (error);
 		return;
 	}
@@ -556,8 +556,7 @@ cal_opened_cb (GObject *source_object,
 		icalcomp = e_cal_component_get_icalcomponent (pitip->comp);
 
 		show_recur_check = check_is_instance (icalcomp);
-		itip_view_set_show_recur_check (
-			ITIP_VIEW (pitip->view), show_recur_check);
+		itip_view_set_show_recur_check (view, show_recur_check);
 	}
 
 	if (pitip->type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS) {
@@ -566,19 +565,18 @@ cal_opened_cb (GObject *source_object,
 		needs_decline = e_client_check_capability (
 			E_CLIENT (client),
 			CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING);
-		itip_view_set_needs_decline (
-			ITIP_VIEW (pitip->view), needs_decline);
-		itip_view_set_mode (
-			ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_PUBLISH);
+		itip_view_set_needs_decline (view, needs_decline);
+		itip_view_set_mode (view, ITIP_VIEW_MODE_PUBLISH);
 	}
 
 	pitip->current_client = cal_client;
 
-	set_buttons_sensitive (pitip);
+	set_buttons_sensitive (pitip, view);
 }
 
 static void
-start_calendar_server (struct _itip_puri *pitip,
+start_calendar_server (ItipPURI *pitip,
+                       ItipView *view,
                        ESource *source,
                        ECalClientSourceType type,
                        GAsyncReadyCallback func,
@@ -592,10 +590,10 @@ start_calendar_server (struct _itip_puri *pitip,
 	if (client) {
 		pitip->current_client = client;
 
-		itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->progress_info_id);
+		itip_view_remove_lower_info_item (view, pitip->progress_info_id);
 		pitip->progress_info_id = 0;
 
-		set_buttons_sensitive (pitip);
+		set_buttons_sensitive (pitip, view);
 
 		return;
 	}
@@ -610,20 +608,21 @@ start_calendar_server (struct _itip_puri *pitip,
 }
 
 static void
-start_calendar_server_by_uid (struct _itip_puri *pitip,
+start_calendar_server_by_uid (ItipPURI *pitip,
+                              ItipView *view,
                               const gchar *uid,
                               ECalClientSourceType type)
 {
 	gint i;
 
-	itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
+	itip_view_set_buttons_sensitive (view, FALSE);
 
 	for (i = 0; i < E_CAL_CLIENT_SOURCE_TYPE_LAST; i++) {
 		ESource *source;
 
 		source = e_source_list_peek_source_by_uid (pitip->source_lists[i], uid);
 		if (source) {
-			start_calendar_server (pitip, source, type, cal_opened_cb, pitip);
+			start_calendar_server (pitip, view, source, type, cal_opened_cb, view);
 			break;
 		}
 	}
@@ -634,25 +633,27 @@ source_selected_cb (ItipView *view,
                     ESource *source,
                     gpointer data)
 {
-	struct _itip_puri *pitip = data;
+	ItipPURI *pitip = data;
 
-	itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
+	itip_view_set_buttons_sensitive (view, FALSE);
 
 	g_return_if_fail (source != NULL);
 
-	start_calendar_server (pitip, source, pitip->type, cal_opened_cb, pitip);
+	start_calendar_server (pitip, view, source, pitip->type, cal_opened_cb, view);
 }
 
 static void
 find_cal_update_ui (FormatItipFindData *fd,
                     ECalClient *cal_client)
 {
-	struct _itip_puri *pitip;
+	ItipPURI *pitip;
+	ItipView *view;
 	ESource *source;
 
 	g_return_if_fail (fd != NULL);
 
 	pitip = fd->puri;
+	view = fd->view;
 
 	/* UI part gone */
 	if (g_cancellable_is_cancelled (fd->cancellable))
@@ -661,13 +662,13 @@ find_cal_update_ui (FormatItipFindData *fd,
 	source = cal_client ? e_client_get_source (E_CLIENT (cal_client)) : NULL;
 
 	if (cal_client && g_hash_table_lookup (fd->conflicts, cal_client)) {
-		itip_view_add_upper_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
+		itip_view_add_upper_info_item_printf (view, ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
 						      _("An appointment in the calendar '%s' conflicts with this meeting"), e_source_peek_name (source));
 	}
 
 	/* search for a master object if the detached object doesn't exist in the calendar */
 	if (pitip->current_client && pitip->current_client == cal_client) {
-		itip_view_set_show_keep_alarm_check (ITIP_VIEW (pitip->view), fd->keep_alarm_check);
+		itip_view_set_show_keep_alarm_check (view, fd->keep_alarm_check);
 
 		pitip->current_client = cal_client;
 
@@ -681,35 +682,35 @@ find_cal_update_ui (FormatItipFindData *fd,
 		/* We clear everything because we don't really care
 		 * about any other info/warnings now we found an
 		 * existing versions */
-		itip_view_clear_lower_info_items (ITIP_VIEW (pitip->view));
+		itip_view_clear_lower_info_items (view);
 		pitip->progress_info_id = 0;
 
 		/* FIXME Check read only state of calendar? */
-		itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
-						      _("Found the appointment in the calendar '%s'"), e_source_peek_name (source));
+		itip_view_add_lower_info_item_printf (view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                        _("Found the appointment in the calendar '%s'"), e_source_peek_name (source));
 
-		set_buttons_sensitive (pitip);
+		set_buttons_sensitive (pitip, view);
 	} else if (!pitip->current_client)
-		itip_view_set_show_keep_alarm_check (ITIP_VIEW (pitip->view), FALSE);
+		itip_view_set_show_keep_alarm_check (view, FALSE);
 
 	if (pitip->current_client && pitip->current_client == cal_client) {
 		if (e_cal_client_check_recurrences_no_master (pitip->current_client)) {
 			icalcomponent *icalcomp = e_cal_component_get_icalcomponent (pitip->comp);
 
 			if (check_is_instance (icalcomp))
-				itip_view_set_show_recur_check (ITIP_VIEW (pitip->view), TRUE);
+				itip_view_set_show_recur_check (view, TRUE);
 			else
-				itip_view_set_show_recur_check (ITIP_VIEW (pitip->view), FALSE);
+				itip_view_set_show_recur_check (view, FALSE);
 		}
 
 		if (pitip->type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS) {
 			/* TODO The static capability should be made generic to convey that the calendar contains unaccepted items */
 			if (e_client_check_capability (E_CLIENT (pitip->current_client), CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING))
-				itip_view_set_needs_decline (ITIP_VIEW (pitip->view), TRUE);
+				itip_view_set_needs_decline (view, TRUE);
 			else
-				itip_view_set_needs_decline (ITIP_VIEW (pitip->view), FALSE);
+				itip_view_set_needs_decline (view, FALSE);
 
-			itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_PUBLISH);
+			itip_view_set_mode (view, ITIP_VIEW_MODE_PUBLISH);
 		}
 	}
 }
@@ -724,9 +725,10 @@ decrease_find_data (FormatItipFindData *fd)
 
 	if (fd->count == 0 && !g_cancellable_is_cancelled (fd->cancellable)) {
 		gboolean rsvp_enabled = FALSE;
-		struct _itip_puri *pitip = fd->puri;
+		ItipPURI *pitip = fd->puri;
+		ItipView *view = fd->view;
 
-		itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->progress_info_id);
+		itip_view_remove_lower_info_item (view, pitip->progress_info_id);
 		pitip->progress_info_id = 0;
 
 		/*
@@ -740,10 +742,10 @@ decrease_find_data (FormatItipFindData *fd)
 		    pitip->has_organizer) {
 			rsvp_enabled = TRUE;
 		}
-		itip_view_set_show_rsvp (ITIP_VIEW (pitip->view), rsvp_enabled);
+		itip_view_set_show_rsvp_check (view, rsvp_enabled);
 
 		/* default is chosen in extract_itip_data() based on content of the VEVENT */
-		itip_view_set_rsvp (ITIP_VIEW (pitip->view), !pitip->no_reply_wanted);
+		itip_view_set_rsvp (view, !pitip->no_reply_wanted);
 
 		if ((pitip->method == ICAL_METHOD_PUBLISH || pitip->method ==  ICAL_METHOD_REQUEST)
 		    && !pitip->current_client) {
@@ -789,32 +791,35 @@ decrease_find_data (FormatItipFindData *fd)
 			if (!source)
 				source = e_source_list_peek_source_any (pitip->source_lists[pitip->type]);
 
-			itip_view_set_source_list (ITIP_VIEW (pitip->view), pitip->source_lists[pitip->type]);
+			itip_view_set_source_list (view, pitip->source_lists[pitip->type]);
 			g_signal_connect (
-				pitip->view, "source_selected",
+				view, "source_selected",
 				G_CALLBACK (source_selected_cb), pitip);
 
 			if (source) {
-				itip_view_set_source (ITIP_VIEW (pitip->view), source);
+				itip_view_set_source (view, source);
 
 				/* FIXME Shouldn't the buttons be sensitized here? */
 			} else {
-				itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to find any calendars"));
-				itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
+				itip_view_add_lower_info_item (view, ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to find any calendars"));
+				itip_view_set_buttons_sensitive (view, FALSE);
 			}
 		} else if (!pitip->current_client) {
 			switch (pitip->type) {
 			case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-				itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
-								      _("Unable to find this meeting in any calendar"));
+				itip_view_add_lower_info_item_printf (
+					view, ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
+					_("Unable to find this meeting in any calendar"));
 				break;
 			case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-				itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
-								      _("Unable to find this task in any task list"));
+				itip_view_add_lower_info_item_printf (
+					view, ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
+					_("Unable to find this task in any task list"));
 				break;
 			case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-				itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
-								      _("Unable to find this memo in any memo list"));
+				itip_view_add_lower_info_item_printf (
+					view, ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
+					_("Unable to find this memo in any memo list"));
 				break;
 			default:
 				g_assert_not_reached ();
@@ -828,6 +833,8 @@ decrease_find_data (FormatItipFindData *fd)
 		g_object_unref (fd->cancellable);
 		g_free (fd->uid);
 		g_free (fd->rid);
+		if (fd->sexp)
+			g_free (fd->sexp);
 		g_free (fd);
 	}
 }
@@ -982,7 +989,8 @@ find_cal_opened_cb (GObject *source_object,
 {
 	ESource *source = E_SOURCE (source_object);
 	FormatItipFindData *fd = user_data;
-	struct _itip_puri *pitip = fd->puri;
+	ItipPURI *pitip = fd->puri;
+	ItipView *view = fd->view;
 	ECalClientSourceType source_type;
 	EClient *client = NULL;
 	ECalClient *cal_client;
@@ -1011,8 +1019,7 @@ find_cal_opened_cb (GObject *source_object,
 		 * to find the item, this won't be cleared but the
 		 * selector might be shown */
 		g_warn_if_fail (client == NULL);
-		add_failed_to_load_msg (
-			ITIP_VIEW (pitip->view), source, error);
+		add_failed_to_load_msg (view, source, error);
 		decrease_find_data (fd);
 		g_error_free (error);
 		return;
@@ -1053,7 +1060,8 @@ find_cal_opened_cb (GObject *source_object,
 }
 
 static void
-find_server (struct _itip_puri *pitip,
+find_server (ItipPURI *pitip,
+             ItipView *view,
              ECalComponent *comp)
 {
 	FormatItipFindData *fd = NULL;
@@ -1076,7 +1084,7 @@ find_server (struct _itip_puri *pitip,
 	uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
 	camel_url_free (url);
 
-	itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
+	itip_view_set_buttons_sensitive (view, FALSE);
 
 	groups = e_source_list_peek_groups (pitip->source_lists[pitip->type]);
 	for (l = groups; l; l = l->next) {
@@ -1115,11 +1123,13 @@ find_server (struct _itip_puri *pitip,
 	if (current_source) {
 		l = sources_conflict;
 
-		pitip->progress_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
-				_("Opening the calendar. Please wait..."));
+		pitip->progress_info_id = itip_view_add_lower_info_item (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
+			_("Opening the calendar. Please wait..."));
 	} else {
-		pitip->progress_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
-				_("Searching for an existing version of this appointment"));
+		pitip->progress_info_id = itip_view_add_lower_info_item (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
+			_("Searching for an existing version of this appointment"));
 
 		l = all_sources;
 	}
@@ -1132,6 +1142,7 @@ find_server (struct _itip_puri *pitip,
 
 			fd = g_new0 (FormatItipFindData, 1);
 			fd->puri = pitip;
+			fd->view = view;
 			fd->cancellable = g_object_ref (pitip->cancellable);
 			fd->conflicts = g_hash_table_new (g_direct_hash, g_direct_equal);
 			fd->uid = g_strdup (uid);
@@ -1154,9 +1165,9 @@ find_server (struct _itip_puri *pitip,
 		d(printf ("Increasing itip formatter search count to %d\n", fd->count));
 
 		if (current_source == source)
-			start_calendar_server (pitip, source, pitip->type, find_cal_opened_cb, fd);
+			start_calendar_server (pitip, view, source, pitip->type, find_cal_opened_cb, fd);
 		else
-			start_calendar_server (pitip, source, pitip->type, find_cal_opened_cb, fd);
+			start_calendar_server (pitip, view, source, pitip->type, find_cal_opened_cb, fd);
 
 	}
 
@@ -1349,32 +1360,36 @@ get_uri_for_part (CamelMimePart *mime_part)
 }
 
 static void
-update_item_progress_info (struct _itip_puri *pitip,
+update_item_progress_info (ItipPURI *pitip,
+                           ItipView *view,
                            const gchar *message)
 {
 	if (pitip->update_item_progress_info_id) {
-		itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->update_item_progress_info_id);
+		itip_view_remove_lower_info_item (view, pitip->update_item_progress_info_id);
 		pitip->update_item_progress_info_id = 0;
 
 		if (!message)
-			itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), TRUE);
+			itip_view_set_buttons_sensitive (view, TRUE);
 	}
 
 	if (pitip->update_item_error_info_id) {
-		itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->update_item_error_info_id);
+		itip_view_remove_lower_info_item (view, pitip->update_item_error_info_id);
 		pitip->update_item_error_info_id = 0;
 	}
 
 	if (message) {
-		itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
-		pitip->update_item_progress_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
-			ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
-			message);
+		itip_view_set_buttons_sensitive (view, FALSE);
+		pitip->update_item_progress_info_id =
+			itip_view_add_lower_info_item (
+				view,
+				ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
+				message);
 	}
 }
 
 static void
-finish_message_delete_with_rsvp (struct _itip_puri *pitip,
+finish_message_delete_with_rsvp (ItipPURI *pitip,
+                                 ItipView *view,
                                  ECalClient *client)
 {
 	gboolean save_schedules = e_cal_client_check_save_schedules (client);
@@ -1382,7 +1397,7 @@ finish_message_delete_with_rsvp (struct _itip_puri *pitip,
 	if (!save_schedules && pitip->delete_message && pitip->folder)
 		camel_folder_delete_message (pitip->folder, pitip->uid);
 
-	if (itip_view_get_rsvp (ITIP_VIEW (pitip->view))) {
+	if (itip_view_get_rsvp (view)) {
 		ECalComponent *comp = NULL;
 		icalcomponent *ical_comp;
 		icalproperty *prop;
@@ -1435,7 +1450,7 @@ finish_message_delete_with_rsvp (struct _itip_puri *pitip,
 		g_slist_free (list);
 
 		/* Add a comment if there user set one */
-		comment = itip_view_get_rsvp_comment (ITIP_VIEW (pitip->view));
+		comment = itip_view_get_rsvp_comment (view);
 		if (comment) {
 			GSList comments;
 			ECalComponentText text;
@@ -1462,7 +1477,7 @@ finish_message_delete_with_rsvp (struct _itip_puri *pitip,
 		g_object_unref (comp);
 	}
 
-	update_item_progress_info (pitip, NULL);
+	update_item_progress_info (pitip, view, NULL);
 }
 
 static void
@@ -1472,44 +1487,51 @@ receive_objects_ready_cb (GObject *ecalclient,
 {
 	ECalClient *client = E_CAL_CLIENT (ecalclient);
 	ESource *source = e_client_get_source (E_CLIENT (client));
-	struct _itip_puri *pitip = user_data;
+	ItipView *view = user_data;
+	ItipPURI *pitip = itip_view_get_puri (view);
 	gboolean save_schedules;
 	GError *error = NULL;
 
 	if (!e_cal_client_receive_objects_finish (client, result, &error)) {
 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
 		    !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)) {
-			update_item_progress_info (pitip, NULL);
-			pitip->update_item_error_info_id = itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
-						      _("Unable to send item to calendar '%s'.  %s"),
-						      e_source_peek_name (source), error ? error->message : _("Unknown error"));
+			update_item_progress_info (pitip, view, NULL);
+			pitip->update_item_error_info_id =
+				itip_view_add_lower_info_item_printf (
+					view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                                        _("Unable to send item to calendar '%s'.  %s"),
+					e_source_peek_name (source), error ? error->message : _("Unknown error"));
 		}
 		g_clear_error (&error);
 		return;
 	}
 
-	itip_view_set_source_list (ITIP_VIEW (pitip->view), NULL);
+	itip_view_set_source_list (view, NULL);
 
-	itip_view_clear_lower_info_items (ITIP_VIEW (pitip->view));
+	itip_view_clear_lower_info_items (view);
 
 	switch (pitip->update_item_response) {
 	case ITIP_VIEW_RESPONSE_ACCEPT:
-		itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
-						      _("Sent to calendar '%s' as accepted"), e_source_peek_name (source));
+		itip_view_add_lower_info_item_printf (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+			_("Sent to calendar '%s' as accepted"), e_source_peek_name (source));
 		break;
 	case ITIP_VIEW_RESPONSE_TENTATIVE:
-		itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
-						      _("Sent to calendar '%s' as tentative"), e_source_peek_name (source));
+		itip_view_add_lower_info_item_printf (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+			_("Sent to calendar '%s' as tentative"), e_source_peek_name (source));
 		break;
 	case ITIP_VIEW_RESPONSE_DECLINE:
 		/* FIXME some calendars just might not save it at all, is this accurate? */
-		itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
-						      _("Sent to calendar '%s' as declined"), e_source_peek_name (source));
+		itip_view_add_lower_info_item_printf (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+			_("Sent to calendar '%s' as declined"), e_source_peek_name (source));
 		break;
 	case ITIP_VIEW_RESPONSE_CANCEL:
 		/* FIXME some calendars just might not save it at all, is this accurate? */
-		itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
-						      _("Sent to calendar '%s' as canceled"), e_source_peek_name (source));
+		itip_view_add_lower_info_item_printf (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                        _("Sent to calendar '%s' as canceled"), e_source_peek_name (source));
 		break;
 	default:
 		g_assert_not_reached ();
@@ -1528,7 +1550,7 @@ receive_objects_ready_cb (GObject *ecalclient,
 		if (mi) {
 			changes = camel_folder_change_info_new ();
 
-			if (itip_view_get_recur_check_state (ITIP_VIEW (pitip->view))) {
+			if (itip_view_get_recur_check_state (view)) {
 				/* Recurring appointment and "apply-to-all" is selected */
 				tag = camel_message_info_user_tag (mi, "recurrence-key");
 				if (tag) {
@@ -1565,11 +1587,12 @@ receive_objects_ready_cb (GObject *ecalclient,
 		}
 	}
 
-	finish_message_delete_with_rsvp (pitip, client);
+	finish_message_delete_with_rsvp (pitip, view, client);
 }
 
 static void
-update_item (struct _itip_puri *pitip,
+update_item (ItipPURI *pitip,
+             ItipView *view,
              ItipViewResponse response)
 {
 	struct icaltimetype stamp;
@@ -1578,7 +1601,7 @@ update_item (struct _itip_puri *pitip,
 	ECalComponent *clone_comp;
 	gchar *str;
 
-	update_item_progress_info (pitip, _("Saving changes to the calendar. Please wait..."));
+	update_item_progress_info (pitip, view, _("Saving changes to the calendar. Please wait..."));
 
 	/* Set X-MICROSOFT-CDO-REPLYTIME to record the time at which
 	 * the user accepted/declined the request. (Outlook ignores
@@ -1600,7 +1623,7 @@ update_item (struct _itip_puri *pitip,
 	icalcomponent_add_component (pitip->top_level, clone);
 	icalcomponent_set_method (pitip->top_level, pitip->method);
 
-	if (!itip_view_get_inherit_alarm_check_state (ITIP_VIEW (pitip->view))) {
+	if (!itip_view_get_inherit_alarm_check_state (view)) {
 		icalcomponent *alarm_comp;
 		icalcompiter alarm_iter;
 
@@ -1615,13 +1638,13 @@ update_item (struct _itip_puri *pitip,
 
 	clone_comp = e_cal_component_new ();
 	if (!e_cal_component_set_icalcomponent (clone_comp, clone)) {
-		update_item_progress_info (pitip, NULL);
-		pitip->update_item_error_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+		update_item_progress_info (pitip, view, NULL);
+		pitip->update_item_error_info_id = itip_view_add_lower_info_item (view,
 			ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to parse item"));
 		goto cleanup;
 	}
 
-	if (itip_view_get_keep_alarm_check_state (ITIP_VIEW (pitip->view))) {
+	if (itip_view_get_keep_alarm_check_state (view)) {
 		ECalComponent *real_comp;
 		GList *alarms, *l;
 		ECalComponentAlarm *alarm;
@@ -1704,7 +1727,12 @@ update_item (struct _itip_puri *pitip,
 
 	pitip->update_item_response = response;
 
-	e_cal_client_receive_objects (pitip->current_client, pitip->top_level, pitip->cancellable, receive_objects_ready_cb, pitip);
+	e_cal_client_receive_objects (
+		pitip->current_client,
+		pitip->top_level,
+		pitip->cancellable,
+		receive_objects_ready_cb,
+		view);
 
  cleanup:
 	icalcomponent_remove_component (pitip->top_level, clone);
@@ -1791,7 +1819,8 @@ send_comp_to_attendee (ECalComponentItipMethod method,
 }
 
 static void
-remove_delegate (struct _itip_puri *pitip,
+remove_delegate (ItipPURI *pitip,
+                 ItipView *view,
                  const gchar *delegate,
                  const gchar *delegator,
                  ECalComponent *comp)
@@ -1800,13 +1829,21 @@ remove_delegate (struct _itip_puri *pitip,
 	gchar *comment = g_strdup_printf (_("Organizer has removed the delegate %s "), itip_strip_mailto (delegate));
 
 	/* send cancellation notice to delegate */
-	status = send_comp_to_attendee (E_CAL_COMPONENT_METHOD_CANCEL, pitip->comp, delegate, pitip->current_client, comment);
+	status = send_comp_to_attendee (
+		E_CAL_COMPONENT_METHOD_CANCEL, pitip->comp,
+		delegate, pitip->current_client, comment);
 	if (status)
-		send_comp_to_attendee (E_CAL_COMPONENT_METHOD_REQUEST, pitip->comp, delegator, pitip->current_client, comment);
+		send_comp_to_attendee (
+			E_CAL_COMPONENT_METHOD_REQUEST, pitip->comp,
+			 delegator, pitip->current_client, comment);
 	if (status) {
-		itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Sent a cancelation notice to the delegate"));
+		itip_view_add_lower_info_item (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                        _("Sent a cancelation notice to the delegate"));
 	} else
-		itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Could not send the cancelation notice to the delegate"));
+		itip_view_add_lower_info_item (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                        _("Could not send the cancelation notice to the delegate"));
 
 	g_free (comment);
 
@@ -1839,7 +1876,8 @@ modify_object_cb (GObject *ecalclient,
                   gpointer user_data)
 {
 	ECalClient *client = E_CAL_CLIENT (ecalclient);
-	struct _itip_puri *pitip = user_data;
+	ItipView *view = user_data;
+	ItipPURI *pitip = itip_view_get_puri (view);
 	GError *error = NULL;
 
 	if (!e_cal_client_modify_object_finish (client, result, &error)) {
@@ -1849,21 +1887,25 @@ modify_object_cb (GObject *ecalclient,
 			return;
 		}
 
-		update_item_progress_info (pitip, NULL);
-		pitip->update_item_error_info_id = itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view),
-			ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
-			_("Unable to update attendee. %s"), error ? error->message : _("Unknown error"));
+		update_item_progress_info (pitip, view, NULL);
+		pitip->update_item_error_info_id =
+			itip_view_add_lower_info_item_printf (
+				view,
+				ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+			        _("Unable to update attendee. %s"),
+                                error ? error->message : _("Unknown error"));
 
 		g_clear_error (&error);
 	} else {
-		update_item_progress_info (pitip, NULL);
-		itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+		update_item_progress_info (pitip, view, NULL);
+		itip_view_add_lower_info_item (view,
 			ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Attendee status updated"));
 	}
 }
 
 static void
-update_attendee_status_icalcomp (struct _itip_puri *pitip,
+update_attendee_status_icalcomp (ItipPURI *pitip,
+                                 ItipView *view,
                                  icalcomponent *icalcomp)
 {
 	ECalComponent *comp;
@@ -1878,7 +1920,9 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 	if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
 		icalcomponent_free (icalcomp);
 
-		itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("The meeting is invalid and cannot be updated"));
+		itip_view_add_lower_info_item (
+			view, ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+                        _("The meeting is invalid and cannot be updated"));
 	} else {
 		icalcomponent *org_icalcomp;
 		const gchar *delegate;
@@ -1889,12 +1933,13 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 		if (attendees != NULL) {
 			ECalComponentAttendee *a = attendees->data;
 			icalproperty *prop, *del_prop;
+			EShell *shell = e_shell_get_default ();
 
 			prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
 			if ((a->status == ICAL_PARTSTAT_DELEGATED) && (del_prop = find_attendee (org_icalcomp, itip_strip_mailto (a->delto))) && !(find_attendee (icalcomp, itip_strip_mailto (a->delto)))) {
 				gint response;
 				delegate = icalproperty_get_attendee (del_prop);
-				response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
+				response = e_alert_run_dialog_for_args (e_shell_get_active_window (shell),
 									"org.gnome.itip-formatter:add-delegate",
 									itip_strip_mailto (a->value),
 									itip_strip_mailto (delegate), NULL);
@@ -1902,7 +1947,7 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 					icalcomponent_add_property (icalcomp, icalproperty_new_clone (del_prop));
 					e_cal_component_rescan (comp);
 				} else if (response == GTK_RESPONSE_NO) {
-					remove_delegate (pitip, delegate, itip_strip_mailto (a->value), comp);
+					remove_delegate (pitip, view, delegate, itip_strip_mailto (a->value), comp);
 					goto cleanup;
 				} else {
 					goto cleanup;
@@ -1913,7 +1958,7 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 				gint response;
 
 				if (a->delfrom && *a->delfrom) {
-					response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
+					response = e_alert_run_dialog_for_args (e_shell_get_active_window (shell),
 										"org.gnome.itip-formatter:add-delegate",
 										itip_strip_mailto (a->delfrom),
 										itip_strip_mailto (a->value), NULL);
@@ -1924,6 +1969,7 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 						e_cal_component_rescan (comp);
 					} else if (response == GTK_RESPONSE_NO) {
 						remove_delegate (pitip,
+								 view,
 								 itip_strip_mailto (a->value),
 								 itip_strip_mailto (a->delfrom),
 								 comp);
@@ -1933,7 +1979,7 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 					}
 				}
 
-				response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
+				response = e_alert_run_dialog_for_args (e_shell_get_active_window (shell),
 									"org.gnome.itip-formatter:add-unknown-attendee", NULL);
 
 				if (response == GTK_RESPONSE_YES) {
@@ -1943,8 +1989,9 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 					goto cleanup;
 				}
 			} else if (a->status == ICAL_PARTSTAT_NONE || a->status == ICAL_PARTSTAT_X) {
-				itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
-							       _("Attendee status could not be updated because the status is invalid"));
+				itip_view_add_lower_info_item (
+					view, ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+					_("Attendee status could not be updated because the status is invalid"));
 				goto cleanup;
 			} else {
 				if (a->status == ICAL_PARTSTAT_DELEGATED) {
@@ -1966,14 +2013,19 @@ update_attendee_status_icalcomp (struct _itip_puri *pitip,
 
 	update_x (pitip->comp, comp);
 
-	if (itip_view_get_update (ITIP_VIEW (pitip->view))) {
+	if (itip_view_get_update (view)) {
 		e_cal_component_commit_sequence (comp);
 		itip_send_comp (E_CAL_COMPONENT_METHOD_REQUEST, comp, pitip->current_client, NULL, NULL, NULL, TRUE, FALSE);
 	}
 
-	update_item_progress_info (pitip, _("Saving changes to the calendar. Please wait..."));
+	update_item_progress_info (pitip, view, _("Saving changes to the calendar. Please wait..."));
 
-	e_cal_client_modify_object (pitip->current_client, icalcomp, rid ? CALOBJ_MOD_THIS : CALOBJ_MOD_ALL, pitip->cancellable, modify_object_cb, pitip);
+	e_cal_client_modify_object (
+		pitip->current_client,
+		icalcomp, rid ? CALOBJ_MOD_THIS : CALOBJ_MOD_ALL,
+		pitip->cancellable,
+		modify_object_cb,
+		view);
 
  cleanup:
 	g_object_unref (comp);
@@ -1985,7 +2037,8 @@ update_attendee_status_get_object_without_rid_cb (GObject *ecalclient,
                                                   gpointer user_data)
 {
 	ECalClient *client = E_CAL_CLIENT (ecalclient);
-	struct _itip_puri *pitip = user_data;
+	ItipView *view = user_data;
+	ItipPURI *pitip = itip_view_get_puri (view);
 	icalcomponent *icalcomp = NULL;
 	GError *error = NULL;
 
@@ -1998,14 +2051,15 @@ update_attendee_status_get_object_without_rid_cb (GObject *ecalclient,
 
 		g_clear_error (&error);
 
-		update_item_progress_info (pitip, NULL);
-		pitip->update_item_error_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+		update_item_progress_info (pitip, view, NULL);
+		pitip->update_item_error_info_id = itip_view_add_lower_info_item (
+			view,
 			ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
 			_("Attendee status can not be updated because the item no longer exists"));
 		return;
 	}
 
-	update_attendee_status_icalcomp (pitip, icalcomp);
+	update_attendee_status_icalcomp (pitip, view, icalcomp);
 }
 
 static void
@@ -2014,7 +2068,8 @@ update_attendee_status_get_object_with_rid_cb (GObject *ecalclient,
                                                gpointer user_data)
 {
 	ECalClient *client = E_CAL_CLIENT (ecalclient);
-	struct _itip_puri *pitip = user_data;
+	ItipView *view = user_data;
+	ItipPURI *pitip = itip_view_get_puri (view);
 	icalcomponent *icalcomp = NULL;
 	GError *error = NULL;
 
@@ -2036,24 +2091,32 @@ update_attendee_status_get_object_with_rid_cb (GObject *ecalclient,
 		if (!rid || !*rid) {
 			g_free (rid);
 
-			update_item_progress_info (pitip, NULL);
-			pitip->update_item_error_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+			update_item_progress_info (pitip, view, NULL);
+			pitip->update_item_error_info_id = itip_view_add_lower_info_item (
+				view,
 				ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
 				_("Attendee status can not be updated because the item no longer exists"));
 			return;
 		}
 
-		e_cal_client_get_object (pitip->current_client, uid, NULL, pitip->cancellable, update_attendee_status_get_object_without_rid_cb, pitip);
+		e_cal_client_get_object (
+			pitip->current_client,
+			uid,
+			NULL,
+			pitip->cancellable,
+			update_attendee_status_get_object_without_rid_cb,
+			view);
 
 		g_free (rid);
 		return;
 	}
 
-	update_attendee_status_icalcomp (pitip, icalcomp);
+	update_attendee_status_icalcomp (pitip, view, icalcomp);
 }
 
 static void
-update_attendee_status (struct _itip_puri *pitip)
+update_attendee_status (ItipPURI *pitip,
+                        ItipView *view)
 {
 	const gchar *uid = NULL;
 	gchar *rid;
@@ -2062,16 +2125,22 @@ update_attendee_status (struct _itip_puri *pitip)
 	e_cal_component_get_uid (pitip->comp, &uid);
 	rid = e_cal_component_get_recurid_as_string (pitip->comp);
 
-	update_item_progress_info (pitip, _("Saving changes to the calendar. Please wait..."));
+	update_item_progress_info (pitip, view, _("Saving changes to the calendar. Please wait..."));
 
 	/* search for a master object if the detached object doesn't exist in the calendar */
-	e_cal_client_get_object (pitip->current_client, uid, rid, pitip->cancellable, update_attendee_status_get_object_with_rid_cb, pitip);
+	e_cal_client_get_object (
+		pitip->current_client,
+		uid, rid,
+		pitip->cancellable,
+		update_attendee_status_get_object_with_rid_cb,
+		view);
 
 	g_free (rid);
 }
 
 static void
-send_item (struct _itip_puri *pitip)
+send_item (ItipPURI *pitip,
+           ItipView *view)
 {
 	ECalComponent *comp;
 
@@ -2083,13 +2152,19 @@ send_item (struct _itip_puri *pitip)
 
 		switch (pitip->type) {
 		case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-			itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Meeting information sent"));
+			itip_view_add_lower_info_item (
+				view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                                _("Meeting information sent"));
 			break;
 		case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-			itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Task information sent"));
+			itip_view_add_lower_info_item (
+				view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                                _("Task information sent"));
 			break;
 		case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-			itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Memo information sent"));
+			itip_view_add_lower_info_item (
+				view, ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+                                _("Memo information sent"));
 			break;
 		default:
 			g_assert_not_reached ();
@@ -2098,13 +2173,19 @@ send_item (struct _itip_puri *pitip)
 	} else {
 		switch (pitip->type) {
 		case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-			itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to send meeting information, the meeting does not exist"));
+			itip_view_add_lower_info_item (
+				view, ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+                                _("Unable to send meeting information, the meeting does not exist"));
 			break;
 		case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-			itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to send task information, the task does not exist"));
+			itip_view_add_lower_info_item (
+				view, ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+                                _("Unable to send task information, the task does not exist"));
 			break;
 		case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-			itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to send memo information, the memo does not exist"));
+			itip_view_add_lower_info_item (
+				view, ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+                                _("Unable to send memo information, the memo does not exist"));
 			break;
 		default:
 			g_assert_not_reached ();
@@ -2155,8 +2236,7 @@ attachment_load_finish (EAttachment *attachment,
 }
 
 static void
-save_vcalendar_cb (GtkWidget *button,
-                   struct _itip_puri *pitip)
+save_vcalendar_cb (ItipPURI *pitip)
 {
 	EAttachment *attachment;
 	EShell *shell;
@@ -2187,39 +2267,28 @@ save_vcalendar_cb (GtkWidget *button,
 		attachment_load_finish, file);
 }
 
-static GtkWidget *
-set_itip_error (struct _itip_puri *pitip,
-                GtkContainer *container,
+static void
+set_itip_error (ItipView *view,
                 const gchar *primary,
-                const gchar *secondary)
+                const gchar *secondary,
+                gboolean save_btn)
 {
-	GtkWidget *vbox, *label;
-	gchar *message;
+	gchar *error;
 
-	vbox = gtk_vbox_new (FALSE, 12);
-	gtk_widget_show (vbox);
+	error = g_strdup_printf (
+                "<div class=\"error\">"
+                "<p><b>%s</b></p>"
+                "<p>%s</p>",
+		primary, secondary);
 
-	message = g_strdup_printf ("<b>%s</b>", primary);
-	label = gtk_label_new (NULL);
-	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-	gtk_label_set_markup (GTK_LABEL (label), message);
-	g_free (message);
-	gtk_widget_show (label);
-	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
-
-	label = gtk_label_new (secondary);
-	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-	gtk_widget_show (label);
-	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+	itip_view_set_error (view, error, save_btn);
 
-	gtk_container_add (container, vbox);
-
-	return vbox;
+	g_free (error);
 }
 
 static gboolean
-extract_itip_data (struct _itip_puri *pitip,
-                   GtkContainer *container,
+extract_itip_data (ItipPURI *pitip,
+                   ItipView *view,
                    gboolean *have_alarms)
 {
 	EShell *shell;
@@ -2237,9 +2306,10 @@ extract_itip_data (struct _itip_puri *pitip,
 	shell_settings = e_shell_get_shell_settings (shell);
 
 	if (!pitip->vcalendar) {
-		set_itip_error (pitip, container,
-				_("The calendar attached is not valid"),
-				_("The message claims to contain a calendar, but the calendar is not a valid iCalendar."));
+		set_itip_error (view,
+                        _("The calendar attached is not valid"),
+			_("The message claims to contain a calendar, but the calendar is not a valid iCalendar."),
+			FALSE);
 
 		return FALSE;
 	}
@@ -2248,9 +2318,10 @@ extract_itip_data (struct _itip_puri *pitip,
 
 	pitip->main_comp = icalparser_parse_string (pitip->vcalendar);
 	if (pitip->main_comp == NULL || !is_icalcomp_valid (pitip->main_comp)) {
-		set_itip_error (pitip, container,
-				_("The calendar attached is not valid"),
-				_("The message claims to contain a calendar, but the calendar is not a valid iCalendar."));
+		set_itip_error (view,
+                        _("The calendar attached is not valid"),
+			_("The message claims to contain a calendar, but the calendar is not a valid iCalendar."),
+			FALSE);
 
 		if (pitip->main_comp) {
 			icalcomponent_free (pitip->main_comp);
@@ -2289,9 +2360,10 @@ extract_itip_data (struct _itip_puri *pitip,
 	}
 
 	if (pitip->ical_comp == NULL) {
-		set_itip_error (pitip, container,
-				_("The item in the calendar is not valid"),
-				_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"));
+		set_itip_error (view,
+                        _("The item in the calendar is not valid"),
+			_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"),
+			FALSE);
 
 		return FALSE;
 	}
@@ -2317,9 +2389,11 @@ extract_itip_data (struct _itip_puri *pitip,
 		pitip->type = E_CAL_CLIENT_SOURCE_TYPE_MEMOS;
 		break;
 	default:
-		set_itip_error (pitip, container,
-				_("The item in the calendar is not valid"),
-				_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"));
+		set_itip_error (view,
+                        _("The item in the calendar is not valid"),
+			_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"),
+			FALSE);
+
 		return FALSE;
 	}
 
@@ -2329,27 +2403,12 @@ extract_itip_data (struct _itip_puri *pitip,
 	pitip->total += icalcomponent_count_components (pitip->main_comp, ICAL_VJOURNAL_COMPONENT);
 
 	if (pitip->total > 1) {
-		GtkWidget *save, *vbox, *hbox;
-
-		vbox = set_itip_error (pitip, container,
-				_("The calendar attached contains multiple items"),
-				_("To process all of these items, the file should be saved and the calendar imported"));
-
-		g_return_val_if_fail (vbox != NULL, FALSE);
 
-		hbox = gtk_hbox_new (FALSE, 0);
+		set_itip_error (view,
+                        _("The calendar attached contains multiple items"),
+			_("To process all of these items, the file should be saved and the calendar imported"),
+			TRUE);
 
-		save = gtk_button_new_from_stock (GTK_STOCK_SAVE);
-		gtk_container_set_border_width (GTK_CONTAINER (save), 10);
-		gtk_box_pack_start (GTK_BOX (hbox), save, FALSE, FALSE, 0);
-
-		gtk_widget_show_all (hbox);
-		gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-		g_signal_connect (
-			save, "clicked",
-			G_CALLBACK (save_vcalendar_cb), pitip);
-		return FALSE;
 	} if (pitip->total > 0) {
 		pitip->current = 1;
 	} else {
@@ -2428,9 +2487,10 @@ extract_itip_data (struct _itip_puri *pitip,
 		g_object_unref (pitip->comp);
 		pitip->comp = NULL;
 
-		set_itip_error (pitip, container,
-				_("The item in the calendar is not valid"),
-				_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"));
+		set_itip_error (view,
+                        _("The item in the calendar is not valid"),
+			_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"),
+			FALSE);
 
 		return FALSE;
 	};
@@ -2527,7 +2587,7 @@ static MailMsgInfo open_calendar_info = {
 static gboolean
 idle_open_cb (gpointer data)
 {
-	struct _itip_puri *pitip = data;
+	ItipPURI *pitip = data;
 	struct _opencal_msg *m;
 	gchar *start, *end;
 
@@ -2544,18 +2604,23 @@ idle_open_cb (gpointer data)
 }
 
 static void
-view_response_cb (GtkWidget *widget,
+view_response_cb (ItipView *view,
                   ItipViewResponse response,
                   gpointer data)
 {
-	struct _itip_puri *pitip = data;
+	ItipPURI *pitip = data;
 	gboolean status = FALSE;
 	icalproperty *prop;
 	ECalComponentTransparency trans;
 
+	if (response == ITIP_VIEW_RESPONSE_SAVE) {
+		save_vcalendar_cb (pitip);
+		return;
+	}
+
 	pitip->can_delete_invitation_from_cache = FALSE;
 	if (pitip->method == ICAL_METHOD_PUBLISH || pitip->method ==  ICAL_METHOD_REQUEST) {
-		if (itip_view_get_free_time_check_state (ITIP_VIEW (pitip->view)))
+		if (itip_view_get_free_time_check_state (view))
 			e_cal_component_set_transparency (pitip->comp, E_CAL_COMPONENT_TRANSP_TRANSPARENT);
 		else
 			e_cal_component_set_transparency (pitip->comp, E_CAL_COMPONENT_TRANSP_OPAQUE);
@@ -2571,7 +2636,7 @@ view_response_cb (GtkWidget *widget,
 
 	/* check if it is a  recur instance (no master object) and
 	 * add a property */
-	if (itip_view_get_recur_check_state (ITIP_VIEW (pitip->view))) {
+	if (itip_view_get_recur_check_state (view)) {
 		prop = icalproperty_new_x ("All");
 		icalproperty_set_x_name (prop, "X-GW-RECUR-INSTANCES-MOD-TYPE");
 		icalcomponent_add_property (pitip->ical_comp, prop);
@@ -2587,7 +2652,7 @@ view_response_cb (GtkWidget *widget,
 			if (status) {
 				e_cal_component_rescan (pitip->comp);
 				pitip->can_delete_invitation_from_cache = TRUE;
-				update_item (pitip, response);
+				update_item (pitip, view, response);
 			}
 			break;
 		case ITIP_VIEW_RESPONSE_TENTATIVE:
@@ -2596,7 +2661,7 @@ view_response_cb (GtkWidget *widget,
 			if (status) {
 				e_cal_component_rescan (pitip->comp);
 				pitip->can_delete_invitation_from_cache = TRUE;
-				update_item (pitip, response);
+				update_item (pitip, view, response);
 			}
 			break;
 		case ITIP_VIEW_RESPONSE_DECLINE:
@@ -2613,17 +2678,17 @@ view_response_cb (GtkWidget *widget,
 			if (status) {
 				e_cal_component_rescan (pitip->comp);
 				pitip->can_delete_invitation_from_cache = TRUE;
-				update_item (pitip, response);
+				update_item (pitip, view, response);
 			}
 			break;
 		case ITIP_VIEW_RESPONSE_UPDATE:
-			update_attendee_status (pitip);
+			update_attendee_status (pitip, view);
 			break;
 		case ITIP_VIEW_RESPONSE_CANCEL:
-			update_item (pitip, response);
+			update_item (pitip, view, response);
 			break;
 		case ITIP_VIEW_RESPONSE_REFRESH:
-			send_item (pitip);
+			send_item (pitip, view);
 			break;
 		case ITIP_VIEW_RESPONSE_OPEN:
 			g_idle_add (idle_open_cb, pitip);
@@ -2697,14 +2762,12 @@ in_proper_folder (CamelFolder *folder)
 	return res;
 }
 
-static gboolean
-format_itip_object (EMFormatHTML *efh,
-                    GtkHTMLEmbedded *eb,
-                    EMFormatHTMLPObject *pobject)
+static void
+init_itip_view (ItipPURI *info,
+                ItipView *view)
 {
 	EShell *shell;
 	EShellSettings *shell_settings;
-	struct _itip_puri *info;
 	ECalComponentText text;
 	ECalComponentOrganizer organizer;
 	ECalComponentDateTime datetime;
@@ -2716,189 +2779,190 @@ format_itip_object (EMFormatHTML *efh,
 	gint i;
 	gboolean response_enabled;
 	gboolean have_alarms = FALSE;
+	EMFormat *emf = info->puri.emf;
 
 	shell = e_shell_get_default ();
 	shell_settings = e_shell_get_shell_settings (shell);
 
-	info = (struct _itip_puri *) em_format_find_puri ((EMFormat *) efh, pobject->classid);
+        /* Reset current client before initializing view */
+	info->current_client = NULL;
 
-	/* Accounts */
+        /* Accounts */
 	info->accounts = e_get_account_list ();
 
-	/* Source Lists and open ecal clients */
+        /* Source Lists and open ecal clients */
 	for (i = 0; i < E_CAL_CLIENT_SOURCE_TYPE_LAST; i++) {
 		if (!e_cal_client_get_sources (&info->source_lists[i], i, NULL))
-			/* FIXME More error handling? */
+                        /* FIXME More error handling? */
 			info->source_lists[i] = NULL;
 
-		/* Initialize the ecal hashes */
+                /* Initialize the ecal hashes */
 		info->clients[i] = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 	}
 
-	/* FIXME Handle multiple VEVENTS with the same UID, ie detached instances */
-	if (!extract_itip_data (info, GTK_CONTAINER (eb), &have_alarms))
-		return TRUE;
-
-	info->view = itip_view_new ();
-	gtk_container_add (GTK_CONTAINER (eb), info->view);
-	gtk_widget_show (info->view);
+        /* FIXME Handle multiple VEVENTS with the same UID, ie detached instances */
+	if (!extract_itip_data (info, view, &have_alarms))
+		return;
 
-	response_enabled = in_proper_folder (((EMFormat *) efh)->folder);
+	response_enabled = in_proper_folder (emf->folder);
 
 	if (!response_enabled) {
-		itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_HIDE_ALL);
+		itip_view_set_mode (view, ITIP_VIEW_MODE_HIDE_ALL);
 	} else {
-		itip_view_set_show_inherit_alarm_check (ITIP_VIEW (info->view), have_alarms && (info->method == ICAL_METHOD_PUBLISH || info->method ==  ICAL_METHOD_REQUEST));
+		itip_view_set_show_inherit_alarm_check (
+			view,
+			have_alarms && (info->method == ICAL_METHOD_PUBLISH || info->method ==  ICAL_METHOD_REQUEST));
 
 		switch (info->method) {
-		case ICAL_METHOD_PUBLISH:
-		case ICAL_METHOD_REQUEST:
-			/*
-			 * Treat meeting request (sent by organizer directly) and
-			 * published evend (forwarded by organizer or attendee) alike:
-			 * if the event has an organizer, then it can be replied to and
-			 * we show the "accept/tentative/decline" choice.
-			 * Otherwise only show "accept".
-			 */
-			itip_view_set_mode (ITIP_VIEW (info->view),
-					    info->has_organizer ?
-					    ITIP_VIEW_MODE_REQUEST :
-					    ITIP_VIEW_MODE_PUBLISH);
-			break;
-		case ICAL_METHOD_REPLY:
-			itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_REPLY);
-			break;
-		case ICAL_METHOD_ADD:
-			itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_ADD);
-			break;
-		case ICAL_METHOD_CANCEL:
-			itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_CANCEL);
-			break;
-		case ICAL_METHOD_REFRESH:
-			itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_REFRESH);
-			break;
-		case ICAL_METHOD_COUNTER:
-			itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_COUNTER);
-			break;
-		case ICAL_METHOD_DECLINECOUNTER:
-			itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_DECLINECOUNTER);
-			break;
-		case ICAL_METHOD_X :
-			/* Handle appointment requests from Microsoft Live. This is
-			 * a best-at-hand-now handling. Must be revisited when we have
-			 * better access to the source of such meetings */
-			info->method = ICAL_METHOD_REQUEST;
-			itip_view_set_mode (ITIP_VIEW (info->view), ITIP_VIEW_MODE_REQUEST);
-			break;
-		default:
-			return FALSE;
+			case ICAL_METHOD_PUBLISH:
+			case ICAL_METHOD_REQUEST:
+                                /*
+                                 * Treat meeting request (sent by organizer directly) and
+                                 * published evend (forwarded by organizer or attendee) alike:
+                                 * if the event has an organizer, then it can be replied to and
+                                 * we show the "accept/tentative/decline" choice.
+                                 * Otherwise only show "accept".
+                                 */
+				itip_view_set_mode (view,
+						    info->has_organizer ?
+						    ITIP_VIEW_MODE_REQUEST :
+						    ITIP_VIEW_MODE_PUBLISH);
+				break;
+			case ICAL_METHOD_REPLY:
+				itip_view_set_mode (view, ITIP_VIEW_MODE_REPLY);
+				break;
+			case ICAL_METHOD_ADD:
+				itip_view_set_mode (view, ITIP_VIEW_MODE_ADD);
+				break;
+			case ICAL_METHOD_CANCEL:
+				itip_view_set_mode (view, ITIP_VIEW_MODE_CANCEL);
+				break;
+			case ICAL_METHOD_REFRESH:
+				itip_view_set_mode (view, ITIP_VIEW_MODE_REFRESH);
+				break;
+			case ICAL_METHOD_COUNTER:
+				itip_view_set_mode (view, ITIP_VIEW_MODE_COUNTER);
+				break;
+			case ICAL_METHOD_DECLINECOUNTER:
+				itip_view_set_mode (view, ITIP_VIEW_MODE_DECLINECOUNTER);
+				break;
+			case ICAL_METHOD_X :
+                                /* Handle appointment requests from Microsoft Live. This is
+                                 * a best-at-hand-now handling. Must be revisited when we have
+                                 * better access to the source of such meetings */
+				info->method = ICAL_METHOD_REQUEST;
+				itip_view_set_mode (view, ITIP_VIEW_MODE_REQUEST);
+				break;
+			default:
+				return;
 		}
 	}
 
-	itip_view_set_item_type (ITIP_VIEW (info->view), info->type);
+	itip_view_set_item_type (view, info->type);
 
 	if (response_enabled) {
 		switch (info->method) {
-		case ICAL_METHOD_REQUEST:
-			/* FIXME What about the name? */
-			itip_view_set_delegator (ITIP_VIEW (info->view), info->delegator_name ? info->delegator_name : info->delegator_address);
-		case ICAL_METHOD_PUBLISH:
-		case ICAL_METHOD_ADD:
-		case ICAL_METHOD_CANCEL:
-		case ICAL_METHOD_DECLINECOUNTER:
-			itip_view_set_show_update (ITIP_VIEW (info->view), FALSE);
-
-			/* An organizer sent this */
-			e_cal_component_get_organizer (info->comp, &organizer);
-			org = organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value);
-
-			itip_view_set_organizer (ITIP_VIEW (info->view), org);
-			if (organizer.sentby)
-				itip_view_set_organizer_sentby (ITIP_VIEW (info->view), itip_strip_mailto (organizer.sentby));
-
-			if (info->my_address) {
-				if (!(organizer.value && !g_ascii_strcasecmp (itip_strip_mailto (organizer.value), info->my_address))
-				&& !(organizer.sentby && !g_ascii_strcasecmp (itip_strip_mailto (organizer.sentby), info->my_address))
-				&& (info->to_address && g_ascii_strcasecmp (info->to_address, info->my_address)))
-					itip_view_set_proxy (ITIP_VIEW (info->view), info->to_name ? info->to_name : info->to_address);
-			}
-			break;
-		case ICAL_METHOD_REPLY:
-		case ICAL_METHOD_REFRESH:
-		case ICAL_METHOD_COUNTER:
-			itip_view_set_show_update (ITIP_VIEW (info->view), TRUE);
+			case ICAL_METHOD_REQUEST:
+                                /* FIXME What about the name? */
+				itip_view_set_delegator (view, info->delegator_name ? info->delegator_name : info->delegator_address);
+			case ICAL_METHOD_PUBLISH:
+			case ICAL_METHOD_ADD:
+			case ICAL_METHOD_CANCEL:
+			case ICAL_METHOD_DECLINECOUNTER:
+				itip_view_set_show_update_check (view, FALSE);
+
+                                /* An organizer sent this */
+				e_cal_component_get_organizer (info->comp, &organizer);
+				org = organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value);
+
+				itip_view_set_organizer (view, org);
+				if (organizer.sentby)
+					itip_view_set_organizer_sentby (
+						view, itip_strip_mailto (organizer.sentby));
+
+					if (info->my_address) {
+						if (!(organizer.value && !g_ascii_strcasecmp (itip_strip_mailto (organizer.value), info->my_address))
+							&& !(organizer.sentby && !g_ascii_strcasecmp (itip_strip_mailto (organizer.sentby), info->my_address))
+							&& (info->to_address && g_ascii_strcasecmp (info->to_address, info->my_address)))
+							itip_view_set_proxy (view, info->to_name ? info->to_name : info->to_address);
+					}
+					break;
+			case ICAL_METHOD_REPLY:
+			case ICAL_METHOD_REFRESH:
+			case ICAL_METHOD_COUNTER:
+				itip_view_set_show_update_check (view, TRUE);
 
-			/* An attendee sent this */
-			e_cal_component_get_attendee_list (info->comp, &list);
-			if (list != NULL) {
-				ECalComponentAttendee *attendee;
+                                /* An attendee sent this */
+				e_cal_component_get_attendee_list (info->comp, &list);
+				if (list != NULL) {
+					ECalComponentAttendee *attendee;
 
-				attendee = list->data;
+					attendee = list->data;
 
-				itip_view_set_attendee (ITIP_VIEW (info->view), attendee->cn ? attendee->cn : itip_strip_mailto (attendee->value));
+					itip_view_set_attendee (view, attendee->cn ? attendee->cn : itip_strip_mailto (attendee->value));
 
-				if (attendee->sentby)
-					itip_view_set_attendee_sentby (ITIP_VIEW (info->view), itip_strip_mailto (attendee->sentby));
+					if (attendee->sentby)
+						itip_view_set_attendee_sentby (view, itip_strip_mailto (attendee->sentby));
 
-				if (info->my_address) {
-					if (!(attendee->value && !g_ascii_strcasecmp (itip_strip_mailto (attendee->value), info->my_address))
-					&& !(attendee->sentby && !g_ascii_strcasecmp (itip_strip_mailto (attendee->sentby), info->my_address))
-					&& (info->from_address && g_ascii_strcasecmp (info->from_address, info->my_address)))
-						itip_view_set_proxy (ITIP_VIEW (info->view), info->from_name ? info->from_name : info->from_address);
-				}
+					if (info->my_address) {
+						if (!(attendee->value && !g_ascii_strcasecmp (itip_strip_mailto (attendee->value), info->my_address))
+							&& !(attendee->sentby && !g_ascii_strcasecmp (itip_strip_mailto (attendee->sentby), info->my_address))
+							&& (info->from_address && g_ascii_strcasecmp (info->from_address, info->my_address)))
+							itip_view_set_proxy (view, info->from_name ? info->from_name : info->from_address);
+					}
 
-				e_cal_component_free_attendee_list (list);
-			}
-			break;
-		default:
-			g_assert_not_reached ();
-			break;
+					e_cal_component_free_attendee_list (list);
+				}
+				break;
+			default:
+				g_assert_not_reached ();
+				break;
 		}
 	}
 
 	e_cal_component_get_summary (info->comp, &text);
-	itip_view_set_summary (ITIP_VIEW (info->view), text.value ? text.value : C_("cal-itip", "None"));
+        itip_view_set_summary (view, text.value ? text.value : C_("cal-itip", "None"));
 
 	e_cal_component_get_location (info->comp, &string);
-	itip_view_set_location (ITIP_VIEW (info->view), string);
+	itip_view_set_location (view, string);
 
-	/* Status really only applies for REPLY */
+        /* Status really only applies for REPLY */
 	if (response_enabled && info->method == ICAL_METHOD_REPLY) {
 		e_cal_component_get_attendee_list (info->comp, &list);
 		if (list != NULL) {
 			ECalComponentAttendee *a = list->data;
 
 			switch (a->status) {
-			case ICAL_PARTSTAT_ACCEPTED:
-				itip_view_set_status (ITIP_VIEW (info->view), _("Accepted"));
-				break;
-			case ICAL_PARTSTAT_TENTATIVE:
-				itip_view_set_status (ITIP_VIEW (info->view), _("Tentatively Accepted"));
-				break;
-			case ICAL_PARTSTAT_DECLINED:
-				itip_view_set_status (ITIP_VIEW (info->view), _("Declined"));
-				break;
-			case ICAL_PARTSTAT_DELEGATED:
-				itip_view_set_status (ITIP_VIEW (info->view), _("Delegated"));
-				break;
-			default:
-				itip_view_set_status (ITIP_VIEW (info->view), _("Unknown"));
+				case ICAL_PARTSTAT_ACCEPTED:
+                                        itip_view_set_status (view, _("Accepted"));
+					break;
+				case ICAL_PARTSTAT_TENTATIVE:
+                                        itip_view_set_status (view, _("Tentatively Accepted"));
+					break;
+				case ICAL_PARTSTAT_DECLINED:
+                                        itip_view_set_status (view, _("Declined"));
+					break;
+				case ICAL_PARTSTAT_DELEGATED:
+                                        itip_view_set_status (view, _("Delegated"));
+					break;
+				default:
+                                        itip_view_set_status (view, _("Unknown"));
 			}
 		}
 		e_cal_component_free_attendee_list (list);
 	}
 
 	if (info->method == ICAL_METHOD_REPLY
-	    || info->method == ICAL_METHOD_COUNTER
-	    || info->method == ICAL_METHOD_DECLINECOUNTER) {
-		/* FIXME Check spec to see if multiple comments are actually valid */
-		/* Comments for iTIP are limited to one per object */
+		|| info->method == ICAL_METHOD_COUNTER
+		|| info->method == ICAL_METHOD_DECLINECOUNTER) {
+                /* FIXME Check spec to see if multiple comments are actually valid */
+                /* Comments for iTIP are limited to one per object */
 		e_cal_component_get_comment_list (info->comp, &list);
 		if (list) {
 			ECalComponentText *text = list->data;
 
 			if (text->value)
-				itip_view_set_comment (ITIP_VIEW (info->view), text->value);
+				itip_view_set_comment (view, text->value);
 		}
 		e_cal_component_free_text_list (list);
 	}
@@ -2910,24 +2974,25 @@ format_itip_object (EMFormatHTML *efh,
 		if (!gstring && text->value)
 			gstring = g_string_new (text->value);
 		else if (text->value)
-			g_string_append_printf (gstring, "\n\n%s", text->value);
+                        g_string_append_printf (gstring, "\n\n%s", text->value);
 	}
+
 	e_cal_component_free_text_list (list);
 
 	if (gstring) {
-		itip_view_set_description (ITIP_VIEW (info->view), gstring->str);
+		itip_view_set_description (view, gstring->str);
 		g_string_free (gstring, TRUE);
 	}
 
-	to_zone = e_shell_settings_get_pointer (shell_settings, "cal-timezone");
+        to_zone = e_shell_settings_get_pointer (shell_settings, "cal-timezone");
 
 	e_cal_component_get_dtstart (info->comp, &datetime);
 	info->start_time = 0;
 	if (datetime.value) {
 		struct tm start_tm;
 
-		/* If the timezone is not in the component, guess the local time */
-		/* Should we guess if the timezone is an olsen name somehow? */
+                /* If the timezone is not in the component, guess the local time */
+                /* Should we guess if the timezone is an olsen name somehow? */
 		if (datetime.value->is_utc)
 			from_zone = icaltimezone_get_utc_timezone ();
 		else if (!datetime.value->is_utc && datetime.tzid)
@@ -2937,13 +3002,13 @@ format_itip_object (EMFormatHTML *efh,
 
 		start_tm = icaltimetype_to_tm_with_zone (datetime.value, from_zone, to_zone);
 
-		itip_view_set_start (ITIP_VIEW (info->view), &start_tm, datetime.value->is_date);
+		itip_view_set_start (view, &start_tm, datetime.value->is_date);
 		info->start_time = icaltime_as_timet_with_zone (*datetime.value, from_zone);
 	}
 
 	icalcomp = e_cal_component_get_icalcomponent (info->comp);
 
-	/* Set the recurrence id */
+        /* Set the recurrence id */
 	if (check_is_instance (icalcomp) && datetime.value) {
 		ECalComponentRange *recur_id;
 		struct icaltimetype icaltime = icaltime_convert_to_zone (*datetime.value, to_zone);
@@ -2962,8 +3027,8 @@ format_itip_object (EMFormatHTML *efh,
 	if (datetime.value) {
 		struct tm end_tm;
 
-		/* If the timezone is not in the component, guess the local time */
-		/* Should we guess if the timezone is an olsen name somehow? */
+                /* If the timezone is not in the component, guess the local time */
+                /* Should we guess if the timezone is an olsen name somehow? */
 		if (datetime.value->is_utc)
 			from_zone = icaltimezone_get_utc_timezone ();
 		else if (!datetime.value->is_utc && datetime.tzid)
@@ -2972,61 +3037,59 @@ format_itip_object (EMFormatHTML *efh,
 			from_zone = NULL;
 
 		if (datetime.value->is_date) {
-			/* RFC says the DTEND is not inclusive, thus subtract one day
-			 * if we have a date */
+                        /* RFC says the DTEND is not inclusive, thus subtract one day
+                         * if we have a date */
 
 			icaltime_adjust (datetime.value, -1, 0, 0, 0);
 		}
 
 		end_tm = icaltimetype_to_tm_with_zone (datetime.value, from_zone, to_zone);
 
-		itip_view_set_end (ITIP_VIEW (info->view), &end_tm, datetime.value->is_date);
+		itip_view_set_end (view, &end_tm, datetime.value->is_date);
 		info->end_time = icaltime_as_timet_with_zone (*datetime.value, from_zone);
 	}
 	e_cal_component_free_datetime (&datetime);
 
-	/* Recurrence info */
-	/* FIXME Better recurring description */
+        /* Recurrence info */
+        /* FIXME Better recurring description */
 	if (e_cal_component_has_recurrences (info->comp)) {
-		/* FIXME Tell the user we don't support recurring tasks */
+                /* FIXME Tell the user we don't support recurring tasks */
 		switch (info->type) {
-		case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-			itip_view_add_upper_info_item (ITIP_VIEW (info->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This meeting recurs"));
-			break;
-		case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-			itip_view_add_upper_info_item (ITIP_VIEW (info->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This task recurs"));
-			break;
-		case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-			itip_view_add_upper_info_item (ITIP_VIEW (info->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This memo recurs"));
-			break;
-		default:
-			g_assert_not_reached ();
-			break;
+			case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
+                                itip_view_add_upper_info_item (view, ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This meeting recurs"));
+				break;
+			case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
+                                itip_view_add_upper_info_item (view, ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This task recurs"));
+				break;
+			case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
+                                itip_view_add_upper_info_item (view, ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This memo recurs"));
+				break;
+			default:
+				g_assert_not_reached ();
+				break;
 		}
 	}
 
 	if (response_enabled) {
 		g_signal_connect (
-			info->view, "response",
+                        view, "response",
 			G_CALLBACK (view_response_cb), info);
 
-		itip_view_set_show_free_time_check (ITIP_VIEW (info->view), info->type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS && (info->method == ICAL_METHOD_PUBLISH || info->method ==  ICAL_METHOD_REQUEST));
+		itip_view_set_show_free_time_check (view, info->type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS && (info->method == ICAL_METHOD_PUBLISH || info->method ==  ICAL_METHOD_REQUEST));
 
 		if (info->calendar_uid) {
-			start_calendar_server_by_uid (info, info->calendar_uid, info->type);
+			start_calendar_server_by_uid (info, view, info->calendar_uid, info->type);
 		} else {
-			find_server (info, info->comp);
-			set_buttons_sensitive (info);
+			find_server (info, view, info->comp);
+			set_buttons_sensitive (info, view);
 		}
 	}
-
-	return TRUE;
 }
 
 static void
 puri_free (EMFormatPURI *puri)
 {
-	struct _itip_puri *pitip = (struct _itip_puri *) puri;
+	ItipPURI *pitip = (ItipPURI *) puri;
 	gint i;
 
 	g_cancellable_cancel (pitip->cancellable);
@@ -3081,40 +3144,125 @@ puri_free (EMFormatPURI *puri)
 	g_hash_table_destroy (pitip->real_comps);
 }
 
+static void
+write_itip_view (EMFormat *emf,
+                 EMFormatPURI *puri,
+                 CamelStream *stream,
+                 EMFormatWriterInfo *info,
+                 GCancellable *cancellable)
+{
+	GString *buffer;
+
+	if (info->mode == EM_FORMAT_WRITE_MODE_PRINTING) {
+		ItipView *view;
+		ItipPURI *ipuri;
+
+		buffer = g_string_sized_new (1024);
+
+		ipuri = (ItipPURI *) puri;
+		view = itip_view_new (ipuri);
+
+		init_itip_view (ipuri, view);
+		itip_view_write_for_printing (view, buffer);
+
+                /* Destroy the view when the formatter is destroyed */
+		g_object_weak_ref (G_OBJECT (emf), (GWeakNotify) g_object_unref, view);
+
+	} else if (info->mode == EM_FORMAT_WRITE_MODE_RAW) {
+		buffer = g_string_sized_new (2048);
+
+		itip_view_write (buffer);
+
+	} else {
+		gchar *uri;
+
+		uri = em_format_build_mail_uri (
+			emf->folder, emf->message_uid,
+                        "part_id", G_TYPE_STRING, puri->uri,
+                        "mode", G_TYPE_INT, EM_FORMAT_WRITE_MODE_RAW,
+			NULL);
+
+		buffer = g_string_sized_new (256);
+		g_string_append_printf (buffer,
+                        "<div class=\"part-container\" "
+                             "style=\"border: none; background: none;\">"
+                        "<iframe width=\"100%%\" height=\"auto\""
+                        " frameborder=\"0\" src=\"%s\" name=\"%s\" id=\"%s\"></iframe>"
+                        "</div>",
+			uri, puri->uri, puri->uri);
+
+		g_free (uri);
+	}
+
+	camel_stream_write_string (stream, buffer->str, cancellable, NULL);
+
+	g_string_free (buffer, TRUE);
+}
+
+static void
+bind_itip_view (WebKitDOMElement *element,
+                EMFormatPURI *puri)
+{
+	if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (element)) {
+                GString *buffer = g_string_new ("");
+		WebKitDOMDocument *document;
+		ItipView *view;
+
+		document = webkit_dom_html_iframe_element_get_content_document (
+				WEBKIT_DOM_HTML_IFRAME_ELEMENT (element));
+
+		view = itip_view_new ((ItipPURI *) puri);
+                g_object_set_data_full (G_OBJECT (element), "view", view,
+					(GDestroyNotify) g_object_unref);
+
+		itip_view_create_dom_bindings (view,
+			webkit_dom_document_get_document_element (document));
+
+		init_itip_view ((ItipPURI *) puri, view);
+		g_string_free (buffer, TRUE);
+	}
+}
+
 void
 format_itip (EPlugin *ep,
              EMFormatHookTarget *target)
 {
 	GSettings *settings;
-	gchar *classid;
-	struct _itip_puri *puri;
+	ItipPURI *puri;
 	CamelDataWrapper *content;
 	CamelStream *stream;
 	GByteArray *byte_array;
-	gchar *string;
+	gint len;
 
-	classid = g_strdup_printf("itip:///%s", ((EMFormat *) target->format)->part_id->str);
+	len = target->part_id->len;
+	g_string_append_printf (target->part_id, ".itip");
 
 	/* mark message as containing calendar, thus it will show the icon in message list now on */
-	if (target->format->uid && target->format->folder &&
-	    !camel_folder_get_message_user_flag (target->format->folder, target->format->uid, "$has_cal"))
-		camel_folder_set_message_user_flag (target->format->folder, target->format->uid, "$has_cal", TRUE);
-
-	puri = (struct _itip_puri *) em_format_add_puri (target->format, sizeof (struct _itip_puri), classid, target->part, itip_attachment_frame);
-
-	em_format_html_add_pobject ((EMFormatHTML *) target->format, sizeof (EMFormatHTMLPObject), classid, target->part, format_itip_object);
+	if (target->format->message_uid && target->format->folder &&
+	    !camel_folder_get_message_user_flag (target->format->folder, target->format->message_uid, "$has_cal"))
+		camel_folder_set_message_user_flag (target->format->folder, target->format->message_uid, "$has_cal", TRUE);
 
 	settings = g_settings_new ("org.gnome.evolution.plugin.itip");
+
+	puri = (ItipPURI *) em_format_puri_new (
+		target->format, sizeof (ItipPURI),
+		target->part, target->part_id->str);
+	puri->puri.write_func = write_itip_view;
+	puri->puri.bind_func = bind_itip_view;
+	puri->puri.free = puri_free;
+	puri->puri.is_attachment = target->info->is_attachment;
+        puri->puri.mime_type = g_strdup ("text/html");
 	puri->delete_message = g_settings_get_boolean (settings, CONF_KEY_DELETE);
 	puri->has_organizer = FALSE;
 	puri->no_reply_wanted = FALSE;
 	puri->folder = ((EMFormat *) target->format)->folder;
-	puri->uid = g_strdup (((EMFormat *) target->format)->uid);
+	puri->uid = g_strdup (((EMFormat *) target->format)->message_uid);
 	puri->msg = ((EMFormat *) target->format)->message;
 	puri->part = target->part;
 	puri->cancellable = g_cancellable_new ();
 	puri->real_comps = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-	puri->puri.free = puri_free;
+
+	em_format_add_puri (target->format, (EMFormatPURI *) puri);
 
 	g_object_unref (settings);
 
@@ -3132,16 +3280,7 @@ format_itip (EPlugin *ep,
 			(gchar *) byte_array->data, byte_array->len);
 
 	g_object_unref (stream);
-
-	string = g_strdup_printf (
-		"<table border=0 width=\"100%%\" cellpadding=3><tr>"
-		"<td valign=top><object classid=\"%s\"></object></td>"
-		"<td width=100%% valign=top></td></tr></table>",
-		classid);
-	camel_stream_write_string (target->stream, string, NULL, NULL);
-	g_free (string);
-
-	g_free (classid);
+	g_string_truncate (target->part_id, len);
 }
 
 static void
@@ -3315,19 +3454,3 @@ itip_formatter_page_factory (EPlugin *ep,
 
 	return page;
 }
-
-static void
-itip_attachment_frame (EMFormat *emf,
-                       CamelStream *stream,
-                       EMFormatPURI *puri,
-                       GCancellable *cancellable)
-{
-	struct _itip_puri *info = (struct _itip_puri *) puri;
-
-	info->handle->handler (
-		emf, stream, info->puri.part,
-		info->handle, cancellable, FALSE);
-
-	camel_stream_close (stream, cancellable, NULL);
-}
-
diff --git a/plugins/itip-formatter/itip-view.c b/plugins/itip-formatter/itip-view.c
index 2732384..53bba25 100644
--- a/plugins/itip-formatter/itip-view.c
+++ b/plugins/itip-formatter/itip-view.c
@@ -31,22 +31,25 @@
 #include <libedataserverui/e-source-combo-box.h>
 #include <libecal/e-cal-client.h>
 #include <libecal/e-cal-time-util.h>
-#include <gtkhtml/gtkhtml-embedded.h>
 #include <mail/em-format-hook.h>
 #include <mail/em-format-html.h>
 #include <libedataserver/e-account-list.h>
 #include <e-util/e-util.h>
 #include <e-util/e-unicode.h>
 #include <calendar/gui/itip-utils.h>
+#include <webkit/webkitdom.h>
+
 #include "itip-view.h"
 
+#define d(x)
+
 #define MEETING_ICON "stock_new-meeting"
 
 #define ITIP_VIEW_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
 	((obj), ITIP_TYPE_VIEW, ItipViewPrivate))
 
-G_DEFINE_TYPE (ItipView, itip_view, GTK_TYPE_HBOX)
+G_DEFINE_TYPE (ItipView, itip_view, G_TYPE_OBJECT)
 
 typedef struct  {
 	ItipViewInfoItemType type;
@@ -59,7 +62,7 @@ struct _ItipViewPrivate {
 	ItipViewMode mode;
 	ECalClientSourceType type;
 
-	GtkWidget *sender_label;
+        gchar *sender;
 	gchar *organizer;
 	gchar *organizer_sentby;
 	gchar *delegator;
@@ -67,71 +70,85 @@ struct _ItipViewPrivate {
 	gchar *attendee_sentby;
 	gchar *proxy;
 
-	GtkWidget *summary_label;
 	gchar *summary;
 
-	GtkWidget *location_header;
-	GtkWidget *location_label;
 	gchar *location;
-
-	GtkWidget *status_header;
-	GtkWidget *status_label;
-	gchar *status;
-
-	GtkWidget *comment_header;
-	GtkWidget *comment_label;
+        gchar *status;
 	gchar *comment;
 
-	GtkWidget *start_header;
-	GtkWidget *start_label;
 	struct tm *start_tm;
-	gboolean start_tm_is_date;
+	gint start_tm_is_date : 1;
+        gchar *start_label;
+        const gchar *start_header;
 
-	GtkWidget *end_header;
-	GtkWidget *end_label;
 	struct tm *end_tm;
-	gboolean end_tm_is_date;
+	gint end_tm_is_date : 1;
+        gchar *end_label;
+        const gchar *end_header;
 
-	GtkWidget *upper_info_box;
 	GSList *upper_info_items;
-
-	GtkWidget *lower_info_box;
 	GSList *lower_info_items;
 
 	guint next_info_item_id;
 
-	GtkWidget *description_label;
 	gchar *description;
 
-	GtkWidget *selector_box;
-	GtkWidget *escb;
-	GtkWidget *escb_header;
 	ESourceList *source_list;
 
-	GtkWidget *rsvp_box;
-	GtkWidget *rsvp_check;
-	GtkWidget *rsvp_comment_header;
-	GtkWidget *rsvp_comment_text;
-	gboolean rsvp_show;
-
-	GtkWidget *recur_box;
-	GtkWidget *recur_check;
+	gint buttons_sensitive : 1;
 
-	GtkWidget *update_box;
-	GtkWidget *update_check;
-	gboolean update_show;
+        gboolean is_recur_set;
 
-	GtkWidget *options_box;
-	GtkWidget *free_time_check;
-	GtkWidget *keep_alarm_check;
-	GtkWidget *inherit_alarm_check;
+	gint needs_decline : 1;
 
-	GtkWidget *button_box;
-	gboolean buttons_sensitive;
+        WebKitDOMDocument *dom_document;
+        ItipPURI *puri;
 
-	gboolean needs_decline;
+        gchar *error;
 };
 
+#define TEXT_ROW_SENDER "text_row_sender"
+#define TABLE_ROW_SUMMARY "table_row_summary"
+#define TABLE_ROW_LOCATION "table_row_location"
+#define TABLE_ROW_START_DATE "table_row_start_time"
+#define TABLE_ROW_END_DATE "table_row_end_time"
+#define TABLE_ROW_STATUS "table_row_status"
+#define TABLE_ROW_COMMENT "table_row_comment"
+#define TABLE_ROW_DESCRIPTION "table_row_description"
+#define TABLE_ROW_RSVP_COMMENT "table_row_rsvp_comment"
+#define TABLE_ROW_ESCB "table_row_escb"
+#define TABLE_ROW_BUTTONS "table_row_buttons"
+
+#define TABLE_BUTTONS "table_buttons"
+
+#define SELECT_ESOURCE "select_esource"
+#define TEXTAREA_RSVP_COMMENT "textarea_rsvp_comment"
+
+#define CHECKBOX_RSVP "checkbox_rsvp"
+#define CHECKBOX_RECUR "checkbox_recur"
+#define CHECKBOX_UPDATE "checkbox_update"
+#define CHECKBOX_FREE_TIME "checkbox_free_time"
+#define CHECKBOX_KEEP_ALARM "checkbox_keep_alarm"
+#define CHECKBOX_INHERIT_ALARM "checkbox_inherit_alarm"
+
+#define BUTTON_OPEN_CALENDAR "button_open_calendar"
+#define BUTTON_DECLINE "button_decline"
+#define BUTTON_DECLINE_ALL "button_decline_all"
+#define BUTTON_ACCEPT "button_accept"
+#define BUTTON_ACCEPT_ALL "button_accept_all"
+#define BUTTON_TENTATIVE "button_tentative"
+#define BUTTON_TENTATIVE_ALL "button_tentative_all"
+#define BUTTON_SEND_INFORMATION "button_send_information"
+#define BUTTON_UPDATE "button_update"
+#define BUTTON_UPDATE_ATTENDEE_STATUS "button_update_attendee_status"
+#define BUTTON_SAVE "button_save"
+
+#define TABLE_UPPER_ITIP_INFO "table_upper_itip_info"
+#define TABLE_LOWER_ITIP_INFO "table_lower_itip_info"
+
+#define DIV_ITIP_CONTENT "div_itip_content"
+#define DIV_ITIP_ERROR "div_itip_error"
+
 /* Signal IDs */
 enum {
 	SOURCE_SELECTED,
@@ -354,7 +371,7 @@ dupe_first_bold (const gchar *format,
 	return res;
 }
 
-static void
+static gchar *
 set_calendar_sender_text (ItipView *view)
 {
 	ItipViewPrivate *priv;
@@ -435,14 +452,12 @@ set_calendar_sender_text (ItipView *view)
 	if (sender && on_behalf_of)
 		sender = g_strjoin (NULL, sender, "\n", on_behalf_of, NULL);
 
-	gtk_label_set_text (GTK_LABEL (priv->sender_label), sender);
-	gtk_label_set_use_markup (GTK_LABEL (priv->sender_label), TRUE);
-
 	g_free (on_behalf_of);
-	g_free (sender);
+
+	return sender;
 }
 
-static void
+static gchar *
 set_tasklist_sender_text (ItipView *view)
 {
 	ItipViewPrivate *priv;
@@ -523,14 +538,12 @@ set_tasklist_sender_text (ItipView *view)
 	if (sender && on_behalf_of)
 		sender = g_strjoin (NULL, sender, "\n", on_behalf_of, NULL);
 
-	gtk_label_set_text (GTK_LABEL (priv->sender_label), sender);
-	gtk_label_set_use_markup (GTK_LABEL (priv->sender_label), TRUE);
-
 	g_free (on_behalf_of);
-	g_free (sender);
+
+	return sender;
 }
 
-static void
+static gchar *
 set_journal_sender_text (ItipView *view)
 {
 	ItipViewPrivate *priv;
@@ -575,106 +588,47 @@ set_journal_sender_text (ItipView *view)
 	if (sender && on_behalf_of)
 		sender = g_strjoin (NULL, sender, "\n", on_behalf_of, NULL);
 
-	gtk_label_set_text (GTK_LABEL (priv->sender_label), sender);
-	gtk_label_set_use_markup (GTK_LABEL (priv->sender_label), TRUE);
-
 	g_free (on_behalf_of);
-	g_free (sender);
+
+	return sender;
 }
 
 static void
 set_sender_text (ItipView *view)
 {
 	ItipViewPrivate *priv;
-
 	priv = view->priv;
 
 	switch (priv->type) {
 	case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-		set_calendar_sender_text (view);
+		priv->sender = set_calendar_sender_text (view);
 		break;
 	case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-		set_tasklist_sender_text (view);
+		priv->sender = set_tasklist_sender_text (view);
 		break;
 	case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-		set_journal_sender_text (view);
+		priv->sender = set_journal_sender_text (view);
 		break;
 	default:
+		priv->sender = NULL;
 		break;
 	}
-}
-
-static void
-set_summary_text (ItipView *view)
-{
-	ItipViewPrivate *priv;
-	gchar *summary = NULL;
-
-	priv = view->priv;
-
-	summary = g_markup_printf_escaped ("<b>%s</b>", priv->summary);
-
-	gtk_label_set_text (GTK_LABEL (priv->summary_label), summary);
-	gtk_label_set_use_markup (GTK_LABEL (priv->summary_label), TRUE);
-
-	g_free (summary);
-}
-
-static void
-set_location_text (ItipView *view)
-{
-	ItipViewPrivate *priv;
-
-	priv = view->priv;
-
-	gtk_label_set_text (GTK_LABEL (priv->location_label), priv->location);
-
-	priv->location ? gtk_widget_show (priv->location_header) : gtk_widget_hide (priv->location_header);
-	priv->location ? gtk_widget_show (priv->location_label) : gtk_widget_hide (priv->location_label);
-}
-
-static void
-set_status_text (ItipView *view)
-{
-	ItipViewPrivate *priv;
-
-	priv = view->priv;
-
-	gtk_label_set_text (GTK_LABEL (priv->status_label), priv->status);
-
-	priv->status ? gtk_widget_show (priv->status_header) : gtk_widget_hide (priv->status_header);
-	priv->status ? gtk_widget_show (priv->status_label) : gtk_widget_hide (priv->status_label);
-}
-
-static void
-set_comment_text (ItipView *view)
-{
-	ItipViewPrivate *priv;
-
-	priv = view->priv;
-
-	gtk_label_set_text (GTK_LABEL (priv->comment_label), priv->comment);
-
-	priv->comment ? gtk_widget_show (priv->comment_header) : gtk_widget_hide (priv->comment_header);
-	priv->comment ? gtk_widget_show (priv->comment_label) : gtk_widget_hide (priv->comment_label);
-}
-
-static void
-set_description_text (ItipView *view)
-{
-	ItipViewPrivate *priv;
-
-	priv = view->priv;
 
-	gtk_label_set_text (GTK_LABEL (priv->description_label), priv->description);
+	if (priv->sender && priv->dom_document) {
+		WebKitDOMElement *div;
 
-	priv->description ? gtk_widget_show (priv->description_label) : gtk_widget_hide (priv->description_label);
+		div = webkit_dom_document_get_element_by_id (
+			priv->dom_document, TEXT_ROW_SENDER);
+		webkit_dom_html_element_set_inner_html (
+			WEBKIT_DOM_HTML_ELEMENT (div), priv->sender, NULL);
+	}
 }
 
 static void
 update_start_end_times (ItipView *view)
 {
 	ItipViewPrivate *priv;
+	WebKitDOMElement *row, *col;
 	gchar buffer[256];
 	time_t now;
 	struct tm *now_tm;
@@ -684,240 +638,211 @@ update_start_end_times (ItipView *view)
 	now = time (NULL);
 	now_tm = localtime (&now);
 
+	if (priv->start_label)
+		g_free (priv->start_label);
+	if (priv->end_label)
+		g_free (priv->end_label);
+
 	#define is_same(_member) (priv->start_tm->_member == priv->end_tm->_member)
 	if (priv->start_tm && priv->end_tm && priv->start_tm_is_date && priv->end_tm_is_date
 	    && is_same (tm_mday) && is_same (tm_mon) && is_same (tm_year)) {
 		/* it's an all day event in one particular day */
 		format_date_and_time_x (priv->start_tm, now_tm, FALSE, TRUE, FALSE, priv->start_tm_is_date, buffer, 256);
-		gtk_label_set_text (GTK_LABEL (priv->start_label), buffer);
-		gtk_label_set_text (GTK_LABEL (priv->start_header), _("All day:"));
-
-		gtk_widget_show (priv->start_header);
-		gtk_widget_show (priv->start_label);
-		gtk_widget_hide (priv->end_header);
-		gtk_widget_hide (priv->end_label);
+		priv->start_label = g_strdup (buffer);
+                priv->start_header = _("All day:");
+		priv->end_header = NULL;
+		priv->end_label = NULL;
 	} else {
 		if (priv->start_tm) {
 			format_date_and_time_x (priv->start_tm, now_tm, FALSE, TRUE, FALSE, priv->start_tm_is_date, buffer, 256);
-			gtk_label_set_text (GTK_LABEL (priv->start_label), buffer);
-			gtk_label_set_text (GTK_LABEL (priv->start_header), priv->start_tm_is_date ? _("Start day:") : _("Start time:"));
-			gtk_widget_show (priv->start_header);
-			gtk_widget_show (priv->start_label);
+                        priv->start_header = priv->start_tm_is_date ? _("Start day:") : _("Start time:");
+			priv->start_label = g_strdup (buffer);
 		} else {
-			gtk_label_set_text (GTK_LABEL (priv->start_label), NULL);
-			gtk_widget_hide (priv->start_header);
-			gtk_widget_hide (priv->start_label);
+			priv->start_header = NULL;
+			priv->start_label = NULL;
 		}
 
 		if (priv->end_tm) {
 			format_date_and_time_x (priv->end_tm, now_tm, FALSE, TRUE, FALSE, priv->end_tm_is_date, buffer, 256);
-			gtk_label_set_text (GTK_LABEL (priv->end_label), buffer);
-			gtk_label_set_text (GTK_LABEL (priv->end_header), priv->end_tm_is_date ? _("End day:") : _("End time:"));
-			gtk_widget_show (priv->end_header);
-			gtk_widget_show (priv->end_label);
+                        priv->end_header = priv->end_tm_is_date ? _("End day:") : _("End time:");
+			priv->end_label = g_strdup (buffer);
 		} else {
-			gtk_label_set_text (GTK_LABEL (priv->end_label), NULL);
-			gtk_widget_hide (priv->end_header);
-			gtk_widget_hide (priv->end_label);
+			priv->end_header = NULL;
+			priv->end_label = NULL;
 		}
 	}
-
 	#undef is_same
-}
-
-static void
-set_info_items (GtkWidget *info_box,
-                GSList *info_items)
-{
-	GSList *l;
-
-	gtk_container_foreach (GTK_CONTAINER (info_box), (GtkCallback) gtk_widget_destroy, NULL);
 
-	for (l = info_items; l; l = l->next) {
-		ItipViewInfoItem *item = l->data;
-		GtkWidget *hbox, *image, *label;
+	if (priv->dom_document) {
+		row = webkit_dom_document_get_element_by_id (
+			priv->dom_document, TABLE_ROW_START_DATE);
+		if (priv->start_header && priv->start_label) {
+			webkit_dom_html_element_set_hidden (
+				WEBKIT_DOM_HTML_ELEMENT (row), FALSE);
 
-		hbox = gtk_hbox_new (FALSE, 0);
+			col = webkit_dom_element_get_first_element_child (row);
+			webkit_dom_html_element_set_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (col), priv->start_header, NULL);
 
-		switch (item->type) {
-		case ITIP_VIEW_INFO_ITEM_TYPE_INFO:
-			image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_SMALL_TOOLBAR);
-			break;
-		case ITIP_VIEW_INFO_ITEM_TYPE_WARNING:
-			image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
-			break;
-		case ITIP_VIEW_INFO_ITEM_TYPE_ERROR:
-			image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_SMALL_TOOLBAR);
-			break;
-		case ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS:
-			image = gtk_spinner_new ();
-			gtk_spinner_start (GTK_SPINNER (image));
-			break;
-		case ITIP_VIEW_INFO_ITEM_TYPE_NONE:
-		default:
-			image = NULL;
+			col = webkit_dom_element_get_last_element_child (row);
+			webkit_dom_html_element_set_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (col), priv->start_label, NULL);
+		} else {
+			webkit_dom_html_element_set_hidden (
+				WEBKIT_DOM_HTML_ELEMENT (row), TRUE);
 		}
 
-		if (image) {
-			gtk_widget_show (image);
-			gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 6);
-		}
+		row = webkit_dom_document_get_element_by_id (
+			priv->dom_document, TABLE_ROW_END_DATE);
+		if (priv->end_header && priv->end_label) {
+			webkit_dom_html_element_set_hidden (
+				WEBKIT_DOM_HTML_ELEMENT (row), FALSE);
 
-		label = gtk_label_new (item->message);
-		gtk_label_set_selectable (GTK_LABEL (label), TRUE);
-		gtk_widget_show (label);
-		gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
+			col = webkit_dom_element_get_first_element_child (row);
+			webkit_dom_html_element_set_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (col), priv->end_header, NULL);
 
-		gtk_widget_show (hbox);
-		gtk_box_pack_start (GTK_BOX (info_box), hbox, FALSE, FALSE, 6);
+			col = webkit_dom_element_get_last_element_child (row);
+			webkit_dom_html_element_set_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (col), priv->end_label, NULL);
+		} else {
+			webkit_dom_html_element_set_hidden (
+				WEBKIT_DOM_HTML_ELEMENT (row), TRUE);
+		}
 	}
 }
 
 static void
-set_upper_info_items (ItipView *view)
+button_clicked_cb (WebKitDOMElement *element,
+                   WebKitDOMEvent *event,
+                   gpointer data)
 {
-	ItipViewPrivate *priv;
+	ItipViewResponse response;
+	gchar *responseStr;
 
-	priv = view->priv;
+	responseStr = webkit_dom_html_button_element_get_value (
+		WEBKIT_DOM_HTML_BUTTON_ELEMENT (element));
+
+	response = atoi (responseStr);
 
-	set_info_items (priv->upper_info_box, priv->upper_info_items);
+        //d(printf("Clicked btton %d\n", response));
+	g_signal_emit (G_OBJECT (data), signals[RESPONSE], 0, response);
 }
 
 static void
-set_lower_info_items (ItipView *view)
+itip_view_finalize (GObject *object)
 {
 	ItipViewPrivate *priv;
+	GSList *iter;
 
-	priv = view->priv;
+	priv = ITIP_VIEW_GET_PRIVATE (object);
 
-	set_info_items (priv->lower_info_box, priv->lower_info_items);
-}
+        d(printf("Itip view finalized!\n"));
 
-#define DATA_RESPONSE_KEY "ItipView::button_response"
+	if (priv->sender) {
+		g_free (priv->sender);
+		priv->sender = NULL;
+	}
 
-static void
-button_clicked_cb (GtkWidget *widget,
-                   gpointer data)
-{
-	ItipViewResponse response;
+	if (priv->organizer) {
+		g_free (priv->organizer);
+		priv->organizer = NULL;
+	}
 
-	response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), DATA_RESPONSE_KEY));
+	if (priv->organizer_sentby) {
+		g_free (priv->organizer_sentby);
+		priv->organizer_sentby = NULL;
+	}
 
-	g_signal_emit (G_OBJECT (data), signals[RESPONSE], 0, response);
-}
+	if (priv->delegator) {
+		g_free (priv->delegator);
+		priv->delegator = NULL;
+	}
 
-static void
-set_one_button (ItipView *view,
-                const gchar *label,
-                const gchar *stock_id,
-                ItipViewResponse response)
-{
-	ItipViewPrivate *priv;
-	GtkWidget *button;
-	GtkWidget *image;
-	gpointer data;
+	if (priv->attendee) {
+		g_free (priv->attendee);
+		priv->attendee = NULL;
+	}
 
-	priv = view->priv;
+	if (priv->attendee_sentby) {
+		g_free (priv->attendee_sentby);
+		priv->attendee_sentby = NULL;
+	}
 
-	button = gtk_button_new_with_mnemonic (label);
-	image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
-	gtk_button_set_image (GTK_BUTTON (button), image);
+	if (priv->proxy) {
+		g_free (priv->proxy);
+		priv->proxy = NULL;
+	}
 
-	data = GINT_TO_POINTER (response);
-	g_object_set_data (G_OBJECT (button), DATA_RESPONSE_KEY, data);
+	if (priv->summary) {
+		g_free (priv->summary);
+		priv->summary = NULL;
+	}
 
-	gtk_widget_show (button);
-	gtk_container_add (GTK_CONTAINER (priv->button_box), button);
+	if (priv->location) {
+		g_free (priv->location);
+		priv->location = NULL;
+	}
 
-	g_signal_connect (
-		button, "clicked", G_CALLBACK (button_clicked_cb), view);
-}
+	if (priv->status) {
+		g_free (priv->status);
+		priv->status = NULL;
+	}
 
-static void
-set_buttons (ItipView *view)
-{
-	ItipViewPrivate *priv;
-	gboolean is_recur_set = FALSE;
+	if (priv->comment) {
+		g_free (priv->comment);
+		priv->comment = NULL;
+	}
 
-	priv = view->priv;
+	if (priv->start_tm) {
+		g_free (priv->start_tm);
+		priv->start_tm = NULL;
+	}
 
-	is_recur_set = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->recur_check));
-	gtk_container_foreach (GTK_CONTAINER (priv->button_box), (GtkCallback) gtk_widget_destroy, NULL);
+	if (priv->start_label) {
+		g_free (priv->start_label);
+		priv->start_label = NULL;
+	}
 
-	if (priv->mode == ITIP_VIEW_MODE_HIDE_ALL)
-		return;
+	if (priv->end_tm) {
+		g_free (priv->end_tm);
+		priv->end_tm = NULL;
+	}
 
-	/* Everything gets the open button */
-	set_one_button (view, _("_Open Calendar"), GTK_STOCK_JUMP_TO, ITIP_VIEW_RESPONSE_OPEN);
+	if (priv->end_label) {
+		g_free (priv->end_label);
+		priv->end_label = NULL;
+	}
 
-	switch (priv->mode) {
-	case ITIP_VIEW_MODE_PUBLISH:
-		/* FIXME Is this really the right button? */
-		if (priv->needs_decline)
-			set_one_button (view, _("_Decline"), GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
-		set_one_button (view, _("A_ccept"), GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
-		break;
-	case ITIP_VIEW_MODE_REQUEST:
-		set_one_button (view, is_recur_set ? _("_Decline all") : _("_Decline"), GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
-		set_one_button (view, is_recur_set ? _("_Tentative all") : _("_Tentative"), GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
-		set_one_button (view, is_recur_set ? _("A_ccept all") : _("A_ccept"), GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
-		break;
-	case ITIP_VIEW_MODE_ADD:
-		if (priv->type != E_CAL_CLIENT_SOURCE_TYPE_MEMOS) {
-			set_one_button (view, _("_Decline"), GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
-			set_one_button (view, _("_Tentative"), GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
-		}
-		set_one_button (view, _("A_ccept"), GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
-		break;
-	case ITIP_VIEW_MODE_REFRESH:
-		/* FIXME Is this really the right button? */
-		set_one_button (view, _("_Send Information"), GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_REFRESH);
-		break;
-	case ITIP_VIEW_MODE_REPLY:
-		/* FIXME Is this really the right button? */
-		set_one_button (view, _("_Update Attendee Status"), GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_UPDATE);
-		break;
-	case ITIP_VIEW_MODE_CANCEL:
-		set_one_button (view, _("_Update"), GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_CANCEL);
-		break;
-	case ITIP_VIEW_MODE_COUNTER:
-		set_one_button (view, _("_Decline"), GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
-		set_one_button (view, _("_Tentative"), GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
-		set_one_button (view, _("A_ccept"), GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
-		break;
-	case ITIP_VIEW_MODE_DECLINECOUNTER:
-		set_one_button (view, _("_Decline"), GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
-		set_one_button (view, _("_Tentative"), GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
-		set_one_button (view, _("A_ccept"), GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
-		break;
-	default:
-		break;
+	if (priv->description) {
+		g_free (priv->description);
+		priv->description = NULL;
 	}
-}
 
-static void
-itip_view_finalize (GObject *object)
-{
-	ItipViewPrivate *priv;
+	for (iter = priv->lower_info_items; iter; iter = iter->next) {
+		ItipViewInfoItem *item = iter->data;
+		g_free (item->message);
+		g_free (item);
+	}
+	if (priv->lower_info_items) {
+		g_slist_free (priv->lower_info_items);
+		priv->lower_info_items = NULL;
+	}
 
-	priv = ITIP_VIEW_GET_PRIVATE (object);
+	for (iter = priv->upper_info_items; iter; iter = iter->next) {
+		ItipViewInfoItem *item = iter->data;
+		g_free (item->message);
+		g_free (item);
+	}
+	if (priv->upper_info_items) {
+		g_slist_free (priv->upper_info_items);
+		priv->upper_info_items = NULL;
+	}
 
-	g_free (priv->organizer);
-	g_free (priv->organizer_sentby);
-	g_free (priv->delegator);
-	g_free (priv->attendee);
-	g_free (priv->attendee_sentby);
-	g_free (priv->proxy);
-	g_free (priv->summary);
-	g_free (priv->location);
-	g_free (priv->status);
-	g_free (priv->comment);
-	g_free (priv->start_tm);
-	g_free (priv->end_tm);
-	g_free (priv->description);
-
-	itip_view_clear_upper_info_items (ITIP_VIEW (object));
-	itip_view_clear_lower_info_items (ITIP_VIEW (object));
+	if (priv->error) {
+		g_free (priv->error);
+		priv->error = NULL;
+	}
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (itip_view_parent_class)->finalize (object);
@@ -953,31 +878,31 @@ itip_view_class_init (ItipViewClass *class)
 }
 
 static void
-rsvp_toggled_cb (GtkWidget *widget,
+rsvp_toggled_cb (WebKitDOMHTMLInputElement *input,
+                 WebKitDOMEvent *event,
                  gpointer data)
 {
+	WebKitDOMElement *el;
+
 	ItipView *view = data;
-	ItipViewPrivate *priv;
 	gboolean rsvp;
 
-	priv = view->priv;
-
-	rsvp = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->rsvp_check));
+	rsvp = webkit_dom_html_input_element_get_checked (input);
 
-	gtk_widget_set_sensitive (priv->rsvp_comment_header, rsvp);
-	gtk_widget_set_sensitive (priv->rsvp_comment_text, rsvp);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TEXTAREA_RSVP_COMMENT);
+	webkit_dom_html_text_area_element_set_disabled (
+		WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), !rsvp);
 }
 
 static void
-recur_toggled_cb (GtkWidget *widget,
+recur_toggled_cb (WebKitDOMHTMLInputElement *input,
+                  WebKitDOMEvent *event,
                   gpointer data)
 {
 	ItipView *view = data;
-	ItipViewPrivate *priv;
-
-	priv = view->priv;
 
-	itip_view_set_mode (view, priv->mode);
+	itip_view_set_mode (view, view->priv->mode);
 }
 
 /*
@@ -985,322 +910,669 @@ recur_toggled_cb (GtkWidget *widget,
   check1 was changed, so make the second available based on state of the first check.
 */
 static void
-alarm_check_toggled_cb (GtkWidget *check1,
-                        GtkWidget *check2)
+alarm_check_toggled_cb (WebKitDOMHTMLInputElement *check1,
+                        WebKitDOMEvent *event,
+                        ItipView *view)
 {
-	g_return_if_fail (check1 != NULL);
-	g_return_if_fail (check2 != NULL);
+	WebKitDOMElement *check2;
+	gchar *id = webkit_dom_html_element_get_id (WEBKIT_DOM_HTML_ELEMENT (check1));
+
+	if (g_strcmp0 (id, CHECKBOX_INHERIT_ALARM)) {
+		check2 = webkit_dom_document_get_element_by_id (
+			view->priv->dom_document, CHECKBOX_KEEP_ALARM);
+	} else {
+		check2 = webkit_dom_document_get_element_by_id (
+			view->priv->dom_document, CHECKBOX_INHERIT_ALARM);
+	}
 
-	gtk_widget_set_sensitive (check2, !(gtk_widget_get_visible (check1) && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check1))));
+	g_free (id);
+
+	webkit_dom_html_input_element_set_disabled (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (check2),
+		(webkit_dom_html_element_get_hidden (
+				WEBKIT_DOM_HTML_ELEMENT (check1)) &&
+			webkit_dom_html_input_element_get_checked (check1)));
 }
 
 static void
-itip_view_init (ItipView *view)
+source_changed_cb (WebKitDOMElement *select,
+                   WebKitDOMEvent *event,
+                   ItipView *view)
 {
-	GtkWidget *icon, *vbox, *hbox, *separator, *table, *label;
-	GtkWidget *scrolled_window;
+	ESource *source;
 
-	view->priv = ITIP_VIEW_GET_PRIVATE (view);
+	source = itip_view_get_source (view);
 
-	view->priv->mode = ITIP_VIEW_MODE_NONE;
-
-	gtk_box_set_spacing (GTK_BOX (view), 12);
-
-	/* The meeting icon */
-	icon = gtk_image_new_from_icon_name (
-		MEETING_ICON, GTK_ICON_SIZE_LARGE_TOOLBAR);
-	gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0);
-	gtk_widget_show (icon);
-
-	gtk_box_pack_start (GTK_BOX (view), icon, FALSE, FALSE, 0);
-
-	/* The RHS */
-	vbox = gtk_vbox_new (FALSE, 12);
-	gtk_widget_show (vbox);
-	gtk_box_pack_start (GTK_BOX (view), vbox, FALSE, FALSE, 0);
-
-	/* The first section listing the sender */
-	/* FIXME What to do if the send and organizer do not match */
-	view->priv->sender_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->sender_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->sender_label), 0, 0.5);
-	gtk_widget_show (view->priv->sender_label);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->sender_label, FALSE, FALSE, 0);
-
-	separator = gtk_hseparator_new ();
-	gtk_widget_show (separator);
-	gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
-
-	/* A table with information on the meeting and any extra info/warnings */
-	table = gtk_table_new (4, 2, FALSE);
-	gtk_table_set_row_spacings (GTK_TABLE (table), 6);
-	gtk_table_set_col_spacings (GTK_TABLE (table), 6);
-	gtk_widget_show (table);
-	gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
-
-	/* Summary */
-	view->priv->summary_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->summary_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->summary_label), 0, 0.5);
-	gtk_label_set_line_wrap_mode (GTK_LABEL (view->priv->summary_label), PANGO_WRAP_WORD);
-	gtk_label_set_line_wrap (GTK_LABEL (view->priv->summary_label), TRUE);
-	gtk_widget_show (view->priv->summary_label);
-	gtk_table_attach (GTK_TABLE (table), view->priv->summary_label, 0, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
-
-	/* Location */
-	view->priv->location_header = gtk_label_new (_("Location:"));
-	view->priv->location_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->location_header), TRUE);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->location_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->location_header), 0, 0.5);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->location_label), 0, 0.5);
-	gtk_table_attach (GTK_TABLE (table), view->priv->location_header, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
-	gtk_table_attach (GTK_TABLE (table), view->priv->location_label, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0);
-
-	/* Start time */
-	view->priv->start_header = gtk_label_new (_("Start time:"));
-	view->priv->start_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->start_header), TRUE);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->start_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->start_header), 0, 0.5);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->start_label), 0, 0.5);
-	gtk_widget_show (view->priv->start_header);
-	gtk_table_attach (GTK_TABLE (table), view->priv->start_header, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
-	gtk_table_attach (GTK_TABLE (table), view->priv->start_label, 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 0, 0);
-
-	/* End time */
-	view->priv->end_header = gtk_label_new (_("End time:"));
-	view->priv->end_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->end_header), TRUE);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->end_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->end_header), 0, 0.5);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->end_label), 0, 0.5);
-	gtk_table_attach (GTK_TABLE (table), view->priv->end_header, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
-	gtk_table_attach (GTK_TABLE (table), view->priv->end_label, 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, 0, 0, 0);
-
-	/* Status */
-	view->priv->status_header = gtk_label_new (_("Status:"));
-	view->priv->status_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->status_header), TRUE);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->status_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->status_header), 0, 0.5);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->status_label), 0, 0.5);
-	gtk_table_attach (GTK_TABLE (table), view->priv->status_header, 0, 1, 4, 5, GTK_FILL, 0, 0, 0);
-	gtk_table_attach (GTK_TABLE (table), view->priv->status_label, 1, 2, 4, 5, GTK_FILL | GTK_EXPAND, 0, 0, 0);
-
-	/* Comment */
-	view->priv->comment_header = gtk_label_new (_("Comment:"));
-	view->priv->comment_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->comment_header), TRUE);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->comment_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->comment_header), 0, 0.5);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->comment_label), 0, 0.5);
-	gtk_table_attach (GTK_TABLE (table), view->priv->comment_header, 0, 1, 5, 6, GTK_FILL, 0, 0, 0);
-	gtk_table_attach (GTK_TABLE (table), view->priv->comment_label, 1, 2, 5, 6, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+        d(printf("Source changed to '%s'\n", e_source_peek_name (source)));
+	g_signal_emit (view, signals[SOURCE_SELECTED], 0, source);
+}
 
-	/* Upper Info items */
-	view->priv->upper_info_box = gtk_vbox_new (FALSE, 12);
-	gtk_widget_show (view->priv->upper_info_box);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->upper_info_box, FALSE, FALSE, 0);
+static void
+append_checkbox_table_row (GString *buffer,
+                           const gchar *name,
+                           const gchar *label)
+{
+	g_string_append_printf (
+		buffer,
+                "<tr id=\"table_row_%s\" hidden=\"\"><td colspan=\"2\">"
+                "<input type=\"checkbox\" name=\"%s\" id=\"%s\" value=\"%s\" >"
+                "<label for=\"%s\">%s</label>"
+                "</td></tr>\n",
+		name, name, name, name, name, label);
+}
 
-	/* Description */
-	view->priv->description_label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (view->priv->description_label), TRUE);
-	gtk_label_set_line_wrap (GTK_LABEL (view->priv->description_label), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->description_label), 0, 0.5);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->description_label, FALSE, FALSE, 0);
+static void
+append_text_table_row (GString *buffer,
+                       const gchar *id,
+                       const gchar *label,
+                       const gchar *value)
+{
+	if (label && *label) {
 
-	separator = gtk_hseparator_new ();
-	gtk_widget_show (separator);
-	gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
+		g_string_append_printf (buffer,
+                        "<tr id=\"%s\" %s><th>%s</th><td>%s</td></tr>\n",
+                        id, (value && *value) ? "" : "hidden=\"\"", label, value);
 
-	/* Lower Info items */
-	view->priv->lower_info_box = gtk_vbox_new (FALSE, 12);
-	gtk_widget_show (view->priv->lower_info_box);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->lower_info_box, FALSE, FALSE, 0);
+	} else {
 
-	/* Selector area */
-	view->priv->selector_box = gtk_hbox_new (FALSE, 12);
-	gtk_widget_show (view->priv->selector_box);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->selector_box, FALSE, FALSE, 0);
+		g_string_append_printf (
+			buffer,
+                        "<tr id=\"%s\" hidden=\"\"><td colspan=\"2\"></td></tr>\n",
+			id);
 
-	/* RSVP area */
-	view->priv->rsvp_box = gtk_vbox_new (FALSE, 12);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->rsvp_box, FALSE, FALSE, 0);
-
-	view->priv->rsvp_check = gtk_check_button_new_with_mnemonic (_("Send _reply to sender"));
-	gtk_widget_show (view->priv->rsvp_check);
-	gtk_box_pack_start (GTK_BOX (view->priv->rsvp_box), view->priv->rsvp_check, FALSE, FALSE, 0);
-
-	g_signal_connect (
-		view->priv->rsvp_check, "toggled",
-		G_CALLBACK (rsvp_toggled_cb), view);
-
-	hbox = gtk_hbox_new (FALSE, 12);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (view->priv->rsvp_box), hbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new (NULL);
-	gtk_label_set_selectable (GTK_LABEL (label), TRUE);
-	gtk_widget_show (label);
-	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
-	view->priv->rsvp_comment_header = gtk_label_new (_("Comment:"));
-	gtk_label_set_selectable (GTK_LABEL (view->priv->rsvp_comment_header), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (view->priv->rsvp_comment_header), 0.0, 0.0);
-	gtk_widget_set_sensitive (view->priv->rsvp_comment_header, FALSE);
-	gtk_widget_show (view->priv->rsvp_comment_header);
-	gtk_box_pack_start (GTK_BOX (hbox), view->priv->rsvp_comment_header, FALSE, FALSE, 0);
-
-	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
-	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-	gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (scrolled_window), 120);
-	gtk_widget_show (scrolled_window);
-	gtk_box_pack_start (GTK_BOX (hbox), scrolled_window, TRUE, TRUE, 0);
-
-	view->priv->rsvp_comment_text = gtk_text_view_new ();
-	gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->priv->rsvp_comment_text), GTK_WRAP_WORD_CHAR);
-	gtk_widget_set_sensitive (view->priv->rsvp_comment_text, FALSE);
-	gtk_widget_show (view->priv->rsvp_comment_text);
-	gtk_container_add (GTK_CONTAINER (scrolled_window), view->priv->rsvp_comment_text);
+	}
+}
 
-	/* RSVP area */
-	view->priv->update_box = gtk_vbox_new (FALSE, 12);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->update_box, FALSE, FALSE, 0);
+static void
+append_info_item_row (ItipView *view,
+                      const gchar *table_id,
+                      ItipViewInfoItem *item)
+{
+	WebKitDOMElement *table;
+	WebKitDOMHTMLElement *row, *cell;
+	const gchar *icon_name;
+	gchar *id;
+
+	table = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, table_id);
+	row = webkit_dom_html_table_element_insert_row (
+		WEBKIT_DOM_HTML_TABLE_ELEMENT (table), -1, NULL);
+
+        id = g_strdup_printf ("%s_row_%d", table_id, item->id);
+	webkit_dom_html_element_set_id (row, id);
+	g_free (id);
+
+	switch (item->type) {
+		case ITIP_VIEW_INFO_ITEM_TYPE_INFO:
+			icon_name = GTK_STOCK_DIALOG_INFO;
+			break;
+		case ITIP_VIEW_INFO_ITEM_TYPE_WARNING:
+			icon_name = GTK_STOCK_DIALOG_WARNING;
+			break;
+		case ITIP_VIEW_INFO_ITEM_TYPE_ERROR:
+			icon_name = GTK_STOCK_DIALOG_ERROR;
+			break;
+		case ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS:
+			icon_name = GTK_STOCK_FIND;
+			break;
+		case ITIP_VIEW_INFO_ITEM_TYPE_NONE:
+			default:
+			icon_name = NULL;
+	}
 
-	view->priv->update_check = gtk_check_button_new_with_mnemonic (_("Send _updates to attendees"));
-	gtk_widget_show (view->priv->update_check);
-	gtk_box_pack_start (GTK_BOX (view->priv->update_box), view->priv->update_check, FALSE, FALSE, 0);
+	cell = webkit_dom_html_table_row_element_insert_cell (
+		(WebKitDOMHTMLTableRowElement *) row, -1, NULL);
 
-	/* The recurrence check button */
-	view->priv->recur_box = gtk_vbox_new (FALSE, 12);
-	gtk_widget_show (view->priv->recur_box);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->recur_box, FALSE, FALSE, 0);
+	if (icon_name) {
+		WebKitDOMElement *image;
+		gchar *icon_uri;
 
-	view->priv->recur_check = gtk_check_button_new_with_mnemonic (_("_Apply to all instances"));
-	gtk_box_pack_start (GTK_BOX (view->priv->recur_box), view->priv->recur_check, FALSE, FALSE, 0);
+		image = webkit_dom_document_create_element (
+                        view->priv->dom_document, "IMG", NULL);
 
-	g_signal_connect (
-		view->priv->recur_check, "toggled",
-		G_CALLBACK (recur_toggled_cb), view);
+                icon_uri = g_strdup_printf ("gtk-stock://%s", icon_name);
+		webkit_dom_html_image_element_set_src (
+			WEBKIT_DOM_HTML_IMAGE_ELEMENT (image), icon_uri);
+		g_free (icon_uri);
 
-	view->priv->options_box = gtk_vbox_new (FALSE, 2);
-	gtk_widget_show (view->priv->options_box);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->options_box, FALSE, FALSE, 0);
+		webkit_dom_node_append_child (
+			WEBKIT_DOM_NODE (cell),
+			WEBKIT_DOM_NODE (image),
+			NULL);
+	}
+
+	cell = webkit_dom_html_table_row_element_insert_cell (
+		(WebKitDOMHTMLTableRowElement *) row, -1, NULL);
 
-	view->priv->free_time_check = gtk_check_button_new_with_mnemonic (_("Show time as _free"));
-	gtk_box_pack_start (GTK_BOX (view->priv->options_box), view->priv->free_time_check, FALSE, FALSE, 0);
+	webkit_dom_html_element_set_inner_html (cell, item->message, NULL);
 
-	view->priv->keep_alarm_check = gtk_check_button_new_with_mnemonic (_("_Preserve my reminder"));
-	/* default value is to keep user's alarms */
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view->priv->keep_alarm_check), TRUE);
-	gtk_box_pack_start (GTK_BOX (view->priv->options_box), view->priv->keep_alarm_check, FALSE, FALSE, 0);
+        d(printf("Added row %s_row_%d ('%s')\n", table_id, item->id, item->message));
+}
 
-	/* To Translators: This is a check box to inherit a reminder. */
-	view->priv->inherit_alarm_check = gtk_check_button_new_with_mnemonic (_("_Inherit reminder"));
-	gtk_box_pack_start (GTK_BOX (view->priv->options_box), view->priv->inherit_alarm_check, FALSE, FALSE, 0);
+static void
+remove_info_item_row (ItipView *view,
+                      const gchar *table_id,
+                      guint id)
+{
+	WebKitDOMElement *row;
+	gchar *row_id;
 
-	g_signal_connect (
-		view->priv->keep_alarm_check, "toggled",
-		G_CALLBACK (alarm_check_toggled_cb),
-		view->priv->inherit_alarm_check);
-	g_signal_connect (
-		view->priv->inherit_alarm_check, "toggled",
-		G_CALLBACK (alarm_check_toggled_cb),
-		view->priv->keep_alarm_check);
+        row_id = g_strdup_printf ("%s_row_%d", table_id, id);
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, row_id);
+	g_free (row_id);
 
-	/* The buttons for actions */
-	view->priv->button_box = gtk_hbutton_box_new ();
-	gtk_button_box_set_layout (GTK_BUTTON_BOX (view->priv->button_box), GTK_BUTTONBOX_START);
-	gtk_box_set_spacing (GTK_BOX (view->priv->button_box), 12);
-	gtk_widget_show (view->priv->button_box);
-	gtk_box_pack_start (GTK_BOX (vbox), view->priv->button_box, FALSE, FALSE, 0);
+	webkit_dom_node_remove_child (
+		webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row)),
+		WEBKIT_DOM_NODE (row),
+		NULL);
 
-	view->priv->buttons_sensitive = TRUE;
+        d(printf("Removed row %s_row_%d\n", table_id, id));
 }
 
-GtkWidget *
-itip_view_new (void)
+static void
+buttons_table_write_button (GString *buffer,
+                            const gchar *name,
+                            const gchar *label,
+                            const gchar *icon,
+                            ItipViewResponse response)
 {
-	 ItipView *itip_view = g_object_new (ITIP_TYPE_VIEW, "homogeneous", FALSE, "spacing", 6, NULL);
+	g_string_append_printf (
+		buffer,
+                "<td><button type=\"button\" name=\"%s\" value=\"%d\" id=\"%s\" hidden>"
+                "<div><img src=\"gtk-stock://%s?size=%d\"> <span>%s</span></div>"
+                "</button></td>\n",
+		name, response, name, icon, GTK_ICON_SIZE_BUTTON, label);
+}
 
-	 return GTK_WIDGET (itip_view);
+static void
+append_buttons_table (GString *buffer)
+{
+	g_string_append (buffer,
+                         "<table class=\"itip buttons\" border=\"0\" "
+                                "id=\"" TABLE_BUTTONS "\" cellspacing=\"6\" "
+                                "cellpadding=\"0\" >"
+                         "<tr id=\"" TABLE_ROW_BUTTONS "\">");
+
+        /* Everything gets the open button */
+	buttons_table_write_button (
+                buffer, BUTTON_OPEN_CALENDAR, _("Open Calendar"),
+		GTK_STOCK_JUMP_TO, ITIP_VIEW_RESPONSE_OPEN);
+	buttons_table_write_button (
+                buffer, BUTTON_DECLINE_ALL, _("Decline all"),
+		GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
+	buttons_table_write_button (
+                buffer, BUTTON_DECLINE, _("Decline"),
+		GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
+	buttons_table_write_button (
+                buffer, BUTTON_TENTATIVE_ALL, _("Tentative all"),
+		GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
+	buttons_table_write_button (
+                buffer, BUTTON_TENTATIVE, _("Tentative"),
+		GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
+	buttons_table_write_button (
+                buffer, BUTTON_ACCEPT_ALL, _("Accept all"),
+		GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
+	buttons_table_write_button (
+                buffer, BUTTON_ACCEPT, _("Accept"),
+		GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
+	buttons_table_write_button (
+                buffer, BUTTON_SEND_INFORMATION, _("Send Information"),
+		GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_REFRESH);
+	buttons_table_write_button (
+                buffer, BUTTON_UPDATE_ATTENDEE_STATUS, _("Update Attendee Status"),
+		GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_UPDATE);
+	buttons_table_write_button (
+                buffer, BUTTON_UPDATE,  _("Update"),
+		GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_CANCEL);
+
+        g_string_append (buffer, "</tr></table>");
 }
 
 void
-itip_view_set_mode (ItipView *view,
-                    ItipViewMode mode)
+itip_view_write (GString *buffer)
 {
-	ItipViewPrivate *priv;
+	g_string_append (buffer,
+                "<html>\n"
+                "<head>\n"
+                "<title>ITIP</title>\n"
+                "<link type=\"text/css\" rel=\"stylesheet\" href=\"evo-file://" EVOLUTION_PRIVDATADIR "/theme/webview.css\" />\n"
+                "</head>\n"
+                "<body>\n");
 
-	g_return_if_fail (view != NULL);
-	g_return_if_fail (ITIP_IS_VIEW (view));
+	g_string_append_printf (buffer,
+                "<img src=\"gtk-stock://%s?size=%d\" class=\"itip icon\" />\n",
+			MEETING_ICON, GTK_ICON_SIZE_BUTTON);
 
-	priv = view->priv;
+	g_string_append (buffer,
+                "<div class=\"itip content\" id=\"" DIV_ITIP_CONTENT "\">\n");
 
-	priv->mode = mode;
+        /* The first section listing the sender */
+        /* FIXME What to do if the send and organizer do not match */
+	g_string_append (buffer,
+                "<div id=\"" TEXT_ROW_SENDER "\" class=\"itip sender\"></div>\n");
 
-	set_sender_text (view);
-	set_buttons (view);
-}
+        g_string_append (buffer, "<hr>\n");
 
-ItipViewMode
-itip_view_get_mode (ItipView *view)
-{
-	ItipViewPrivate *priv;
+        /* Elementary event information */
+	g_string_append (buffer,
+                "<table class=\"itip table\" border=\"0\" "
+                       "cellspacing=\"5\" cellpadding=\"0\">\n");
 
-	g_return_val_if_fail (view != NULL, ITIP_VIEW_MODE_NONE);
-	g_return_val_if_fail (ITIP_IS_VIEW (view), ITIP_VIEW_MODE_NONE);
+	append_text_table_row (buffer, TABLE_ROW_SUMMARY, NULL, NULL);
+        append_text_table_row (buffer, TABLE_ROW_LOCATION, _("Location:"), NULL);
+        append_text_table_row (buffer, TABLE_ROW_START_DATE, _("Start time:"), NULL);
+        append_text_table_row (buffer, TABLE_ROW_END_DATE, _("End time:"), NULL);
+        append_text_table_row (buffer, TABLE_ROW_STATUS, _("Status:"), NULL);
+        append_text_table_row (buffer, TABLE_ROW_COMMENT, _("Comment:"), NULL);
 
-	priv = view->priv;
+        g_string_append (buffer, "</table>\n");
 
-	return priv->mode;
-}
+	/* Upper Info items */
+	g_string_append (buffer,
+                "<table class=\"itip info\" id=\"" TABLE_UPPER_ITIP_INFO "\" border=\"0\" "
+                       "cellspacing=\"5\" cellpadding=\"0\">");
 
-void
-itip_view_set_item_type (ItipView *view,
-                         ECalClientSourceType type)
-{
-	ItipViewPrivate *priv;
+        /* Description */
+	g_string_append (buffer,
+                "<div id=\"" TABLE_ROW_DESCRIPTION "\" class=\"itip description\" hidden=\"\"></div>\n");
 
-	g_return_if_fail (view != NULL);
-	g_return_if_fail (ITIP_IS_VIEW (view));
+	g_string_append (buffer, "<hr>\n");
 
-	priv = view->priv;
+	/* Lower Info items */
+	g_string_append (buffer,
+                "<table class=\"itip info\" id=\"" TABLE_LOWER_ITIP_INFO "\" border=\"0\" "
+                       "cellspacing=\"5\" cellpadding=\"0\">");
 
-	priv->type = type;
+	g_string_append (buffer,
+                "<table class=\"itip table\" border=\"0\" "
+                       "cellspacing=\"5\" cellpadding=\"0\">\n");
 
-	set_sender_text (view);
+	g_string_append (buffer,
+                "<tr id=\"" TABLE_ROW_ESCB "\" hidden=\"\""">"
+                "<th></th>"
+                "<td><select name=\"" SELECT_ESOURCE "\" id=\"" SELECT_ESOURCE "\"></select></td>"
+                "</tr>\n");
+
+	/* RSVP area */
+        append_checkbox_table_row (buffer, CHECKBOX_RSVP, _("Send reply to sender"));
+
+        /* Comments */
+	g_string_append_printf (buffer,
+                "<tr id=\"" TABLE_ROW_RSVP_COMMENT "\" hidden=\"\">"
+                "<th>%s</th>"
+                "<td><textarea name=\"" TEXTAREA_RSVP_COMMENT "\" "
+                              "id=\"" TEXTAREA_RSVP_COMMENT "\" "
+                              "rows=\"3\" cols=\"40\" disabled=\"\">"
+                "</textarea></td>\n"
+                "</tr>\n",
+                _("Comment:"));
+
+        /* Updates */
+        append_checkbox_table_row (buffer, CHECKBOX_UPDATE, _("Send updates to attendees"));
+
+        /* The recurrence check button */
+        append_checkbox_table_row (buffer, CHECKBOX_RECUR, _("Apply to all instances"));
+        append_checkbox_table_row (buffer, CHECKBOX_FREE_TIME, _("Show time as free"));
+        append_checkbox_table_row (buffer, CHECKBOX_KEEP_ALARM, _("Preserve my reminder"));
+        append_checkbox_table_row (buffer, CHECKBOX_INHERIT_ALARM, _("Inherit reminder"));
+
+        g_string_append (buffer, "</table>\n");
+
+        /* Buttons table */
+	append_buttons_table (buffer);
+
+        /* <div class="itip content" > */
+        g_string_append (buffer, "</div>\n");
+
+        g_string_append (buffer, "<div class=\"itip error\" id=\"" DIV_ITIP_ERROR "\"></div>");
+
+        g_string_append (buffer, "</body></html>");
 }
 
-ECalClientSourceType
-itip_view_get_item_type (ItipView *view)
+void
+itip_view_write_for_printing (ItipView *view,
+                              GString *buffer)
 {
-	ItipViewPrivate *priv;
+	if (view->priv->error && *view->priv->error) {
+		g_string_append (buffer, view->priv->error);
+		return;
+	}
+
+	g_string_append (buffer,
+                "<div class=\"itip print_content\" id=\"" DIV_ITIP_CONTENT "\">\n");
+
+        /* The first section listing the sender */
+        /* FIXME What to do if the send and organizer do not match */
+	g_string_append_printf (buffer,
+                "<div id=\"" TEXT_ROW_SENDER "\" class=\"itip sender\">%s</div>\n",
+                view->priv->sender ? view->priv->sender : "");
+
+        g_string_append (buffer, "<hr>\n");
+
+        /* Elementary event information */
+	g_string_append (buffer,
+                "<table class=\"itip table\" border=\"0\" "
+                       "cellspacing=\"5\" cellpadding=\"0\">\n");
+
+	append_text_table_row (
+		buffer, TABLE_ROW_SUMMARY,
+		NULL, view->priv->summary);
+	append_text_table_row (
+		buffer, TABLE_ROW_LOCATION,
+                _("Location:"), view->priv->location);
+	append_text_table_row (
+		buffer, TABLE_ROW_START_DATE,
+		view->priv->start_header, view->priv->start_label);
+	append_text_table_row (
+		buffer, TABLE_ROW_END_DATE,
+		view->priv->end_header, view->priv->end_label);
+	append_text_table_row (
+		buffer, TABLE_ROW_STATUS,
+                _("Status:"), view->priv->status);
+	append_text_table_row (
+		buffer, TABLE_ROW_COMMENT,
+                _("Comment:"), view->priv->comment);
+
+        g_string_append (buffer, "</table>\n");
+
+        /* Description */
+	g_string_append_printf (
+		buffer,
+                "<div id=\"" TABLE_ROW_DESCRIPTION "\" "
+                     "class=\"itip description\" %s>%s</div>\n",
+                view->priv->description ? "" : "hidden=\"\"", view->priv->description);
+
+        g_string_append (buffer, "</div>");
+}
+
+void
+itip_view_create_dom_bindings (ItipView *view,
+                               WebKitDOMElement *element)
+{
+	WebKitDOMElement *el;
+	WebKitDOMDocument *doc;
+
+	doc = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+	view->priv->dom_document = doc;
+
+	el = webkit_dom_document_get_element_by_id (doc, CHECKBOX_RECUR);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (recur_toggled_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, CHECKBOX_RSVP);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (rsvp_toggled_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, CHECKBOX_INHERIT_ALARM);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (alarm_check_toggled_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, CHECKBOX_KEEP_ALARM);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (alarm_check_toggled_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_OPEN_CALENDAR);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_ACCEPT);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_ACCEPT_ALL);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_TENTATIVE);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_TENTATIVE_ALL);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_DECLINE);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_DECLINE_ALL);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_UPDATE);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_UPDATE_ATTENDEE_STATUS);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, BUTTON_SEND_INFORMATION);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+
+	el = webkit_dom_document_get_element_by_id (doc, SELECT_ESOURCE);
+	if (el) {
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "change",
+			G_CALLBACK (source_changed_cb), FALSE, view);
+	}
+}
+
+static void
+itip_view_init (ItipView *view)
+{
+	view->priv = ITIP_VIEW_GET_PRIVATE (view);
+}
+
+ItipView *
+itip_view_new (ItipPURI *puri)
+{
+	ItipView *view;
+
+	view = ITIP_VIEW (g_object_new (ITIP_TYPE_VIEW, NULL));
+	view->priv->puri = puri;
+
+	return view;
+}
+
+ItipPURI *
+itip_view_get_puri (ItipView *view)
+{
+	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
+
+	return view->priv->puri;
+}
+
+static void
+show_button (ItipView *view,
+             const gchar *id)
+{
+	WebKitDOMElement *button;
+
+	button = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, id);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (button), FALSE);
+}
+
+void
+itip_view_set_mode (ItipView *view,
+                    ItipViewMode mode)
+{
+	WebKitDOMElement *row, *cell;
+	WebKitDOMElement *button;
+
+	g_return_if_fail (ITIP_IS_VIEW (view));
+
+	view->priv->mode = mode;
 
-	g_return_val_if_fail (view != NULL, ITIP_VIEW_MODE_NONE);
+	set_sender_text (view);
+
+	if (!view->priv->dom_document)
+		return;
+
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_BUTTONS);
+	cell = webkit_dom_element_get_first_element_child (row);
+	do {
+		button = webkit_dom_element_get_first_element_child (cell);
+		webkit_dom_html_element_set_hidden (
+			WEBKIT_DOM_HTML_ELEMENT (button), TRUE);
+	} while ((cell = webkit_dom_element_get_next_element_sibling (cell)) != NULL);
+
+	view->priv->is_recur_set = itip_view_get_recur_check_state (view);
+
+        /* Always visible */
+	show_button (view, BUTTON_OPEN_CALENDAR);
+
+	switch (mode) {
+	case ITIP_VIEW_MODE_PUBLISH:
+		if (view->priv->needs_decline) {
+			show_button (view, BUTTON_DECLINE);
+		}
+		show_button (view, BUTTON_ACCEPT);
+		break;
+	case ITIP_VIEW_MODE_REQUEST:
+		show_button (view, view->priv->is_recur_set ? BUTTON_DECLINE_ALL : BUTTON_DECLINE);
+		show_button (view, view->priv->is_recur_set ? BUTTON_TENTATIVE_ALL : BUTTON_TENTATIVE);
+		show_button (view, view->priv->is_recur_set ? BUTTON_ACCEPT_ALL : BUTTON_ACCEPT);
+		break;
+	case ITIP_VIEW_MODE_ADD:
+		if (view->priv->type != E_CAL_CLIENT_SOURCE_TYPE_MEMOS) {
+			show_button (view, BUTTON_DECLINE);
+			show_button (view, BUTTON_TENTATIVE);
+		}
+		show_button (view, BUTTON_ACCEPT);
+		break;
+	case ITIP_VIEW_MODE_REFRESH:
+		show_button (view, BUTTON_SEND_INFORMATION);
+		break;
+	case ITIP_VIEW_MODE_REPLY:
+		show_button (view, BUTTON_UPDATE_ATTENDEE_STATUS);
+		break;
+	case ITIP_VIEW_MODE_CANCEL:
+		show_button (view, BUTTON_UPDATE);
+		break;
+	case ITIP_VIEW_MODE_COUNTER:
+	case ITIP_VIEW_MODE_DECLINECOUNTER:
+		show_button (view, BUTTON_DECLINE);
+		show_button (view, BUTTON_TENTATIVE);
+		show_button (view, BUTTON_ACCEPT);
+		break;
+	default:
+		break;
+	}
+}
+
+ItipViewMode
+itip_view_get_mode (ItipView *view)
+{
 	g_return_val_if_fail (ITIP_IS_VIEW (view), ITIP_VIEW_MODE_NONE);
 
-	priv = view->priv;
+	return view->priv->mode;
+}
+
+void
+itip_view_set_item_type (ItipView *view,
+                         ECalClientSourceType type)
+{
+	WebKitDOMElement *row, *cell;
+	const gchar *header;
+
+	g_return_if_fail (ITIP_IS_VIEW (view));
+
+	view->priv->type = type;
+
+	if (!view->priv->dom_document)
+		return;
+
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_ESCB);
+	cell = webkit_dom_element_get_first_element_child (row);
+
+	switch (view->priv->type) {
+		case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
+                        header = _("Calendar:");
+			break;
+		case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
+                        header = _("Tasks:");
+			break;
+		case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
+                        header = _("Memos:");
+			break;
+		default:
+			header = NULL;
+			break;
+	}
+
+	webkit_dom_html_element_set_inner_html (
+                WEBKIT_DOM_HTML_ELEMENT (cell), header ? header : "", NULL);
+
+	set_sender_text (view);
+}
+
+ECalClientSourceType
+itip_view_get_item_type (ItipView *view)
+{
+	g_return_val_if_fail (ITIP_IS_VIEW (view), ITIP_VIEW_MODE_NONE);
 
-	return priv->type;
+	return view->priv->type;
 }
 
 void
 itip_view_set_organizer (ItipView *view,
                          const gchar *organizer)
 {
-	ItipViewPrivate *priv;
-
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->organizer)
+		g_free (view->priv->organizer);
 
-	if (priv->organizer)
-		g_free (priv->organizer);
-
-	priv->organizer = e_utf8_ensure_valid (organizer);
+	view->priv->organizer = e_utf8_ensure_valid (organizer);
 
 	set_sender_text (view);
 }
@@ -1308,31 +1580,21 @@ itip_view_set_organizer (ItipView *view,
 const gchar *
 itip_view_get_organizer (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->organizer;
+	return view->priv->organizer;
 }
 
 void
 itip_view_set_organizer_sentby (ItipView *view,
                                 const gchar *sentby)
 {
-	ItipViewPrivate *priv;
-
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->organizer_sentby)
+		g_free (view->priv->organizer_sentby);
 
-	if (priv->organizer_sentby)
-		g_free (priv->organizer_sentby);
-
-	priv->organizer_sentby = e_utf8_ensure_valid (sentby);
+	view->priv->organizer_sentby = e_utf8_ensure_valid (sentby);
 
 	set_sender_text (view);
 }
@@ -1340,31 +1602,21 @@ itip_view_set_organizer_sentby (ItipView *view,
 const gchar *
 itip_view_get_organizer_sentby (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->organizer_sentby;
+	return view->priv->organizer_sentby;
 }
 
 void
 itip_view_set_attendee (ItipView *view,
                         const gchar *attendee)
 {
-	ItipViewPrivate *priv;
-
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
-
-	if (priv->attendee)
-		g_free (priv->attendee);
+	if (view->priv->attendee)
+		g_free (view->priv->attendee);
 
-	priv->attendee = e_utf8_ensure_valid (attendee);
+	view->priv->attendee = e_utf8_ensure_valid (attendee);
 
 	set_sender_text (view);
 }
@@ -1372,31 +1624,21 @@ itip_view_set_attendee (ItipView *view,
 const gchar *
 itip_view_get_attendee (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->attendee;
+	return view->priv->attendee;
 }
 
 void
 itip_view_set_attendee_sentby (ItipView *view,
                                const gchar *sentby)
 {
-	ItipViewPrivate *priv;
-
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->attendee_sentby)
+		g_free (view->priv->attendee_sentby);
 
-	if (priv->attendee_sentby)
-		g_free (priv->attendee_sentby);
-
-	priv->attendee_sentby = e_utf8_ensure_valid (sentby);
+	view->priv->attendee_sentby = e_utf8_ensure_valid (sentby);
 
 	set_sender_text (view);
 }
@@ -1404,31 +1646,21 @@ itip_view_set_attendee_sentby (ItipView *view,
 const gchar *
 itip_view_get_attendee_sentby (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->attendee_sentby;
+	return view->priv->attendee_sentby;
 }
 
 void
 itip_view_set_proxy (ItipView *view,
                      const gchar *proxy)
 {
-	ItipViewPrivate *priv;
-
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->proxy)
+		g_free (view->priv->proxy);
 
-	if (priv->proxy)
-		g_free (priv->proxy);
-
-	priv->proxy = e_utf8_ensure_valid (proxy);
+	view->priv->proxy = e_utf8_ensure_valid (proxy);
 
 	set_sender_text (view);
 }
@@ -1436,31 +1668,21 @@ itip_view_set_proxy (ItipView *view,
 const gchar *
 itip_view_get_proxy (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->proxy;
+	return view->priv->proxy;
 }
 
 void
 itip_view_set_delegator (ItipView *view,
                          const gchar *delegator)
 {
-	ItipViewPrivate *priv;
-
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
-
-	if (priv->delegator)
-		g_free (priv->delegator);
+	if (view->priv->delegator)
+		g_free (view->priv->delegator);
 
-	priv->delegator = e_utf8_ensure_valid (delegator);
+	view->priv->delegator = e_utf8_ensure_valid (delegator);
 
 	set_sender_text (view);
 }
@@ -1468,174 +1690,188 @@ itip_view_set_delegator (ItipView *view,
 const gchar *
 itip_view_get_delegator (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->delegator;
+	return view->priv->delegator;
 }
 
 void
 itip_view_set_summary (ItipView *view,
                        const gchar *summary)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *row, *col;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->summary)
+		g_free (view->priv->summary);
 
-	if (priv->summary)
-		g_free (priv->summary);
+	view->priv->summary = summary ? g_strstrip (e_utf8_ensure_valid (summary)) : NULL;
+
+	if (!view->priv->dom_document)
+		return;
 
-	priv->summary = summary ? g_strstrip (e_utf8_ensure_valid (summary)) : NULL;
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_SUMMARY);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (row), (view->priv->summary == NULL));
 
-	set_summary_text (view);
+	col = webkit_dom_element_get_last_element_child (row);
+	webkit_dom_html_element_set_inner_html (
+		WEBKIT_DOM_HTML_ELEMENT (col),
+                view->priv->summary ? view->priv->summary : "",
+		NULL);
 }
 
 const gchar *
 itip_view_get_summary (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->summary;
+	return view->priv->summary;
 }
 
 void
 itip_view_set_location (ItipView *view,
                         const gchar *location)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *row, *col;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->location)
+		g_free (view->priv->location);
 
-	if (priv->location)
-		g_free (priv->location);
+	view->priv->location = location ? g_strstrip (e_utf8_ensure_valid (location)) : NULL;
+
+	if (!view->priv->dom_document)
+		return;
 
-	priv->location = location ? g_strstrip (e_utf8_ensure_valid (location)) : NULL;
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_LOCATION);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (row), (view->priv->location == NULL));
 
-	set_location_text (view);
+	col = webkit_dom_element_get_last_element_child (row);
+	webkit_dom_html_element_set_inner_html (
+		WEBKIT_DOM_HTML_ELEMENT (col),
+                view->priv->location ? view->priv->location : "",
+		NULL);
 }
 
 const gchar *
 itip_view_get_location (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->location;
+	return view->priv->location;
 }
 
 void
 itip_view_set_status (ItipView *view,
                       const gchar *status)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *row, *col;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->status)
+		g_free (view->priv->status);
 
-	if (priv->status)
-		g_free (priv->status);
+	view->priv->status = status ? g_strstrip (e_utf8_ensure_valid (status)) : NULL;
+
+	if (!view->priv->dom_document)
+		return;
 
-	priv->status = status ? g_strstrip (e_utf8_ensure_valid (status)) : NULL;
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_STATUS);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (row), (view->priv->status == NULL));
 
-	set_status_text (view);
+	col = webkit_dom_element_get_last_element_child (row);
+	webkit_dom_html_element_set_inner_html (
+		WEBKIT_DOM_HTML_ELEMENT (col),
+                view->priv->status ? view->priv->status : "",
+		NULL);
 }
 
 const gchar *
 itip_view_get_status (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->status;
+	return view->priv->status;
 }
 
 void
 itip_view_set_comment (ItipView *view,
                        const gchar *comment)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *row, *col;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->comment)
+		g_free (view->priv->comment);
 
-	if (priv->comment)
-		g_free (priv->comment);
+	view->priv->comment = comment ? g_strstrip (e_utf8_ensure_valid (comment)) : NULL;
 
-	priv->comment = comment ? g_strstrip (e_utf8_ensure_valid (comment)) : NULL;
+	if (!view->priv->dom_document)
+		return;
+
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_COMMENT);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (row), (view->priv->comment == NULL));
 
-	set_comment_text (view);
+	col = webkit_dom_element_get_last_element_child (row);
+	webkit_dom_html_element_set_inner_html (
+		WEBKIT_DOM_HTML_ELEMENT (col),
+                view->priv->comment ? view->priv->comment : "",
+		NULL);
 }
 
 const gchar *
 itip_view_get_comment (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->comment;
+	return view->priv->comment;
 }
 
 void
 itip_view_set_description (ItipView *view,
                            const gchar *description)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *div;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (view->priv->description)
+		g_free (view->priv->description);
 
-	if (priv->description)
-		g_free (priv->description);
+	view->priv->description = description ? g_strstrip (e_utf8_ensure_valid (description)) : NULL;
 
-	priv->description = description ? g_strstrip (e_utf8_ensure_valid (description)) : NULL;
+	if (!view->priv->dom_document)
+		return;
 
-	set_description_text (view);
+	div = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_DESCRIPTION);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (div), (view->priv->description == NULL));
+
+	webkit_dom_html_element_set_inner_html (
+		WEBKIT_DOM_HTML_ELEMENT (div),
+                view->priv->description ? view->priv->description : "",
+		NULL);
 }
 
 const gchar *
 itip_view_get_description (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->description;
+	return view->priv->description;
 }
 
 void
@@ -1645,7 +1881,6 @@ itip_view_set_start (ItipView *view,
 {
 	ItipViewPrivate *priv;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
 	priv = view->priv;
@@ -1669,17 +1904,12 @@ const struct tm *
 itip_view_get_start (ItipView *view,
                      gboolean *is_date)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
 	if (is_date)
-		*is_date = priv->start_tm_is_date;
+		*is_date = view->priv->start_tm_is_date;
 
-	return priv->start_tm;
+	return view->priv->start_tm;
 }
 
 void
@@ -1689,7 +1919,6 @@ itip_view_set_end (ItipView *view,
 {
 	ItipViewPrivate *priv;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
 	priv = view->priv;
@@ -1713,17 +1942,12 @@ const struct tm *
 itip_view_get_end (ItipView *view,
                    gboolean *is_date)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
 	if (is_date)
-		*is_date = priv->end_tm_is_date;
+		*is_date = view->priv->end_tm_is_date;
 
-	return priv->end_tm;
+	return view->priv->end_tm;
 }
 
 guint
@@ -1734,7 +1958,6 @@ itip_view_add_upper_info_item (ItipView *view,
 	ItipViewPrivate *priv;
 	ItipViewInfoItem *item;
 
-	g_return_val_if_fail (view != NULL, 0);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), 0);
 
 	priv = view->priv;
@@ -1747,7 +1970,10 @@ itip_view_add_upper_info_item (ItipView *view,
 
 	priv->upper_info_items = g_slist_append (priv->upper_info_items, item);
 
-	set_upper_info_items (view);
+	if (!view->priv->dom_document)
+		return item->id;
+
+	append_info_item_row (view, TABLE_UPPER_ITIP_INFO, item);
 
 	return item->id;
 }
@@ -1762,7 +1988,6 @@ itip_view_add_upper_info_item_printf (ItipView *view,
 	gchar *message;
 	guint id;
 
-	g_return_val_if_fail (view != NULL, 0);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), 0);
 
 	va_start (args, format);
@@ -1782,7 +2007,6 @@ itip_view_remove_upper_info_item (ItipView *view,
 	ItipViewPrivate *priv;
 	GSList *l;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
 	priv = view->priv;
@@ -1796,7 +2020,8 @@ itip_view_remove_upper_info_item (ItipView *view,
 			g_free (item->message);
 			g_free (item);
 
-			set_upper_info_items (view);
+			if (!view->priv->dom_document)
+				remove_info_item_row (view, TABLE_UPPER_ITIP_INFO, id);
 
 			return;
 		}
@@ -1809,16 +2034,16 @@ itip_view_clear_upper_info_items (ItipView *view)
 	ItipViewPrivate *priv;
 	GSList *l;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
 	priv = view->priv;
 
-	gtk_container_foreach (GTK_CONTAINER (priv->upper_info_box), (GtkCallback) gtk_widget_destroy, NULL);
-
 	for (l = priv->upper_info_items; l; l = l->next) {
 		ItipViewInfoItem *item = l->data;
 
+		if (view->priv->dom_document)
+			remove_info_item_row (view, TABLE_UPPER_ITIP_INFO, item->id);
+
 		g_free (item->message);
 		g_free (item);
 	}
@@ -1835,7 +2060,6 @@ itip_view_add_lower_info_item (ItipView *view,
 	ItipViewPrivate *priv;
 	ItipViewInfoItem *item;
 
-	g_return_val_if_fail (view != NULL, 0);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), 0);
 
 	priv = view->priv;
@@ -1848,7 +2072,10 @@ itip_view_add_lower_info_item (ItipView *view,
 
 	priv->lower_info_items = g_slist_append (priv->lower_info_items, item);
 
-	set_lower_info_items (view);
+	if (!view->priv->dom_document)
+		return item->id;
+
+	append_info_item_row (view, TABLE_LOWER_ITIP_INFO, item);
 
 	return item->id;
 }
@@ -1863,7 +2090,6 @@ itip_view_add_lower_info_item_printf (ItipView *view,
 	gchar *message;
 	guint id;
 
-	g_return_val_if_fail (view != NULL, 0);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), 0);
 
 	va_start (args, format);
@@ -1883,7 +2109,6 @@ itip_view_remove_lower_info_item (ItipView *view,
 	ItipViewPrivate *priv;
 	GSList *l;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
 	priv = view->priv;
@@ -1897,7 +2122,8 @@ itip_view_remove_lower_info_item (ItipView *view,
 			g_free (item->message);
 			g_free (item);
 
-			set_lower_info_items (view);
+			if (view->priv->dom_document)
+				remove_info_item_row (view, TABLE_LOWER_ITIP_INFO, id);
 
 			return;
 		}
@@ -1910,16 +2136,16 @@ itip_view_clear_lower_info_items (ItipView *view)
 	ItipViewPrivate *priv;
 	GSList *l;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
 	priv = view->priv;
 
-	gtk_container_foreach (GTK_CONTAINER (priv->lower_info_box), (GtkCallback) gtk_widget_destroy, NULL);
-
 	for (l = priv->lower_info_items; l; l = l->next) {
 		ItipViewInfoItem *item = l->data;
 
+		if (view->priv->dom_document)
+			remove_info_item_row (view, TABLE_LOWER_ITIP_INFO, item->id);
+
 		g_free (item->message);
 		g_free (item);
 	}
@@ -1929,14 +2155,76 @@ itip_view_clear_lower_info_items (ItipView *view)
 }
 
 static void
-source_changed_cb (ESourceComboBox *escb,
-                   ItipView *view)
+source_list_changed_cb (ESourceList *source_list,
+                        ItipView *view)
 {
-	ESource *source;
+	GSList *groups, *iter;
+	WebKitDOMElement *select;
 
-	source = e_source_combo_box_get_active (escb);
+        d(printf("Assigning a new source list!\n"));
 
-	g_signal_emit (view, signals[SOURCE_SELECTED], 0, source);
+	if (!view->priv->dom_document)
+		return;
+
+	select = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, SELECT_ESOURCE);
+
+	while (webkit_dom_node_has_child_nodes (WEBKIT_DOM_NODE (select))) {
+		webkit_dom_node_remove_child (
+			WEBKIT_DOM_NODE (select),
+			webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (select)),
+			NULL);
+	}
+
+	groups = e_source_list_peek_groups (source_list);
+	for (iter = groups; iter; iter = iter->next) {
+
+		ESourceGroup *group = iter->data;
+		GSList *sources, *iter2;
+		WebKitDOMElement *optgroup;
+
+		sources = e_source_group_peek_sources (group);
+		if (sources == NULL)
+			continue;
+
+		optgroup = webkit_dom_document_create_element (
+                        view->priv->dom_document, "OPTGROUP", NULL);
+		webkit_dom_html_opt_group_element_set_label (
+			WEBKIT_DOM_HTML_OPT_GROUP_ELEMENT (optgroup),
+			e_source_group_peek_name (group));
+
+		webkit_dom_node_append_child (
+			WEBKIT_DOM_NODE (select),
+			WEBKIT_DOM_NODE (optgroup),
+			NULL);
+
+		for (iter2 = sources; iter2; iter2 = iter2->next) {
+
+			WebKitDOMElement *option;
+			ESource *source = iter2->data;
+
+			option = webkit_dom_document_create_element (
+                                view->priv->dom_document, "OPTION", NULL);
+			webkit_dom_html_option_element_set_value (
+				WEBKIT_DOM_HTML_OPTION_ELEMENT (option),
+				e_source_peek_uid (source));
+			webkit_dom_html_option_element_set_label (
+				WEBKIT_DOM_HTML_OPTION_ELEMENT (option),
+				e_source_peek_name (source));
+			webkit_dom_html_element_set_inner_html (
+				WEBKIT_DOM_HTML_ELEMENT (option),
+				e_source_peek_name (source), NULL);
+			webkit_dom_html_element_set_class_name (
+                                WEBKIT_DOM_HTML_ELEMENT (option), "calendar");
+
+			webkit_dom_node_append_child (
+				WEBKIT_DOM_NODE (optgroup),
+				WEBKIT_DOM_NODE (option),
+				NULL);
+		}
+	}
+
+	source_changed_cb (select, NULL, view);
 }
 
 void
@@ -1945,7 +2233,6 @@ itip_view_set_source_list (ItipView *view,
 {
 	ItipViewPrivate *priv;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
 	priv = view->priv;
@@ -1953,380 +2240,660 @@ itip_view_set_source_list (ItipView *view,
 	if (priv->source_list)
 		g_object_unref (priv->source_list);
 
-	if (priv->escb)
-		gtk_widget_destroy (priv->escb);
-
 	if (!source_list) {
-		if (priv->escb_header)
-			gtk_widget_destroy (priv->escb_header);
-
 		priv->source_list = NULL;
-		priv->escb = NULL;
-		priv->escb_header = NULL;
-
 		return;
 	}
 
 	priv->source_list = g_object_ref (source_list);
 
-	priv->escb = e_source_combo_box_new (source_list);
-	gtk_widget_show (priv->escb);
-	g_signal_connect (
-		priv->escb, "changed",
-		G_CALLBACK (source_changed_cb), view);
-
-	if (!priv->escb_header) {
-		if (priv->type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS)
-			priv->escb_header = gtk_label_new_with_mnemonic (_("_Calendar:"));
-		else if (priv->type == E_CAL_CLIENT_SOURCE_TYPE_TASKS)
-			priv->escb_header = gtk_label_new_with_mnemonic (_("_Tasks:"));
-		else if (priv->type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS)
-			priv->escb_header = gtk_label_new_with_mnemonic (_("_Memos:"));
-
-		gtk_label_set_selectable (GTK_LABEL (priv->escb_header), TRUE);
-		gtk_label_set_mnemonic_widget (GTK_LABEL (priv->escb_header), priv->escb);
-		gtk_widget_show (priv->escb_header);
-	}
+	source_list_changed_cb (source_list, view);
 
-	gtk_box_pack_start (GTK_BOX (priv->selector_box), priv->escb_header, FALSE, TRUE, 6);
-	gtk_box_pack_start (GTK_BOX (priv->selector_box), priv->escb, FALSE, TRUE, 0);
+        g_signal_connect (source_list, "changed",
+		G_CALLBACK (source_list_changed_cb), view);
 }
 
 ESourceList *
 itip_view_get_source_list (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	return priv->source_list;
+	return view->priv->source_list;
 }
 
 void
 itip_view_set_source (ItipView *view,
                       ESource *source)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *select;
+	WebKitDOMElement *row;
+	gulong i, len;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+        d(printf("Settings default source '%s'\n", e_source_peek_name (source)));
 
-	if (!priv->escb)
+	if (!view->priv->dom_document)
 		return;
 
-	e_source_combo_box_set_active (
-		E_SOURCE_COMBO_BOX (priv->escb), source);
+	row = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_ESCB);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (row), (source == NULL));
+	if (source == NULL)
+		return;
+
+	select = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, SELECT_ESOURCE);
+
+        /* <select> does not emit 'change' event when already selected <option>
+         * is re-selected, but we need to notify itip formatter, so that it would
+         * make all the buttons sensitive */
+	if (source == itip_view_get_source (view)) {
+		source_changed_cb (select, NULL, view);
+	}
+
+	if (webkit_dom_html_select_element_get_disabled (
+			WEBKIT_DOM_HTML_SELECT_ELEMENT (select))) {
+		webkit_dom_html_select_element_set_disabled (
+			WEBKIT_DOM_HTML_SELECT_ELEMENT (select), FALSE);
+	}
+
+	len = webkit_dom_html_select_element_get_length (
+		WEBKIT_DOM_HTML_SELECT_ELEMENT (select));
+	for (i = 0; i < len; i++) {
+
+		WebKitDOMNode *node;
+		WebKitDOMHTMLOptionElement *option;
+		gchar *value;
+
+		node = webkit_dom_html_select_element_item (
+			WEBKIT_DOM_HTML_SELECT_ELEMENT (select), i);
+		option = WEBKIT_DOM_HTML_OPTION_ELEMENT (node);
+
+		value = webkit_dom_html_option_element_get_value (option);
+		if (g_strcmp0 (value, e_source_peek_uid (source)) == 0) {
+			webkit_dom_html_option_element_set_selected (
+				option, TRUE);
+
+			g_free (value);
+			break;
+		}
+
+		g_free (value);
+	}
 }
 
 ESource *
 itip_view_get_source (ItipView *view)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *select;
+	gchar *uid;
+	ESource *source;
+	gboolean disable = FALSE;
 
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
-
-	if (!priv->escb)
+	if (!view->priv->dom_document)
 		return NULL;
 
-	return e_source_combo_box_get_active (
-		E_SOURCE_COMBO_BOX (priv->escb));
+	select = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, SELECT_ESOURCE);
+	if (webkit_dom_html_select_element_get_disabled (
+			WEBKIT_DOM_HTML_SELECT_ELEMENT (select))) {
+		webkit_dom_html_select_element_set_disabled (
+		WEBKIT_DOM_HTML_SELECT_ELEMENT (select), FALSE);
+		disable = TRUE;
+	}
+
+	uid = webkit_dom_html_select_element_get_value (
+		WEBKIT_DOM_HTML_SELECT_ELEMENT (select));
+
+	source = e_source_list_peek_source_by_uid (
+		view->priv->source_list, uid);
+	g_free (uid);
+
+	if (disable) {
+		webkit_dom_html_select_element_set_disabled (
+			WEBKIT_DOM_HTML_SELECT_ELEMENT (select), TRUE);
+	}
+
+	return source;
 }
 
 void
 itip_view_set_rsvp (ItipView *view,
                     gboolean rsvp)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *el;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return;
 
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->rsvp_check), rsvp);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_RSVP);
+	webkit_dom_html_input_element_set_checked (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), rsvp);
 
-	gtk_widget_set_sensitive (priv->rsvp_comment_header, rsvp);
-	gtk_widget_set_sensitive (priv->rsvp_comment_text, rsvp);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TEXTAREA_RSVP_COMMENT);
+	webkit_dom_html_text_area_element_set_disabled (
+		WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), !rsvp);
 }
 
 gboolean
 itip_view_get_rsvp (ItipView *view)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *el;
 
-	g_return_val_if_fail (view != NULL, FALSE);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return FALSE;
 
-	return priv->rsvp_show && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->rsvp_check));
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_UPDATE);
+	return webkit_dom_html_input_element_get_checked (WEBKIT_DOM_HTML_INPUT_ELEMENT (el));
 }
 
 void
-itip_view_set_show_rsvp (ItipView *view,
-                         gboolean rsvp)
+itip_view_set_show_rsvp_check (ItipView *view,
+                               gboolean show)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *label;
+	WebKitDOMElement *el;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return;
 
-	priv->rsvp_show = rsvp;
+	el = webkit_dom_document_get_element_by_id (
+                view->priv->dom_document, "table_row_" CHECKBOX_RSVP);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
 
-	priv->rsvp_show ? gtk_widget_show (priv->rsvp_box) : gtk_widget_hide (priv->rsvp_box);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_RSVP);
+	label = webkit_dom_element_get_next_element_sibling (el);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (label), !show);
+
+	if (!show) {
+		webkit_dom_html_input_element_set_checked (
+			WEBKIT_DOM_HTML_INPUT_ELEMENT (el), FALSE);
+	}
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_RSVP_COMMENT);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
 }
 
 gboolean
-itip_view_get_show_rsvp (ItipView *view)
+itip_view_get_show_rsvp_check (ItipView *view)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *el;
 
-	g_return_val_if_fail (view != NULL, FALSE);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return FALSE;
 
-	return priv->rsvp_show;
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_RSVP);
+	return !webkit_dom_html_element_get_hidden (WEBKIT_DOM_HTML_ELEMENT (el));
 }
 
 void
 itip_view_set_update (ItipView *view,
                       gboolean update)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *el;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return;
 
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->update_check), update);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_UPDATE);
+
+	webkit_dom_html_input_element_set_checked (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), update);
 }
 
 gboolean
 itip_view_get_update (ItipView *view)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *el;
 
-	g_return_val_if_fail (view != NULL, FALSE);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return FALSE;
 
-	return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->update_check));
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_UPDATE);
+	return webkit_dom_html_input_element_get_checked (WEBKIT_DOM_HTML_INPUT_ELEMENT (el));
 }
 
 void
-itip_view_set_show_update (ItipView *view,
-                           gboolean update)
+itip_view_set_show_update_check (ItipView *view,
+                                 gboolean show)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *label;
+	WebKitDOMElement *el;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return;
+
+	el = webkit_dom_document_get_element_by_id (
+                view->priv->dom_document, "table_row_" CHECKBOX_UPDATE);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
 
-	priv->update_show = update;
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_UPDATE);
+	label = webkit_dom_element_get_next_element_sibling (el);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (label), !show);
 
-	priv->update_show ? gtk_widget_show (priv->update_box) : gtk_widget_hide (priv->update_box);
+	if (!show) {
+		webkit_dom_html_input_element_set_checked (
+			WEBKIT_DOM_HTML_INPUT_ELEMENT (el), FALSE);
+	}
 }
 
 gboolean
-itip_view_get_show_update (ItipView *view)
+itip_view_get_show_update_check (ItipView *view)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *el;
 
-	g_return_val_if_fail (view != NULL, FALSE);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return FALSE;
 
-	return priv->update_show;
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_UPDATE);
+	return !webkit_dom_html_element_get_hidden (WEBKIT_DOM_HTML_ELEMENT (el));
 }
 
 void
 itip_view_set_rsvp_comment (ItipView *view,
                             const gchar *comment)
 {
-	ItipViewPrivate *priv;
-	GtkTextBuffer *text_buffer;
+	WebKitDOMElement *el;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return;
 
-	text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->rsvp_comment_text));
-	gtk_text_buffer_set_text (text_buffer, comment, -1);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TEXTAREA_RSVP_COMMENT);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (el), (comment == NULL));
+
+	if (comment) {
+		webkit_dom_html_text_area_element_set_value (
+			WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), comment);
+	}
 }
 
 gchar *
 itip_view_get_rsvp_comment (ItipView *view)
 {
-	ItipViewPrivate *priv;
-	GtkTextBuffer *text_buffer;
-	GtkTextIter start, end;
+	WebKitDOMElement *el;
 
-	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
 
-	priv = view->priv;
+	if (!view->priv->dom_document)
+		return NULL;
 
-	text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->rsvp_comment_text));
-	gtk_text_buffer_get_bounds (text_buffer, &start, &end);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TEXTAREA_RSVP_COMMENT);
 
-	return gtk_text_buffer_get_text (text_buffer, &start, &end, FALSE);
+	if (webkit_dom_html_element_get_hidden (WEBKIT_DOM_HTML_ELEMENT (el))) {
+		return NULL;
+	}
+
+	return webkit_dom_html_text_area_element_get_value (
+		WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el));
 }
 
 void
 itip_view_set_needs_decline (ItipView *view,
                              gboolean needs_decline)
 {
-	ItipViewPrivate *priv;
-
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
-
-	priv->needs_decline = needs_decline;
+	view->priv->needs_decline = needs_decline;
 }
 
 void
 itip_view_set_buttons_sensitive (ItipView *view,
                                  gboolean sensitive)
 {
-	ItipViewPrivate *priv;
+	WebKitDOMElement *el, *cell;
 
-	g_return_if_fail (view != NULL);
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	priv = view->priv;
+        d(printf("Settings buttons %s\n", sensitive ? "sensitive" : "insensitive"));
+
+	view->priv->buttons_sensitive = sensitive;
 
-	priv->buttons_sensitive = sensitive;
+	if (!view->priv->dom_document)
+		return;
 
-	gtk_widget_set_sensitive (priv->button_box, priv->buttons_sensitive);
-	gtk_widget_set_sensitive (priv->update_box, priv->buttons_sensitive);
-	gtk_widget_set_sensitive (priv->recur_box, priv->buttons_sensitive);
-	gtk_widget_set_sensitive (priv->options_box, priv->buttons_sensitive);
-	gtk_widget_set_sensitive (priv->selector_box, priv->buttons_sensitive);
-	gtk_widget_set_sensitive (priv->rsvp_box, priv->buttons_sensitive);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_UPDATE);
+	webkit_dom_html_input_element_set_disabled (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_RECUR);
+	webkit_dom_html_input_element_set_disabled (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_FREE_TIME);
+	webkit_dom_html_input_element_set_disabled (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_KEEP_ALARM);
+	webkit_dom_html_input_element_set_disabled (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_INHERIT_ALARM);
+	webkit_dom_html_input_element_set_disabled (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_RSVP);
+	webkit_dom_html_input_element_set_disabled (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TEXTAREA_RSVP_COMMENT);
+	webkit_dom_html_text_area_element_set_disabled (
+		WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, SELECT_ESOURCE);
+	webkit_dom_html_select_element_set_disabled (
+		WEBKIT_DOM_HTML_SELECT_ELEMENT (el), !sensitive);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, TABLE_ROW_BUTTONS);
+	cell = webkit_dom_element_get_first_element_child (el);
+	do {
+		WebKitDOMElement *btn;
+		btn = webkit_dom_element_get_first_element_child (cell);
+		if (!webkit_dom_html_element_get_hidden (
+			WEBKIT_DOM_HTML_ELEMENT (btn))) {
+			webkit_dom_html_button_element_set_disabled (
+				WEBKIT_DOM_HTML_BUTTON_ELEMENT (btn), !sensitive);
+		}
+	} while ((cell = webkit_dom_element_get_next_element_sibling (cell)) != NULL);
 }
 
 gboolean
 itip_view_get_buttons_sensitive (ItipView *view)
 {
-	ItipViewPrivate *priv;
-
-	g_return_val_if_fail (view != NULL, FALSE);
 	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
 
-	priv = view->priv;
-
-	return priv->buttons_sensitive;
+	return view->priv->buttons_sensitive;
 }
 
 gboolean
 itip_view_get_recur_check_state (ItipView *view)
 {
-	return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (view->priv->recur_check));
+	WebKitDOMElement *el;
+
+	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
+
+	if (!view->priv->dom_document)
+		return FALSE;
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_RECUR);
+	return webkit_dom_html_input_element_get_checked (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el));
 }
 
 void
 itip_view_set_show_recur_check (ItipView *view,
                                 gboolean show)
 {
-	g_return_if_fail (view != NULL);
+	WebKitDOMElement *label;
+	WebKitDOMElement *el;
+
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	if (show)
-		gtk_widget_show (view->priv->recur_check);
-	else {
-		gtk_widget_hide (view->priv->recur_check);
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view->priv->recur_check), FALSE);
+	if (!view->priv->dom_document)
+		return;
+
+	el = webkit_dom_document_get_element_by_id (
+                view->priv->dom_document, "table_row_" CHECKBOX_RECUR);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_RECUR);
+	label = webkit_dom_element_get_next_element_sibling (el);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (label), !show);
+
+	if (!show) {
+		webkit_dom_html_input_element_set_checked (
+			WEBKIT_DOM_HTML_INPUT_ELEMENT (el), FALSE);
 	}
+
+        /* and update state of the second check */
+	alarm_check_toggled_cb (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el),
+		NULL, view);
 }
 
 void
 itip_view_set_show_free_time_check (ItipView *view,
                                     gboolean show)
 {
-	g_return_if_fail (view != NULL);
+	WebKitDOMElement *label;
+	WebKitDOMElement *el;
+
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	if (show)
-		gtk_widget_show (view->priv->free_time_check);
-	else {
-		gtk_widget_hide (view->priv->free_time_check);
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view->priv->free_time_check), FALSE);
+	if (!view->priv->dom_document)
+		return;
+
+	el = webkit_dom_document_get_element_by_id (
+                view->priv->dom_document, "table_row_" CHECKBOX_FREE_TIME);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_FREE_TIME);
+	label = webkit_dom_element_get_next_element_sibling (el);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (label), !show);
+
+	if (!show) {
+		webkit_dom_html_input_element_set_checked (
+			WEBKIT_DOM_HTML_INPUT_ELEMENT (el), FALSE);
 	}
+
+        /* and update state of the second check */
+	alarm_check_toggled_cb (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el),
+		NULL, view);
 }
 
 gboolean
 itip_view_get_free_time_check_state (ItipView *view)
 {
-	g_return_val_if_fail (view != NULL, FALSE);
+	WebKitDOMElement *el;
+
+	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
 
-	return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (view->priv->free_time_check));
+	if (!view->priv->dom_document)
+		return FALSE;
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_FREE_TIME);
+	return webkit_dom_html_input_element_get_checked (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el));
 }
 
 void
 itip_view_set_show_keep_alarm_check (ItipView *view,
                                      gboolean show)
 {
-	g_return_if_fail (view != NULL);
+	WebKitDOMElement *label;
+	WebKitDOMElement *el;
+
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	if (show)
-		gtk_widget_show (view->priv->keep_alarm_check);
-	else
-		gtk_widget_hide (view->priv->keep_alarm_check);
+	if (!view->priv->dom_document)
+		return;
+
+	el = webkit_dom_document_get_element_by_id (
+                view->priv->dom_document, "table_row_" CHECKBOX_KEEP_ALARM);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
 
-	/* and update state of the second check */
-	alarm_check_toggled_cb (view->priv->keep_alarm_check, view->priv->inherit_alarm_check);
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_KEEP_ALARM);
+	label = webkit_dom_element_get_next_element_sibling (el);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (label), !show);
+
+	if (!show) {
+		webkit_dom_html_input_element_set_checked (
+			WEBKIT_DOM_HTML_INPUT_ELEMENT (el), FALSE);
+	}
+
+        /* and update state of the second check */
+	alarm_check_toggled_cb (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el),
+		NULL, view);
 }
 
 gboolean
 itip_view_get_keep_alarm_check_state (ItipView *view)
 {
-	g_return_val_if_fail (view != NULL, FALSE);
+	WebKitDOMElement *el;
+
+	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
 
-	return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (view->priv->keep_alarm_check));
+	if (!view->priv->dom_document)
+		return FALSE;
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_KEEP_ALARM);
+	return webkit_dom_html_input_element_get_checked (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el));
 }
 
 void
 itip_view_set_show_inherit_alarm_check (ItipView *view,
                                         gboolean show)
 {
-	g_return_if_fail (view != NULL);
+	WebKitDOMElement *label;
+	WebKitDOMElement *el;
+
 	g_return_if_fail (ITIP_IS_VIEW (view));
 
-	if (show)
-		gtk_widget_show (view->priv->inherit_alarm_check);
-	else {
-		gtk_widget_hide (view->priv->inherit_alarm_check);
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view->priv->inherit_alarm_check), FALSE);
+	if (!view->priv->dom_document)
+		return;
+
+	el = webkit_dom_document_get_element_by_id (
+                view->priv->dom_document, "table_row_" CHECKBOX_INHERIT_ALARM);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (el), !show);
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_INHERIT_ALARM);
+	label = webkit_dom_element_get_next_element_sibling (el);
+	webkit_dom_html_element_set_hidden (WEBKIT_DOM_HTML_ELEMENT (label), !show);
+
+	if (!show) {
+		webkit_dom_html_input_element_set_checked (
+			WEBKIT_DOM_HTML_INPUT_ELEMENT (el), FALSE);
 	}
 
 	/* and update state of the second check */
-	alarm_check_toggled_cb (view->priv->inherit_alarm_check, view->priv->keep_alarm_check);
+	alarm_check_toggled_cb (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el),
+		NULL, view);
 }
 
 gboolean
 itip_view_get_inherit_alarm_check_state (ItipView *view)
 {
-	g_return_val_if_fail (view != NULL, FALSE);
+	WebKitDOMElement *el;
 
-	return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (view->priv->inherit_alarm_check));
+	g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
+
+	if (!view->priv->dom_document)
+		return FALSE;
+
+	el = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, CHECKBOX_INHERIT_ALARM);
+	return webkit_dom_html_input_element_get_checked (
+		WEBKIT_DOM_HTML_INPUT_ELEMENT (el));
 }
+
+void
+itip_view_set_error (ItipView *view,
+                     const gchar *error_html,
+                     gboolean show_save_btn)
+{
+	WebKitDOMElement *content, *error;
+	GString *str;
+
+	g_return_if_fail (ITIP_IS_VIEW (view));
+	g_return_if_fail (error_html);
+
+	str = g_string_new (error_html);
+
+	if (show_save_btn) {
+		g_string_append (str,
+                        "<table border=\"0\" width=\"100%\">"
+                        "<tr width=\"100%\" id=\"" TABLE_ROW_BUTTONS "\">");
+
+		buttons_table_write_button (
+                        str, BUTTON_SAVE, _("Save"),
+			GTK_STOCK_SAVE, ITIP_VIEW_RESPONSE_SAVE);
+
+                g_string_append (str, "</tr></table>");
+	}
+
+	view->priv->error = str->str;
+	g_string_free (str, FALSE);
+
+	if (!view->priv->dom_document)
+		return;
+
+	content = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, DIV_ITIP_CONTENT);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (content), TRUE);
+
+	error = webkit_dom_document_get_element_by_id (
+		view->priv->dom_document, DIV_ITIP_ERROR);
+	webkit_dom_html_element_set_hidden (
+		WEBKIT_DOM_HTML_ELEMENT (error), FALSE);
+
+	webkit_dom_html_element_set_inner_html (
+		WEBKIT_DOM_HTML_ELEMENT (error), view->priv->error, NULL);
+
+	if (show_save_btn) {
+		WebKitDOMElement *el;
+
+		show_button (view, BUTTON_SAVE);
+
+		el = webkit_dom_document_get_element_by_id (
+			view->priv->dom_document, BUTTON_SAVE);
+		webkit_dom_event_target_add_event_listener (
+                        WEBKIT_DOM_EVENT_TARGET (el), "click",
+			G_CALLBACK (button_clicked_cb), FALSE, view);
+	}
+}
+
diff --git a/plugins/itip-formatter/itip-view.h b/plugins/itip-formatter/itip-view.h
index 538306c..5ae8d9c 100644
--- a/plugins/itip-formatter/itip-view.h
+++ b/plugins/itip-formatter/itip-view.h
@@ -29,6 +29,7 @@
 #include <gtk/gtk.h>
 #include <libedataserver/e-source-list.h>
 #include <libecal/e-cal-client.h>
+#include <webkit/webkitdom.h>
 
 G_BEGIN_DECLS
 
@@ -42,6 +43,7 @@ G_BEGIN_DECLS
 typedef struct _ItipView        ItipView;
 typedef struct _ItipViewPrivate ItipViewPrivate;
 typedef struct _ItipViewClass   ItipViewClass;
+typedef struct _ItipPURI        ItipPURI;
 
 typedef enum {
 	ITIP_VIEW_MODE_NONE,
@@ -64,7 +66,8 @@ typedef enum {
 	ITIP_VIEW_RESPONSE_UPDATE,
 	ITIP_VIEW_RESPONSE_CANCEL,
 	ITIP_VIEW_RESPONSE_REFRESH,
-	ITIP_VIEW_RESPONSE_OPEN
+	ITIP_VIEW_RESPONSE_OPEN,
+	ITIP_VIEW_RESPONSE_SAVE
 } ItipViewResponse;
 
 typedef enum {
@@ -76,115 +79,188 @@ typedef enum {
 } ItipViewInfoItemType;
 
 struct _ItipView {
-	GtkHBox parent_instance;
+	GObject parent_instance;
 
 	ItipViewPrivate *priv;
-
-	GtkWidget *action_vbox;
 };
 
 struct _ItipViewClass {
-	GtkHBoxClass parent_class;
-
-	void (* source_selected) (ItipView *view, ESource *selected_source);
-	void (* response) (ItipView *view, gint response);
-};
-
-GType      itip_view_get_type (void);
-GtkWidget *itip_view_new      (void);
-
-void itip_view_set_mode (ItipView *view, ItipViewMode mode);
-ItipViewMode itip_view_get_mode (ItipView *view);
-
-void itip_view_set_item_type (ItipView *view, ECalClientSourceType type);
-ECalClientSourceType itip_view_get_item_type (ItipView *view);
-
-void itip_view_set_organizer (ItipView *view, const gchar *organizer);
-const gchar *itip_view_get_organizer (ItipView *view);
-
-void itip_view_set_organizer_sentby (ItipView *view, const gchar *sentby);
-const gchar *itip_view_get_organizer_sentby (ItipView *view);
-
-void itip_view_set_attendee (ItipView *view, const gchar *attendee);
-const gchar *itip_view_get_attendee (ItipView *view);
-
-void itip_view_set_attendee_sentby (ItipView *view, const gchar *sentby);
-const gchar *itip_view_get_attendee_sentby (ItipView *view);
-
-void itip_view_set_delegator (ItipView *view, const gchar *delegator);
-const gchar *itip_view_get_delegator (ItipView *view);
-
-void itip_view_set_proxy (ItipView *view, const gchar *proxy);
-const gchar *itip_view_get_proxy (ItipView *view);
-
-void itip_view_set_summary (ItipView *view, const gchar *summary);
-const gchar *itip_view_get_summary (ItipView *view);
-
-void itip_view_set_location (ItipView *view, const gchar *location);
-const gchar *itip_view_get_location (ItipView *view);
-
-void itip_view_set_status (ItipView *view, const gchar *status);
-const gchar *itip_view_get_status (ItipView *view);
-
-void itip_view_set_comment (ItipView *view, const gchar *comment);
-const gchar *itip_view_get_comment (ItipView *view);
+	GObjectClass parent_class;
 
-void itip_view_set_description (ItipView *view, const gchar *description);
-const gchar *itip_view_get_description (ItipView *view);
+	void    (* source_selected)             (ItipView *view,
+                                                 ESource *selected_source);
 
-void itip_view_set_start (ItipView *view, struct tm *start, gboolean is_date);
-const struct tm *itip_view_get_start (ItipView *view, gboolean *is_date);
-
-void itip_view_set_end (ItipView *view, struct tm *end, gboolean is_date);
-const struct tm *itip_view_get_end (ItipView *view, gboolean *is_date);
-
-guint itip_view_add_upper_info_item (ItipView *view, ItipViewInfoItemType type, const gchar *message);
-guint itip_view_add_upper_info_item_printf (ItipView *view, ItipViewInfoItemType, const gchar *format, ...) G_GNUC_PRINTF (3, 4);
-void itip_view_remove_upper_info_item (ItipView *view, guint id);
-void itip_view_clear_upper_info_items (ItipView *view);
-
-guint itip_view_add_lower_info_item (ItipView *view, ItipViewInfoItemType type, const gchar *message);
-guint itip_view_add_lower_info_item_printf (ItipView *view, ItipViewInfoItemType type, const gchar *format, ...) G_GNUC_PRINTF (3, 4);
-void itip_view_remove_lower_info_item (ItipView *view, guint id);
-void itip_view_clear_lower_info_items (ItipView *view);
-
-void itip_view_set_source_list (ItipView *view, ESourceList *source_list);
-ESourceList *itip_view_get_source_list (ItipView *view);
-
-void itip_view_set_source (ItipView *view, ESource *source);
-ESource *itip_view_get_source (ItipView *view);
-
-void itip_view_set_rsvp (ItipView *view, gboolean rsvp);
-gboolean itip_view_get_rsvp (ItipView *view);
-
-void itip_view_set_show_rsvp (ItipView *view, gboolean rsvp);
-gboolean itip_view_get_show_rsvp (ItipView *view);
-
-void itip_view_set_update (ItipView *view, gboolean update);
-gboolean itip_view_get_update (ItipView *view);
-
-void itip_view_set_show_update (ItipView *view, gboolean update);
-gboolean itip_view_get_show_update (ItipView *view);
-
-void itip_view_set_rsvp_comment (ItipView *view, const gchar *comment);
-gchar *itip_view_get_rsvp_comment (ItipView *view);
-
-void itip_view_set_buttons_sensitive (ItipView *view, gboolean sensitive);
-gboolean itip_view_get_buttons_sensitive (ItipView *view);
-
-void itip_view_set_show_recur_check (ItipView *view, gboolean show);
-gboolean itip_view_get_recur_check_state (ItipView *view);
-
-void itip_view_set_needs_decline (ItipView *view, gboolean needs_decline);
-
-void itip_view_set_show_free_time_check (ItipView *view, gboolean show);
-gboolean itip_view_get_free_time_check_state (ItipView *view);
-
-void itip_view_set_show_keep_alarm_check (ItipView *view, gboolean show);
-gboolean itip_view_get_keep_alarm_check_state (ItipView *view);
+	void    (* response)                    (ItipView *view,
+                                                 gint response);
+};
 
-void itip_view_set_show_inherit_alarm_check (ItipView *view, gboolean show);
-gboolean itip_view_get_inherit_alarm_check_state (ItipView *view);
+GType           itip_view_get_type              (void);
+
+ItipView *       itip_view_new                   (ItipPURI *puri);
+
+void            itip_view_write                 (GString *buffer);
+
+void            itip_view_write_for_printing    (ItipView *view,
+                                                 GString *buffer);
+
+void            itip_view_create_dom_bindings   (ItipView *view,
+                                                 WebKitDOMElement *element);
+
+ItipPURI *       itip_view_get_puri              (ItipView *view);
+
+void            itip_view_set_mode              (ItipView *view,
+                                                 ItipViewMode mode);
+ItipViewMode    itip_view_get_mode              (ItipView *view);
+
+void            itip_view_set_item_type         (ItipView *view,
+                                                 ECalClientSourceType type);
+ECalClientSourceType
+                itip_view_get_item_type         (ItipView *view);
+
+void            itip_view_set_organizer         (ItipView *view,
+                                                 const gchar *organizer);
+const gchar *    itip_view_get_organizer         (ItipView *view);
+
+void            itip_view_set_organizer_sentby  (ItipView *view,
+                                                 const gchar *sentby);
+const gchar *    itip_view_get_organizer_sentby  (ItipView *view);
+
+void            itip_view_set_attendee          (ItipView *view,
+                                                 const gchar *attendee);
+const gchar *    itip_view_get_attendee          (ItipView *view);
+
+void            itip_view_set_attendee_sentby   (ItipView *view,
+                                                 const gchar *sentby);
+const gchar *    itip_view_get_attendee_sentby   (ItipView *view);
+
+void            itip_view_set_delegator         (ItipView *view,
+                                                 const gchar *delegator);
+const gchar *    itip_view_get_delegator         (ItipView *view);
+
+void            itip_view_set_proxy             (ItipView *view,
+                                                 const gchar *proxy);
+const gchar *    itip_view_get_proxy             (ItipView *view);
+
+void            itip_view_set_summary           (ItipView *view,
+                                                 const gchar *summary);
+const gchar *    itip_view_get_summary           (ItipView *view);
+
+void            itip_view_set_location          (ItipView *view,
+                                                 const gchar *location);
+const gchar *    itip_view_get_location          (ItipView *view);
+
+void            itip_view_set_status            (ItipView *view,
+                                                 const gchar *status);
+const gchar *    itip_view_get_status            (ItipView *view);
+
+void            itip_view_set_comment           (ItipView *view,
+                                                 const gchar *comment);
+const gchar *    itip_view_get_comment           (ItipView *view);
+
+void            itip_view_set_description       (ItipView *view,
+                                                 const gchar *description);
+const gchar *    itip_view_get_description       (ItipView *view);
+
+void            itip_view_set_start             (ItipView *view,
+                                                 struct tm *start,
+                                                 gboolean is_date);
+const struct tm *
+                itip_view_get_start             (ItipView *view,
+                                                 gboolean *is_date);
+
+void            itip_view_set_end               (ItipView *view,
+                                                 struct tm *end,
+                                                 gboolean is_date);
+const struct tm *
+                itip_view_get_end               (ItipView *view,
+                                                 gboolean *is_date);
+
+guint           itip_view_add_upper_info_item   (ItipView *view,
+                                                 ItipViewInfoItemType type,
+                                                 const gchar *message);
+guint           itip_view_add_upper_info_item_printf
+                                                (ItipView *view,
+                                                 ItipViewInfoItemType,
+                                                 const gchar *format, ...) G_GNUC_PRINTF (3, 4);
+void            itip_view_remove_upper_info_item
+                                                (ItipView *view,
+                                                 guint id);
+void            itip_view_clear_upper_info_items
+                                                (ItipView *view);
+
+guint           itip_view_add_lower_info_item   (ItipView *view,
+                                                 ItipViewInfoItemType type,
+                                                 const gchar *message);
+guint           itip_view_add_lower_info_item_printf
+                                                (ItipView *view,
+                                                 ItipViewInfoItemType type,
+                                                 const gchar *format, ...) G_GNUC_PRINTF (3, 4);
+void            itip_view_remove_lower_info_item
+                                                (ItipView *view,
+                                                 guint id);
+void            itip_view_clear_lower_info_items
+                                                (ItipView *view);
+
+void            itip_view_set_source_list       (ItipView *view,
+                                                 ESourceList *source_list);
+ESourceList *    itip_view_get_source_list       (ItipView *view);
+
+void            itip_view_set_source            (ItipView *view,
+                                                 ESource *source);
+ESource *        itip_view_get_source            (ItipView *view);
+
+void            itip_view_set_rsvp              (ItipView *view,
+                                                 gboolean rsvp);
+gboolean        itip_view_get_rsvp              (ItipView *view);
+
+void            itip_view_set_show_rsvp_check   (ItipView *view,
+                                                 gboolean show);
+gboolean        itip_view_get_show_rsvp_check   (ItipView *view);
+
+void            itip_view_set_update            (ItipView *view,
+                                                 gboolean update);
+gboolean        itip_view_get_update            (ItipView *view);
+
+void            itip_view_set_show_update_check (ItipView *view,
+                                                 gboolean show);
+gboolean        itip_view_get_show_update_check (ItipView *view);
+
+void            itip_view_set_rsvp_comment      (ItipView *view,
+                                                 const gchar *comment);
+gchar *          itip_view_get_rsvp_comment      (ItipView *view);
+
+void            itip_view_set_buttons_sensitive (ItipView *view,
+                                                 gboolean sensitive);
+gboolean        itip_view_get_buttons_sensitive (ItipView *view);
+
+void            itip_view_set_show_recur_check  (ItipView *view,
+                                                 gboolean show);
+gboolean        itip_view_get_recur_check_state (ItipView *view);
+
+void            itip_view_set_needs_decline     (ItipView *view,
+                                                 gboolean needs_decline);
+
+void            itip_view_set_show_free_time_check
+                                                (ItipView *view,
+                                                 gboolean show);
+gboolean        itip_view_get_free_time_check_state
+                                                (ItipView *view);
+
+void            itip_view_set_show_keep_alarm_check
+                                                (ItipView *view,
+                                                 gboolean show);
+gboolean        itip_view_get_keep_alarm_check_state
+                                                (ItipView *view);
+
+void            itip_view_set_show_inherit_alarm_check
+                                                (ItipView *view,
+                                                 gboolean show);
+gboolean        itip_view_get_inherit_alarm_check_state
+                                                (ItipView *view);
+
+void            itip_view_set_error             (ItipView *view,
+                                                 const gchar *error_html,
+                                                 gboolean show_save_btn);
 
 G_END_DECLS
 
diff --git a/plugins/mail-to-task/Makefile.am b/plugins/mail-to-task/Makefile.am
index 66f6ff5..da78753 100644
--- a/plugins/mail-to-task/Makefile.am
+++ b/plugins/mail-to-task/Makefile.am
@@ -9,8 +9,7 @@ liborg_gnome_mail_to_task_la_CPPFLAGS =			\
 	-I$(top_srcdir)					\
 	-I$(top_srcdir)/widgets				\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
-	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GTKHTML_CFLAGS)
+	$(GNOME_PLATFORM_CFLAGS)
 
 liborg_gnome_mail_to_task_la_SOURCES = mail-to-task.c
 
@@ -26,8 +25,7 @@ liborg_gnome_mail_to_task_la_LIBADD =	\
 	$(top_builddir)/libemail-utils/libemail-utils.la		\
 	$(top_builddir)/libemail-engine/libemail-engine.la		\
 	$(EVOLUTION_DATA_SERVER_LIBS)					\
-	$(GNOME_PLATFORM_LIBS)						\
-	$(GTKHTML_LIBS)
+	$(GNOME_PLATFORM_LIBS)
 
 EXTRA_DIST = org-gnome-mail-to-task.eplug.xml
 
diff --git a/plugins/mail-to-task/mail-to-task.c b/plugins/mail-to-task/mail-to-task.c
index 6cf942a..09ec15d 100644
--- a/plugins/mail-to-task/mail-to-task.c
+++ b/plugins/mail-to-task/mail-to-task.c
@@ -32,7 +32,6 @@
 #include <string.h>
 #include <glib/gi18n-lib.h>
 
-#include <gtkhtml/gtkhtml.h>
 #include <libecal/e-cal-client.h>
 #include <libecal/e-cal-component.h>
 #include <libedataserver/e-account.h>
@@ -1062,18 +1061,16 @@ text_contains_nonwhitespace (const gchar *text,
 static gchar *
 get_selected_text (EMailReader *reader)
 {
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 	gchar *text = NULL;
 	gint len;
 
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 
-	if (!e_web_view_is_selection_active (web_view))
+	if (!e_web_view_is_selection_active (E_WEB_VIEW (display)))
 		return NULL;
 
-	text = gtk_html_get_selection_plain_text (GTK_HTML (web_view), &len);
+	text = e_mail_display_get_selection_plain_text (display, &len);
 
 	if (text == NULL || !text_contains_nonwhitespace (text, len)) {
 		g_free (text);
diff --git a/plugins/mark-all-read/Makefile.am b/plugins/mark-all-read/Makefile.am
index 739601c..4740bff 100644
--- a/plugins/mark-all-read/Makefile.am
+++ b/plugins/mark-all-read/Makefile.am
@@ -9,8 +9,7 @@ liborg_gnome_mark_all_read_la_CPPFLAGS =		\
 	-I$(top_srcdir)					\
 	-I$(top_srcdir)/widgets				\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
-	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GTKHTML_CFLAGS)
+	$(GNOME_PLATFORM_CFLAGS)
 
 liborg_gnome_mark_all_read_la_SOURCES = mark-all-read.c  
 
@@ -22,8 +21,7 @@ liborg_gnome_mark_all_read_la_LIBADD = 			\
 	$(top_builddir)/shell/libeshell.la		\
 	$(top_builddir)/libevolution-utils/libevolution-utils.la \
 	$(EVOLUTION_DATA_SERVER_LIBS)			\
-	$(GNOME_PLATFORM_LIBS)				\
-	$(GTKHTML_LIBS)
+	$(GNOME_PLATFORM_LIBS)
 
 EXTRA_DIST = org-gnome-mark-all-read.eplug.xml
 
diff --git a/plugins/prefer-plain/prefer-plain.c b/plugins/prefer-plain/prefer-plain.c
index 4b1ac49..5793370 100644
--- a/plugins/prefer-plain/prefer-plain.c
+++ b/plugins/prefer-plain/prefer-plain.c
@@ -49,14 +49,12 @@ static gboolean epp_show_suppressed = TRUE;
 
 static void
 make_part_attachment (EMFormat *format,
-                      CamelStream *stream,
-                      CamelMimePart *part,
-                      gint i)
+                                      CamelMimePart *part,
+                                      GString *part_id,
+                                      gboolean force_html,
+                                      GCancellable *cancellable)
 {
-	gint partidlen = format->part_id->len;
-
-	if (i != -1)
-		g_string_append_printf (format->part_id, ".alternative-prefer-plain.%d", i);
+	EMFormatParserInfo info = {0};
 
 	if (camel_content_type_is (camel_mime_part_get_content_type (part), "text", "html")) {
 		/* always show HTML as attachments and not inline */
@@ -68,11 +66,9 @@ make_part_attachment (EMFormat *format,
 			g_free (str);
 		}
 
-		/* FIXME Not passing a GCancellable here. */
-		em_format_part_as (
-			format, stream, part,
-			"application/octet-stream", NULL);
-	} else if (i == -1 && CAMEL_IS_MIME_MESSAGE (part)) {
+		em_format_parse_part_as (
+			format, part, part_id, &info, "application/octet-stream", cancellable);
+	} else if (force_html && CAMEL_IS_MIME_MESSAGE (part)) {
 		/* message was asked to be formatted as text/html;
 		 * might be for cases where message itself is a text/html part */
 		CamelMimePart *new_part;
@@ -84,15 +80,12 @@ make_part_attachment (EMFormat *format,
 		new_part = camel_mime_part_new ();
 		camel_medium_set_content (CAMEL_MEDIUM (new_part), content);
 
-		em_format_part (format, stream, new_part, NULL);
+		em_format_parse_part (format, new_part, part_id, &info, cancellable);
 
 		g_object_unref (new_part);
 	} else {
-		/* FIXME Not passing a GCancellable here. */
-		em_format_part (format, stream, part, NULL);
+		em_format_parse_part (format, part, part_id, &info, cancellable);
 	}
-
-	g_string_truncate (format->part_id, partidlen);
 }
 
 void
@@ -101,28 +94,30 @@ org_gnome_prefer_plain_text_html (gpointer ep,
 {
 	/* In text-only mode, all html output is suppressed for the first processing */
 	if (epp_mode != EPP_TEXT
-	    || strstr (t->format->part_id->str, ".alternative-prefer-plain.") != NULL
-	    || em_format_is_inline (t->format, t->format->part_id->str, t->part, &(t->item->handler)))
+	    || strstr (t->part_id->str, ".alternative-prefer-plain.") != NULL
+	    || em_format_is_inline (t->format, t->part_id->str, t->part, t->info->handler)) {
 		/* FIXME Not passing a GCancellable here. */
-		t->item->handler.old->handler (
-			t->format, t->stream, t->part,
-			t->item->handler.old, NULL, FALSE);
-	else if (epp_show_suppressed)
-		make_part_attachment (t->format, t->stream, t->part, -1);
+		t->info->handler->old->parse_func (
+			t->format, t->part, t->part_id,
+			t->info, NULL);
+	} else if (epp_show_suppressed)
+		make_part_attachment (t->format, t->part, t->part_id, TRUE, NULL);
 }
 
 static void
 export_as_attachments (CamelMultipart *mp,
-                       EMFormat *format,
-                       CamelStream *stream,
-                       CamelMimePart *except)
+                                           EMFormat *format,
+                                           CamelMimePart *except,
+                                           GString *part_id)
 {
 	gint i, nparts;
 	CamelMimePart *part;
+	gint len;
 
 	if (!mp || !CAMEL_IS_MULTIPART (mp))
 		return;
 
+	len = part_id->len;
 	nparts = camel_multipart_get_number (mp);
 	for (i = 0; i < nparts; i++) {
 		part = camel_multipart_get_part (mp, i);
@@ -130,11 +125,13 @@ export_as_attachments (CamelMultipart *mp,
 		if (part != except) {
 			CamelMultipart *multipart = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
 
+			g_string_append_printf (part_id, ".aleternative-prefer-plain.%d", i);
 			if (CAMEL_IS_MULTIPART (multipart)) {
-				export_as_attachments (multipart, format, stream, except);
+				export_as_attachments (multipart, format, except, part_id);
 			} else {
-				make_part_attachment (format, stream, part, i);
+				make_part_attachment (format, part, part_id, FALSE, NULL);
 			}
+			g_string_truncate (part_id, len);
 		}
 	}
 }
@@ -147,8 +144,7 @@ org_gnome_prefer_plain_multipart_alternative (gpointer ep,
 	CamelMimePart *part, *display_part = NULL, *calendar_part = NULL;
 	gint i, nparts, partidlen, displayid = 0, calendarid = 0;
 
-	/* FIXME: this part-id stuff is poking private data, needs api */
-	partidlen = t->format->part_id->len;
+	partidlen = t->part_id->len;
 
 	if (epp_mode == EPP_NORMAL) {
 		gboolean have_plain = FALSE;
@@ -185,21 +181,20 @@ org_gnome_prefer_plain_multipart_alternative (gpointer ep,
 		}
 
 		if (display_part && have_plain && nparts == 2) {
-			g_string_append_printf (t->format->part_id, ".alternative-prefer-plain.%d", displayid);
+			g_string_append_printf (t->part_id, ".alternative-prefer-plain.%d", displayid);
 			/* FIXME Not passing a GCancellable here. */
-			em_format_part_as (
-				t->format, t->stream,
-				display_part, "text/html", NULL);
-			g_string_truncate (t->format->part_id, partidlen);
+			em_format_parse_part_as (
+				t->format, display_part, t->part_id, t->info, "text/html", NULL);
+			g_string_truncate (t->part_id, partidlen);
 		} else {
 			/* FIXME Not passing a GCancellable here. */
-			t->item->handler.old->handler (
-				t->format, t->stream, t->part,
-				t->item->handler.old, NULL, FALSE);
+			t->info->handler->old->parse_func (
+				t->format, t->part, t->part_id, t->info, NULL);
 		}
 		return;
 	} else if (!CAMEL_IS_MULTIPART (mp)) {
-		em_format_format_source (t->format, t->stream, t->part, NULL);
+		/* FIXME Not passing GCancellable here. */
+		em_format_parse_part_as (t->format, t->part, t->part_id, t->info, "x-evolution/message/source", NULL);
 		return;
 	}
 
@@ -224,21 +219,22 @@ org_gnome_prefer_plain_multipart_alternative (gpointer ep,
 
 	/* if we found a text part, show it */
 	if (display_part) {
-		g_string_append_printf(t->format->part_id, ".alternative-prefer-plain.%d", displayid);
+		g_string_append_printf(t->part_id, ".alternative-prefer-plain.%d", displayid);
 		/* FIXME Not passing a GCancellable here. */
-		em_format_part_as (
-			t->format, t->stream,
-			display_part, "text/plain", NULL);
-		g_string_truncate (t->format->part_id, partidlen);
+		em_format_parse_part_as (
+			t->format, display_part, t->part_id, t->info, "text/plain", NULL);
+		g_string_truncate (t->part_id, partidlen);
 	}
 
 	/* all other parts are attachments */
 	if (epp_show_suppressed)
-		export_as_attachments (mp, t->format, t->stream, display_part);
-	else if (calendar_part)
-		make_part_attachment (t->format, t->stream, calendar_part, calendarid);
+		export_as_attachments (mp, t->format, display_part, t->part_id);
+	else if (calendar_part) {
+		g_string_append_printf(t->part_id, ".alternative-prefer-plain.%d", calendarid);
+		make_part_attachment (t->format, calendar_part, t->part_id, FALSE, NULL);
+	}
 
-	g_string_truncate (t->format->part_id, partidlen);
+	g_string_truncate (t->part_id, partidlen);
 }
 
 static struct {
diff --git a/plugins/pst-import/Makefile.am b/plugins/pst-import/Makefile.am
index 5aeb114..b81e0d2 100644
--- a/plugins/pst-import/Makefile.am
+++ b/plugins/pst-import/Makefile.am
@@ -18,7 +18,6 @@ liborg_gnome_pst_import_la_CPPFLAGS =			\
 	-I$(top_builddir)				\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
 	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GTKHTML_CFLAGS)				\
 	$(LIBPST_CFLAGS)
 
 liborg_gnome_pst_import_la_SOURCES = pst-importer.c
@@ -34,7 +33,6 @@ liborg_gnome_pst_import_la_LIBADD =				\
 	$(top_builddir)/libevolution-utils/libevolution-utils.la \
 	$(EVOLUTION_DATA_SERVER_LIBS)				\
 	$(GNOME_PLATFORM_LIBS)					\
-	$(GTKHTML_LIBS)						\
 	$(LIBPST_LIBS)
 
 EXTRA_DIST = org-gnome-pst-import.eplug.xml
diff --git a/plugins/tnef-attachments/Makefile.am b/plugins/tnef-attachments/Makefile.am
index 250453d..6a39304 100644
--- a/plugins/tnef-attachments/Makefile.am
+++ b/plugins/tnef-attachments/Makefile.am
@@ -16,7 +16,6 @@ liborg_gnome_tnef_attachments_la_CPPFLAGS =		\
 	-I$(top_srcdir)/widgets				\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
 	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GTKHTML_CFLAGS)				\
 	$(TNEF_CFLAGS)
 
 liborg_gnome_tnef_attachments_la_SOURCES = tnef-plugin.c
@@ -28,7 +27,6 @@ liborg_gnome_tnef_attachments_la_LIBADD = 		\
 	$(top_builddir)/em-format/libemformat.la	\
 	$(EVOLUTION_DATA_SERVER_LIBS)			\
 	$(GNOME_PLATFORM_LIBS)				\
-	$(GTKHTML_LIBS)					\
 	-lytnef
 
 EXTRA_DIST = org-gnome-tnef-attachments.eplug.xml
diff --git a/plugins/tnef-attachments/tnef-plugin.c b/plugins/tnef-attachments/tnef-plugin.c
index 5ef2f27..0621c12 100644
--- a/plugins/tnef-attachments/tnef-plugin.c
+++ b/plugins/tnef-attachments/tnef-plugin.c
@@ -92,6 +92,7 @@ org_gnome_format_tnef (gpointer ep,
 	CamelMultipart *mp;
 	CamelMimePart *mainpart;
 	CamelDataWrapper *content;
+	const EMFormatHandler *handler;
 	gint len;
 	TNEFStruct tnef;
 
@@ -102,15 +103,21 @@ org_gnome_format_tnef (gpointer ep,
 	name = g_build_filename(tmpdir, ".evo-attachment.tnef", NULL);
 
 	out = camel_stream_fs_new_with_name (name, O_RDWR | O_CREAT, 0666, NULL);
-	if (out == NULL)
-	    goto fail;
+	if (out == NULL) {
+	    g_free (name);
+	    return;
+	}
 	content = camel_medium_get_content ((CamelMedium *) t->part);
-	if (content == NULL)
-		goto fail;
+	if (content == NULL) {
+		g_free (name);
+		g_object_unref (out);
+		return;
+	}
 	if (camel_data_wrapper_decode_to_stream_sync (content, out, NULL, NULL) == -1
 	    || camel_stream_close (out, NULL, NULL) == -1) {
 		g_object_unref (out);
-		goto fail;
+		g_free (name);
+		return;
 	}
 	g_object_unref (out);
 
@@ -126,8 +133,11 @@ org_gnome_format_tnef (gpointer ep,
 	/* Extraction done */
 
 	dir = opendir (tmpdir);
-	if (dir == NULL)
-	    goto fail;
+	if (dir == NULL) {
+	    g_object_unref (out);
+	    g_free (name);
+	    return;
+	}
 
 	mainpart = camel_mime_part_new ();
 
@@ -177,33 +187,26 @@ org_gnome_format_tnef (gpointer ep,
 
 	closedir (dir);
 
-	len = t->format->part_id->len;
-	g_string_append_printf(t->format->part_id, ".tnef");
-
-	if (camel_multipart_get_number (mp) > 0)
-		/* FIXME Not passing a GCancellable here. */
-		em_format_part_as (
-			t->format, t->stream, mainpart,
-			"multipart/mixed", NULL);
-	else if (t->item->handler.old)
-		/* FIXME Not passing a GCancellable here. */
-		t->item->handler.old->handler (
-			t->format, t->stream, t->part,
-			t->item->handler.old, NULL, FALSE);
+	len = t->part_id->len;
+	g_string_append_printf(t->part_id, ".tnef");
+
+	if (camel_multipart_get_number (mp) > 0) {
+                handler = em_format_find_handler (t->format, "multiplart/mixed");
+                /* FIXME Not passing a GCancellable here. */
+		if (handler && handler->parse_func) {
+			CamelMimePart *part = camel_mime_part_new ();
+			camel_medium_set_content ((CamelMedium *) part,
+				CAMEL_DATA_WRAPPER (mp));
+			handler->parse_func (t->format, part, t->part_id, t->info, NULL);
+			g_object_unref (part);
+		}
+	}
 
-	g_string_truncate (t->format->part_id, len);
+	g_string_truncate (t->part_id, len);
 
 	g_object_unref (mp);
 	g_object_unref (mainpart);
 
-	goto ok;
- fail:
-	if (t->item->handler.old)
-		/* FIXME Not passing a GCancellable here. */
-		t->item->handler.old->handler (
-			t->format, t->stream, t->part,
-			t->item->handler.old, NULL, FALSE);
- ok:
 	g_free (name);
 	g_free (tmpdir);
 }
diff --git a/plugins/vcard-inline/Makefile.am b/plugins/vcard-inline/Makefile.am
index 07b747a..afde012 100644
--- a/plugins/vcard-inline/Makefile.am
+++ b/plugins/vcard-inline/Makefile.am
@@ -16,8 +16,7 @@ liborg_gnome_vcard_inline_la_CPPFLAGS = \
 	-I$(top_srcdir)					\
 	-I$(top_srcdir)/widgets				\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
-	$(GNOME_PLATFORM_CFLAGS)			\
-	$(GTKHTML_CFLAGS)
+	$(GNOME_PLATFORM_CFLAGS)
 
 liborg_gnome_vcard_inline_la_SOURCES = vcard-inline.c
 
@@ -29,9 +28,9 @@ liborg_gnome_vcard_inline_la_LIBADD =					\
 	$(top_builddir)/addressbook/gui/widgets/libeabwidgets.la	\
 	$(top_builddir)/addressbook/gui/merging/libeabbookmerging.la	\
 	$(top_builddir)/addressbook/printing/libecontactprint.la	\
+	$(top_builddir)/em-format/libemformat.la			\
 	$(EVOLUTION_DATA_SERVER_LIBS)					\
-	$(GNOME_PLATFORM_LIBS)						\
-	$(GTKHTML_LIBS)
+	$(GNOME_PLATFORM_LIBS)
 
 EXTRA_DIST = org-gnome-vcard-inline.eplug.xml
 
diff --git a/plugins/vcard-inline/vcard-inline.c b/plugins/vcard-inline/vcard-inline.c
index cfe461b..7d83ab2 100644
--- a/plugins/vcard-inline/vcard-inline.c
+++ b/plugins/vcard-inline/vcard-inline.c
@@ -24,30 +24,33 @@
 #include <glib/gi18n-lib.h>
 #include <libebook/e-book-client.h>
 #include <libebook/e-contact.h>
-#include <gtkhtml/gtkhtml-embedded.h>
 #include <libedataserverui/e-client-utils.h>
 #include <libedataserverui/e-source-selector-dialog.h>
 
 #include "addressbook/gui/merging/eab-contact-merging.h"
-#include "addressbook/gui/widgets/eab-contact-display.h"
+#include "addressbook/gui/widgets/eab-contact-formatter.h"
 #include "addressbook/util/eab-book-util.h"
 #include "mail/em-format-hook.h"
 #include "mail/em-format-html.h"
+#include "mail/e-mail-display.h"
 
 #define d(x)
 
-typedef struct _VCardInlinePObject VCardInlinePObject;
+typedef struct _VCardInlinePURI VCardInlinePURI;
 
-struct _VCardInlinePObject {
-	EMFormatHTMLPObject object;
+struct _VCardInlinePURI {
+	EMFormatPURI puri;
 
 	GSList *contact_list;
 	ESourceList *source_list;
 	GtkWidget *contact_display;
 	GtkWidget *message_label;
-};
 
-static gint org_gnome_vcard_inline_classid;
+	EABContactFormatter *formatter;
+	WebKitDOMElement *iframe;
+	WebKitDOMElement *toggle_button;
+	WebKitDOMElement *save_button;
+};
 
 /* Forward Declarations */
 void org_gnome_vcard_inline_format (gpointer ep, EMFormatHookTarget *target);
@@ -61,11 +64,11 @@ e_plugin_lib_enable (EPlugin *ep,
 }
 
 static void
-org_gnome_vcard_inline_pobject_free (EMFormatHTMLPObject *object)
+org_gnome_vcard_inline_pobject_free (EMFormatPURI *object)
 {
-	VCardInlinePObject *vcard_object;
+	VCardInlinePURI *vcard_object;
 
-	vcard_object = (VCardInlinePObject *) object;
+	vcard_object = (VCardInlinePURI *) object;
 
 	e_client_util_free_object_slist (vcard_object->contact_list);
 	vcard_object->contact_list = NULL;
@@ -84,10 +87,30 @@ org_gnome_vcard_inline_pobject_free (EMFormatHTMLPObject *object)
 		g_object_unref (vcard_object->message_label);
 		vcard_object->message_label = NULL;
 	}
+
+	if (vcard_object->formatter != NULL) {
+		g_object_unref (vcard_object->formatter);
+		vcard_object->formatter = NULL;
+	}
+
+	if (vcard_object->iframe != NULL) {
+		g_object_unref (vcard_object->iframe);
+		vcard_object->iframe = NULL;
+	}
+
+	if (vcard_object->toggle_button != NULL) {
+		g_object_unref (vcard_object->toggle_button);
+		vcard_object->toggle_button = NULL;
+	}
+
+	if (vcard_object->save_button != NULL) {
+		g_object_unref (vcard_object->save_button);
+		vcard_object->save_button = NULL;
+	}
 }
 
 static void
-org_gnome_vcard_inline_decode (VCardInlinePObject *vcard_object,
+org_gnome_vcard_inline_decode (VCardInlinePURI *vcard_object,
                                CamelMimePart *mime_part)
 {
 	CamelDataWrapper *data_wrapper;
@@ -157,7 +180,9 @@ org_gnome_vcard_inline_client_loaded_cb (ESource *source,
 }
 
 static void
-org_gnome_vcard_inline_save_cb (VCardInlinePObject *vcard_object)
+org_gnome_vcard_inline_save_cb (WebKitDOMEventTarget *button,
+                                WebKitDOMEvent *event,
+                                VCardInlinePURI *vcard_object)
 {
 	ESource *source;
 	GSList *contact_list;
@@ -192,159 +217,223 @@ org_gnome_vcard_inline_save_cb (VCardInlinePObject *vcard_object)
 }
 
 static void
-org_gnome_vcard_inline_toggle_cb (VCardInlinePObject *vcard_object,
-                                  GtkButton *button)
+org_gnome_vcard_inline_toggle_cb (WebKitDOMEventTarget *button,
+                                  WebKitDOMEvent *event,
+                                  EMFormatPURI *puri)
 {
-	EABContactDisplay *contact_display;
+	VCardInlinePURI *vcard_object;
 	EABContactDisplayMode mode;
-	const gchar *label;
+	gchar *uri;
 
-	contact_display = EAB_CONTACT_DISPLAY (vcard_object->contact_display);
-	mode = eab_contact_display_get_mode (contact_display);
+	vcard_object = (VCardInlinePURI *) puri;
 
-	/* Toggle between "full" and "compact" modes. */
+	mode = eab_contact_formatter_get_display_mode (vcard_object->formatter);
 	if (mode == EAB_CONTACT_DISPLAY_RENDER_NORMAL) {
 		mode = EAB_CONTACT_DISPLAY_RENDER_COMPACT;
-		label = _("Show Full vCard");
+
+		webkit_dom_html_element_set_inner_text (
+			WEBKIT_DOM_HTML_ELEMENT (button),
+			_("Show Full vCard"), NULL);
+
 	} else {
 		mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL;
-		label = _("Show Compact vCard");
+
+		webkit_dom_html_element_set_inner_text (
+			WEBKIT_DOM_HTML_ELEMENT (button),
+			_("Show Compact vCard"), NULL);
 	}
 
-	eab_contact_display_set_mode (contact_display, mode);
-	gtk_button_set_label (button, label);
+	eab_contact_formatter_set_display_mode (vcard_object->formatter, mode);
+
+	uri = em_format_build_mail_uri (
+		puri->emf->folder, puri->emf->message_uid,
+		"part_id", G_TYPE_STRING, puri->uri,
+		"mode", G_TYPE_INT, EM_FORMAT_WRITE_MODE_RAW, NULL);
+
+	webkit_dom_html_iframe_element_set_src (
+		WEBKIT_DOM_HTML_IFRAME_ELEMENT (vcard_object->iframe), uri);
+
+	g_free (uri);
 }
 
-static gboolean
-org_gnome_vcard_inline_embed (EMFormatHTML *format,
-                              GtkHTMLEmbedded *embedded,
-                              EMFormatHTMLPObject *object)
+static void
+org_gnome_vcard_inline_bind_dom (WebKitDOMElement *attachment,
+                                 EMFormatPURI *puri)
 {
-	VCardInlinePObject *vcard_object;
-	GtkWidget *button_box;
-	GtkWidget *container;
-	GtkWidget *widget;
-	EContact *contact;
-	guint length;
-
-	vcard_object = (VCardInlinePObject *) object;
-	length = g_slist_length (vcard_object->contact_list);
-
-	if (vcard_object->contact_list != NULL)
-		contact = E_CONTACT (vcard_object->contact_list->data);
-	else
-		contact = NULL;
-
-	container = GTK_WIDGET (embedded);
-
-	widget = gtk_vbox_new (FALSE, 0);
-	gtk_container_add (GTK_CONTAINER (container), widget);
-	gtk_widget_show (widget);
-
-	container = widget;
-
-	widget = gtk_hbutton_box_new ();
-	gtk_button_box_set_layout (
-		GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
-	gtk_box_set_spacing (GTK_BOX (widget), 12);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0);
-	gtk_widget_show (widget);
-
-	button_box = widget;
-
-	widget = eab_contact_display_new ();
-	eab_contact_display_set_contact (
-		EAB_CONTACT_DISPLAY (widget), contact);
-	eab_contact_display_set_mode (
-		EAB_CONTACT_DISPLAY (widget),
-		EAB_CONTACT_DISPLAY_RENDER_COMPACT);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	vcard_object->contact_display = g_object_ref (widget);
-	gtk_widget_show (widget);
-
-	widget = gtk_label_new (NULL);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	vcard_object->message_label = g_object_ref (widget);
-
-	if (length == 2) {
-		const gchar *text;
-
-		text = _("There is one other contact.");
-		gtk_label_set_text (GTK_LABEL (widget), text);
-		gtk_widget_show (widget);
-
-	} else if (length > 2) {
-		gchar *text;
-
-		/* Translators: This will always be two or more. */
-		text = g_strdup_printf (ngettext (
-			"There is %d other contact.",
-			"There are %d other contacts.",
-			length - 1), length - 1);
-		gtk_label_set_text (GTK_LABEL (widget), text);
-		gtk_widget_show (widget);
-		g_free (text);
-
-	} else
-		gtk_widget_hide (widget);
-
-	container = button_box;
-
-	widget = gtk_button_new_with_label (_("Show Full vCard"));
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	g_signal_connect_swapped (
-		widget, "clicked",
-		G_CALLBACK (org_gnome_vcard_inline_toggle_cb),
-		vcard_object);
-
-	widget = gtk_button_new_with_label (_("Save in Address Book"));
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-
-	/* This depends on having a source list. */
-	if (vcard_object->source_list != NULL)
-		gtk_widget_show (widget);
-	else
-		gtk_widget_hide (widget);
-
-	g_signal_connect_swapped (
-		widget, "clicked",
-		G_CALLBACK (org_gnome_vcard_inline_save_cb),
-		vcard_object);
-
-	return TRUE;
+	WebKitDOMNodeList *list;
+	WebKitDOMElement *iframe, *toggle_button, *save_button;
+	VCardInlinePURI *vcard_object;
+
+	vcard_object = (VCardInlinePURI *) puri;
+
+        /* IFRAME */
+	list = webkit_dom_element_get_elements_by_tag_name (attachment, "iframe");
+	if (webkit_dom_node_list_get_length (list) != 1)
+		return;
+	iframe = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (list, 0));
+	if (vcard_object->iframe)
+		g_object_unref (vcard_object->iframe);
+	vcard_object->iframe = g_object_ref (iframe);
+
+	/* TOGGLE DISPLAY MODE BUTTON */
+	list = webkit_dom_element_get_elements_by_class_name (
+		attachment, "org-gnome-vcard-inline-display-mode-button");
+	if (webkit_dom_node_list_get_length (list) != 1)
+		return;
+	toggle_button = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (list, 0));
+	if (vcard_object->toggle_button)
+		g_object_unref (vcard_object->toggle_button);
+	vcard_object->toggle_button = g_object_ref (toggle_button);
+
+	/* SAVE TO ADDRESSBOOK BUTTON */
+	list = webkit_dom_element_get_elements_by_class_name (
+		attachment, "org-gnome-vcard-inline-save-button");
+	if (webkit_dom_node_list_get_length (list) != 1)
+		return;
+	save_button = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (list, 0));
+	if (vcard_object->save_button)
+		g_object_unref (vcard_object->save_button);
+	vcard_object->save_button = g_object_ref (save_button);
+
+	webkit_dom_event_target_add_event_listener (
+		WEBKIT_DOM_EVENT_TARGET (toggle_button),
+		"click", G_CALLBACK (org_gnome_vcard_inline_toggle_cb),
+		FALSE, puri);
+
+	webkit_dom_event_target_add_event_listener (
+		WEBKIT_DOM_EVENT_TARGET (save_button),
+		"click", G_CALLBACK (org_gnome_vcard_inline_save_cb),
+		FALSE, puri);
+}
+
+static void
+org_gnome_vcard_inline_write (EMFormat *emf,
+                              EMFormatPURI *puri,
+                              CamelStream *stream,
+                              EMFormatWriterInfo *info,
+                              GCancellable *cancellable)
+{
+	VCardInlinePURI *vpuri;
+
+	vpuri = (VCardInlinePURI *) puri;
+
+	if (info->mode == EM_FORMAT_WRITE_MODE_RAW)  {
+
+		EContact *contact;
+
+		if (vpuri->contact_list != NULL)
+			contact = E_CONTACT (vpuri->contact_list->data);
+		else
+			contact = NULL;
+
+		eab_contact_formatter_format_contact_sync (
+			vpuri->formatter, contact, stream, cancellable);
+
+	} else {
+		gchar *str, *uri;
+		gint length;
+		const gchar *label = NULL;
+		EABContactDisplayMode mode;
+		const gchar *info = NULL;
+
+		length = g_slist_length (vpuri->contact_list);
+		if (length < 1)
+			return;
+
+		uri = em_format_build_mail_uri (
+			emf->folder, emf->message_uid,
+			"part_id", G_TYPE_STRING, puri->uri,
+			"mode", G_TYPE_INT, EM_FORMAT_WRITE_MODE_RAW, NULL);
+
+		mode = eab_contact_formatter_get_display_mode (vpuri->formatter);
+		if (mode == EAB_CONTACT_DISPLAY_RENDER_COMPACT) {
+			mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL;
+			label =_("Show Full vCard");
+		} else {
+			mode = EAB_CONTACT_DISPLAY_RENDER_COMPACT;
+			label = _("Show Compact vCard");
+		}
+
+		str = g_strdup_printf (
+			"<div id=\"%s\">"
+			"<button type=\"button\" "
+				"name=\"set-display-mode\" "
+				"class=\"org-gnome-vcard-inline-display-mode-button\" "
+				"value=\"%d\">%s</button>"
+			"<button type=\"button\" "
+				"name=\"save-to-addressbook\" "
+				"class=\"org-gnome-vcard-inline-save-button\" "
+				"value=\"%s\">%s</button><br/>"
+			"<iframe width=\"100%%\" height=\"auto\" frameborder=\"0\""
+				"src=\"%s\" name=\"%s\"></iframe>"
+			"</div>",
+			 puri->uri,
+			 mode, label,
+			 puri->uri, _("Save To Addressbook"),
+			 uri, puri->uri);
+
+		camel_stream_write_string (stream, str, cancellable, NULL);
+
+		g_free (str);
+
+		if (length == 2) {
+
+			info = _("There is one other contact.");
+
+		} else if (length > 2) {
+
+			/* Translators: This will always be two or more. */
+			info = g_strdup_printf (ngettext (
+				"There is %d other contact.",
+				"There are %d other contacts.",
+				length - 1), length - 1);
+		}
+
+		if (info) {
+
+			str = g_strdup_printf (
+				"<div class=\"attachment-info\">%s</div>",
+				info);
+
+			camel_stream_write_string (stream, str, cancellable, NULL);
+
+			g_free (str);
+		}
+
+		g_free (uri);
+	}
 }
 
 void
 org_gnome_vcard_inline_format (gpointer ep,
                                EMFormatHookTarget *target)
 {
-	VCardInlinePObject *vcard_object;
-	gchar *classid;
-	gchar *content;
-
-	classid = g_strdup_printf (
-		"org-gnome-vcard-inline-display-%d",
-		org_gnome_vcard_inline_classid++);
-
-	vcard_object = (VCardInlinePObject *)
-		em_format_html_add_pobject (
-			EM_FORMAT_HTML (target->format),
-			sizeof (VCardInlinePObject),
-			classid, target->part,
-			org_gnome_vcard_inline_embed);
+	VCardInlinePURI *vcard_object;
+	gint len;
+
+	len = target->part_id->len;
+	g_string_append (target->part_id, ".org-gnome-vcard-inline-display");
+
+	vcard_object = (VCardInlinePURI *) em_format_puri_new (
+			target->format, sizeof (VCardInlinePURI),
+			target->part, target->part_id->str);
+	vcard_object->puri.mime_type = g_strdup("text/html");
+	vcard_object->puri.write_func = org_gnome_vcard_inline_write;
+	vcard_object->puri.bind_func = org_gnome_vcard_inline_bind_dom;
+	vcard_object->puri.free = org_gnome_vcard_inline_pobject_free;
+	vcard_object->puri.is_attachment = true;
+	vcard_object->formatter
+		= g_object_new (
+			EAB_TYPE_CONTACT_FORMATTER,
+			"display-mode", EAB_CONTACT_DISPLAY_RENDER_COMPACT,
+			"render-maps", FALSE, NULL);
+
+	em_format_add_puri (target->format, (EMFormatPURI *) vcard_object);
 
 	g_object_ref (target->part);
 
-	vcard_object->object.free = org_gnome_vcard_inline_pobject_free;
 	org_gnome_vcard_inline_decode (vcard_object, target->part);
-
 	e_book_client_get_sources (&vcard_object->source_list, NULL);
 
-	content = g_strdup_printf ("<object classid=%s></object>", classid);
-	camel_stream_write_string (target->stream, content, NULL, NULL);
-	g_free (content);
-
-	g_free (classid);
+	g_string_truncate (target->part_id, len);
 }



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