/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* mail-config.c: Mail configuration dialogs/wizard. */

/* 
 * Authors: 
 *  Dan Winship <danw@helixcode.com>
 *  Jeffrey Stedfast <fejj@helixcode.com>
 *  JP Rosevear <jpr@helixcode.com>
 *
 * Copyright 2000 Helix Code, Inc. (http://www.helixcode.com)
 *
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include <config.h>
#include <pwd.h>

#include <gnome.h>
#include <gtkhtml/gtkhtml.h>
#include <glade/glade.h>

#include "e-util/e-html-utils.h"
#include "e-util/e-setup.h"
#include "mail.h"

typedef struct _MailDialogIdentityPage MailDialogIdentityPage;
typedef struct _MailDialogServicePage MailDialogServicePage;

typedef void (*IdentityPageCallback) (MailDialogIdentityPage *, gpointer);
typedef void (*ServicePageCallback) (MailDialogServicePage *, gpointer);

typedef struct 
{
	CamelProvider *provider;
	CamelService *service;
	CamelProviderType type;
	GList *authtypes;
} MailService;

struct _MailDialogIdentityPage
{
	GtkWidget *vbox;
	GtkWidget *name;
	GtkWidget *address;
	GtkWidget *org;
	GtkWidget *sig;
	IdentityPageCallback cb;
	gpointer data;
};

typedef struct
{
	GtkWidget *item;
	GtkWidget *vbox;
	CamelProviderType type;
	gchar *protocol;
	GtkWidget *user;
	gboolean userneed;
	GtkWidget *host;
	gboolean hostneed;
	GtkWidget *path;
	gboolean pathneed;
	GtkWidget *auth_optionmenu;
	GList *auth_items;
	GtkWidget *auth_html;
	GtkWidget *auth_detect;
	gint pnum;
} MailDialogServicePageItem;

struct _MailDialogServicePage
{
	GtkWidget *vbox;
	GtkWidget *optionmenu;
	GList *items;
	GtkWidget *notebook;
	MailDialogServicePageItem *spitem;
	ServicePageCallback changedcb;
	gpointer changeddata;
	ServicePageCallback donecb;
	gpointer donedata;
};

typedef struct
{
	GtkWidget *vbox;
	MailDialogServicePage *page;
} MailDialogSourcePage;

typedef struct
{
	GtkWidget *vbox;
	MailDialogServicePage *page;
} MailDialogNewsPage;

typedef struct
{
	GtkWidget *vbox;
	MailDialogServicePage *page;
} MailDialogTransportPage;

typedef struct 
{
	GtkWidget *dialog;
	MailDialogIdentityPage *page;
	MailConfigIdentity *id;
} MailDialogIdentity;

typedef struct
{
	GtkWidget *dialog;
	MailDialogSourcePage *page;
	MailConfigService *source;
} MailDialogSource;

typedef struct
{
	GtkWidget *dialog;
	MailDialogNewsPage *page;
	MailConfigService *source;
} MailDialogNews;

typedef struct
{
	GladeXML *gui;
	GtkWidget *dialog;
	GtkWidget *druid;
	MailDialogIdentityPage *idpage;
	MailDialogSourcePage *spage;
	MailDialogTransportPage *tpage;
} MailDruidDialog;

typedef struct
{
	GladeXML *gui;
	GtkWidget *dialog;
	GtkWidget *notebook;
	GtkWidget *clistIdentities;
	gint idrow;
	gint maxidrow;
	GtkWidget *clistSources;
	gint srow;
	gint maxsrow;
	GtkWidget *clistNewsServers;
	gint nrow;
	gint maxnrow;
	MailDialogTransportPage *page;
	gboolean tpagedone;
	GtkWidget *chkFormat;
} MailDialog;

static const char GCONFPATH[] = "/apps/Evolution/Mail";
static MailConfig *config = NULL;

/* private prototypes - these are ugly, rename some of them? */
static void html_size_req (GtkWidget *widget, GtkRequisition *requisition);
static GtkWidget *html_new (gboolean white);
static void put_html (GtkHTML *html, char *text);
static void error_dialog (GtkWidget *parent_finder, const char *fmt, ...);
static GdkImlibImage *load_image (const char *name);
static void service_page_menuitem_activate (GtkWidget *item, 
					    MailDialogServicePage *page);
static void service_page_item_changed (GtkWidget *item, 
				       MailDialogServicePage *page);
static void service_page_item_auth_activate (GtkWidget *menuitem, 
					     MailDialogServicePageItem *spitem);


/* HTML Helpers */
static void
html_size_req (GtkWidget *widget, GtkRequisition *requisition)
{
	 requisition->height = GTK_LAYOUT (widget)->height;
}

/* Returns a GtkHTML which is already inside a GtkScrolledWindow. If
 * @white is TRUE, the GtkScrolledWindow will be inside a GtkFrame.
 */
static GtkWidget *
html_new (gboolean white)
{
	GtkWidget *html, *scrolled, *frame;
	GtkStyle *style;
	
	html = gtk_html_new ();
	GTK_LAYOUT (html)->height = 0;
	gtk_signal_connect (GTK_OBJECT (html), "size_request",
			    GTK_SIGNAL_FUNC (html_size_req), NULL);
	gtk_html_set_editable (GTK_HTML (html), FALSE);
	style = gtk_rc_get_style (html);
	if (style) {
		gtk_html_set_default_background_color (GTK_HTML (html),
						       white ? &style->white :
						       &style->bg[0]);
	}
	gtk_widget_set_sensitive (html, FALSE);
	scrolled = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
					GTK_POLICY_NEVER,
					GTK_POLICY_NEVER);
	gtk_container_add (GTK_CONTAINER (scrolled), html);
	
	if (white) {
		frame = gtk_frame_new (NULL);
		gtk_frame_set_shadow_type (GTK_FRAME (frame),
					   GTK_SHADOW_ETCHED_IN);
		gtk_container_add (GTK_CONTAINER (frame), scrolled);
		gtk_widget_show_all (frame);
	} else
		gtk_widget_show_all (scrolled);
	
	return html;
}

static void
put_html (GtkHTML *html, char *text)
{
	GtkHTMLStream *handle;
	
	text = e_text_to_html (text, E_TEXT_TO_HTML_CONVERT_NL);
	handle = gtk_html_begin (html);
	gtk_html_write (html, handle, "<HTML><BODY>", 12);
	gtk_html_write (html, handle, text, strlen (text));
	gtk_html_write (html, handle, "</BODY></HTML>", 14);
	g_free (text);
	gtk_html_end (html, handle, GTK_HTML_STREAM_OK);
}


/* Standard Dialog Helpers */
static void
error_dialog (GtkWidget *parent_finder, const char *fmt, ...)
{
	GtkWidget *parent, *dialog;
	char *msg;
	va_list ap;
	
	parent = gtk_widget_get_ancestor (parent_finder, GTK_TYPE_WINDOW);
	
	va_start (ap, fmt);
	msg = g_strdup_vprintf (fmt, ap);
	va_end (ap);
	
	dialog = gnome_error_dialog_parented (msg, GTK_WINDOW (parent));
	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
	g_free (msg);
}

static void
info_dialog (GtkWidget *parent_finder, const char *fmt, ...)
{
	GtkWidget *parent, *dialog;
	char *msg;
	va_list ap;
	
	parent = gtk_widget_get_ancestor (parent_finder, GTK_TYPE_WINDOW);
	
	va_start (ap, fmt);
	msg = g_strdup_vprintf (fmt, ap);
	va_end (ap);
	
	dialog = gnome_ok_dialog_parented (msg, GTK_WINDOW (parent));
	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
	g_free (msg);
}

/* Provider List */
static GSList *
provider_list_add (GSList *services, CamelProviderType type, 
		   CamelProvider *prov)
{
	MailService *mcs;
	CamelService *service;
	CamelException *ex;
	char *url;

	ex = camel_exception_new ();

	url = g_strdup_printf ("%s:", prov->protocol);
	service = camel_session_get_service (session, url, type, ex);
	g_free (url);
	if (!service) {
		camel_exception_free (ex);
		return services;
	}

	mcs = g_new (MailService, 1);
	mcs->provider = prov;
	mcs->service = service;
	mcs->type = type;
	mcs->authtypes = camel_service_query_auth_types (mcs->service, ex);
	camel_exception_free (ex);

	return g_slist_prepend (services, mcs);
}

static void 
provider_list (GSList **sources, GSList **news, GSList **transports)
{
	GList *providers, *p;
	
	/* Fetch list of all providers. */
	providers = camel_session_list_providers (session, TRUE);
	*sources = *transports = *news = NULL;
	for (p = providers; p; p = p->next) {
		CamelProvider *prov = p->data;
		
		if (!strcmp (prov->domain, "news")) {
			if (prov->object_types[CAMEL_PROVIDER_STORE]) {
				*news = provider_list_add (*news,
							   CAMEL_PROVIDER_STORE,
							   prov);
			}
		}
    
		if (strcmp (prov->domain, "mail"))
			continue;
		
		if (prov->object_types[CAMEL_PROVIDER_STORE]) {
			*sources = provider_list_add (*sources,
						      CAMEL_PROVIDER_STORE,
						      prov);
		} else if (prov->object_types[CAMEL_PROVIDER_TRANSPORT]) {
			*transports = provider_list_add (*transports,
							 CAMEL_PROVIDER_TRANSPORT,
							 prov);
		}
	}	
}

