From 0f2a13586b155c0e97eab0b1bc9ab59e5587555d Mon Sep 17 00:00:00 2001 From: Not Zed Date: Wed, 21 Feb 2001 02:19:26 +0000 Subject: Fix for api changes to append_mail. 2001-02-21 Not Zed * mail-callbacks.c (composer_postpone_cb): Fix for api changes to append_mail. * Makefile.am (evolution_mail_SOURCES): Removed mail-threads.[ch]. * mail-threads.[ch]: Removed. * subscribe-dialog.c (subscribe_do_get_store): Chagned to use new thread stuff. This is really getting boring. (subscribe_do_subscribe_folder): Changed to use new thread stuff. Last one at last, phew. * session.c (register_callback): Changed to use new thread stuff. YUCK. I dropped some functionality, now the timeout callback return is ignored, so basically it keeps running till finished. * mail-ops.c (mail_operation_run): Removed, no longer used/needed. (mail_do_append_mail): Changed to use new thread stuff. (mail_do_transfer_messages): ditto. * mail-local.c (local_storage_new_folder_cb): Use new thread stuff, also only run synchronous for this operation. (mail_local_reconfigure_folder): (reconfigure_clicked): Changed to use new mail thread stuff. * mail-config.c (mail_config_check_service): Changed to use new thread stuff. svn path=/trunk/; revision=8314 --- mail/mail-threads.c | 1158 --------------------------------------------------- 1 file changed, 1158 deletions(-) delete mode 100644 mail/mail-threads.c (limited to 'mail/mail-threads.c') diff --git a/mail/mail-threads.c b/mail/mail-threads.c deleted file mode 100644 index 8f0e263765..0000000000 --- a/mail/mail-threads.c +++ /dev/null @@ -1,1158 +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 - -#include -#include -#include - -#include - -#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 - -/** - * @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 - -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; - - /* DISPATCH_WRITER will only have been initialized if any - * calls have been made using the old thread system. - */ - if (DISPATCH_WRITER != -1) { - 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 (); -} -- cgit v1.2.3