Removed, all functionality moved to mail-session.

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.

svn path=/trunk/; revision=13952
This commit is contained in:
3
2001-10-23 20:42:57 +00:00
committed by Michael Zucci
parent 174691b212
commit a0974e678a
4 changed files with 414 additions and 398 deletions

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
return mail_user_message (message_type, prompt, cancel);
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);
}
}
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 = mail_msg_new(&timeout_op, NULL, sizeof (*m));
m->session = td->session;
camel_object_ref((CamelObject *)td->session);
m->id = td->id;
m->cb = td->cb;
m->camel_data = td->camel_data;
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