/* Utility routines */
static GdkImlibImage *
load_image (const char *name)
{
	char *path;
	GdkImlibImage *image;

	path = g_strdup_printf (EVOLUTION_ICONSDIR "/%s", name);
	image = gdk_imlib_load_image (path);
	g_free (path);

	return image;
}

/* Identity struct */
static MailConfigIdentity *
identity_copy (MailConfigIdentity *id) 
{
	MailConfigIdentity *newid;
	
	g_return_val_if_fail (id, NULL);
	
	newid = g_new0 (MailConfigIdentity, 1);
	newid->name = g_strdup (id->name);
	newid->address = g_strdup (id->address);
	newid->org = g_strdup (id->org);
	newid->sig = g_strdup (id->sig);
	
	return newid;
}

static void
identity_destroy (MailConfigIdentity *id)
{
	if (!id)
		return;
	
	g_free (id->name);
	g_free (id->address);
	g_free (id->org);
	g_free (id->sig);
	
	g_free (id);
}

static void
identity_destroy_each (gpointer item, gpointer data)
{
	identity_destroy ((MailConfigIdentity *)item);
}

/* Source struct */
static MailConfigService *
service_copy (MailConfigService *source) 
{
	MailConfigService *newsource;
	
	g_return_val_if_fail (source, NULL);
	
	newsource = g_new0 (MailConfigService, 1);
	newsource->url = g_strdup (source->url);
	
	return newsource;
}

static void
service_destroy (MailConfigService *source)
{
	if (!source)
		return;

	g_free (source->url);
	
	g_free (source);
}

static void
service_destroy_each (gpointer item, gpointer data)
{
	service_destroy ((MailConfigService *)item);
}

/* Config struct routines */
static void
init_config ()
{
	if (config)
		return;
	
	config = g_new0 (MailConfig, 1);

	config->ids = NULL;
	config->sources = NULL;
	config->transport = NULL;
}

static void
clear_config ()
{
	if (!config)
		return;
	
	if (config->ids) {
		g_slist_foreach (config->ids, identity_destroy_each, NULL);
		g_slist_free (config->ids);
		config->ids = NULL;
	}
	
	if (config->sources) {
		g_slist_foreach (config->sources, service_destroy_each, NULL);
		g_slist_free (config->sources);
		config->sources = NULL;
	}
	
	service_destroy (config->transport);
	config->transport = NULL;
}

static void
read_config ()
{
	gchar *str;
	gint len, i;
	
	init_config ();
	clear_config ();

	/* Configured */
	str = g_strdup_printf ("=%s/config/General=/General/configured", evolution_dir);
	config->configured = gnome_config_get_bool (str);
	g_free (str);
	
	/* Identities */
	str = g_strdup_printf ("=%s/config/Mail=/Identities/", evolution_dir);
	gnome_config_push_prefix (str);
	g_free (str);

	len = gnome_config_get_int ("num");
	for (i = 0; i < len; i++) {
		MailConfigIdentity *id;
		gchar *path;
		
		id = g_new0 (MailConfigIdentity, 1);

		path = g_strdup_printf ("name_%d", i);
		id->name = gnome_config_get_string (path);
		g_free (path);
		path = g_strdup_printf ("address_%d", i);
		id->address = gnome_config_get_string (path);
		g_free (path);
		path = g_strdup_printf ("org_%d", i);
		id->org = gnome_config_get_string (path);
		g_free (path);
		path = g_strdup_printf ("sig_%d", i);
		id->sig = gnome_config_get_string (path);
		g_free (path);

		config->ids = g_slist_append (config->ids, id);
	}
	gnome_config_pop_prefix ();

	/* Sources */
	str = g_strdup_printf ("=%s/config/Mail=/Sources/", evolution_dir);
	gnome_config_push_prefix (str);
	g_free (str);

	len = gnome_config_get_int ("num");
	for (i = 0; i < len; i++) {
		MailConfigService *s;
		gchar *path;
		
		s = g_new0 (MailConfigService, 1);
		
		path = g_strdup_printf ("url_%d", i);
		s->url = gnome_config_get_string (path);
		g_free (path);
		
		config->sources = g_slist_append (config->sources, s);
	}
	gnome_config_pop_prefix ();
	
	/* News */
	str = g_strdup_printf ("=%s/config/News=/Sources/", evolution_dir);
	gnome_config_push_prefix (str);
	g_free (str);

	len = gnome_config_get_int ("num");
	for (i = 0; i < len; i++) {
		MailConfigService *n;
		gchar *path;
		
		n = g_new0 (MailConfigService, 1);

		path = g_strdup_printf ("url_%d", i);
		n->url = gnome_config_get_string (path);
		g_free (path);

		config->news = g_slist_append (config->news, n);
	}
	gnome_config_pop_prefix ();
	
	/* Transport */
	config->transport = g_new0 (MailConfigService, 1);
	str = g_strdup_printf ("=%s/config/Mail=/Transport/url", 
			       evolution_dir);
	config->transport->url = gnome_config_get_string (str);
	g_free (str);
	
	/* Format */
	str = g_strdup_printf ("=%s/config/Mail=/Format/send_html", 
			       evolution_dir);
	config->send_html = gnome_config_get_bool (str);
	g_free (str);
	
	gnome_config_sync ();
}

static void
write_config ()
{
	gchar *str;
	gint len, i;
	
	init_config ();

	/* Configured switch */
	str = g_strdup_printf ("=%s/config/General=/General/configured", 
			       evolution_dir);
	gnome_config_set_bool (str, TRUE);
	g_free (str);
	
	/* Identities */
	str = g_strdup_printf ("=%s/config/Mail=/Identities/", evolution_dir);
	gnome_config_push_prefix (str);
	g_free (str);

	len = g_slist_length (config->ids);
	gnome_config_set_int ("num", len);
	for (i = 0; i < len; i++) {
		MailConfigIdentity *id;
		gchar *path;
		
		id = (MailConfigIdentity *)g_slist_nth_data (config->ids, i);
		
		path = g_strdup_printf ("name_%d", i);
		gnome_config_set_string (path, id->name);
		g_free (path);
		path = g_strdup_printf ("address_%d", i);
		gnome_config_set_string (path, id->address);
		g_free (path);
		path = g_strdup_printf ("org_%d", i);
		gnome_config_set_string (path, id->org);
		g_free (path);
		path = g_strdup_printf ("sig_%d", i);
		gnome_config_set_string (path, id->sig);
		g_free (path);
	}
	gnome_config_pop_prefix ();
	
	/* Sources */
	str = g_strdup_printf ("=%s/config/Mail=/Sources/", evolution_dir);
	gnome_config_push_prefix (str);
	g_free (str);

	len = g_slist_length (config->sources);
	gnome_config_set_int ("num", len);
	for (i=0; i<len; i++) {
		MailConfigService *s;
		gchar *path;
		
		s = (MailConfigService *)g_slist_nth_data (config->sources, i);
		
		path = g_strdup_printf ("url_%d", i);
		gnome_config_set_string (path, s->url);
		g_free (path);
	}
	gnome_config_pop_prefix ();

	/* News */
	str = g_strdup_printf ("=%s/config/News=/Sources/", evolution_dir);
	gnome_config_push_prefix (str);
	g_free (str);

  	len = g_slist_length (config->news);
	gnome_config_set_int ("num", len);
	for (i=0; i<len; i++) {
		MailConfigService *n;
		gchar *path;
		
		n = (MailConfigService *)g_slist_nth_data (config->news, i);
		
		path = g_strdup_printf ("url_%d", i);
		gnome_config_set_string (path, n->url);
		g_free (path);
	}
	gnome_config_pop_prefix ();

	/* Transport */
	str = g_strdup_printf ("=%s/config/Mail=/Transport/url", 
			       evolution_dir);
	gnome_config_set_string (str, config->transport->url);
	g_free (str);
	
	/* Format */
	str = g_strdup_printf ("=%s/config/Mail=/Format/send_html", 
			       evolution_dir);
	gnome_config_set_bool (str, config->send_html);
	g_free (str);
	
	gnome_config_sync ();
}

/* Identity Page */
static void
identity_page_changed (GtkWidget *widget, MailDialogIdentityPage *page)
{
	gchar *name, *addr;
	
	name = gtk_editable_get_chars (GTK_EDITABLE (page->name), 0, -1);
	addr = gtk_editable_get_chars (GTK_EDITABLE (page->address), 0, -1);
	
	if (addr && name && page->cb)
		page->cb (page, page->data);
	
	g_free (name);
	g_free (addr);
}

