aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog35
-rw-r--r--mail/mail-config.c10
-rw-r--r--mail/mail-mt.c320
-rw-r--r--mail/mail-session.c447
4 files changed, 414 insertions, 398 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 89c05dd99f..61738bea97 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,35 @@
+2001-10-23 <NotZed@Ximian.com>
+
+ * mail-mt.c (mail_user_message):
+ (mail_get_password): Removed, all functionality moved to
+ mail-session.
+
+ * mail-config.c (mail_config_write_on_exit): Check
+ threaded/preview hash is null before using it, its setup on demand
+ so itmight nto be initialised here.
+
+ * mail-session.c (request_password): Remove password_current
+ stuff.
+ (alert_user): Redont, similar to get_pass. Do things as async as
+ possible, and dont even wait for a response if we're not asking
+ for the cancel button (this may or may not be right behaviour -
+ need to check). mail_user_message() code replaced from the stuff
+ in mail-mt.c
+ (MailSession): Added a lock field.
+ (init): Setup lock.
+ (finalise): fRee lock.
+ (register_timeout): Redone. We now allocate our own 'timeoutid's,
+ and <> to the real things asynchronously. Use async_event's so we
+ can make sure we have no outstanding ones after shutdown.
+ (mail_session_enable_interaction): If interaction has been
+ disabled, and we have either a message-box open, or a password
+ request open and/or any pending message boxes/passwords, blow 'em
+ away.
+ (main_register_timeout): If we have pending remove of this same
+ timeout, dont do anything.
+ (timeout_timeout): Properly honour the result, remove the timout
+ if it returns false.
+
2001-10-23 Jeffrey Stedfast <fejj@ximian.com>
* mail-callbacks.c (reply_to_sender): Make sure the fb and it's
@@ -34,6 +66,9 @@
* mail-mt.c: Added missing errno.h
(mail_msg_new): Fix the logic a bit, dont try to open the log file
unless logging is actually requested.
+ (mail_enable_stop, mail_disable_stop, do_set_busy,
+ mail_operation_statys): Dont bother propagating events if
+ global_shell_client isn't up yet.
2001-10-23 Dan Winship <danw@ximian.com>
diff --git a/mail/mail-config.c b/mail/mail-config.c
index 9e66eea531..772ff76428 100644
--- a/mail/mail-config.c
+++ b/mail/mail-config.c
@@ -875,12 +875,12 @@ mail_config_write_on_exit (void)
bonobo_config_set_string_wrapper (config->db, "/Mail/Filters/log_path",
config->filter_log_path, NULL);
+
+ if (config->threaded_hash)
+ g_hash_table_foreach_remove (config->threaded_hash, hash_save_state, "Threads");
- g_hash_table_foreach_remove (config->threaded_hash,
- hash_save_state, "Threads");
-
- g_hash_table_foreach_remove (config->preview_hash,
- hash_save_state, "Preview");
+ if (config->preview_hash)
+ g_hash_table_foreach_remove (config->preview_hash, hash_save_state, "Preview");
CORBA_exception_init (&ev);
Bonobo_ConfigDatabase_sync (config->db, &ev);
diff --git a/mail/mail-mt.c b/mail/mail-mt.c
index 3f45617b84..9c0c9bb18a 100644
--- a/mail/mail-mt.c
+++ b/mail/mail-mt.c
@@ -351,6 +351,7 @@ EMsgPort *mail_gui_port;
static GIOChannel *mail_gui_channel;
static guint mail_gui_watch;
+/* TODO: Merge these, gui_port2 doesn't do any mail_msg processing on the request (replies, forwards, frees) */
EMsgPort *mail_gui_port2;
static GIOChannel *mail_gui_channel2;
static guint mail_gui_watch2;
@@ -562,315 +563,6 @@ static pthread_mutex_t status_lock = PTHREAD_MUTEX_INITIALIZER;
/* ********************************************************************** */
-#if 0
-static GnomeDialog *password_dialogue = NULL;
-static EDList password_list = E_DLIST_INITIALISER(password_list);
-static struct _pass_msg *password_current = NULL;
-
-static void do_get_pass (struct _mail_msg *mm);
-
-struct _pass_msg {
- struct _mail_msg msg;
- const char *prompt;
- gboolean secret;
- gboolean *cache;
- char *result;
- char *service_url;
- GtkWidget *check;
- int inmain;
-};
-
-static void
-pass_got (char *string, void *data)
-{
- struct _pass_msg *m = data;
-
- printf("password got! string = '%s'\n", string?string:"<nil>");
-
- if (string) {
- MailConfigService *service = NULL;
- const MailConfigAccount *mca;
- gboolean remember;
-
- m->result = g_strdup (string);
-
- remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m->check));
- if (m->service_url) {
- mca = mail_config_get_account_by_source_url (m->service_url);
- if (mca) {
- service = mca->source;
- } else {
- mca = mail_config_get_account_by_transport_url (m->service_url);
- if (mca)
- service = mca->transport;
- }
-
- if (service) {
- mail_config_service_set_save_passwd (service, remember);
-
- /* set `remember' to TRUE because people don't want to have to
- re-enter their passwords for this session even if they told
- us not to cache their passwords in the dialog...*sigh* */
- remember = TRUE;
- }
- }
-
- if (m->cache)
- *(m->cache) = remember;
-
- }
-
- if (!m->inmain)
- e_msgport_reply((EMsg *)m);
-
- password_dialogue = NULL;
-
- m = e_dlist_remhead(&password_list);
- if (m) {
- printf("Have queued password request, showing now the other is finished\n");
- do_get_pass(m);
- }
-}
-
-static void
-do_get_pass (struct _mail_msg *mm)
-{
- struct _pass_msg *m = (struct _pass_msg *)mm;
- const MailConfigAccount *mca = NULL;
- GtkWidget *dialogue;
- GtkWidget *check, *entry;
- GList *children, *iter;
- gboolean show;
- char *title;
-
- /* If we already have a password_dialogue up, save this request till later */
- if (!m->inmain && password_dialogue) {
- e_dlist_addtail(&password_list, (EDListNode *)mm);
- return;
- }
-
- password_current = m;
-
- /* this api is just awful ... hence the hacks */
- dialogue = gnome_request_dialog (m->secret, m->prompt, NULL, 0, pass_got, m, NULL);
-
- /* Remember the password? */
- check = gtk_check_button_new_with_label (m->service_url ? _("Remember this password") :
- _("Remember this password for the remainder of this session"));
- show = TRUE;
-
- if (m->service_url) {
- mca = mail_config_get_account_by_source_url (m->service_url);
- if (mca)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), mca->source->save_passwd);
- else {
- mca = mail_config_get_account_by_transport_url (m->service_url);
- if (mca)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), mca->transport->save_passwd);
- else {
- d(printf ("Cannot figure out which account owns URL \"%s\"\n", m->service_url));
- show = FALSE;
- }
- }
- }
-
- if (show)
- gtk_widget_show (check);
-
- /* do some dirty stuff to put the checkbutton after the entry */
- entry = NULL;
- children = gtk_container_children (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox));
- for (iter = children; iter; iter = iter->next) {
- if (GTK_IS_ENTRY (iter->data)) {
- entry = GTK_WIDGET (iter->data);
- break;
- }
- }
- g_list_free (children);
-
- if (entry) {
- gtk_object_ref (GTK_OBJECT (entry));
- gtk_container_remove (GTK_CONTAINER (GNOME_DIALOG (dialogue)->vbox), entry);
- }
-
- gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), check, TRUE, FALSE, 0);
-
- if (entry) {
- gtk_box_pack_end (GTK_BOX (GNOME_DIALOG (dialogue)->vbox), entry, TRUE, FALSE, 0);
- gtk_widget_grab_focus (entry);
- gtk_object_unref (GTK_OBJECT (entry));
- }
-
- m->check = check;
-
- /* hrm, we can't run this async since the gui_port from which we're called
- will reply to our message for us */
-
- if (mca) {
- char *name;
-
- name = e_utf8_to_gtk_string (GTK_WIDGET (dialogue), mca->name);
- title = g_strdup_printf (_("Enter Password for %s"), name);
- g_free (name);
- } else
- title = g_strdup (_("Enter Password"));
-
- gtk_window_set_title (GTK_WINDOW (dialogue), title);
- g_free (title);
-
- if (m->inmain) {
- printf("showing dialogue in main\n");
- password_current = NULL;
- gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
- e_msgport_reply((EMsg *)m);
- } else {
- printf("showing dialogue async\n");
- gtk_widget_show(dialogue);
- }
-}
-
-static void
-do_free_pass(struct _mail_msg *mm)
-{
- /*struct _pass_msg *m = (struct _pass_msg *)mm;*/
-
- /* the string is passed out so we dont need to free it */
-}
-
-struct _mail_msg_op get_pass_op = {
- NULL,
- do_get_pass,
- NULL,
- do_free_pass,
-};
-
-/* returns the password, or NULL if cancelled */
-char *
-mail_get_password (CamelService *service, const char *prompt, gboolean secret, gboolean *cache)
-{
- char *ret;
- struct _pass_msg *m, *r;
- EMsgPort *pass_reply;
-
- pass_reply = e_msgport_new ();
-
- m = mail_msg_new (&get_pass_op, pass_reply, sizeof (struct _pass_msg));
-
- m->prompt = prompt;
- m->secret = secret;
- m->cache = cache;
- m->inmain = pthread_self() == mail_gui_thread;
- if (service) {
- m->service_url = camel_url_to_string (service->url, CAMEL_URL_HIDE_ALL);
- } else
- m->service_url = NULL;
-
- if (m->inmain) {
- do_get_pass ((struct _mail_msg *)m);
- r = m;
- } else {
- e_msgport_put (mail_gui_port2, (EMsg *)m);
- e_msgport_wait (pass_reply);
- r = (struct _pass_msg *)e_msgport_get (pass_reply);
- }
-
- g_assert (r == m);
-
- ret = m->result;
-
- g_free (m->service_url);
- mail_msg_free (m);
- e_msgport_destroy (pass_reply);
-
- return ret;
-}
-#endif
-
-/* ******************** */
-
-/* ********************************************************************** */
-
-struct _user_message_msg {
- struct _mail_msg msg;
- const char *type;
- const char *prompt;
- gboolean allow_cancel;
- gboolean result;
-};
-
-static void
-do_user_message (struct _mail_msg *mm)
-{
- struct _user_message_msg *m = (struct _user_message_msg *)mm;
- int dialog_result;
- GtkWidget *dialog;
-
- dialog = gnome_message_box_new (m->prompt, m->type,
- GNOME_STOCK_BUTTON_OK,
- m->allow_cancel ? GNOME_STOCK_BUTTON_CANCEL : NULL,
- NULL);
- gnome_dialog_set_default (GNOME_DIALOG (dialog), 1);
- gtk_window_set_policy (GTK_WINDOW (dialog), TRUE, TRUE, TRUE);
-
- /* hrm, we can't run this async since the gui_port from which we're called
- will reply to our message for us */
- dialog_result = gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
-
- if (dialog_result == -1 || dialog_result == 1)
- m->result = FALSE;
- else
- m->result = TRUE;
-}
-
-struct _mail_msg_op user_message_op = {
- NULL,
- do_user_message,
- NULL,
- NULL,
-};
-
-/* prompt the user with a yes/no question and return the response */
-gboolean
-mail_user_message (const char *type, const char *prompt, gboolean allow_cancel)
-{
- struct _user_message_msg *m, *r;
- EMsgPort *user_message_reply;
- gboolean accept;
-
- user_message_reply = e_msgport_new ();
-
- m = mail_msg_new (&user_message_op, user_message_reply, sizeof (*m));
-
- m->type = type;
- m->prompt = prompt;
- m->allow_cancel = allow_cancel;
-
- if (pthread_self () == mail_gui_thread) {
- do_user_message ((struct _mail_msg *)m);
- r = m;
- } else {
- static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
- /* we want this single-threaded, this is the easiest way to do it without blocking ? */
- pthread_mutex_lock (&lock);
- e_msgport_put (mail_gui_port, (EMsg *)m);
- e_msgport_wait (user_message_reply);
- r = (struct _user_message_msg *)e_msgport_get (user_message_reply);
- pthread_mutex_unlock (&lock);
- }
-
- g_assert (r == m);
-
- accept = m->result;
-
- mail_msg_free (m);
- e_msgport_destroy (user_message_reply);
-
- return accept;
-}
-
-/* ******************** */
-
struct _proxy_msg {
struct _mail_msg msg;
MailAsyncEvent *ea;
@@ -1057,7 +749,8 @@ static int busy_state;
static void do_set_busy(struct _mail_msg *mm)
{
- set_stop(busy_state > 0);
+ if (global_shell_client)
+ set_stop(busy_state > 0);
}
struct _mail_msg_op set_busy_op = {
@@ -1073,7 +766,7 @@ static void mail_enable_stop(void)
MAIL_MT_LOCK(status_lock);
busy_state++;
- if (busy_state == 1) {
+ if (busy_state == 1 && global_shell_client) {
m = mail_msg_new(&set_busy_op, NULL, sizeof(*m));
e_msgport_put(mail_gui_port, (EMsg *)m);
}
@@ -1086,7 +779,7 @@ static void mail_disable_stop(void)
MAIL_MT_LOCK(status_lock);
busy_state--;
- if (busy_state == 0) {
+ if (busy_state == 0 && global_shell_client) {
m = mail_msg_new(&set_busy_op, NULL, sizeof(*m));
e_msgport_put(mail_gui_port, (EMsg *)m);
}
@@ -1229,6 +922,9 @@ mail_operation_status (struct _CamelOperation *op, const char *what, int pc, voi
struct _op_status_msg *m;
d(printf("got operation statys: %s %d%%\n", what, pc));
+
+ if (global_shell_client == NULL)
+ return;
m = mail_msg_new(&op_status_op, NULL, sizeof(*m));
m->op = op;
diff --git a/mail/mail-session.c b/mail/mail-session.c
index 36dcb1e3be..662d80acb7 100644
--- a/mail/mail-session.c
+++ b/mail/mail-session.c
@@ -30,6 +30,9 @@
#include <libgnomeui/gnome-dialog-util.h>
#include <libgnomeui/gnome-messagebox.h>
#include <libgnomeui/gnome-stock.h>
+
+#include <gal/widgets/e-unicode.h>
+
#include "camel/camel-filter-driver.h"
#include "filter/filter-context.h"
#include "filter/filter-filter.h"
@@ -38,6 +41,7 @@
#include "mail-tools.h"
#include "mail-mt.h"
#include "e-util/e-passwords.h"
+#include "e-util/e-msgport.h"
#define d(x)
@@ -49,12 +53,22 @@ CamelSession *session;
#define MAIL_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), MAIL_SESSION_TYPE, MailSessionClass))
#define MAIL_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), MAIL_SESSION_TYPE))
+#define MAIL_SESSION_LOCK(s, l) (e_mutex_lock(((MailSession *)s)->l))
+#define MAIL_SESSION_UNLOCK(s, l) (e_mutex_unlock(((MailSession *)s)->l))
typedef struct _MailSession {
CamelSession parent_object;
gboolean interaction_enabled;
FILE *filter_logfile;
+
+ EMutex *lock;
+
+ MailAsyncEvent *async;
+
+ /* must all be accessed with lock held ! */
+ unsigned int timeout_id;/* next camel timneout id */
+ EDList timeouts; /* list of struct _timeout_data's of current or pending removed timeouts */
} MailSession;
typedef struct _MailSessionClass {
@@ -62,32 +76,33 @@ typedef struct _MailSessionClass {
} MailSessionClass;
-
-static char *get_password (CamelSession *session, const char *prompt,
- gboolean secret, CamelService *service,
- const char *item, CamelException *ex);
-static void forget_password (CamelSession *session, CamelService *service,
- const char *item, CamelException *ex);
-static gboolean alert_user (CamelSession *session, CamelSessionAlertType type,
- const char *prompt, gboolean cancel);
-static guint register_timeout (CamelSession *session, guint32 interval,
- CamelTimeoutCallback cb, gpointer camel_data);
-static gboolean remove_timeout (CamelSession *session, guint handle);
-static CamelFilterDriver *get_filter_driver (CamelSession *session,
- const char *type,
- CamelException *ex);
-
+static char *get_password(CamelSession *session, const char *prompt, gboolean secret, CamelService *service, const char *item, CamelException *ex);
+static void forget_password(CamelSession *session, CamelService *service, const char *item, CamelException *ex);
+static gboolean alert_user(CamelSession *session, CamelSessionAlertType type, const char *prompt, gboolean cancel);
+static guint register_timeout(CamelSession *session, guint32 interval, CamelTimeoutCallback cb, gpointer camel_data);
+static gboolean remove_timeout(CamelSession *session, guint handle);
+static CamelFilterDriver *get_filter_driver(CamelSession *session, const char *type, CamelException *ex);
static void
init (MailSession *session)
{
+ session->lock = e_mutex_new(E_MUTEX_REC);
+ session->timeout_id = 1; /* first timeout id */
+ session->async = mail_async_event_new();
+ e_dlist_init(&session->timeouts);
+}
+
+static void
+finalise (MailSession *session)
+{
+ mail_async_event_destroy(session->async);
+ e_mutex_destroy(session->lock);
}
static void
class_init (MailSessionClass *mail_session_class)
{
- CamelSessionClass *camel_session_class =
- CAMEL_SESSION_CLASS (mail_session_class);
+ CamelSessionClass *camel_session_class = CAMEL_SESSION_CLASS (mail_session_class);
/* virtual method override */
camel_session_class->get_password = get_password;
@@ -112,7 +127,7 @@ mail_session_get_type (void)
(CamelObjectClassInitFunc) class_init,
NULL,
(CamelObjectInitFunc) init,
- NULL);
+ (CamelObjectFinalizeFunc) finalise);
}
return mail_session_type;
@@ -136,7 +151,6 @@ make_key (CamelService *service, const char *item)
static GnomeDialog *password_dialogue = NULL;
static EDList password_list = E_DLIST_INITIALISER(password_list);
-static struct _pass_msg *password_current = NULL;
static int password_destroy_id;
struct _pass_msg {
@@ -232,12 +246,10 @@ request_password(struct _pass_msg *m)
return;
}
- password_current = m;
-
/* FIXME: Remove this total snot */
/* this api is just awful ... hence the major hacks */
- password_dialogue = dialogue = gnome_request_dialog (m->secret, m->prompt, NULL, 0, pass_got, m, NULL);
+ password_dialogue = (GnomeDialog *)dialogue = gnome_request_dialog (m->secret, m->prompt, NULL, 0, pass_got, m, NULL);
/* cant bleieve how @!@#!@# 5this api is, it doesn't handle this for you, BLAH! */
password_destroy_id = gtk_signal_connect((GtkObject *)dialogue, "destroy", request_password_deleted, m);
@@ -303,12 +315,10 @@ request_password(struct _pass_msg *m)
gtk_window_set_title (GTK_WINDOW (dialogue), title);
g_free (title);
- if (m->ismain) {
- password_current = NULL;
+ if (m->ismain)
gnome_dialog_run_and_close ((GnomeDialog *)dialogue);
- } else {
+ else
gtk_widget_show(dialogue);
- }
}
static void
@@ -377,7 +387,7 @@ get_password (CamelSession *session, const char *prompt, gboolean secret, CamelS
m->key = make_key(service, item);
if (m->ismain)
- do_get_pass(m);
+ do_get_pass((struct _mail_msg *)m);
else {
extern EMsgPort *mail_gui_port2;
@@ -412,60 +422,249 @@ forget_password (CamelSession *session, CamelService *service, const char *item,
session, service, item, ex);
}
-static gboolean
-alert_user (CamelSession *session, CamelSessionAlertType type,
- const char *prompt, gboolean cancel)
+/* ********************************************************************** */
+
+static GnomeDialog *message_dialogue;
+static EDList message_list = E_DLIST_INITIALISER(password_list);
+static guint message_destroy_id;
+
+struct _user_message_msg {
+ struct _mail_msg msg;
+
+ CamelSessionAlertType type;
+ const char *prompt;
+
+ unsigned int allow_cancel:1;
+ unsigned int result:1;
+ unsigned int ismain:1;
+};
+
+static void do_user_message (struct _mail_msg *mm);
+
+/* if we dont have to wait for reply, we just check to see if any newly waiting prompts are there */
+static void
+user_message_destroy_noreply(GnomeDialog *gd, void *data)
{
- MailSession *mail_session = MAIL_SESSION (session);
- const char *message_type = NULL;
-
- if (!mail_session->interaction_enabled)
- return FALSE;
-
- switch (type) {
+ struct _user_message_msg *m;
+
+ message_dialogue = NULL;
+ if ((m = (struct _user_message_msg *)e_dlist_remhead(&message_list)))
+ do_user_message((struct _mail_msg *)m);
+}
+
+/* clicked, send back the reply */
+static void
+user_message_clicked(GnomeDialog *gd, int button, struct _user_message_msg *m)
+{
+ message_dialogue = NULL;
+
+ if (message_destroy_id) {
+ gtk_signal_disconnect((GtkObject *)gd, message_destroy_id);
+ message_destroy_id = 0;
+ }
+
+ m->result = button == 0;
+ e_msgport_reply((EMsg *)m);
+
+ /* check for pendings */
+ if ((m = (struct _user_message_msg *)e_dlist_remhead(&message_list)))
+ do_user_message((struct _mail_msg *)m);
+}
+
+static void
+user_message_destroy(GnomeDialog *gd, struct _user_message_msg *m)
+{
+ message_destroy_id = 0;
+ user_message_clicked(gd, -1, m);
+}
+
+static void
+do_user_message (struct _mail_msg *mm)
+{
+ struct _user_message_msg *m = (struct _user_message_msg *)mm;
+ const char *msg_type;
+
+ if (!m->ismain && message_dialogue != NULL) {
+ e_dlist_addtail(&message_list, (EDListNode *)m);
+ return;
+ }
+
+ switch (m->type) {
case CAMEL_SESSION_ALERT_INFO:
- message_type = GNOME_MESSAGE_BOX_INFO;
+ msg_type = GNOME_MESSAGE_BOX_INFO;
break;
case CAMEL_SESSION_ALERT_WARNING:
- message_type = GNOME_MESSAGE_BOX_WARNING;
+ msg_type = GNOME_MESSAGE_BOX_WARNING;
break;
case CAMEL_SESSION_ALERT_ERROR:
- message_type = GNOME_MESSAGE_BOX_ERROR;
+ msg_type = GNOME_MESSAGE_BOX_ERROR;
break;
+ default:
+ msg_type = NULL;
+ }
+
+ message_dialogue = (GnomeDialog *)gnome_message_box_new(m->prompt, msg_type, GNOME_STOCK_BUTTON_OK,
+ m->allow_cancel ? GNOME_STOCK_BUTTON_CANCEL : NULL,
+ NULL);
+ gnome_dialog_set_default(message_dialogue, 1);
+ gnome_dialog_set_close(message_dialogue, TRUE);
+ gtk_window_set_policy (GTK_WINDOW (message_dialogue), TRUE, TRUE, TRUE);
+
+ /* We only need to wait for the result if we allow cancel otherwise show but send result back instantly */
+ if (m->allow_cancel) {
+ gtk_signal_connect((GtkObject*)message_dialogue, "clicked", user_message_clicked, m);
+ gtk_signal_connect((GtkObject*)message_dialogue, "destroy", user_message_destroy, m);
+ if (m->ismain)
+ gnome_dialog_run_and_close ((GnomeDialog *)message_dialogue);
+ else
+ gtk_widget_show((GtkWidget *)message_dialogue);
+ } else {
+ gtk_signal_connect((GtkObject *)message_dialogue, "destroy", user_message_destroy_noreply, NULL);
+ gtk_widget_show((GtkWidget *)message_dialogue);
+ m->result = TRUE;
+ e_msgport_reply((EMsg *)m);
}
- return mail_user_message (message_type, prompt, cancel);
+}
+
+static struct _mail_msg_op user_message_op = { NULL, do_user_message, NULL, NULL };
+
+static gboolean
+alert_user(CamelSession *session, CamelSessionAlertType type, const char *prompt, gboolean cancel)
+{
+ MailSession *mail_session = MAIL_SESSION (session);
+ struct _user_message_msg *m, *r;
+ EMsgPort *user_message_reply;
+ gboolean ret;
+
+ if (!mail_session->interaction_enabled)
+ return FALSE;
+
+ user_message_reply = e_msgport_new ();
+ m = mail_msg_new (&user_message_op, user_message_reply, sizeof (*m));
+ m->ismain = pthread_self() == mail_gui_thread;
+ m->type = type;
+ m->prompt = prompt;
+ m->allow_cancel = cancel;
+
+ if (m->ismain)
+ do_user_message((struct _mail_msg *)m);
+ else {
+ extern EMsgPort *mail_gui_port2;
+
+ e_msgport_put(mail_gui_port2, (EMsg *)m);
+ }
+
+ e_msgport_wait(user_message_reply);
+ r = (struct _user_message_msg *)e_msgport_get(user_message_reply);
+ g_assert(m == r);
+
+ ret = m->result;
+ mail_msg_free(m);
+ e_msgport_destroy(user_message_reply);
+
+ return ret;
}
/* ******************** */
struct _timeout_data {
- CamelTimeoutCallback cb;
+ struct _timeout_data *next;
+ struct _timeout_data *prev;
+
+ CamelSession *session;
+
guint32 interval;
+
+ CamelTimeoutCallback cb;
void *camel_data;
- int result;
+
+ guint id; /* the camel 'id' */
+ guint timeout_id; /* the gtk 'id' */
+
+ unsigned int busy:1; /* on if its currently running */
+ unsigned int removed:1; /* if its been removed since */
};
struct _timeout_msg {
struct _mail_msg msg;
-
- CamelTimeoutCallback cb;
- gpointer camel_data;
+
+ CamelSession *session;
+ unsigned int id;
+ int result;
};
+static struct _timeout_data *
+find_timeout(EDList *list, unsigned int id)
+{
+ struct _timeout_data *td, *tn;
+
+ td = (struct _timeout_data *)list->head;
+ tn = td->next;
+ while (tn) {
+ if (td->id == id)
+ return td;
+ td = tn;
+ tn = tn->next;
+ }
+
+ return NULL;
+}
+
static void
timeout_timeout (struct _mail_msg *mm)
{
struct _timeout_msg *m = (struct _timeout_msg *)mm;
-
- /* we ignore the callback result, do we care?? no. */
- m->cb (m->camel_data);
+ MailSession *ms = (MailSession *)m->session;
+ struct _timeout_data *td;
+
+ MAIL_SESSION_LOCK(ms, lock);
+ td = find_timeout(&ms->timeouts, m->id);
+ if (td && !td->removed) {
+ if (td->busy) {
+ g_warning("Timeout event dropped, still busy with last one");
+ } else {
+ td->busy = TRUE;
+ m->result = td->cb(td->camel_data);
+ td->busy = FALSE;
+ td->removed = !m->result;
+ }
+ }
+ MAIL_SESSION_UNLOCK(ms, lock);
+}
+
+static void
+timeout_done(struct _mail_msg *mm)
+{
+ struct _timeout_msg *m = (struct _timeout_msg *)mm;
+ MailSession *ms = (MailSession *)m->session;
+ struct _timeout_data *td;
+
+ if (!m->result) {
+ MAIL_SESSION_LOCK(ms, lock);
+ td = find_timeout(&ms->timeouts, m->id);
+ if (td) {
+ e_dlist_remove((EDListNode *)td);
+ if (td->timeout_id)
+ gtk_timeout_remove(td->timeout_id);
+ g_free(td);
+ }
+ MAIL_SESSION_UNLOCK(ms, lock);
+ }
+}
+
+static void
+timeout_free(struct _mail_msg *mm)
+{
+ struct _timeout_msg *m = (struct _timeout_msg *)mm;
+
+ camel_object_unref((CamelObject *)m->session);
}
static struct _mail_msg_op timeout_op = {
NULL,
timeout_timeout,
- NULL,
- NULL,
+ timeout_done,
+ timeout_free,
};
static gboolean
@@ -473,65 +672,120 @@ camel_timeout (gpointer data)
{
struct _timeout_data *td = data;
struct _timeout_msg *m;
+
+ /* stop if we are removed pending */
+ if (td->removed)
+ return FALSE;
- m = mail_msg_new (&timeout_op, NULL, sizeof (*m));
-
- m->cb = td->cb;
- m->camel_data = td->camel_data;
+ m = mail_msg_new(&timeout_op, NULL, sizeof (*m));
+
+ m->session = td->session;
+ camel_object_ref((CamelObject *)td->session);
+ m->id = td->id;
- e_thread_put (mail_thread_queued, (EMsg *)m);
+ e_thread_put(mail_thread_queued, (EMsg *)m);
return TRUE;
}
static void
-main_register_timeout(struct _timeout_data *td)
+main_register_timeout(CamelSession *session, void *event_data, void *data)
{
- td->result = gtk_timeout_add_full(td->interval, camel_timeout, NULL, td, g_free);
+ MailSession *ms = (MailSession *)session;
+ unsigned int handle = (unsigned int)event_data;
+ struct _timeout_data *td;
+
+ MAIL_SESSION_LOCK(session, lock);
+ td = find_timeout(&ms->timeouts, handle);
+ if (td) {
+ if (td->removed) {
+ e_dlist_remove((EDListNode *)td);
+ if (td->timeout_id)
+ gtk_timeout_remove(td->timeout_id);
+ g_free(td);
+ } else {
+ td->timeout_id = gtk_timeout_add(td->interval, camel_timeout, td);
+ }
+ }
+ MAIL_SESSION_UNLOCK(session, lock);
+
+ camel_object_unref((CamelObject *)ms);
}
static guint
register_timeout (CamelSession *session, guint32 interval, CamelTimeoutCallback cb, gpointer camel_data)
{
struct _timeout_data *td;
-
- /* We do this because otherwise the timeout can get called
- * more often than the dispatch thread can get rid of it,
- * leading to timeout calls piling up, and we don't have a
- * good way to watch the return values. It's not cool.
- */
- if (interval < 1000) {
- g_warning("Timeout %u too small, increased to 1000", interval);
- interval = 1000;
- }
+ MailSession *ms = (MailSession *)session;
+ guint ret;
- /* This is extremely messy, we need to proxy to gtk thread for this */
- td = g_malloc (sizeof (*td));
- td->interval = interval;
- td->result = 0;
+ MAIL_SESSION_LOCK(session, lock);
+
+ ret = ms->timeout_id;
+ ms->timeout_id ++;
+
+ /* just debugging, the timeout code now ignores excessive events anyway */
+ if (interval < 100)
+ g_warning("Timeout requested %d is small, may cause performance problems", interval);
+
+ td = g_malloc(sizeof(*td));
td->cb = cb;
td->camel_data = camel_data;
+ td->interval = interval;
+ td->id = ret;
+ td->session = session;
+ td->removed = FALSE;
+ td->busy = FALSE;
+ e_dlist_addhead(&ms->timeouts, (EDListNode *)td);
- mail_call_main(MAIL_CALL_p_p, (MailMainFunc)main_register_timeout, td);
+ MAIL_SESSION_UNLOCK(session, lock);
- if (td->result == 0) {
- g_free(td);
- return 0;
- }
+ camel_object_ref((CamelObject *)ms);
+ mail_async_event_emit(ms->async, (CamelObjectEventHookFunc)main_register_timeout, (CamelObject *)session, (void *)ret, NULL);
- return td->result;
+ return ret;
}
static void
-main_remove_timeout(guint *edata)
+main_remove_timeout(CamelSession *session, void *event_data, void *data)
{
- gtk_timeout_remove(*edata);
+ MailSession *ms = (MailSession *)session;
+ unsigned int handle = (unsigned int)event_data;
+ struct _timeout_data *td;
+
+ MAIL_SESSION_LOCK(session, lock);
+ td = find_timeout(&ms->timeouts, handle);
+ if (td) {
+ e_dlist_remove((EDListNode *)td);
+ if (td->timeout_id)
+ gtk_timeout_remove(td->timeout_id);
+ g_free(td);
+ }
+ MAIL_SESSION_UNLOCK(session, lock);
+
+ camel_object_unref((CamelObject *)ms);
}
static gboolean
remove_timeout (CamelSession *session, guint handle)
{
- mail_call_main(MAIL_CALL_p_p, (MailMainFunc)main_remove_timeout, &handle);
+ MailSession *ms = (MailSession *)session;
+ struct _timeout_data *td;
+ int remove = FALSE;
+
+ MAIL_SESSION_LOCK(session, lock);
+ td = find_timeout(&ms->timeouts, handle);
+ if (td && !td->removed) {
+ td->removed = TRUE;
+ remove = TRUE;
+ }
+ MAIL_SESSION_UNLOCK(session, lock);
+
+ if (remove) {
+ camel_object_ref((CamelObject *)ms);
+ mail_async_event_emit(ms->async, (CamelObjectEventHookFunc)main_remove_timeout, (CamelObject *)session, (void *)handle, NULL);
+ } else
+ g_warning("Removing a timeout i dont know about (or twice): %d", handle);
return TRUE;
}
@@ -676,6 +930,37 @@ void
mail_session_enable_interaction (gboolean enable)
{
MAIL_SESSION (session)->interaction_enabled = enable;
+
+ if (!enable) {
+ struct _pass_msg *pm;
+ struct _user_message_msg *um;
+
+ printf("Gone non-interactive, checking for outstanding interactive tasks\n");
+
+ /* clear out pending password requests */
+ while ((pm = (struct _pass_msg *)e_dlist_remhead(&password_list))) {
+ printf("Flushing password request : %s\n", pm->prompt);
+ e_msgport_reply((EMsg *)pm);
+ }
+
+ /* destroy the current */
+ if (password_dialogue) {
+ printf("Destroying password dialogue\n");
+ gtk_object_destroy((GtkObject *)password_dialogue);
+ }
+
+ /* same for pending user messages */
+ while ((um = (struct _user_message_msg *)e_dlist_remhead(&message_list))) {
+ printf("Flusing message request: %s\n", um->prompt);
+ e_msgport_reply((EMsg *)um);
+ }
+
+ /* and the current */
+ if (message_dialogue) {
+ printf("Destroying message dialogue\n");
+ gtk_object_destroy((GtkObject *)message_dialogue);
+ }
+ }
}
void