aboutsummaryrefslogtreecommitdiffstats
path: root/mail/em-folder-view.c.dead
diff options
context:
space:
mode:
Diffstat (limited to 'mail/em-folder-view.c.dead')
-rw-r--r--mail/em-folder-view.c.dead1014
1 files changed, 1014 insertions, 0 deletions
diff --git a/mail/em-folder-view.c.dead b/mail/em-folder-view.c.dead
new file mode 100644
index 0000000000..3f76572f18
--- /dev/null
+++ b/mail/em-folder-view.c.dead
@@ -0,0 +1,1014 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gdk/gdkkeysyms.h>
+
+#ifdef G_OS_WIN32
+/* Work around 'DATADIR' and 'interface' lossage in <windows.h> */
+#define DATADIR crap_DATADIR
+#include <windows.h>
+#undef DATADIR
+#undef interface
+#endif
+
+#include <gconf/gconf-client.h>
+
+#include <camel/camel-mime-message.h>
+#include <camel/camel-stream.h>
+#include <camel/camel-stream-filter.h>
+#include <camel/camel-mime-filter.h>
+#include <camel/camel-mime-filter-tohtml.h>
+#include <camel/camel-mime-filter-enriched.h>
+#include <camel/camel-multipart.h>
+#include <camel/camel-stream-mem.h>
+#include <camel/camel-url.h>
+#include <camel/camel-vee-folder.h>
+#include <camel/camel-disco-store.h>
+#include <camel/camel-offline-store.h>
+#include <camel/camel-vee-store.h>
+
+#include <gtkhtml/gtkhtml.h>
+#include <gtkhtml/gtkhtml-embedded.h>
+#include <gtkhtml/gtkhtml-stream.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-msgport.h>
+
+#include "menus/gal-view-etable.h"
+#include "menus/gal-view-factory-etable.h"
+#include "menus/gal-view-instance.h"
+
+#include "misc/e-charset-picker.h"
+#include <misc/e-spinner.h>
+
+#include "e-util/e-error.h"
+#include "e-util/e-dialog-utils.h"
+#include "e-util/e-icon-factory.h"
+#include "e-util/e-print.h"
+#include "e-util/e-profile-event.h"
+#include "e-util/e-util-private.h"
+#include "e-util/e-util-labels.h"
+#include "shell/e-shell.h"
+
+#include "filter/filter-rule.h"
+
+#include "em-format-html-display.h"
+#include "em-format-html-print.h"
+#include "em-folder-selection.h"
+#include "em-folder-view.h"
+#include "em-folder-browser.h"
+#include "em-mailer-prefs.h"
+#include "em-folder-browser.h"
+#include "message-list.h"
+#include "em-utils.h"
+#include "em-composer-utils.h"
+#include "em-menu.h"
+#include "em-event.h"
+#include "e-mail-shell-backend.h"
+
+#include "mail-mt.h"
+#include "mail-ops.h"
+#include "mail-config.h"
+#include "mail-autofilter.h"
+#include "mail-vfolder.h"
+#include "mail-tools.h"
+
+#ifdef HAVE_XFREE
+#include <X11/XF86keysym.h>
+#endif
+
+/* this is added to emfv->enable_map in :init() */
+static const EMFolderViewEnable emfv_enable_map[] = {
+ { "EditCut", EM_POPUP_SELECT_MANY },
+ { "EditCopy", EM_FOLDER_VIEW_SELECT_SELECTION },
+ { "EditPaste", EM_POPUP_SELECT_FOLDER },
+// { "SelectAllText", EM_POPUP_SELECT_ONE },
+
+ /* FIXME: should these be single-selection? */
+ { "MailNext", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_NEXT_MSG },
+// { "MailNextFlagged", EM_POPUP_SELECT_MANY },
+// { "MailNextUnread", EM_POPUP_SELECT_MANY },
+// { "MailNextThread", EM_POPUP_SELECT_MANY },
+ { "MailPrevious", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_PREV_MSG },
+// { "MailPreviousFlagged", EM_POPUP_SELECT_MANY },
+// { "MailPreviousUnread", EM_POPUP_SELECT_MANY },
+
+ { "AddSenderToAddressbook", EM_POPUP_SELECT_ADD_SENDER },
+
+// { "MessageApplyFilters", EM_POPUP_SELECT_MANY },
+// { "MessageFilterJunk", EM_POPUP_SELECT_MANY },
+// { "MessageCopy", EM_POPUP_SELECT_MANY },
+// { "MessageDelete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_DELETE },
+// { "MessageDeleteKey", EM_POPUP_SELECT_MANY},
+// { "MessageForward", EM_POPUP_SELECT_MANY },
+// { "MessageForwardAttached", EM_POPUP_SELECT_MANY },
+// { "MessageForwardInline", EM_POPUP_SELECT_ONE },
+// { "MessageForwardQuoted", EM_POPUP_SELECT_ONE },
+// { "MessageRedirect", EM_POPUP_SELECT_ONE },
+// { "MessageMarkAsRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_READ },
+// { "MessageMarkAsUnRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNREAD },
+// { "MessageMarkAsImportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_IMPORTANT },
+// { "MessageMarkAsUnimportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNIMPORTANT },
+// { "MessageMarkAsJunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_JUNK },
+// { "MessageMarkAsNotJunk", EM_POPUP_SELECT_MANY},
+ { "MessageFollowUpFlag", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_FLAG_FOLLOWUP },
+ { "MessageFollowUpComplete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_FLAG_COMPLETED },
+ { "MessageFollowUpClear", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_FLAG_CLEAR },
+// { "MessageMove", EM_POPUP_SELECT_MANY },
+// { "MessageOpen", EM_POPUP_SELECT_MANY },
+// { "MessageReplyAll", EM_POPUP_SELECT_ONE },
+// { "MessageReplyList", EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST },
+// { "MessageReplySender", EM_POPUP_SELECT_ONE },
+// { "MessageEdit", EM_POPUP_SELECT_ONE },
+// { "MessageSaveAs", EM_POPUP_SELECT_MANY },
+ { "MessageSearch", EM_POPUP_SELECT_ONE| EM_FOLDER_VIEW_PREVIEW_PRESENT },
+// { "MessageUndelete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_UNDELETE },
+// { "PrintMessage", EM_POPUP_SELECT_ONE },
+// { "PrintPreviewMessage", EM_POPUP_SELECT_ONE },
+
+// { "TextZoomIn", EM_POPUP_SELECT_ONE },
+// { "TextZoomOut", EM_POPUP_SELECT_ONE },
+// { "TextZoomReset", EM_POPUP_SELECT_ONE },
+
+ { "ToolsFilterMailingList", EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST},
+ { "ToolsFilterRecipient", EM_POPUP_SELECT_ONE },
+ { "ToolsFilterSender", EM_POPUP_SELECT_ONE },
+ { "ToolsFilterSubject", EM_POPUP_SELECT_ONE },
+ { "ToolsVFolderMailingList", EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST},
+ { "ToolsVFolderRecipient", EM_POPUP_SELECT_ONE },
+ { "ToolsVFolderSender", EM_POPUP_SELECT_ONE },
+ { "ToolsVFolderSubject", EM_POPUP_SELECT_ONE },
+
+// { "ViewLoadImages", EM_POPUP_SELECT_ONE },
+// { "ViewSource", EM_POPUP_SELECT_ONE },
+
+// /* always enabled */
+// { "MailStop", 0 },
+
+ { NULL },
+};
+
+struct _EMFolderViewPrivate {
+ guint setting_notify_id;
+ guint selected_id;
+ guint nomarkseen:1;
+ guint destroyed:1;
+
+ GtkWidget *invisible;
+ gchar *selection_uri;
+
+ gchar *selected_uid;
+};
+
+static GtkVBoxClass *emfv_parent;
+
+enum {
+ EMFV_ON_URL,
+ EMFV_LOADED,
+ EMFV_CHANGED,
+ LAST_SIGNAL
+};
+
+extern CamelSession *session;
+
+static guint signals[LAST_SIGNAL];
+
+static void
+emfv_init(GObject *o)
+{
+ EMFolderView *emfv = (EMFolderView *)o;
+ struct _EMFolderViewPrivate *p;
+
+// gtk_box_set_homogeneous (GTK_BOX (emfv), FALSE);
+//
+// p = emfv->priv = g_malloc0(sizeof(struct _EMFolderViewPrivate));
+//
+// emfv->statusbar_active = TRUE;
+// emfv->list_active = FALSE;
+//
+// emfv->ui_files = g_slist_append(NULL,
+// g_build_filename (EVOLUTION_UIDIR,
+// "evolution-mail-message.xml",
+// NULL));
+//
+// emfv->ui_app_name = "evolution-mail";
+
+ emfv->enable_map = g_slist_prepend(NULL, (gpointer)emfv_enable_map);
+
+// emfv->list = (MessageList *)message_list_new();
+// g_signal_connect(emfv->list, "message_selected", G_CALLBACK(emfv_list_message_selected), emfv);
+// g_signal_connect(emfv->list, "message_list_built", G_CALLBACK(emfv_list_built), emfv);
+//
+// /* FIXME: should this hang off message-list instead? */
+// g_signal_connect(emfv->list->tree, "right_click", G_CALLBACK(emfv_list_right_click), emfv);
+// g_signal_connect(emfv->list->tree, "double_click", G_CALLBACK(emfv_list_double_click), emfv);
+// g_signal_connect(emfv->list->tree, "key_press", G_CALLBACK(emfv_list_key_press), emfv);
+// g_signal_connect(emfv->list->tree, "selection_change", G_CALLBACK(emfv_list_selection_change), emfv);
+//
+// emfv->preview = (EMFormatHTMLDisplay *)em_format_html_display_new();
+// /* FIXME: set_session should NOT be called here. Should it be a constructor attribute? */
+// em_format_set_session ((EMFormat *) emfv->preview, session);
+// g_signal_connect(emfv->preview, "link_clicked", G_CALLBACK(emfv_format_link_clicked), emfv);
+ g_signal_connect(emfv->preview, "popup_event", G_CALLBACK(emfv_format_popup_event), emfv);
+// g_signal_connect (emfv->preview, "on_url", G_CALLBACK (emfv_on_url_cb), emfv);
+// g_signal_connect (((EMFormatHTML *)emfv->preview)->html, "button-release-event", G_CALLBACK (emfv_on_html_button_released_cb), emfv);
+//#ifdef ENABLE_PROFILING
+// g_signal_connect(emfv->preview, "complete", G_CALLBACK (emfv_format_complete), emfv);
+//#endif
+// p->invisible = gtk_invisible_new();
+// g_signal_connect(p->invisible, "selection_get", G_CALLBACK(emfv_selection_get), emfv);
+// g_signal_connect(p->invisible, "selection_clear_event", G_CALLBACK(emfv_selection_clear_event), emfv);
+// gtk_selection_add_target(p->invisible, GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 0);
+// gtk_selection_add_target(p->invisible, GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 1);
+
+ emfv->async = mail_async_event_new();
+}
+
+static void
+emfv_class_init(GObjectClass *klass)
+{
+ klass->finalize = emfv_finalise;
+
+ ((GtkObjectClass *) klass)->destroy = emfv_destroy;
+
+ ((GtkWidgetClass *) klass)->popup_menu = emfv_popup_menu;
+
+ ((EMFolderViewClass *) klass)->update_message_style = TRUE;
+
+ ((EMFolderViewClass *)klass)->set_folder = emfv_set_folder;
+ ((EMFolderViewClass *)klass)->set_folder_uri = emfv_set_folder_uri;
+ ((EMFolderViewClass *)klass)->set_message = emfv_set_message;
+ ((EMFolderViewClass *)klass)->activate = emfv_activate;
+
+// ((EMFolderViewClass *)klass)->on_url = emfv_on_url;
+
+ signals[EMFV_ON_URL] = g_signal_new ("on-url",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMFolderViewClass, on_url),
+ NULL, NULL,
+ e_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_STRING);
+
+ signals[EMFV_LOADED] = g_signal_new("loaded",
+ G_OBJECT_CLASS_TYPE(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(EMFolderViewClass, loaded),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ signals[EMFV_CHANGED] = g_signal_new("changed",
+ G_OBJECT_CLASS_TYPE(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(EMFolderViewClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+//static void
+//emfv_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint time_stamp, EMFolderView *emfv)
+//{
+// struct _EMFolderViewPrivate *p = emfv->priv;
+//
+// if (p->selection_uri == NULL)
+// return;
+//
+// gtk_selection_data_set(data, data->target, 8, (guchar *)p->selection_uri, strlen(p->selection_uri));
+//}
+
+//static void
+//emfv_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, EMFolderView *emfv)
+//{
+//#if 0 /* do i care? */
+// struct _EMFolderViewPrivate *p = emfv->priv;
+//
+// g_free(p->selection_uri);
+// p->selection_uri = NULL;
+//#endif
+//}
+
+/* ********************************************************************** */
+
+/* Popup menu
+ In many cases these are the functions called by the bonobo callbacks too */
+
+/* ********************************************************************** */
+
+/* Bonobo menu's */
+
+/* a lot of stuff maps directly to the popup menu equivalent */
+#define EMFV_MAP_CALLBACK(from, to) \
+static void \
+from(BonoboUIComponent *uid, gpointer data, const gchar *path) \
+{ \
+ to(NULL, NULL, data); \
+}
+
+static void
+emfv_edit_cut(BonoboUIComponent *uid, gpointer data, const gchar *path)
+{
+ EMFolderView *emfv = data;
+
+ if (GTK_WIDGET_HAS_FOCUS(emfv->preview->formathtml.html))
+ em_format_html_display_cut(emfv->preview);
+ else
+ message_list_copy(emfv->list, TRUE);
+}
+
+static void
+emfv_edit_copy(BonoboUIComponent *uid, gpointer data, const gchar *path)
+{
+ EMFolderView *emfv = data;
+
+ if (GTK_WIDGET_HAS_FOCUS(emfv->preview->formathtml.html))
+ em_format_html_display_copy(emfv->preview);
+ else
+ message_list_copy(emfv->list, FALSE);
+}
+
+static void
+emfv_edit_paste(BonoboUIComponent *uid, gpointer data, const gchar *path)
+{
+ EMFolderView *emfv = data;
+
+ message_list_paste(emfv->list);
+}
+
+//static void
+//emp_uri_popup_vfolder_sender(EPopup *ep, EPopupItem *pitem, gpointer data)
+//{
+// EMFolderView *emfv = data;
+// EMPopupTargetURI *t = (EMPopupTargetURI *)ep->target;
+// CamelURL *url;
+// CamelInternetAddress *addr;
+//
+// url = camel_url_new(t->uri, NULL);
+// if (url == NULL) {
+// g_warning("cannot parse url '%s'", t->uri);
+// return;
+// }
+//
+// if (url->path && url->path[0]) {
+// /* ensures vfolder is running */
+// vfolder_load_storage ();
+//
+// addr = camel_internet_address_new ();
+// camel_address_decode (CAMEL_ADDRESS (addr), url->path);
+// vfolder_gui_add_from_address (addr, AUTO_FROM, emfv->folder_uri);
+// camel_object_unref (addr);
+// }
+//
+// camel_url_free(url);
+//
+//}
+
+//static void
+//emp_uri_popup_vfolder_recipient(EPopup *ep, EPopupItem *pitem, gpointer data)
+//{
+// EMFolderView *emfv = data;
+// EMPopupTargetURI *t = (EMPopupTargetURI *)ep->target;
+// CamelURL *url;
+// CamelInternetAddress *addr;
+//
+// url = camel_url_new(t->uri, NULL);
+// if (url == NULL) {
+// g_warning("cannot parse url '%s'", t->uri);
+// return;
+// }
+//
+// if (url->path && url->path[0]) {
+// /* ensures vfolder is running */
+// vfolder_load_storage ();
+//
+// addr = camel_internet_address_new ();
+// camel_address_decode (CAMEL_ADDRESS (addr), url->path);
+// vfolder_gui_add_from_address (addr, AUTO_TO, emfv->folder_uri);
+// camel_object_unref (addr);
+// }
+//
+// camel_url_free(url);
+//}
+
+/* ********************************************************************** */
+
+static BonoboUIVerb emfv_message_verbs[] = {
+ BONOBO_UI_UNSAFE_VERB ("EditCut", emfv_edit_cut),
+ BONOBO_UI_UNSAFE_VERB ("EditCopy", emfv_edit_copy),
+ BONOBO_UI_UNSAFE_VERB ("EditPaste", emfv_edit_paste),
+
+// BONOBO_UI_UNSAFE_VERB ("SelectAllText", emfv_select_all_text),
+
+// BONOBO_UI_UNSAFE_VERB ("MessageDelete", emfv_message_delete),
+// BONOBO_UI_UNSAFE_VERB ("MessageDeleteKey", emfv_message_delete),
+// BONOBO_UI_UNSAFE_VERB ("MessageOpen", emfv_message_open),
+// BONOBO_UI_UNSAFE_VERB ("MessageSearch", emfv_message_search),
+
+// BONOBO_UI_UNSAFE_VERB ("ViewSource", emfv_message_source),
+
+ BONOBO_UI_VERB_END
+};
+
+static void
+emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, gint act)
+{
+
+ if (act) {
+ em_format_mode_t style;
+ gboolean state;
+ GSList *l;
+
+ emfv->uic = uic;
+
+ for (l = emfv->ui_files;l;l = l->next)
+ bonobo_ui_util_set_ui(uic, PREFIX, (gchar *)l->data, emfv->ui_app_name, NULL);
+
+ bonobo_ui_component_add_verb_list_with_data(uic, emfv_message_verbs, emfv);
+ /* must do plugin menu's after main ones because of bonobo bustedness */
+ if (emfv->menu)
+ e_menu_activate((EMenu *)emfv->menu, uic, act);
+
+// state = emfv->preview->caret_mode;
+// bonobo_ui_component_set_prop(uic, "/commands/CaretMode", "state", state?"1":"0", NULL);
+// bonobo_ui_component_add_listener(uic, "CaretMode", emfv_caret_mode, emfv);
+
+// style = ((EMFormat *)emfv->preview)->mode?EM_FORMAT_ALLHEADERS:EM_FORMAT_NORMAL;
+// if (style)
+// bonobo_ui_component_set_prop(uic, "/commands/ViewFullHeaders", "state", "1", NULL);
+// bonobo_ui_component_add_listener(uic, "ViewFullHeaders", emfv_view_mode, emfv);
+// em_format_set_mode((EMFormat *)emfv->preview, style);
+
+ if (emfv->folder)
+ bonobo_ui_component_set_prop(uic, "/commands/MessageEdit", "sensitive", "0", NULL);
+
+// /* default charset used in mail view */
+// e_charset_picker_bonobo_ui_populate (uic, "/menu/View", _("Default"), emfv_charset_changed, emfv);
+
+ emfv_enable_menus(emfv);
+ if (emfv->statusbar_active)
+ bonobo_ui_component_set_translate (uic, "/", "<status><item name=\"main\"/></status>", NULL);
+
+ /* We need to set this up to get the right view options for the message-list, even if we're not showing it */
+ if (emfv->folder)
+ emfv_setup_view_instance(emfv);
+ } else {
+ const BonoboUIVerb *v;
+
+ if (emfv->menu)
+ e_menu_activate((EMenu *)emfv->menu, uic, act);
+
+ /* TODO: Should this just rm /? */
+ for (v = &emfv_message_verbs[0]; v->cname; v++)
+ bonobo_ui_component_remove_verb(uic, v->cname);
+
+ if (emfv->folder)
+ mail_sync_folder(emfv->folder, NULL, NULL);
+
+ emfv->uic = NULL;
+ }
+}
+
+EMPopupTargetSelect *
+em_folder_view_get_popup_target(EMFolderView *emfv, EMPopup *emp, gint on_display)
+{
+ EMPopupTargetSelect *t;
+
+ t = em_popup_target_new_select(emp, emfv->folder, emfv->folder_uri, message_list_get_selected(emfv->list));
+ t->target.widget = (GtkWidget *)emfv;
+
+ if (emfv->list->threaded)
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_THREADED;
+
+ if (message_list_hidden(emfv->list) != 0)
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_HIDDEN;
+
+ if (message_list_can_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0))
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_NEXT_MSG;
+
+ if (message_list_can_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0))
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_PREV_MSG;
+
+ if (on_display)
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_DISPLAY;
+ else
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_LISTONLY;
+
+ if (gtk_html_command (((EMFormatHTML *)emfv->preview)->html, "is-selection-active"))
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_SELECTION;
+ else
+ t->target.mask &= ~EM_FOLDER_VIEW_SELECT_NOSELECTION;
+
+ if (emfv->preview_active)
+ t->target.mask &= ~EM_FOLDER_VIEW_PREVIEW_PRESENT;
+
+ /* See bug 352980 */
+ /* See bug #54770 */
+ /* if (!emfv->hide_deleted)
+ t->target.mask &= ~EM_POPUP_SELECT_DELETE;*/
+
+ return t;
+}
+
+void
+em_folder_view_set_hide_deleted(EMFolderView *emfv, gboolean status)
+{
+ if (emfv->folder && (emfv->folder->folder_flags & CAMEL_FOLDER_IS_TRASH))
+ status = FALSE;
+
+ emfv->hide_deleted = status;
+
+ if (emfv->folder) {
+ message_list_set_hidedeleted(emfv->list, status);
+ g_signal_emit(emfv, signals[EMFV_CHANGED], 0);
+ }
+}
+
+/* ********************************************************************** */
+
+struct mst_t {
+ EMFolderView *emfv;
+ gchar *uid;
+};
+
+static void
+mst_free (struct mst_t *mst)
+{
+ mst->emfv->list->seen_id = 0;
+
+ g_free (mst->uid);
+ g_free (mst);
+}
+
+static gint
+do_mark_seen (gpointer user_data)
+{
+ struct mst_t *mst = user_data;
+ EMFolderView *emfv = mst->emfv;
+ MessageList *list = emfv->list;
+
+ if (mst->uid && list->cursor_uid && !strcmp (mst->uid, list->cursor_uid))
+ emfv_set_seen (emfv, mst->uid);
+
+ return FALSE;
+}
+
+static void
+emfv_list_done_message_selected(CamelFolder *folder, const gchar *uid, CamelMimeMessage *msg, gpointer data, CamelException *ex)
+{
+ EMFolderView *emfv = data;
+ EMEvent *eme;
+ EMEventTargetMessage *target;
+ EShell *shell;
+
+ if (emfv->preview == NULL) {
+ emfv->priv->nomarkseen = FALSE;
+ emfv_enable_menus(emfv);
+ g_object_unref (emfv);
+ return;
+
+ }
+
+ e_profile_event_emit("goto.loaded", emfv->displayed_uid, 0);
+
+ shell = e_shell_backend_get_shell (mail_shell_backend);
+ e_shell_event (shell, "mail-icon", "evolution-mail");
+
+ /** @Event: message.reading
+ * @Title: Viewing a message
+ * @Target: EMEventTargetMessage
+ *
+ * message.reading is emitted whenever a user views a message.
+ */
+ /* TODO: do we emit a message.reading with no message when we're looking at nothing or don't care? */
+ eme = em_event_peek();
+ target = em_event_target_new_message(eme, folder, msg, uid, 0, NULL);
+ e_event_emit((EEvent *)eme, "message.reading", (EEventTarget *)target);
+
+ em_format_format((EMFormat *)emfv->preview, folder, uid, msg);
+
+ if (emfv->list->seen_id)
+ g_source_remove(emfv->list->seen_id);
+
+ if (msg && emfv->mark_seen && !emfv->priv->nomarkseen) {
+ if (emfv->mark_seen_timeout > 0) {
+ struct mst_t *mst;
+
+ mst = g_new (struct mst_t, 1);
+ mst->emfv = emfv;
+ mst->uid = g_strdup (uid);
+
+ emfv->list->seen_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, emfv->mark_seen_timeout,
+ (GSourceFunc)do_mark_seen, mst, (GDestroyNotify)mst_free);
+ } else {
+ emfv_set_seen (emfv, uid);
+ }
+ } else if (camel_exception_is_set(ex)) {
+ GtkHTMLStream *hstream = gtk_html_begin(((EMFormatHTML *)emfv->preview)->html);
+
+ /* Display the error inline rather than popping up an annoying box.
+ We also clear the exception, this stops the box popping up */
+
+ gtk_html_stream_printf(hstream, "<h2>%s</h2><p>%s</p>",
+ _("Unable to retrieve message"),
+ ex->desc);
+ gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK);
+ camel_exception_clear(ex);
+ }
+
+ emfv->priv->nomarkseen = FALSE;
+ emfv_enable_menus(emfv);
+ g_object_unref (emfv);
+}
+
+static gboolean
+emfv_message_selected_timeout(gpointer data)
+{
+ EMFolderView *emfv = data;
+
+ if (emfv->priv->selected_uid) {
+ if (emfv->displayed_uid == NULL || strcmp(emfv->displayed_uid, emfv->priv->selected_uid) != 0) {
+ /*GtkHTMLStream *hstream;*/
+
+ g_free(emfv->displayed_uid);
+ emfv->displayed_uid = emfv->priv->selected_uid;
+ emfv->priv->selected_uid = NULL;
+ g_object_ref (emfv);
+ /* TODO: we should manage our own thread stuff, would make cancelling outstanding stuff easier */
+ e_profile_event_emit("goto.load", emfv->displayed_uid, 0);
+ mail_get_messagex(emfv->folder, emfv->displayed_uid, emfv_list_done_message_selected, emfv, mail_msg_fast_ordered_push);
+ } else {
+ e_profile_event_emit("goto.empty", "", 0);
+ g_free(emfv->priv->selected_uid);
+ emfv->priv->selected_uid = NULL;
+ }
+ } else {
+ e_profile_event_emit("goto.empty", "", 0);
+ g_free(emfv->displayed_uid);
+ emfv->displayed_uid = NULL;
+ em_format_format((EMFormat *)emfv->preview, NULL, NULL, NULL);
+ emfv->priv->nomarkseen = FALSE;
+ }
+
+ emfv->priv->selected_id = 0;
+
+ return FALSE;
+}
+
+static gboolean
+emfv_popup_menu (GtkWidget *widget)
+{
+ gboolean ret = FALSE;
+ EMFolderView *emfv = (EMFolderView *)widget;
+
+ /* Try to bring up menu for preview html object.
+ Currently we cannot directly connect to html's "popup_menu" signal
+ since it doesn't work.
+ */
+
+ if (GTK_WIDGET_HAS_FOCUS (emfv->preview->formathtml.html))
+ ret = em_format_html_display_popup_menu (emfv->preview);
+
+ if (!ret)
+ emfv_popup (emfv, NULL, FALSE);
+
+ return TRUE;
+}
+
+//static void
+//emp_uri_popup_link_copy(EPopup *ep, EPopupItem *pitem, gpointer data)
+//{
+// EMFolderView *emfv = data;
+// struct _EMFolderViewPrivate *p = emfv->priv;
+//
+// g_free(p->selection_uri);
+// p->selection_uri = em_utils_url_unescape_amp(pitem->user_data);
+//
+// gtk_selection_owner_set(p->invisible, GDK_SELECTION_PRIMARY, gtk_get_current_event_time());
+// gtk_selection_owner_set(p->invisible, GDK_SELECTION_CLIPBOARD, gtk_get_current_event_time());
+//}
+
+static EPopupItem emfv_uri_popups[] = {
+// { E_POPUP_ITEM, (gchar *) "00.uri.15", (gchar *) N_("_Copy Link Location"), emp_uri_popup_link_copy, NULL, (gchar *) "edit-copy", EM_POPUP_URI_NOT_MAILTO },
+
+// { E_POPUP_SUBMENU, (gchar *) "99.uri.00", (gchar *) N_("Create _Search Folder"), NULL, NULL, NULL, EM_POPUP_URI_MAILTO },
+// { E_POPUP_ITEM, (gchar *) "99.uri.00/00.10", (gchar *) N_("_From this Address"), emp_uri_popup_vfolder_sender, NULL, NULL, EM_POPUP_URI_MAILTO },
+// { E_POPUP_ITEM, (gchar *) "99.uri.00/00.00", (gchar *) N_("_To this Address"), emp_uri_popup_vfolder_recipient, NULL, NULL, EM_POPUP_URI_MAILTO },
+};
+
+static void
+emfv_uri_popup_free(EPopup *ep, GSList *list, gpointer data)
+{
+ while (list) {
+ GSList *n = list->next;
+ struct _EPopupItem *item = list->data;
+
+ g_free(item->user_data);
+ item->user_data = NULL;
+ g_free (item);
+ g_slist_free_1(list);
+
+ list = n;
+ }
+}
+
+static void
+emfv_free_em_popup (gpointer emp)
+{
+ EPopup *ep = (EPopup *)emp;
+
+ if (!ep)
+ return;
+
+ if (ep->target) {
+ /* without this the next unref on ep does nothing */
+ e_popup_target_free (ep, ep->target);
+ ep->target = NULL;
+ }
+
+ g_object_unref (ep);
+}
+
+static GtkMenu *
+emfv_append_menu (EMPopup *des_emp, GtkMenu *des_menu, EMPopup *src_emp, GtkMenu *src_menu)
+{
+ GtkWidget *separator;
+ GList *children, *p;
+ gchar *name;
+
+ if (!src_menu)
+ return des_menu;
+
+ if (!des_menu)
+ return src_menu;
+
+ separator = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator);
+ gtk_menu_shell_append (GTK_MENU_SHELL (des_menu), separator);
+
+ children = gtk_container_get_children (GTK_CONTAINER (src_menu));
+ for (p = children; p; p = p->next) {
+ g_object_ref (p->data);
+ gtk_container_remove (GTK_CONTAINER (src_menu), p->data);
+ gtk_menu_shell_append (GTK_MENU_SHELL (des_menu), p->data);
+ g_object_unref (p->data);
+ }
+
+ g_list_free (children);
+ gtk_widget_destroy (GTK_WIDGET (src_menu));
+
+ /* free src_emp together with des_emp; name contains unique identifier */
+ name = g_strdup_printf ("emp_%p", (gpointer) src_emp);
+ g_object_set_data_full (G_OBJECT (des_emp), name, src_emp, emfv_free_em_popup);
+ g_free (name);
+
+ return des_menu;
+}
+
+static gint
+emfv_format_popup_event(EMFormatHTMLDisplay *efhd, GdkEventButton *event, const gchar *uri, CamelMimePart *part, EMFolderView *emfv)
+{
+ GtkMenu *menu = NULL;
+ EMPopup *main_emp = NULL;
+
+ if (uri == NULL && part == NULL) {
+ /* So we don't try and popup with nothing selected - rather odd result! */
+ GPtrArray *uids = message_list_get_selected(emfv->list);
+ gint doit = uids->len > 0;
+
+ message_list_free_uids(emfv->list, uids);
+ if (doit)
+ emfv_popup(emfv, (GdkEvent *)event, TRUE);
+ return doit;
+ }
+
+ /* FIXME: this maybe should just fit on em-html-display, it has access to the
+ snooped part type */
+
+ /** @HookPoint-EMPopup: Inline URI Context Menu
+ * @Id: org.gnome.evolution.mail.folderview.popup
+ * @Class: org.gnome.evolution.mail.popup:1.0
+ * @Target: EMPopupTargetURI
+ *
+ * This is the context menu shown when clicking on inline URIs,
+ * including addresses or normal HTML links that are displayed inside
+ * the message view.
+ */
+
+ /** @HookPoint-EMPopup: Inline Object Context Menu
+ * @Id: org.gnome.evolution.mail.folderview.popup
+ * @Class: org.gnome.evolution.mail.popup:1.0
+ * @Target: EMPopupTargetPart
+ *
+ * This is the context menu shown when clicking on inline
+ * content such as a picture.
+ */
+
+ if (uri) {
+ gboolean have_more_uris = strchr (uri, '\n') != NULL;
+ const gchar *act, *next;
+
+ for (act = uri; act; act = next) {
+ gchar *u;
+ next = strchr (act, '\n');
+ if (next) {
+ u = g_strndup (act, next - act);
+ next++;
+ } else
+ u = g_strdup (act);
+
+ if (u && *u) {
+ GSList *menus = NULL;
+ gint i;
+ EMPopupTargetURI *t;
+ EMPopup *emp;
+ EPopupTarget *target;
+ GtkMenu *mymenu;
+
+ emp = em_popup_new ("org.gnome.evolution.mail.folderview.popup");
+ t = em_popup_target_new_uri(emp, u);
+ target = (EPopupTarget *)t;
+
+ for (i = 0; i < sizeof (emfv_uri_popups)/sizeof (emfv_uri_popups[0]); i++) {
+ EPopupItem *itm = g_malloc0 (sizeof (EPopupItem));
+
+ memcpy (itm, &emfv_uri_popups[i], sizeof (EPopupItem));
+ itm->user_data = g_strdup (t->uri);
+ menus = g_slist_prepend (menus, itm);
+ }
+ e_popup_add_items ((EPopup *)emp, menus, NULL, emfv_uri_popup_free, emfv);
+ mymenu = e_popup_create_menu_once ((EPopup *)emp, target, 0);
+
+ if (have_more_uris) {
+ GtkWidget *item;
+
+ if (strlen (u) > 100) {
+ GString *str;
+ gchar *c;
+
+ /* the url should be in the form of http://a.b.c/... and we want to
+ see where the image comes from, so skip first 10 characters and
+ find the first '/' there */
+ c = strchr (u + 10, '/');
+ if (!c)
+ str = g_string_new_len (u, 40);
+ else
+ str = g_string_new_len (u, MAX (c - u + 1, 40));
+
+ g_string_append (str, "...");
+ g_string_append (str, u + strlen (u) - 40);
+
+ item = gtk_menu_item_new_with_label (str->str);
+
+ g_string_free (str, TRUE);
+ } else
+ item = gtk_menu_item_new_with_label (u);
+
+ gtk_widget_set_sensitive (item, FALSE);
+ gtk_widget_show (item);
+ gtk_menu_shell_insert (GTK_MENU_SHELL (mymenu), item, 0);
+ }
+
+ menu = emfv_append_menu (main_emp, menu, emp, mymenu);
+ if (!main_emp)
+ main_emp = emp;
+ }
+
+ g_free (u);
+ }
+ }
+
+ if (part) {
+ EMPopup *emp;
+ EPopupTarget *target;
+
+ emp = em_popup_new ("org.gnome.evolution.mail.folderview.popup");
+ target = (EPopupTarget *)em_popup_target_new_part(emp, part, NULL);
+
+ menu = emfv_append_menu (main_emp, menu, emp, e_popup_create_menu_once ((EPopup *)emp, target, 0));
+ if (!main_emp)
+ main_emp = emp;
+ }
+
+ if (event == NULL)
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
+ else
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time);
+
+ return TRUE;
+}
+
+static void
+emfv_set_seen(EMFolderView *emfv, const gchar *uid)
+{
+ guint32 old_flags = camel_folder_get_message_flags(emfv->folder, uid);
+
+ /* If we're setting the SEEN flag on a message, handle receipt requests */
+ if (!(old_flags & CAMEL_MESSAGE_SEEN))
+ em_utils_handle_receipt(emfv->folder, uid, (CamelMimeMessage *)((EMFormat *)emfv->preview)->message);
+
+ camel_folder_set_message_flags(emfv->folder, uid, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
+}
+
+/* keep these two tables in sync */
+enum {
+ EMFV_CHARSET = 1,
+ EMFV_HEADERS,
+ EMFV_SHOW_DELETED,
+ EMFV_SETTINGS /* last, for loop count */
+};
+
+/* IF these get too long, update key field */
+static const gchar * const emfv_display_keys[] = {
+ "charset",
+ "headers",
+ "show_deleted",
+};
+
+static GHashTable *emfv_setting_key;
+
+static void
+emfv_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, EMFolderView *emfv)
+{
+ GConfValue *value;
+ gchar *tkey;
+
+ g_return_if_fail (gconf_entry_get_key (entry) != NULL);
+
+ if (!(value = gconf_entry_get_value (entry)))
+ return;
+
+ tkey = strrchr(entry->key, '/');
+ g_return_if_fail (tkey != NULL);
+
+ switch (GPOINTER_TO_INT(g_hash_table_lookup(emfv_setting_key, tkey+1))) {
+ case EMFV_CHARSET:
+ em_format_set_default_charset((EMFormat *)emfv->preview, gconf_value_get_string (value));
+ break;
+ case EMFV_HEADERS: {
+ GSList *header_config_list, *p;
+ EMFormat *emf = (EMFormat *)emfv->preview;
+
+ header_config_list = gconf_client_get_list(gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, NULL);
+ em_format_clear_headers((EMFormat *)emfv->preview);
+ p = header_config_list;
+ while (p) {
+ EMMailerPrefsHeader *h;
+ gchar *xml = (gchar *)p->data;
+
+ h = em_mailer_prefs_header_from_xml(xml);
+ if (h && h->enabled) {
+ em_format_add_header(emf, h->name, EM_FORMAT_HEADER_BOLD);
+ }
+ em_mailer_prefs_header_free(h);
+ p = g_slist_next(p);
+ }
+ g_slist_foreach(header_config_list, (GFunc) g_free, NULL);
+ g_slist_free(header_config_list);
+ /* force a redraw */
+ if (emf->message)
+ em_format_redraw(emf);
+ break; }
+ case EMFV_SHOW_DELETED: {
+ gboolean state;
+
+ state = gconf_value_get_bool (value);
+ em_folder_view_set_hide_deleted (emfv, !state);
+ /* Set the prop only if the component has already been
+ * activated. */
+ if (emfv->uic)
+ bonobo_ui_component_set_prop (emfv->uic, "/commands/HideDeleted", "state", state ? "0" : "1", NULL);
+ break; }
+ }
+}