static MailConfigIdentity *
identity_page_extract (MailDialogIdentityPage *page)
{
	MailConfigIdentity *id = g_new0 (MailConfigIdentity, 1);

	id->name = gtk_editable_get_chars (GTK_EDITABLE (page->name), 0, -1);
	id->address = 
		gtk_editable_get_chars (GTK_EDITABLE (page->address), 0, -1);
	id->org = gtk_editable_get_chars (GTK_EDITABLE (page->org), 0, -1);
	id->sig = gtk_editable_get_chars (GTK_EDITABLE (page->sig), 0, -1);

	return id;
}

static void
identity_page_set_done_cb (MailDialogIdentityPage *page, 
			   IdentityPageCallback cb, gpointer data)
{
	page->cb = cb;
	page->data = data;
}

static MailDialogIdentityPage *
identity_page_new (const MailConfigIdentity *id)
{
	MailDialogIdentityPage *page = g_new0 (MailDialogIdentityPage, 1);
	GtkWidget *html, *table;
	GtkWidget *label, *fentry, *hsep;
	gchar *user = NULL;
	gboolean new = !id;
	
	page->vbox = gtk_vbox_new (FALSE, 5);
	
	html = html_new (FALSE);
	put_html (GTK_HTML (html),
		  _("Enter your name and email address to be used in "
		    "outgoing mail. You may also, optionally, enter the "
		    "name of your organization, and the name of a file "
		    "to read your signature from."));
	gtk_box_pack_start (GTK_BOX (page->vbox), html->parent, 
			    FALSE, TRUE, 0);

	table = gtk_table_new (5, 2, FALSE);
	gtk_table_set_row_spacings (GTK_TABLE (table), 10);
	gtk_table_set_col_spacings (GTK_TABLE (table), 6);
	gtk_container_set_border_width (GTK_CONTAINER (table), 8);
	gtk_box_pack_start (GTK_BOX (page->vbox), table, FALSE, FALSE, 0);

	label = gtk_label_new (_("Full name:"));
	gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
			  GTK_FILL, 0, 0, 0);
	gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

	page->name = gtk_entry_new ();
	gtk_table_attach (GTK_TABLE (table), page->name, 1, 2, 0, 1,
			  GTK_EXPAND | GTK_FILL, 0, 0, 0);

	if (!id || !id->name)
		user = g_get_real_name ();

	if ((id && id->name) || user) {
		char *name;

		if (id && id->name)
			name = g_strdup (id->name);
		else
			name = g_strdup (user);

		gtk_entry_set_text (GTK_ENTRY (page->name), name);
		g_free (name);
	}

	label = gtk_label_new (_("Email address:"));
	gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
			  GTK_FILL, 0, 0, 0);
	gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

	page->address = gtk_entry_new ();
	if (id && id->address)
		gtk_entry_set_text (GTK_ENTRY (page->address), id->address);
	gtk_table_attach (GTK_TABLE (table), page->address, 1, 2, 1, 2,
			  GTK_EXPAND | GTK_FILL, 0, 0, 0);

	hsep = gtk_hseparator_new ();
	gtk_table_attach (GTK_TABLE (table), hsep, 0, 2, 2, 3,
			  GTK_FILL, 0, 0, 8);

	label = gtk_label_new (_("Organization:"));
	gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
			  GTK_FILL, 0, 0, 0);
	gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

	page->org = gtk_entry_new ();
	if (id && id->org)
		gtk_entry_set_text (GTK_ENTRY (page->org), id->org);
	gtk_table_attach (GTK_TABLE (table), page->org, 1, 2, 3, 4,
			  GTK_EXPAND | GTK_FILL, 0, 0, 0);

	label = gtk_label_new (_("Signature file:"));
	gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5,
			  GTK_FILL, GTK_FILL, 0, 0);
	gtk_misc_set_alignment (GTK_MISC (label), 1, 0);

	fentry = gnome_file_entry_new (NULL, _("Signature File"));
	page->sig = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (fentry));
	if (id && id->sig) {
		gtk_entry_set_text (GTK_ENTRY (page->sig), id->sig);
	} else {
		gchar *default_sig;
		
		default_sig = g_strconcat (g_get_home_dir (), 
					   G_DIR_SEPARATOR_S,
					   ".signature", NULL);
		if (g_file_exists (default_sig))
			gtk_entry_set_text (GTK_ENTRY (page->sig), default_sig);
		g_free (default_sig);
	}
	
	gtk_table_attach (GTK_TABLE (table), fentry, 1, 2, 4, 5,
			  GTK_FILL, 0, 0, 0);
	gnome_file_entry_set_default_path (GNOME_FILE_ENTRY (fentry),
					   g_get_home_dir ());
	
	gtk_signal_connect (GTK_OBJECT (page->name), "changed",
			    GTK_SIGNAL_FUNC (identity_page_changed), page);
	gtk_signal_connect (GTK_OBJECT (page->address), "changed",
			    GTK_SIGNAL_FUNC (identity_page_changed), page);
	if (!new) {
		gtk_signal_connect (GTK_OBJECT (page->org), "changed",
				    GTK_SIGNAL_FUNC (identity_page_changed), 
				    page);
		gtk_signal_connect (GTK_OBJECT (page->sig), "changed",
				    GTK_SIGNAL_FUNC (identity_page_changed), 
				    page);
	}

	gtk_widget_show_all (table);

	return page;
}

/* Service page */
static MailDialogServicePageItem *
service_page_item_by_protocol (MailDialogServicePage *page, gchar *protocol)
{
	MailDialogServicePageItem *spitem;
	gint len, i;
	
	len = g_list_length (page->items);
	for (i = 0; i < len; i++) {
		spitem = (MailDialogServicePageItem *)
			g_list_nth_data (page->items, i);
		if (!g_strcasecmp (spitem->protocol, protocol)) 
			return spitem;
	}
	
	return NULL;
}

static MailDialogServicePageItem *
service_page_item_by_menuitem (MailDialogServicePage *page, 
			       GtkWidget *menuitem)
{
	MailDialogServicePageItem *spitem;
	gint len, i;
	
	len = g_list_length (page->items);
	for (i = 0; i < len; i++) {
		spitem = (MailDialogServicePageItem *)
			g_list_nth_data (page->items, i);
		if (spitem->item == menuitem) 
			return spitem;
	}

	return NULL;
}

static char *
service_page_get_url (MailDialogServicePage *page)
{
	MailDialogServicePageItem *spitem;
	CamelURL *url;
	char *url_str;

	spitem = page->spitem;
	
	url = g_new0 (CamelURL, 1);
	url->protocol = g_strdup (spitem->protocol);

	if (spitem->user)
		url->user = gtk_editable_get_chars (GTK_EDITABLE (spitem->user), 0, -1);
	if (spitem->host)
		url->host = gtk_editable_get_chars (GTK_EDITABLE (spitem->host), 0, -1);
	if (spitem->path) {
		gchar *path;
		path = gtk_editable_get_chars (GTK_EDITABLE (spitem->path),
					       0, -1);
		url->path = g_strdup_printf ("%s%s", url->host ? "/" : "", 
					     path);
		g_free (path);
	}
	
	if (spitem->auth_optionmenu) {
		GtkWidget *menu, *item;
		CamelServiceAuthType *authtype;

		menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (spitem->auth_optionmenu));
		if (menu) {
			item = gtk_menu_get_active (GTK_MENU (menu));
			authtype = gtk_object_get_data (GTK_OBJECT (item),
							"authtype");
			if (*authtype->authproto)
				url->authmech = g_strdup (authtype->authproto);
		}
	}

	url_str = camel_url_to_string (url, FALSE);
	camel_url_free (url);
	
	return url_str;
}

static void
service_page_set_url (MailDialogServicePage *page, MailConfigService *service)
{
	CamelURL *url;
	CamelException *ex;
	MailDialogServicePageItem *spitem = NULL;
	
	if (!service || !service->url)
		return;
	
	ex = camel_exception_new ();
	
	url = camel_url_new (service->url, ex);
	if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE) {
		camel_exception_free (ex);
		return;
	}

	/* Find the right protocol */
	spitem = service_page_item_by_protocol (page, url->protocol);
	service_page_menuitem_activate (spitem->item, page);
	gtk_option_menu_set_history (GTK_OPTION_MENU (page->optionmenu), 
				     spitem->pnum);
	
	if (spitem->user && url && url->user)
		gtk_entry_set_text (GTK_ENTRY (spitem->user), url->user);

	if (spitem->host && url && url->host)
		gtk_entry_set_text (GTK_ENTRY (spitem->host), url->host);
	
	if (spitem->path && url && url->path) {
		if (url->host && *url->path)
			gtk_entry_set_text (GTK_ENTRY (spitem->path),
					    url->path + 1);
		else
			gtk_entry_set_text (GTK_ENTRY (spitem->path), 
					    url->path);
	}

	/* Set the auth menu */
	if (spitem->auth_optionmenu) {
		GtkWidget *menu, *item;
		CamelServiceAuthType *authtype;
		gint len, i;
		
		menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (spitem->auth_optionmenu));
		len = g_list_length (spitem->auth_items);
		for (i = 0; i < len; i++) {
			item = g_list_nth_data (spitem->auth_items, i);
			authtype = gtk_object_get_data (GTK_OBJECT (item),
							"authtype");
			
			if ((!url->authmech && !*authtype->authproto) ||
			    (url->authmech && !strcmp (authtype->authproto, url->authmech)))
				service_page_item_auth_activate (item, spitem);
				gtk_option_menu_set_history (GTK_OPTION_MENU (spitem->auth_optionmenu), i);
		}
	}

	camel_exception_free (ex);
	camel_url_free (url);
}

