aboutsummaryrefslogtreecommitdiffstats
path: root/mail/mail-threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/mail-threads.c')
-rw-r--r--mail/mail-threads.c1153
1 files changed, 0 insertions, 1153 deletions
diff --git a/mail/mail-threads.c b/mail/mail-threads.c
deleted file mode 100644
index 4b989bb762..0000000000
--- a/mail/mail-threads.c
+++ /dev/null
@@ -1,1153 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * Author :
- * Peter Williams (peterw@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 Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include <config.h>
-
-#include <string.h>
-#include <errno.h>
-#include <glib.h>
-
-#include <gal/widgets/e-gui-utils.h>
-
-#include "folder-browser-factory.h"
-
-#include "camel/camel-object.h"
-#include "mail.h"
-#include "mail-threads.h"
-
-#define DEBUG(p) g_print p
-
-/**
- * A function and its userdata
- **/
-
-typedef struct closure_s
-{
- gpointer in_data;
- gboolean free_in_data;
- gpointer op_data;
- const mail_operation_spec *spec;
- CamelException *ex;
- gchar *infinitive;
- gchar *gerund;
-}
-closure_t;
-
-/**
- * A command issued through the compipe
- **/
-
-typedef struct com_msg_s
-{
- enum com_msg_type_e {
- STARTING,
-
-#if 0
- PERCENTAGE,
- HIDE_PBAR,
- SHOW_PBAR,
-#endif
-
- MESSAGE,
- PASSWORD,
- ERROR,
- FORWARD_EVENT,
- FINISHED
- } type;
-
- gfloat percentage;
- gchar *message;
-
- closure_t *clur;
-
- /* Password stuff */
- gchar **reply;
- gboolean secret;
- gboolean *success;
-
- /* Event stuff */
- CamelObjectEventHookFunc event_hook;
- CamelObject *event_obj;
- gpointer event_event_data;
- gpointer event_user_data;
-} com_msg_t;
-
-/**
- * Stuff needed for blocking
- **/
-
-typedef struct block_info_s {
- GMutex *mutex;
- GCond *cond;
- gboolean val;
-} block_info_t;
-
-#define BLOCK_INFO_INIT { NULL, NULL, FALSE }
-
-/**
- * @dispatch_thread_started: gboolean that tells us whether
- * the dispatch thread has been launched.
- **/
-
-static gboolean dispatch_thread_started = FALSE;
-
-/**
- * @queue_len : the number of operations pending
- * and being executed.
- *
- * Because camel is not thread-safe we work
- * with the restriction that more than one mailbox
- * cannot be accessed at once. Thus we cannot
- * concurrently check mail and move messages, etc.
- **/
-
-static gint queue_len = 0;
-
-/**
- * @main_compipe: The pipe through which the dispatcher communicates
- * with the main thread for GTK+ calls
- *
- * @chan_reader: the GIOChannel that reads our pipe
- *
- * @MAIN_READER: the fd in our main pipe that.... reads!
- * @MAIN_WRITER: the fd in our main pipe that.... writes!
- */
-
-#define MAIN_READER main_compipe[0]
-#define MAIN_WRITER main_compipe[1]
-#define DISPATCH_READER dispatch_compipe[0]
-#define DISPATCH_WRITER dispatch_compipe[1]
-
-static int main_compipe[2] = { -1, -1 };
-static int dispatch_compipe[2] = { -1, -1 };
-
-GIOChannel *chan_reader = NULL;
-
-/**
- * @modal_block: a condition maintained so that the
- * calling thread (the dispatch thread) blocks correctly
- * until the user has responded to some kind of modal
- * dialog boxy thing.
- */
-
-static block_info_t modal_block = BLOCK_INFO_INIT;
-
-/**
- * @finish_block: A condition so that the dispatch thread
- * blocks until the main thread has finished the cleanup.
- **/
-
-static block_info_t finish_block = BLOCK_INFO_INIT;
-
-/**
- * @current_message: The current message for the status bar.
- * @busy_status: Whether we are currently busy doing some async operation,
- * for status bar purposes.
- */
-
-static char *current_message = NULL;
-static gboolean busy = FALSE;
-
-/**
- * Static prototypes
- **/
-
-static void ui_set_busy (void);
-
-static void ui_unset_busy (void);
-static void ui_set_message (const char *message);
-static void ui_unset_message (void);
-
-static void block_prepare (block_info_t *info);
-static void block_wait (block_info_t *info);
-static void block_hold (block_info_t *info);
-static void block_release (block_info_t *info);
-
-static void *dispatch (void * data);
-static void check_dispatcher (void);
-static void check_compipes (void);
-static gboolean read_msg (GIOChannel * source, GIOCondition condition,
- gpointer userdata);
-
-static void show_error (com_msg_t * msg);
-
-static void get_password (com_msg_t * msg);
-static void get_password_cb (gchar * string, gpointer data);
-
-static void cleanup_op (com_msg_t * msg);
-
-static closure_t *new_closure (const mail_operation_spec * spec, gpointer input,
- gboolean free_in_data);
-static void free_closure (closure_t *clur);
-
-/* Pthread code */
-/* FIXME: support other thread types!!!! */
-
-#ifdef G_THREADS_IMPL_POSIX
-
-#include <pthread.h>
-
-/**
- * @dispatch_thread: the pthread_t (when using pthreads, of
- * course) representing our dispatcher routine. Never used
- * except to make pthread_create happy
- **/
-
-static pthread_t dispatch_thread;
-
-/* FIXME: do we need to set any attributes for our thread?
- * If so, we need to create a pthread_attr structure and
- * fill it in somewhere. But the defaults should be good
- * enough.
- */
-
-#elif defined( G_THREADS_IMPL_SOLARIS )
-
-#include <thread.h>
-
-static thread_t dispatch_thread;
-
-#else /* no supported thread impl */
-void
-f (void)
-{
- Error_No_supported_thread_implementation_recognized ();
- choke on this;
-}
-#endif
-
-static int
-pipe_write (int fd, const void *buf, size_t count)
-{
- size_t res;
-
- do {
- res = write (fd, buf, count);
- }
- while (res == -1 && errno == EINTR);
-
- return res;
-}
-
-static size_t
-pipe_read (int fd, void *buf, size_t count)
-{
- size_t res;
-
- do {
- res = read (fd, buf, count);
- } while (res == -1 && errno == EINTR);
-
- return res;
-}
-
-/**
- * mail_operation_queue:
- * @spec: describes the operation to be performed
- * @input: input data for the operation.
- *
- * Runs a mail operation asynchronously. If no other operation is running,
- * we start another thread and call the callback in that thread. The function
- * can then use the mail_op_ functions to perform limited UI returns, while
- * the main UI is completely unlocked.
- *
- * If an async operation is going on when this function is called again,
- * it waits for the currently executing operation to finish, then
- * executes the callback function in another thread.
- *
- * Returns TRUE on success, FALSE on some sort of queueing error.
- **/
-
-gboolean
-mail_operation_queue (const mail_operation_spec * spec, gpointer input,
- gboolean free_in_data)
-{
- closure_t *clur;
-
- g_assert (spec);
-
- clur = new_closure (spec, input, free_in_data);
-
- if (spec->setup)
- (spec->setup) (clur->in_data, clur->op_data, clur->ex);
-
- if (camel_exception_is_set (clur->ex)) {
- if (clur->ex->id != CAMEL_EXCEPTION_USER_CANCEL) {
- GtkWidget *err_dialog;
- gchar *msg;
-
- msg =
- g_strdup_printf
- (_("Error while preparing to %s:\n" "%s"),
- clur->infinitive,
- camel_exception_get_description (clur->ex));
- err_dialog = gnome_error_dialog (msg);
- g_free (msg);
- gnome_dialog_set_close (GNOME_DIALOG (err_dialog),
- TRUE);
- gnome_dialog_run_and_close (GNOME_DIALOG (err_dialog));
-
- g_warning ("Setup failed for `%s': %s",
- clur->infinitive,
- camel_exception_get_description (clur->
- ex));
- }
-
- free_closure (clur);
- return FALSE;
- }
-
- if (queue_len == 0) {
- check_compipes ();
- check_dispatcher ();
- } /* else add self to queue */
-
- pipe_write (DISPATCH_WRITER, clur, sizeof (closure_t));
- /* dispatch allocates a separate buffer
- * to hold the closure; it's in the pipe and
- * can safely be freed
- */
- g_free (clur);
- queue_len++;
- return TRUE;
-}
-
-#if 0
-/**
- * mail_op_set_percentage:
- * @percentage: the percentage that will be displayed in the progress bar
- *
- * Set the percentage of the progress bar for the currently executing operation.
- * Threadsafe for, nay, intended to be called by, the dispatching thread.
- **/
-
-void
-mail_op_set_percentage (gfloat percentage)
-{
- com_msg_t msg;
-
- msg.type = PERCENTAGE;
- msg.percentage = percentage;
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
-}
-
-/**
- * mail_op_hide_progressbar:
- *
- * Hide the progress bar in the status box
- * Threadsafe for, nay, intended to be called by, the dispatching thread.
- **/
-
-void
-mail_op_hide_progressbar (void)
-{
- com_msg_t msg;
-
- msg.type = HIDE_PBAR;
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
-}
-
-/**
- * mail_op_show_progressbar:
- *
- * Show the progress bar in the status box
- * Threadsafe for, nay, intended to be called by, the dispatching thread.
- **/
-
-void
-mail_op_show_progressbar (void)
-{
- com_msg_t msg;
-
- msg.type = SHOW_PBAR;
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
-}
-
-#endif
-
-/**
- * mail_op_set_message:
- * @str: message
- *
- * Set the message displayed above the progress bar for the currently
- * executing operation.
- * Threadsafe for, nay, intended to be called by, the dispatching thread.
- **/
-
-static void
-set_message (gchar *str)
-{
- com_msg_t msg;
-
- msg.type = MESSAGE;
- msg.message = str;
-
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
-}
-
-void
-mail_op_set_message_plain (const gchar *str)
-{
- set_message (g_strdup (str));
-}
-
-/**
- * mail_op_set_message:
- * @fmt: printf-style format string for the message
- * @...: arguments to the format string
- *
- * Set the message displayed above the progress bar for the currently
- * executing operation.
- * Threadsafe for, nay, intended to be called by, the dispatching thread.
- **/
-
-void
-mail_op_set_message (const gchar *fmt, ...)
-{
- gchar *str;
- va_list val;
-
- va_start (val, fmt);
- str = g_strdup_vprintf (fmt, val);
- va_end (val);
-
- set_message (str);
-}
-
-/**
- * mail_op_get_password:
- * @prompt: the question put to the user
- * @secret: whether the dialog box shold print stars when the user types
- * @dest: where to store the reply
- *
- * Asks the user for a password (or string entry in general). Waits for
- * the user's response. On success, returns TRUE and @dest contains the
- * response. On failure, returns FALSE and @dest contains the error
- * message.
- **/
-
-gboolean
-mail_op_get_password (gchar * prompt, gboolean secret, gchar ** dest)
-{
- com_msg_t msg;
- gboolean result;
-
- msg.type = PASSWORD;
- msg.secret = secret;
- msg.message = prompt;
- msg.reply = dest;
- msg.success = &result;
-
- (*dest) = NULL;
-
- block_prepare (&modal_block);
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
- block_wait (&modal_block);
-
- return result;
-}
-
-/**
- * mail_op_error:
- * @fmt: printf-style format string for the error
- * @...: arguments to the format string
- *
- * Opens an error dialog for the currently executing operation.
- * Threadsafe for, nay, intended to be called by, the dispatching thread.
- **/
-
-void
-mail_op_error (gchar * fmt, ...)
-{
- com_msg_t msg;
- va_list val;
-
- va_start (val, fmt);
- msg.type = ERROR;
- msg.message = g_strdup_vprintf (fmt, val);
- va_end (val);
-
- block_prepare (&modal_block);
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
- block_wait (&modal_block);
-}
-
-/**
- * mail_op_forward_event:
- *
- * Communicate a camel event over to the main thread.
- **/
-
-void
-mail_op_forward_event (CamelObjectEventHookFunc func, CamelObject *o,
- gpointer event_data, gpointer user_data)
-{
- com_msg_t msg;
-
- msg.type = FORWARD_EVENT;
- msg.event_hook = func;
- msg.event_obj = o;
- msg.event_event_data = event_data;
- msg.event_user_data = user_data;
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
-}
-/**
- * mail_operation_wait_for_finish:
- *
- * Waits for the currently executing async operations
- * to finish executing
- */
-
-void
-mail_operation_wait_for_finish (void)
-{
- while (queue_len)
- gtk_main_iteration ();
- /* Sigh. Otherwise we deadlock upon exit. */
- GDK_THREADS_LEAVE ();
-}
-
-/**
- * mail_operations_are_executing:
- *
- * Returns TRUE if operations are being executed asynchronously
- * when called, FALSE if not.
- **/
-
-gboolean
-mail_operations_are_executing (void)
-{
- return (queue_len > 0);
-}
-
-/**
- * mail_operations_terminate:
- *
- * Let the operations finish then terminate the dispatch thread
- **/
-
-void
-mail_operations_terminate (void)
-{
- closure_t clur;
-
- mail_operation_wait_for_finish();
-
- memset (&clur, 0, sizeof (closure_t));
- clur.spec = NULL;
-
- pipe_write (DISPATCH_WRITER, &clur, sizeof (closure_t));
-
- close (DISPATCH_WRITER);
- close (MAIN_READER);
-}
-
-void
-mail_operations_get_status (int *busy_return,
- const char **message_return)
-{
- *busy_return = busy;
- *message_return = current_message;
-}
-
-/* ** Static functions **************************************************** */
-
-static void check_dispatcher (void)
-{
- int res;
-
- if (dispatch_thread_started)
- return;
-
-#if defined( G_THREADS_IMPL_POSIX )
- res = pthread_create (&dispatch_thread, NULL,
- (void *) &dispatch, NULL);
-#elif defined( G_THREADS_IMPL_SOLARIS )
- res = thr_create (NULL, 0, (void *) &dispatch, NULL, 0, &dispatch_thread);
-#else /* no known impl */
- Error_No_thread_create_implementation ();
- choke on this;
-#endif
- if (res != 0) {
- g_warning ("Error launching dispatch thread!");
- /* FIXME: more error handling */
- } else
- dispatch_thread_started = TRUE;
-}
-
-/**
- * check_compipes:
- *
- * Check and see if our pipe has been opened and open
- * it if necessary.
- **/
-
-static void
-check_compipes (void)
-{
- if (MAIN_READER < 0) {
- if (pipe (main_compipe) < 0) {
- g_warning ("Call to pipe(2) failed!");
-
- /* FIXME: better error handling. How do we react? */
- return;
- }
-
- chan_reader = g_io_channel_unix_new (MAIN_READER);
- g_io_add_watch (chan_reader, G_IO_IN, read_msg, NULL);
- }
-
- if (DISPATCH_READER < 0) {
- if (pipe (dispatch_compipe) < 0) {
- g_warning ("Call to pipe(2) failed!");
-
- /* FIXME: better error handling. How do we react? */
- return;
- }
- }
-}
-
-/**
- * dispatch:
- * @clur: The operation to execute and its parameters
- *
- * Start a thread that executes the closure and exit
- * it when done.
- */
-
-static void *
-dispatch (void *unused)
-{
- size_t len;
- closure_t *clur;
- com_msg_t msg;
-
- /* Let the compipes be created */
- sleep (1);
-
- while (1) {
- clur = g_new (closure_t, 1);
- len = pipe_read (DISPATCH_READER, clur, sizeof (closure_t));
-
- if (len <= 0)
- break;
-
- if (len != sizeof (closure_t)) {
- g_warning ("dispatcher: Didn't read full message!");
- continue;
- }
-
- if (clur->spec == NULL)
- break;
-
- msg.type = STARTING;
- msg.message = g_strdup (clur->gerund);
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
-
- (clur->spec->callback) (clur->in_data, clur->op_data, clur->ex);
-
- if (camel_exception_is_set (clur->ex)) {
- if (clur->ex->id != CAMEL_EXCEPTION_USER_CANCEL) {
- g_warning ("Callback failed for `%s': %s",
- clur->infinitive,
- camel_exception_get_description (clur->
- ex));
- mail_op_error (_("Error while `%s':\n%s"),
- clur->gerund,
- camel_exception_get_description (clur->
- ex));
- }
- }
-
- msg.type = FINISHED;
- msg.clur = clur;
-
- /* Wait for the cleanup to finish before starting our next op */
- block_prepare (&finish_block);
- pipe_write (MAIN_WRITER, &msg, sizeof (msg));
- block_wait (&finish_block);
- }
-
- close (DISPATCH_READER);
- close (MAIN_WRITER);
-
-#ifdef G_THREADS_IMPL_POSIX
- pthread_exit (0);
-#elif defined( G_THREADS_IMPL_SOLARIS )
- thr_exit (NULL);
-#else /* no known impl */
- Error_No_thread_exit_implemented ();
- choke on this;
-#endif
- return NULL;
- /*NOTREACHED*/
-}
-
-/**
- * read_msg:
- * @source: the channel that has data to read
- * @condition: the reason we were called
- * @userdata: unused
- *
- * A message has been recieved on our pipe; perform the appropriate
- * action.
- **/
-
-static gboolean
-read_msg (GIOChannel * source, GIOCondition condition, gpointer userdata)
-{
- com_msg_t *msg;
- guint size;
-
- msg = g_new0 (com_msg_t, 1);
-
- g_io_channel_read (source, (gchar *) msg,
- sizeof (com_msg_t) / sizeof (gchar), &size);
-
- if (size != sizeof (com_msg_t)) {
- g_warning (_("Incomplete message written on pipe!"));
- msg->type = ERROR;
- msg->message =
- g_strdup (_
- ("Error reading commands from dispatching thread."));
- }
-
- /* This is very important, though I'm not quite sure why
- * it is as we are in the main thread right now.
- */
-
- /*g_message ("DLG: IN: read_msg");*/
-
- switch (msg->type) {
- case STARTING:
- DEBUG (("*** Message -- STARTING %s\n", msg->message));
- ui_set_busy ();
- ui_set_message (msg->message);
- g_free (msg->message);
- break;
-#if 0
- case PERCENTAGE:
- DEBUG (("*** Message -- PERCENTAGE\n"));
- g_warning ("PERCENTAGE operation unsupported");
- break;
- case HIDE_PBAR:
- DEBUG (("*** Message -- HIDE_PBAR\n"));
- g_warning ("HIDE_PBAR operation unsupported");
- break;
- case SHOW_PBAR:
- DEBUG (("*** Message -- SHOW_PBAR\n"));
- g_warning ("HIDE_PBAR operation unsupported");
- break;
-#endif
-
- case MESSAGE:
- DEBUG (("*** Message -- MESSAGE\n"));
- ui_set_message (msg->message);
- g_free (msg->message);
- break;
-
- case PASSWORD:
- DEBUG (("*** Message -- PASSWORD\n"));
- g_assert (msg->reply);
- g_assert (msg->success);
- get_password (msg);
- break;
-
- case ERROR:
- DEBUG (("*** Message -- ERROR\n"));
- show_error (msg);
- break;
-
- /* Don't fall through; dispatch_func does the FINISHED
- * call for us
- */
-
- case FORWARD_EVENT:
- DEBUG (("*** Message -- FORWARD_EVENT %p\n", msg->event_hook));
- g_assert (msg->event_hook);
- (msg->event_hook) (msg->event_obj, msg->event_event_data, msg->event_user_data);
- break;
-
- case FINISHED:
- DEBUG (("*** Message -- FINISH %s\n", msg->clur->gerund));
- cleanup_op (msg);
- break;
-
- default:
- g_warning (_("Corrupted message from dispatching thread?"));
- break;
- }
-
- /*g_message ("DLG: OUT: read_msg");*/
- g_free (msg);
-
- return TRUE;
-}
-
-/**
- * cleanup_op:
- *
- * Cleanup after a finished operation
- **/
-
-static void
-cleanup_op (com_msg_t * msg)
-{
- block_hold (&finish_block);
-
- /* Run the cleanup */
-
- if (msg->clur->spec->cleanup)
- (msg->clur->spec->cleanup) (msg->clur->in_data,
- msg->clur->op_data,
- msg->clur->ex);
-
- /* Tell the dispatch thread that it can start
- * the next operation */
-
- block_release (&finish_block);
-
- /* Print an exception if the cleanup caused one */
-
- if (camel_exception_is_set (msg->clur->ex) &&
- msg->clur->ex->id != CAMEL_EXCEPTION_USER_CANCEL) {
- g_warning ("Error on cleanup of `%s': %s",
- msg->clur->infinitive,
- camel_exception_get_description (msg->clur->ex));
- }
-
- free_closure (msg->clur);
- queue_len--;
-
- ui_unset_busy ();
- ui_unset_message ();
-}
-
-/**
- * show_error:
- *
- * Show the error dialog and wait for user OK
- **/
-
-static void
-show_error (com_msg_t * msg)
-{
- GtkWidget *err_dialog;
-
- /* Create the dialog */
-
- err_dialog = gnome_error_dialog (msg->message);
- g_free (msg->message);
-
- /* Stop the other thread until the user reacts */
-
- ui_unset_busy ();
- block_hold (&modal_block);
-
- /* Show the dialog. */
-
- /* Do not GDK_THREADS_ENTER; we're inside the read_msg
- * handler which takes care of this for us. Oh, if
- * only GDK_THREADS_ENTER were recursive...
- */
-
- gnome_dialog_run_and_close (GNOME_DIALOG (err_dialog));
-
- /* Allow the other thread to proceed */
-
- block_release (&modal_block);
- ui_set_busy ();
-}
-
-static void
-focus_on_entry(GtkWidget *widget, gpointer user_data)
-{
- if (GTK_IS_ENTRY(widget)) {
- gtk_widget_grab_focus(widget);
- }
-}
-
-/**
- * get_password:
- *
- * Ask for a password and put the answer in *(msg->reply)
- **/
-
-static void
-get_password (com_msg_t * msg)
-{
- GtkWidget *dialog;
- int button;
-
- /* Create the dialog */
-
- dialog = gnome_request_dialog (msg->secret, msg->message, NULL,
- 0, get_password_cb, msg, NULL);
-
- /* Stop the other thread */
-
- ui_unset_busy ();
- block_hold (&modal_block);
-
- /* Show the dialog (or report an error) */
-
- if (dialog == NULL) {
- *(msg->success) = FALSE;
- *(msg->reply) = g_strdup (_("Could not create dialog box."));
- button = -1;
- } else {
- e_container_foreach_leaf (GTK_CONTAINER (dialog),
- focus_on_entry, NULL);
- *(msg->reply) = NULL;
- button = gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
- }
-
- if (button == 1 || *(msg->reply) == NULL) {
- *(msg->success) = FALSE;
- *(msg->reply) = g_strdup (_("User cancelled query."));
- } else if (button >= 0) {
- *(msg->success) = TRUE;
- }
-
- /* Allow the other thread to proceed */
-
- block_release (&modal_block);
- ui_set_busy ();
-}
-
-static void
-get_password_cb (gchar * string, gpointer data)
-{
- com_msg_t *msg = (com_msg_t *) data;
-
- if (string)
- *(msg->reply) = g_strdup (string);
- else
- *(msg->reply) = NULL;
-}
-
-static closure_t *
-new_closure (const mail_operation_spec * spec, gpointer input,
- gboolean free_in_data)
-{
- closure_t *clur;
-
- clur = g_new0 (closure_t, 1);
- clur->spec = spec;
- clur->in_data = input;
- clur->free_in_data = free_in_data;
- clur->ex = camel_exception_new ();
-
- clur->op_data = g_malloc (spec->datasize);
-
- camel_exception_init (clur->ex);
-
- clur->infinitive = (spec->describe) (input, FALSE);
- clur->gerund = (spec->describe) (input, TRUE);
-
- return clur;
-}
-
-static void
-free_closure (closure_t *clur)
-{
- clur->spec = NULL;
-
- if (clur->free_in_data)
- g_free (clur->in_data);
- clur->in_data = NULL;
-
- g_free (clur->op_data);
- clur->op_data = NULL;
-
- camel_exception_free (clur->ex);
- clur->ex = NULL;
-
- g_free (clur->infinitive);
- g_free (clur->gerund);
-
- g_free (clur);
-}
-
-/* ******************** */
-
-/**
- *
- * Thread A calls block_prepare
- * Thread A causes thread B to do something
- * Thread A calls block_wait
- * Thread A continues when thread B calls block_release
- *
- * Thread B gets thread A's message
- * Thread B calls block_hold
- * Thread B does something
- * Thread B calls block_release
- *
- **/
-
-static void
-block_prepare (block_info_t *info)
-{
- if (info->cond == NULL) {
- info->cond = g_cond_new ();
- info->mutex = g_mutex_new ();
- }
-
- g_mutex_lock (info->mutex);
- info->val = FALSE;
-}
-
-static void
-block_wait (block_info_t *info)
-{
- g_assert (info->cond);
-
- while (info->val == FALSE)
- g_cond_wait (info->cond, info->mutex);
-
- g_mutex_unlock (info->mutex);
-}
-static void
-block_hold (block_info_t *info)
-{
- g_assert (info->cond);
-
- g_mutex_lock (info->mutex);
- info->val = FALSE;
-}
-
-static void
-block_release (block_info_t *info)
-{
- g_assert (info->cond);
-
- info->val = TRUE;
- g_cond_signal (info->cond);
- g_mutex_unlock (info->mutex);
-}
-
-/* ******************** */
-
-/* FIXME FIXME FIXME This is a totally evil hack. */
-
-static GNOME_Evolution_ShellView
-retrieve_shell_view_interface_from_control (BonoboControl *control)
-{
- Bonobo_ControlFrame control_frame;
- GNOME_Evolution_ShellView shell_view_interface;
- CORBA_Environment ev;
-
- control_frame = bonobo_control_get_control_frame (control);
-
- if (control_frame == NULL)
- return CORBA_OBJECT_NIL;
-
- CORBA_exception_init (&ev);
- shell_view_interface = Bonobo_Unknown_queryInterface (control_frame,
- "IDL:GNOME/Evolution/ShellView:1.0",
- &ev);
- CORBA_exception_free (&ev);
-
- if (shell_view_interface != CORBA_OBJECT_NIL)
- gtk_object_set_data (GTK_OBJECT (control),
- "mail_threads_shell_view_interface",
- shell_view_interface);
- else
- g_warning ("Control frame doesn't have Evolution/ShellView.");
-
- return shell_view_interface;
-}
-
-static void
-update_active_views (void)
-{
- EList *controls;
- EIterator *it;
-
- controls = folder_browser_factory_get_control_list ();
- for (it = e_list_get_iterator (controls); e_iterator_is_valid (it); e_iterator_next (it)) {
- BonoboControl *control;
- GNOME_Evolution_ShellView shell_view_interface;
- CORBA_Environment ev;
-
- control = BONOBO_CONTROL (e_iterator_get (it));
-
- shell_view_interface = gtk_object_get_data (GTK_OBJECT (control), "mail_threads_shell_view_interface");
-
- if (shell_view_interface == CORBA_OBJECT_NIL)
- shell_view_interface = retrieve_shell_view_interface_from_control (control);
-
- CORBA_exception_init (&ev);
-
- if (shell_view_interface != CORBA_OBJECT_NIL) {
- if (current_message == NULL && ! busy) {
- GNOME_Evolution_ShellView_unsetMessage (shell_view_interface, &ev);
- } else {
- if (current_message == NULL)
- GNOME_Evolution_ShellView_setMessage (shell_view_interface,
- "",
- busy,
- &ev);
- else
- GNOME_Evolution_ShellView_setMessage (shell_view_interface,
- current_message,
- busy,
- &ev);
- }
- }
-
- CORBA_exception_free (&ev);
- }
- gtk_object_unref(GTK_OBJECT(it));
-}
-
-static void
-ui_set_busy (void)
-{
- busy = TRUE;
- update_active_views ();
-}
-
-static void
-ui_unset_busy (void)
-{
- busy = FALSE;
- update_active_views ();
-}
-
-static void
-ui_set_message (const char *message)
-{
- g_free (current_message);
- current_message = g_strdup (message);
- update_active_views ();
-}
-
-static void
-ui_unset_message (void)
-{
- g_free (current_message);
- current_message = NULL;
- update_active_views ();
-}