static void
service_page_item_auth_activate (GtkWidget *menuitem, 
				 MailDialogServicePageItem *spitem)
{
	CamelServiceAuthType *authtype;

	authtype = gtk_object_get_data (GTK_OBJECT (menuitem), "authtype");
	put_html (GTK_HTML (spitem->auth_html), 
		  authtype->description);
}

static void
service_page_item_auth_fill (MailDialogServicePage *page,
			     MailDialogServicePageItem *spitem, 
			     GList *authtypes)
{
	CamelServiceAuthType *authtype;
	GtkWidget *menu, *item, *firstitem = NULL;

	menu = gtk_menu_new ();
	gtk_option_menu_set_menu (GTK_OPTION_MENU (spitem->auth_optionmenu), 
				  menu);
	for (; authtypes; authtypes = authtypes->next) {
		authtype = authtypes->data;

		item = gtk_menu_item_new_with_label (_(authtype->name));
		if (!firstitem)
			firstitem = item;
		spitem->auth_items = g_list_append (spitem->auth_items, item);

		gtk_menu_append (GTK_MENU (menu), item);
		gtk_object_set_data (GTK_OBJECT (item), "authtype", authtype);

		gtk_signal_connect (GTK_OBJECT (item), "activate",
				    GTK_SIGNAL_FUNC (service_page_item_auth_activate),
				    spitem);
		gtk_signal_connect (GTK_OBJECT (item), "activate",
				    GTK_SIGNAL_FUNC (service_page_item_changed),
				    page);
	}
	gtk_widget_show_all (menu);

	gtk_option_menu_set_history (GTK_OPTION_MENU (spitem->auth_optionmenu), 0);
	if (firstitem)
		service_page_item_auth_activate (firstitem, spitem);
}

static gboolean
service_acceptable (MailDialogServicePage *page)
{
	char *url = NULL;
	CamelService *service;
	CamelException *ex;

	url = service_page_get_url (page);

	ex = camel_exception_new ();
	camel_exception_clear (ex);
	service = camel_session_get_service (session, url, 
					     page->spitem->type, ex);
	g_free (url);

	if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
		goto error;

	if (camel_service_connect (service, ex)) {
		camel_service_disconnect (service, ex);
		gtk_object_unref (GTK_OBJECT (service));
		camel_exception_free (ex);
		
		info_dialog (page->vbox, "Connection successful!");
		
		return TRUE;
	}
	
	gtk_object_unref (GTK_OBJECT (service));
	
 error:
	error_dialog (page->vbox, camel_exception_get_description (ex));
	camel_exception_free (ex);

	return FALSE;
}

static MailConfigService *
service_page_extract (MailDialogServicePage *page)
{
	MailConfigService *source = g_new0 (MailConfigService, 1);

	source->url = service_page_get_url (page);

	return source;
}

static void
service_page_item_changed (GtkWidget *item, MailDialogServicePage *page) 
{
	MailDialogServicePageItem *spitem;
	char *data;
	gboolean complete = TRUE;

	spitem = page->spitem;

	if (complete && page->changedcb) {
		page->changedcb (page, page->changeddata);
	}
	
	if (spitem->host && spitem->hostneed) {
		data = gtk_editable_get_chars (GTK_EDITABLE (spitem->host), 0, -1);
		if (!data || !*data)
			complete = FALSE;
		g_free (data);
	}

	if (complete) {
		if (spitem->user && spitem->userneed) {
			data = gtk_editable_get_chars (GTK_EDITABLE (spitem->user), 0, -1);
			if (!data || !*data)
				complete = FALSE;
			g_free (data);
		}
	}

	if (complete) {
		if (spitem->path && spitem->pathneed) {
			data = gtk_editable_get_chars (GTK_EDITABLE (spitem->path), 0, -1);
			if (!data || !*data)
				complete = FALSE;
		}
	}

	if (spitem->auth_detect)
		gtk_widget_set_sensitive (spitem->auth_detect, complete);

	if (complete && page->donecb) {
		page->donecb (page, page->donedata);
	}
}

static void
service_page_detect (GtkWidget *button, MailDialogServicePage *page)
{
	MailDialogServicePageItem *spitem;
	char *url = NULL;
	CamelException *ex;
	CamelService *service;
	GList *authtypes;

	spitem = page->spitem;
	url = service_page_get_url (page);

	ex = camel_exception_new ();
	service = camel_session_get_service (session, url, spitem->type, ex);
	g_free (url);
	if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
		goto error;

	authtypes = camel_service_query_auth_types (service, ex);
	if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
		goto error;

	service_page_item_auth_fill (page, spitem, authtypes);

	camel_exception_free (ex);

	return;

 error:
	error_dialog (button, "Could not detect supported authentication "
		      "types:\n%s", camel_exception_get_description (ex));
	camel_exception_free (ex);
}

static void
service_page_item_test (GtkWidget *button, MailDialogServicePage *page) 
{
	service_acceptable (page);
}

static GtkWidget *
service_page_add_elem (MailDialogServicePage *page, GtkWidget *table, 
		       int row, const char *label_text)
{
	GtkWidget *label, *entry;

	label = gtk_label_new (label_text);
	gtk_table_attach (GTK_TABLE (table), label, 0, 1, 
			  row, row + 1, GTK_FILL, 0, 0, 0);
	gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

	entry = gtk_entry_new ();
	gtk_table_attach (GTK_TABLE (table), entry, 1, 3, row, row + 1,
			  GTK_EXPAND | GTK_FILL, 0, 0, 0);

	gtk_signal_connect (GTK_OBJECT (entry), "changed",
			    GTK_SIGNAL_FUNC (service_page_item_changed), page);

	return entry;
}

static MailDialogServicePageItem *
service_page_item_new (MailDialogServicePage *page, MailService *mcs)
{
	MailDialogServicePageItem *item;
	GtkWidget *table, *description;
	int row, service_flags;

	item = g_new0 (MailDialogServicePageItem, 1);
	
	item->vbox = gtk_vbox_new (FALSE, 0);

	/* Description */
	description = html_new (TRUE);
	put_html (GTK_HTML (description), mcs->provider->description);
	gtk_box_pack_start (GTK_BOX (item->vbox),
			    description->parent->parent,
			    TRUE, TRUE, 0);
	
	table = gtk_table_new (5, 3, FALSE);
	gtk_table_set_row_spacings (GTK_TABLE (table), 2);
	gtk_table_set_col_spacings (GTK_TABLE (table), 10);
	gtk_container_set_border_width (GTK_CONTAINER (table), 8);
	gtk_box_pack_start (GTK_BOX (item->vbox), table, TRUE, TRUE, 0);

	item->protocol = g_strdup (mcs->provider->protocol);
	item->type = mcs->type;
	
	row = 0;
	service_flags = mcs->service->url_flags & ~CAMEL_SERVICE_URL_NEED_AUTH;

	if (service_flags & CAMEL_SERVICE_URL_ALLOW_HOST) {
		item->host = service_page_add_elem (page, table, row++, _("Server:"));
		item->hostneed = ((service_flags & CAMEL_SERVICE_URL_NEED_HOST)
				  == CAMEL_SERVICE_URL_NEED_HOST);
	}

	if (service_flags & CAMEL_SERVICE_URL_ALLOW_USER) {
		item->user = service_page_add_elem (page, table, row++, _("Username:"));
		item->userneed = ((service_flags & CAMEL_SERVICE_URL_NEED_USER)
				  == CAMEL_SERVICE_URL_NEED_USER);
	}

	if (service_flags & CAMEL_SERVICE_URL_ALLOW_PATH) {
		item->path = service_page_add_elem (page, table, row++, _("Path:"));
		item->pathneed = ((service_flags & CAMEL_SERVICE_URL_NEED_PATH)
				  == CAMEL_SERVICE_URL_NEED_PATH);
	}

	if (mcs->authtypes) {
		GtkWidget *label;

		label = gtk_label_new (_("Authentication:"));
		gtk_table_attach (GTK_TABLE (table), label, 0, 1,
				  row, row + 1, GTK_FILL, 0, 0, 0);
		gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

		item->auth_optionmenu = gtk_option_menu_new ();
		gtk_table_attach (GTK_TABLE (table), 
				  item->auth_optionmenu, 
				  1, 2, row, row + 1, 
				  GTK_FILL | GTK_EXPAND,
				  0, 0, 0);

		item->auth_detect = gtk_button_new_with_label (_("Detect supported types..."));
		gtk_table_attach (GTK_TABLE (table), item->auth_detect, 
				  2, 3, row, row + 1, 0, 0, 0, 0);
		gtk_widget_set_sensitive (item->auth_detect, FALSE);
		gtk_signal_connect (GTK_OBJECT (item->auth_detect), 
				    "clicked",
				    GTK_SIGNAL_FUNC (service_page_detect), 
				    page);

		item->auth_html = html_new (TRUE);
		gtk_table_attach (GTK_TABLE (table), 
				  item->auth_html->parent->parent,
				  0, 3, row + 1, row + 2,
				  GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);

		service_page_item_auth_fill (page, item, mcs->authtypes);

		row += 2;
	}

	if (row != 0) {
		GtkWidget *btn;

		btn = gtk_button_new_with_label (_("Test Settings"));

		gtk_table_attach (GTK_TABLE (table), btn, 2, 3,
				  row, row + 1, GTK_FILL, GTK_FILL, 0, 0);

		gtk_signal_connect (GTK_OBJECT (btn), "clicked",
				    GTK_SIGNAL_FUNC (service_page_item_test), 
				    page);
		row += 1;
	}

	gtk_table_resize (GTK_TABLE (table), row, 3);
	gtk_widget_show_all (table);

	return item;
}

static void
service_page_menuitem_activate (GtkWidget *item, MailDialogServicePage *page)
{
	MailDialogServicePageItem *spitem;

	spitem = service_page_item_by_menuitem (page, item);

	g_return_if_fail (spitem);
	
	gtk_notebook_set_page (GTK_NOTEBOOK (page->notebook), spitem->pnum);
	page->spitem = spitem;

	service_page_item_changed (item, page);
}

static void
service_page_set_changed_cb (MailDialogServicePage *page, 
			     ServicePageCallback cb, gpointer data)
{
	page->changedcb = cb;
	page->changeddata = data;
}

static void
service_page_set_done_cb (MailDialogServicePage *page, 
			  ServicePageCallback cb, gpointer data)
{
	page->donecb = cb;
	page->donedata = data;
}

static MailDialogServicePage *
service_page_new (const char *label_text, GSList *services)
{
	MailDialogServicePage *page;
	GtkWidget *hbox, *label, *menu;
	GtkWidget *first_item = NULL;
	int pnum;
	GSList *s;

	page = g_new0 (MailDialogServicePage, 1);
	
	page->vbox = gtk_vbox_new (FALSE, 5);
	
	hbox = gtk_hbox_new (FALSE, 8);
	gtk_box_pack_start (GTK_BOX (page->vbox), hbox, FALSE, TRUE, 0);

	label = gtk_label_new (label_text);
	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
	gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

	page->optionmenu = gtk_option_menu_new ();
	menu = gtk_menu_new ();
	gtk_option_menu_set_menu (GTK_OPTION_MENU (page->optionmenu), menu);
	gtk_box_pack_start (GTK_BOX (hbox), page->optionmenu, TRUE, TRUE, 0);
	
	/* Notebook */
	page->notebook = gtk_notebook_new ();
	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (page->notebook), FALSE);
	gtk_box_pack_start (GTK_BOX (page->vbox), page->notebook, 
			    TRUE, TRUE, 0);

	/* Build the list of services and the service item pages */
	for (s = services, pnum = 0; s; s = s->next, pnum++) {
		MailService *mcs = s->data;
		MailDialogServicePageItem *spitem;
		
		spitem = service_page_item_new (page, mcs);
		spitem->pnum = pnum;
		
		gtk_notebook_append_page (GTK_NOTEBOOK (page->notebook), 
					  spitem->vbox, NULL);

		spitem->item = gtk_menu_item_new_with_label (_(mcs->provider->name));
		if (!first_item)
			first_item = spitem->item;

		gtk_signal_connect (GTK_OBJECT (spitem->item), "activate",
				    GTK_SIGNAL_FUNC (service_page_menuitem_activate),
				    page);

		gtk_menu_append (GTK_MENU (menu), spitem->item);
		page->items = g_list_append (page->items, spitem);
	}
	
	service_page_menuitem_activate (first_item, page);
	gtk_option_menu_set_history (GTK_OPTION_MENU (page->optionmenu), 0);

	gtk_widget_show_all (page->vbox);

	return page;
}

/* Source Page */
static MailDialogSourcePage *
source_page_new (GSList *sources)
{
	MailDialogSourcePage *page = g_new0 (MailDialogSourcePage, 1);
	GtkWidget *html;

	page->page = service_page_new ("Mail source type:", sources);
	page->vbox = page->page->vbox;
	
	html = html_new (FALSE);
	put_html (GTK_HTML (html),
		  _("Select the kind of mail server you have, and enter "
		    "the relevant information about it.\n\nIf the server "
		    "requires authentication, you can click the "
		    "\"Detect supported types...\" button after entering "
		    "the other information."));
	gtk_box_pack_start (GTK_BOX (page->vbox), html->parent, 
			    FALSE, TRUE, 0);
	gtk_box_reorder_child (GTK_BOX (page->vbox), html->parent, 0);

	return page;
}

/* News Page */
static MailDialogNewsPage *
news_page_new (GSList *sources)
{
	MailDialogNewsPage *page = g_new0 (MailDialogNewsPage, 1);
	GtkWidget *html;

	page->page = service_page_new ("Mail source type:", sources);
	page->vbox = page->page->vbox;
	
	html = html_new (FALSE);
	put_html (GTK_HTML (html),
		  _("Select the kind of news server you have, and enter "
		    "the relevant information about it.\n\nIf the server "
		    "requires authentication, you can click the "
		    "\"Detect supported types...\" button after entering "
		    "the other information."));
	gtk_box_pack_start (GTK_BOX (page->vbox), html->parent, 
			    FALSE, TRUE, 0);
	gtk_box_reorder_child (GTK_BOX (page->vbox), html->parent, 0);

	return page;
}

/* Transport page */
static MailDialogTransportPage *
transport_page_new (GSList *transports)
{
	MailDialogTransportPage *page = g_new0 (MailDialogTransportPage, 1);
	GtkWidget *html;

	page->page = service_page_new ("Mail source type:", transports);
	page->vbox = page->page->vbox;
	
	html = html_new (FALSE);
	put_html (GTK_HTML (html),
		  _("Select the kind of mail server you have, and enter "
		    "the relevant information about it.\n\nIf the server "
		    "requires authentication, you can click the "
		    "\"Detect supported types...\" button after entering "
		    "the other information."));
	gtk_box_pack_start (GTK_BOX (page->vbox), html->parent, 
			    FALSE, TRUE, 0);
	gtk_box_reorder_child (GTK_BOX (page->vbox), html->parent, 0);

	return page;
}

/* Identity dialog */
static void
iddialog_page_done (MailDialogIdentityPage *page, gpointer data)
{
	MailDialogIdentity *iddialog = (MailDialogIdentity *)data;

	gnome_dialog_set_sensitive (GNOME_DIALOG (iddialog->dialog), 0, TRUE);
}

static void
iddialog_ok_clicked (GtkWidget *dialog, MailDialogIdentity *iddialog)
{
	g_return_if_fail (iddialog);
	
	iddialog->id = identity_page_extract (iddialog->page);
}

static MailConfigIdentity *
identity_dialog (const MailConfigIdentity *id, GtkWidget *parent)

{
	MailDialogIdentity *iddialog;
	MailConfigIdentity *returnid;
	GtkWidget *dialog_vbox;
	GtkWidget *area;
	gboolean new = !id;
	
	iddialog = g_new0 (MailDialogIdentity, 1);

	if (new)
		iddialog->dialog = gnome_dialog_new (_("Edit Identity"), NULL);
	else
		iddialog->dialog = gnome_dialog_new (_("Add Identity"), NULL);

	gtk_window_set_modal (GTK_WINDOW (iddialog->dialog), TRUE);
	gtk_window_set_policy (GTK_WINDOW (iddialog->dialog), 
			       TRUE, TRUE, FALSE);
	gnome_dialog_set_parent (GNOME_DIALOG (iddialog->dialog),
				 GTK_WINDOW (parent));

	/* Create the vbox that we will pack the identity widget into */
	dialog_vbox = GNOME_DIALOG (iddialog->dialog)->vbox;
	gtk_widget_show (dialog_vbox);

        /* Get the identity widget */
	iddialog->page = identity_page_new (id);
	identity_page_set_done_cb (iddialog->page, iddialog_page_done, 
				   iddialog);
	gtk_box_pack_start (GTK_BOX (dialog_vbox), 
			    iddialog->page->vbox, TRUE, TRUE, 0);
	gtk_widget_show (iddialog->page->vbox);

	/* Buttons */
	area = GNOME_DIALOG (iddialog->dialog)->action_area;
	gtk_widget_show (area);
	gtk_button_box_set_layout (GTK_BUTTON_BOX (area), GTK_BUTTONBOX_END);
	gtk_button_box_set_spacing (GTK_BUTTON_BOX (area), 8);

	gnome_dialog_append_button (GNOME_DIALOG (iddialog->dialog), 
				    GNOME_STOCK_BUTTON_OK);
	gnome_dialog_append_button (GNOME_DIALOG (iddialog->dialog), 
				    GNOME_STOCK_BUTTON_CANCEL);	

	gnome_dialog_set_default (GNOME_DIALOG (iddialog->dialog), 0);
	gnome_dialog_set_default (GNOME_DIALOG (iddialog->dialog), 1);
	
	gnome_dialog_set_sensitive (GNOME_DIALOG (iddialog->dialog), 0, FALSE);
	
	gnome_dialog_button_connect( GNOME_DIALOG (iddialog->dialog), 0,
				     GTK_SIGNAL_FUNC (iddialog_ok_clicked),
				     iddialog);

	gnome_dialog_run_and_close (GNOME_DIALOG (iddialog->dialog));

	returnid = iddialog->id;
	g_free (iddialog);

	return returnid;
}

/* Source Dialog */
static void
sdialog_page_done (MailDialogServicePage *page, gpointer data)
{
	MailDialogSource *sdialog = (MailDialogSource *)data;

	gnome_dialog_set_sensitive (GNOME_DIALOG (sdialog->dialog), 0, TRUE);
}

static void
sdialog_ok_clicked (GtkWidget *widget, MailDialogSource *sdialog) 
{
	g_return_if_fail (sdialog);
	
	sdialog->source = service_page_extract (sdialog->page->page);
}

static MailConfigService *
source_dialog (MailConfigService *source, GtkWidget *parent)
{
	MailDialogSource *sdialog;
	MailConfigService *returnsource;
	GtkWidget *dialog_vbox, *area;
	GSList *sources, *news, *transports;
	gboolean new = !source;
	
	sdialog = g_new0 (MailDialogSource, 1);
	sdialog->source = source;
	
	provider_list (&sources, &news, &transports);
	
	if (new)
		sdialog->dialog = gnome_dialog_new (_("Edit Source"), NULL);
	else
		sdialog->dialog = gnome_dialog_new (_("Add Source"), NULL);

	gtk_window_set_modal (GTK_WINDOW (sdialog->dialog), TRUE);
	gtk_window_set_policy (GTK_WINDOW (sdialog->dialog), 
			       TRUE, TRUE, FALSE);
	gtk_window_set_default_size (GTK_WINDOW (sdialog->dialog), 380, 450);
	gnome_dialog_set_parent (GNOME_DIALOG (sdialog->dialog),
				 GTK_WINDOW (parent));

	/* Create the vbox that we will pack the identity widget into */
	dialog_vbox = GNOME_DIALOG (sdialog->dialog)->vbox;
	gtk_widget_show (dialog_vbox);

        /* Get the identity widget */
	sdialog->page = source_page_new (sources);
	if (!new)
		service_page_set_url (sdialog->page->page, source);
	service_page_set_done_cb (sdialog->page->page, 
				  sdialog_page_done, sdialog);
	gtk_box_pack_start (GTK_BOX (dialog_vbox), sdialog->page->vbox, 
			    TRUE, TRUE, 0);
	gtk_widget_show (sdialog->page->vbox);
	
	/* Buttons */
	area = GNOME_DIALOG (sdialog->dialog)->action_area;
	gtk_widget_show (area);
	gtk_button_box_set_layout (GTK_BUTTON_BOX (area), GTK_BUTTONBOX_END);
	gtk_button_box_set_spacing (GTK_BUTTON_BOX (area), 8);

	gnome_dialog_append_button (GNOME_DIALOG (sdialog->dialog), 
				    GNOME_STOCK_BUTTON_OK);
	gnome_dialog_append_button (GNOME_DIALOG (sdialog->dialog), 
				    GNOME_STOCK_BUTTON_CANCEL);	

	gnome_dialog_set_default (GNOME_DIALOG (sdialog->dialog), 0);
	gnome_dialog_set_default (GNOME_DIALOG (sdialog->dialog), 1);
	
	gnome_dialog_set_sensitive (GNOME_DIALOG (sdialog->dialog), 0, FALSE);
	
	gnome_dialog_button_connect(GNOME_DIALOG (sdialog->dialog), 0,
				    GTK_SIGNAL_FUNC (sdialog_ok_clicked),
				    sdialog);

	gnome_dialog_run_and_close (GNOME_DIALOG (sdialog->dialog));

	/* FIXME: */
	returnsource = sdialog->source;
	/*g_free (sdialog);*/

	return returnsource;
}

/* News Dialog */
static void
ndialog_page_done (MailDialogServicePage *page, gpointer data)
{
	MailDialogNews *ndialog = (MailDialogNews *)data;

	gnome_dialog_set_sensitive (GNOME_DIALOG (ndialog->dialog), 0, TRUE);
}

static void
ndialog_ok_clicked (GtkWidget *widget, MailDialogNews *ndialog) 
{
	g_return_if_fail (ndialog);
	
	ndialog->source = service_page_extract (ndialog->page->page);
}

static MailConfigService *
news_dialog (MailConfigService *source, GtkWidget *parent)
{
	MailDialogNews *ndialog;
	MailConfigService *returnsource;
	GtkWidget *dialog_vbox, *area;
	GSList *sources, *news, *transports;
	gboolean new = !source;
	
	ndialog = g_new0 (MailDialogNews, 1);
	
	provider_list (&sources, &news, &transports);
	
	if (new)
		ndialog->dialog = gnome_dialog_new (_("Edit News Server"), NULL);
	else
		ndialog->dialog = gnome_dialog_new (_("Add News Server"), NULL);

	gtk_window_set_modal (GTK_WINDOW (ndialog->dialog), TRUE);
	gtk_window_set_policy (GTK_WINDOW (ndialog->dialog), 
			       TRUE, TRUE, FALSE);
	gtk_window_set_default_size (GTK_WINDOW (ndialog->dialog), 380, 450);
	gnome_dialog_set_parent (GNOME_DIALOG (ndialog->dialog),
				 GTK_WINDOW (parent));

	/* Create the vbox that we will pack the identity widget into */
	dialog_vbox = GNOME_DIALOG (ndialog->dialog)->vbox;
	gtk_widget_show (dialog_vbox);

        /* Get the identity widget */
	ndialog->page = news_page_new (news);
	service_page_set_url (ndialog->page->page, source);
	service_page_set_done_cb (ndialog->page->page, 
				  ndialog_page_done, ndialog);
	gtk_box_pack_start (GTK_BOX (dialog_vbox), ndialog->page->vbox, 
			    TRUE, TRUE, 0);
	gtk_widget_show (ndialog->page->vbox);
	
	/* Buttons */
	area = GNOME_DIALOG (ndialog->dialog)->action_area;
	gtk_widget_show (area);
	gtk_button_box_set_layout (GTK_BUTTON_BOX (area), GTK_BUTTONBOX_END);
	gtk_button_box_set_spacing (GTK_BUTTON_BOX (area), 8);

	gnome_dialog_append_button (GNOME_DIALOG (ndialog->dialog), 
				    GNOME_STOCK_BUTTON_OK);
	gnome_dialog_append_button (GNOME_DIALOG (ndialog->dialog), 
				    GNOME_STOCK_BUTTON_CANCEL);	

	gnome_dialog_set_default (GNOME_DIALOG (ndialog->dialog), 0);
	gnome_dialog_set_default (GNOME_DIALOG (ndialog->dialog), 1);
	
	gnome_dialog_set_sensitive (GNOME_DIALOG (ndialog->dialog), 0, FALSE);
	
	gnome_dialog_button_connect(GNOME_DIALOG (ndialog->dialog), 0,
				    GTK_SIGNAL_FUNC (ndialog_ok_clicked),
				    ndialog);

	gnome_dialog_run_and_close (GNOME_DIALOG (ndialog->dialog));

	returnsource = ndialog->source;
	g_free (ndialog);

	return returnsource;
}

/* Mail configuration druid */

/*  static gboolean */
/*  mail_druid_identity_next (GnomeDruidPage *page, gpointer arg1,  */
/*  			  MailDruidDialog *dialog) */
/*  { */
/*  	char *addr, *at; */
	
/*  	FIXME: we need more sanity checking than this.  */
	
/*  	addr = gtk_editable_get_chars (GTK_EDITABLE (dialog->idpage->address), */
/*  				       0, -1); */
/*  	at = strchr (addr, '@'); */
/*  	if (!at || !strchr (at + 1, '.')) { */
/*  		error_dialog (GTK_WIDGET (page), "Email address must be " */
/*  			      "of the form \"user@domain\"."); */
/*  		return TRUE; */
/*  	} */
/*  	g_free (addr); */
	
/*  	dialog->id = identity_page_extract (dialog->idpage); */

/*  	return FALSE; */
/*  } */

static gboolean
mail_druid_prepare (GnomeDruidPage *page, GnomeDruid *druid, gpointer data)
{
	gnome_druid_set_buttons_sensitive (druid, TRUE, FALSE, TRUE);

	return FALSE;
}

static void
mail_druid_identity_done (MailDialogIdentityPage *page, gpointer data)
{
	MailDruidDialog *dialog = (MailDruidDialog *) data;
	
	gnome_druid_set_buttons_sensitive (GNOME_DRUID (dialog->druid), 
					   TRUE, TRUE, TRUE);
}

static void
mail_druid_service_done (MailDialogServicePage *page, gpointer data)
{
	MailDruidDialog *dialog = (MailDruidDialog *) data;

	gnome_druid_set_buttons_sensitive (GNOME_DRUID (dialog->druid), 
					   TRUE, TRUE, TRUE);
}

static void
mail_druid_cancel (GnomeDruid *druid, GtkWindow *window)
{
	gtk_window_set_modal (window, FALSE);
	gtk_widget_destroy (GTK_WIDGET (window));
	gtk_main_quit ();
}

static void
mail_druid_finish (GnomeDruidPage *page, GnomeDruid *druid, 
		   MailDruidDialog *dialog)
{
	MailConfigIdentity *id;
	MailConfigService *source;
	
	clear_config ();

	/* Identity */
	id = identity_page_extract (dialog->idpage);
	config->ids = g_slist_append (config->ids, id);

	/* Source */
	source = service_page_extract (dialog->spage->page);
	config->sources = g_slist_append (config->sources, source);
	
	/* Transport */
	config->transport = service_page_extract (dialog->tpage->page);

	write_config ();
	
	mail_druid_cancel (druid, GTK_WINDOW (dialog->dialog));
}

void
mail_config_druid (void)
{
	MailDruidDialog *dialog;
	GnomeDruidPageStart *spage;
	GnomeDruidPageFinish *fpage;
	GnomeDruidPageStandard *dpage;
	GSList *sources, *news, *transports;
	GdkImlibImage *mail_logo, *identity_logo;
	GdkImlibImage *source_logo, *transport_logo;

	read_config ();
	provider_list (&sources, &news, &transports);

	mail_logo = load_image ("evolution-inbox.png");
	identity_logo = load_image ("malehead.png");
	source_logo = mail_logo;
	transport_logo = load_image ("envelope.png");

	dialog = g_new0 (MailDruidDialog, 1);
	dialog->gui = glade_xml_new (EVOLUTION_GLADEDIR 
				     "/mail-config-druid.glade", NULL);
	dialog->dialog = glade_xml_get_widget (dialog->gui, "dialog");
	dialog->druid = glade_xml_get_widget (dialog->gui, "druid");

	/* Cancel button */
	gtk_signal_connect (GTK_OBJECT (dialog->druid), "cancel", 
			    GTK_SIGNAL_FUNC (mail_druid_cancel), 
			    dialog->dialog);

	/* Start page */
	spage = GNOME_DRUID_PAGE_START (glade_xml_get_widget (dialog->gui, "startpage"));
	gnome_druid_page_start_set_logo (spage, mail_logo);
	
	/* Identity page */
	dpage = GNOME_DRUID_PAGE_STANDARD (glade_xml_get_widget (dialog->gui, "standardpage1"));
	gnome_druid_page_standard_set_logo (dpage, identity_logo);

	dialog->idpage = identity_page_new (NULL);
	identity_page_set_done_cb (dialog->idpage, 
				   mail_druid_identity_done, 
				   dialog);
	gtk_box_pack_start (GTK_BOX (dpage->vbox), 
			    dialog->idpage->vbox, 
			    TRUE, TRUE, 0);

	gtk_signal_connect (GTK_OBJECT (dpage), "prepare", 
			    GTK_SIGNAL_FUNC (mail_druid_prepare), dialog);
	gtk_widget_show (dialog->idpage->vbox);

	/* Source page */
	dpage = GNOME_DRUID_PAGE_STANDARD (glade_xml_get_widget (dialog->gui, "standardpage2"));
	gnome_druid_page_standard_set_logo (dpage, source_logo);

	dialog->spage = source_page_new (sources);
	service_page_set_done_cb (dialog->spage->page, 
				  mail_druid_service_done, dialog);
	gtk_box_pack_start (GTK_BOX (dpage->vbox), 
			    dialog->spage->vbox, 
			    TRUE, TRUE, 0);

	gtk_signal_connect (GTK_OBJECT (dpage), "prepare", 
			    GTK_SIGNAL_FUNC (mail_druid_prepare), dialog);
	gtk_widget_show (dialog->spage->vbox);

	/* Transport page */
	dpage = GNOME_DRUID_PAGE_STANDARD (glade_xml_get_widget (dialog->gui, "standardpage3"));
	gnome_druid_page_standard_set_logo (dpage, transport_logo);

	dialog->tpage = transport_page_new (transports);
	service_page_set_done_cb (dialog->tpage->page, 
				  mail_druid_service_done, dialog);
	gtk_box_pack_start (GTK_BOX (dpage->vbox), 
			    dialog->tpage->vbox, 
			    TRUE, TRUE, 0);

	gtk_signal_connect (GTK_OBJECT (dpage), "prepare", 
			    GTK_SIGNAL_FUNC (mail_druid_prepare), 
			    dialog);
	gtk_widget_show (dialog->tpage->vbox);


	/* Finish page */
	fpage = GNOME_DRUID_PAGE_FINISH (glade_xml_get_widget (dialog->gui, "finishpage"));
	gnome_druid_page_finish_set_logo (fpage, mail_logo);

	gtk_signal_connect (GTK_OBJECT (fpage), "finish",
			    GTK_SIGNAL_FUNC (mail_druid_finish),
			    dialog);

	gtk_main ();
}

/* Main configuration dialog */
static void
identities_select_row (GtkWidget *widget, gint row, gint column,
		       GdkEventButton *event, MailDialog *dialog)
{
	dialog->idrow = row;
}

static void
identities_add_clicked (GtkWidget *widget, MailDialog *dialog)
{
	MailConfigIdentity *id;

	id = identity_dialog (NULL, dialog->dialog);
	if (id) {
		GtkWidget *clist = dialog->clistIdentities;
		gchar *text[4];
		gint row = 0;
		
		text[0] = id->name;
		text[1] = id->address;
		text[2] = id->org;
		text[3] = id->sig;

		row = gtk_clist_append (GTK_CLIST (clist), text);
		gtk_clist_set_row_data (GTK_CLIST (clist), row, id);
		gtk_clist_select_row (GTK_CLIST (clist), row, 0);
		dialog->maxidrow++;

		gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
	}
}

static void
identities_edit_clicked (GtkWidget *widget, MailDialog *dialog)
{
	MailConfigIdentity *id, *id2;

	if (dialog->idrow < 0)
		return;
	
	id = gtk_clist_get_row_data (GTK_CLIST (dialog->clistIdentities), 
				     dialog->idrow);
	
	id2 = identity_dialog (id, dialog->dialog);
	if (id2) {
		GtkCList *clist = GTK_CLIST (dialog->clistIdentities);
	
		gtk_clist_set_text (clist, dialog->idrow, 0, id2->name);
		gtk_clist_set_text (clist, dialog->idrow, 1, id2->address);
		gtk_clist_set_text (clist, dialog->idrow, 2, id2->org);
		gtk_clist_set_text (clist, dialog->idrow, 3, id2->sig);
	
		gtk_clist_set_row_data (clist, dialog->idrow, id2);
		identity_destroy (id);

		gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
	}
}

static void
identities_delete_clicked (GtkWidget *widget, MailDialog *dialog)
{
	GtkCList *clist;
	
	if (dialog->idrow == -1)
		return;

	clist = GTK_CLIST (dialog->clistIdentities);
	
	gtk_clist_remove (clist, dialog->idrow);
	dialog->maxidrow--;

	if (dialog->idrow > dialog->maxidrow)
		gtk_clist_select_row (clist, dialog->maxidrow, 0);
	else
		gtk_clist_select_row (clist, dialog->idrow, 0);

	gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
}

static void
sources_select_row (GtkWidget *widget, gint row, gint column,
		    GdkEventButton *event, MailDialog *dialog)
{
	dialog->srow = row;
}

static void
sources_add_clicked (GtkWidget *widget, MailDialog *dialog)
{
	MailConfigService *source;

	source = source_dialog (NULL, dialog->dialog);
	if (source) {
		GtkCList *clist = GTK_CLIST (dialog->clistSources);
		gchar *text[1];
		gint row = 0;
		
		text[0] = source->url;
		
		row = gtk_clist_append (clist, text);
		gtk_clist_set_row_data (clist, row, source);
		gtk_clist_select_row (clist, row, 0);
		dialog->maxsrow++;
		
		gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
	}
}

static void
sources_edit_clicked (GtkWidget *widget, MailDialog *dialog)
{
	MailConfigService *source, *source2;

	if (dialog->srow < 0)
		return;

	source = gtk_clist_get_row_data (GTK_CLIST (dialog->clistSources),
					 dialog->srow);
	
	source2 = source_dialog (source, dialog->dialog);
	if (source2) {
		GtkCList *clist = GTK_CLIST (dialog->clistSources);
		
		gtk_clist_set_text (clist, dialog->srow, 0, source2->url);
		gtk_clist_set_row_data (clist, dialog->srow, source2);
		service_destroy (source);

		gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
	}
}

static void
sources_delete_clicked (GtkWidget *widget, MailDialog *dialog)
{
	GtkCList *clist;
	
	if (dialog->srow == -1)
		return;
	
	clist = GTK_CLIST (dialog->clistSources);

	gtk_clist_remove (clist, dialog->srow);
	dialog->maxsrow--;

	if (dialog->srow > dialog->maxsrow)
		gtk_clist_select_row (clist, dialog->maxsrow, 0);
	else
		gtk_clist_select_row (clist, dialog->srow, 0);

	gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
}

static void
news_select_row (GtkWidget *widget, gint row, gint column,
		 GdkEventButton *event, MailDialog *dialog)
{
	dialog->nrow = row;
}

static void
news_add_clicked (GtkWidget *widget, MailDialog *dialog)
{
	MailConfigService *news;

	news = news_dialog (NULL, dialog->dialog);
	if (news) {
		GtkCList *clist = GTK_CLIST (dialog->clistNewsServers);
		gchar *text[1];
		gint row = 0;
		
		text[0] = news->url;

		row = gtk_clist_append (clist, text);
		gtk_clist_set_row_data (clist, row, news);
		gtk_clist_select_row (clist, row, 0);
		dialog->maxsrow++;
		
		gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
	}
}

static void
news_edit_clicked (GtkWidget *widget, MailDialog *dialog)
{
	MailConfigService *news, *news2;

	if (dialog->srow < 0)
		return;

	news = gtk_clist_get_row_data (GTK_CLIST (dialog->clistNewsServers),
				       dialog->srow);
	
	news2 = source_dialog (news, dialog->dialog);
	if (news2) {
		GtkCList *clist = GTK_CLIST (dialog->clistNewsServers);
		
		gtk_clist_set_text (clist, dialog->nrow, 0, news2->url);
		gtk_clist_set_row_data (clist, dialog->nrow, news2);
		service_destroy (news);

		gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
	}
}

static void
news_delete_clicked (GtkWidget *widget, MailDialog *dialog)
{
	GtkCList *clist;
	
	if (dialog->nrow == -1)
		return;
	
	clist = GTK_CLIST (dialog->clistNewsServers);

	gtk_clist_remove (clist, dialog->nrow);
	dialog->maxnrow--;

	if (dialog->nrow > dialog->maxnrow)
		gtk_clist_select_row (clist, dialog->maxnrow, 0);
	else
		gtk_clist_select_row (clist, dialog->nrow, 0);

	gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
}

static void
mail_config_tpage_changed (MailDialogServicePage *page, gpointer data)
{
	MailDialog *dialog = (MailDialog *)data;

	gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
}

static void
mail_config_tpage_done (MailDialogServicePage *page, gpointer data)
{
	MailDialog *dialog = (MailDialog *)data;
	
	dialog->tpagedone = TRUE;
}

static void
format_toggled (GtkWidget *widget, MailDialog *dialog)
{
	gnome_property_box_changed (GNOME_PROPERTY_BOX (dialog->dialog));
}

static void
mail_config_apply_clicked (GnomePropertyBox *property_box, gint page_num,
			   MailDialog *dialog)
{
	gpointer data;
	int i;
	
	if (page_num != -1)
		return;

	clear_config ();

	/* Identities */
	for (i = 0; i <= dialog->maxidrow; i++) {	
		data = gtk_clist_get_row_data (GTK_CLIST (dialog->clistIdentities), i);
		config->ids = g_slist_append (config->ids, data);
	}

	/* Sources */
	for (i = 0; i <= dialog->maxsrow; i++) {	
		data = gtk_clist_get_row_data (GTK_CLIST (dialog->clistSources), i);
		config->sources = g_slist_append (config->sources, data);
	}

	/* Transport */
	config->transport = service_page_extract (dialog->page->page);
	
	/* Format */
	config->send_html = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->chkFormat));

	write_config ();
}

void
mail_config (void)
{
	MailDialog *dialog;
	GladeXML *gui;
	GtkCList *clist;
	GtkWidget *button, *tvbox;
	GSList *sources, *news, *transports;
	gint len, row;

	read_config ();
	provider_list (&sources, &news, &transports);

	dialog = g_new0 (MailDialog, 1);	
	gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", NULL);

	dialog->dialog = glade_xml_get_widget (gui, "dialog");
	dialog->notebook = glade_xml_get_widget (gui, "notebook");
	
	/* Identities Page */
	dialog->clistIdentities = 
		glade_xml_get_widget (gui, "clistIdentities");
	clist = GTK_CLIST (dialog->clistIdentities);
	gtk_clist_set_column_width (clist, 0, 80);

	len = g_slist_length (config->ids);	
	for (row = 0; row < len; row++) {
		MailConfigIdentity *id;
		gchar *text[4];
		
		id = identity_copy ((MailConfigIdentity *)
				    g_slist_nth_data (config->ids, row));
		
		text[0] = id->name;
		text[1] = id->address;
		text[2] = id->org;
		text[3] = id->sig;
		
	 	gtk_clist_append (clist, text);
		gtk_clist_set_row_data (clist, row, id);
	}

	dialog->maxidrow = len - 1;
	dialog->idrow = -1;
	gtk_signal_connect (GTK_OBJECT (clist), "select_row",
			    GTK_SIGNAL_FUNC (identities_select_row),
			    dialog);

	button = glade_xml_get_widget (gui, "cmdIdentitiesAdd");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (identities_add_clicked),
			    dialog);
	button = glade_xml_get_widget (gui, "cmdIdentitiesEdit");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (identities_edit_clicked),
			    dialog);
	button = glade_xml_get_widget (gui, "cmdIdentitiesDelete");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (identities_delete_clicked),
			    dialog);

	/* Sources Page */
	dialog->clistSources = glade_xml_get_widget (gui, "clistSources");
	clist = GTK_CLIST (dialog->clistSources);
	gtk_clist_set_column_width (clist, 0, 80);

	len = g_slist_length (config->sources);	
	for (row = 0; row < len; row++) {
		MailConfigService *source;
		gchar *text[1];
		
		source = service_copy ((MailConfigService *)g_slist_nth_data (config->sources, row));
		
		text[0] = source->url;

	 	gtk_clist_append (clist, text);
		gtk_clist_set_row_data (clist, row, source);
	}

	dialog->maxsrow = len - 1;
	dialog->srow = -1;
	gtk_signal_connect (GTK_OBJECT (clist), "select_row",
			    GTK_SIGNAL_FUNC (sources_select_row),
			    dialog);

	button = glade_xml_get_widget (gui, "cmdSourcesAdd");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (sources_add_clicked),
			    dialog);
	button = glade_xml_get_widget (gui, "cmdSourcesEdit");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (sources_edit_clicked),
			    dialog);
	button = glade_xml_get_widget (gui, "cmdSourcesDelete");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (sources_delete_clicked),
			    dialog);

	/* News Page */
	dialog->clistNewsServers = glade_xml_get_widget (gui, "clistNewsServers");
	clist = GTK_CLIST (dialog->clistNewsServers);
	gtk_clist_set_column_width (clist, 0, 80);

	len = g_slist_length (config->news);	
	for (row=0; row<len; row++) {
		MailConfigService *news;
		gchar *text[1];
		
		news = service_copy ((MailConfigService *)
				     g_slist_nth_data (config->news, row));
		
		text[0] = news->url;

	 	gtk_clist_append (clist, text);
		gtk_clist_set_row_data (clist, row, news);
	}

	dialog->maxnrow = len - 1;
	dialog->nrow = -1;
	gtk_signal_connect (GTK_OBJECT (clist), "select_row",
			    GTK_SIGNAL_FUNC (news_select_row),
			    dialog);

	button = glade_xml_get_widget (gui, "cmdNewsServersAdd");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (news_add_clicked),
			    dialog);
	button = glade_xml_get_widget (gui, "cmdNewsServersEdit");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (news_edit_clicked),
			    dialog);
	button = glade_xml_get_widget (gui, "cmdNewsServersDelete");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (news_delete_clicked),
			    dialog);

	/* Transport Page */
	tvbox = glade_xml_get_widget (gui, "transport_vbox");
	dialog->page = transport_page_new (transports);
	service_page_set_url (dialog->page->page, config->transport);
	service_page_set_changed_cb (dialog->page->page,
				     mail_config_tpage_changed, dialog);
	service_page_set_done_cb (dialog->page->page, 
				  mail_config_tpage_done, dialog);
	gtk_box_pack_start (GTK_BOX (tvbox), 
			    dialog->page->vbox, TRUE, TRUE, 0);
	gtk_widget_show (dialog->page->vbox);
	
	/* Other Page */
	dialog->chkFormat = glade_xml_get_widget (gui, "chkFormat");
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->chkFormat), 
				      config->send_html);
	gtk_signal_connect (GTK_OBJECT (dialog->chkFormat), "toggled",
			    GTK_SIGNAL_FUNC (format_toggled),
			    dialog);

	/* Listen for apply signal */
	gtk_signal_connect (GTK_OBJECT (dialog->dialog), "apply",
			    GTK_SIGNAL_FUNC (mail_config_apply_clicked),
			    dialog);

	gnome_dialog_run (GNOME_DIALOG (dialog->dialog));

	/* Clean up */
	gtk_object_unref (GTK_OBJECT (gui));
	g_free (dialog);
}

const MailConfig *
mail_config_fetch (void)
{
	read_config ();
	
	return config;
}