talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

messageview.c (78337B)


      1 /*
      2  * Claws Mail -- a GTK based, lightweight, and fast e-mail client
      3  * Copyright (C) 1999-2025 the Claws Mail team and Hiroyuki Yamamoto
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 3 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #include "defs.h"
     20 
     21 #include <glib.h>
     22 #include <glib/gi18n.h>
     23 #include <gdk/gdkkeysyms.h>
     24 #include <gtk/gtk.h>
     25 #include <stdio.h>
     26 #include <ctype.h>
     27 #include <string.h>
     28 
     29 #include "main.h"
     30 #include "messageview.h"
     31 #include "message_search.h"
     32 #include "summaryview.h"
     33 #include "textview.h"
     34 #include "mimeview.h"
     35 #include "menu.h"
     36 #include "filesel.h"
     37 #include "foldersel.h"
     38 #include "sourcewindow.h"
     39 #include "alertpanel.h"
     40 #include "inputdialog.h"
     41 #include "mainwindow.h"
     42 #include "manage_window.h"
     43 #include "procmsg.h"
     44 #include "procheader.h"
     45 #include "procmime.h"
     46 #include "account.h"
     47 #include "action.h"
     48 #include "prefs_common.h"
     49 #include "prefs_account.h"
     50 #include "gtkutils.h"
     51 #include "utils.h"
     52 #include "send_message.h"
     53 #include "stock_pixmap.h"
     54 #include "hooks.h"
     55 #include "inc.h"
     56 #include "log.h"
     57 #include "combobox.h"
     58 #include "quoted-printable.h"
     59 #include "version.h"
     60 #include "statusbar.h"
     61 #include "folder_item_prefs.h"
     62 #include "file-utils.h"
     63 
     64 #include "addressbook.h"
     65 static GList *messageview_list = NULL;
     66 
     67 static gint messageview_delete_cb	(GtkWidget		*widget,
     68 					 GdkEventAny		*event,
     69 					 MessageView		*messageview);
     70 static void messageview_size_allocate_cb(GtkWidget	*widget,
     71 					 GtkAllocation	*allocation);
     72 static gboolean key_pressed		(GtkWidget	*widget,
     73 					 GdkEventKey	*event,
     74 					 MessageView	*messageview);
     75 
     76 static void save_as_cb			(GtkAction	*action,
     77 					 gpointer	 data);
     78 void messageview_save_as		(MessageView *messageview);
     79 static void close_cb			(GtkAction	*action,
     80 					 gpointer	 data);
     81 static void copy_cb			(GtkAction	*action,
     82 					 gpointer	 data);
     83 static void allsel_cb			(GtkAction	*action,
     84 					 gpointer	 data);
     85 static void search_cb			(GtkAction	*action,
     86 					 gpointer	 data);
     87 
     88 static void prev_cb			(GtkAction	*action,
     89 					 gpointer	 data);
     90 static void next_cb			(GtkAction	*action,
     91 					 gpointer	 data);
     92 static void prev_unread_cb		(GtkAction	*action,
     93 					 gpointer	 data);
     94 static void next_unread_cb		(GtkAction	*action,
     95 					 gpointer	 data);
     96 static void prev_new_cb			(GtkAction	*action,
     97 					 gpointer	 data);
     98 static void next_new_cb			(GtkAction	*action,
     99 					 gpointer	 data);
    100 static void prev_marked_cb		(GtkAction	*action,
    101 					 gpointer	 data);
    102 static void next_marked_cb		(GtkAction	*action,
    103 					 gpointer	 data);
    104 static void prev_labeled_cb		(GtkAction	*action,
    105 					 gpointer	 data);
    106 static void next_labeled_cb		(GtkAction	*action,
    107 					 gpointer	 data);
    108 static void prev_history_cb		(GtkAction	*action,
    109 					 gpointer	 data);
    110 static void next_history_cb		(GtkAction	*action,
    111 					 gpointer	 data);
    112 static void parent_cb			(GtkAction	*action,
    113 					 gpointer	 data);
    114 static void goto_unread_folder_cb	(GtkAction	*action,
    115 					 gpointer	 data);
    116 static void goto_folder_cb		(GtkAction	*action,
    117 					 gpointer	 data);
    118 
    119 static void set_charset_cb		(GtkAction *action, GtkRadioAction *current, gpointer data);
    120 static void set_decode_cb		(GtkAction *action, GtkRadioAction *current, gpointer data);
    121 
    122 static void view_source_cb		(GtkAction	*action,
    123 					 gpointer	 data);
    124 
    125 static void show_all_header_cb		(GtkToggleAction	*action,
    126 					 gpointer	 data);
    127 static void msg_hide_quotes_cb		(GtkToggleAction	*action,
    128 					 gpointer	 data);
    129 
    130 static void compose_cb			(GtkAction	*action,
    131 					 gpointer	 data);
    132 static void reply_cb			(GtkAction	*action,
    133 					 gpointer	 data);
    134 
    135 static void addressbook_open_cb		(GtkAction	*action,
    136 					 gpointer	 data);
    137 static void add_address_cb		(GtkAction	*action,
    138 					 gpointer	 data);
    139 
    140 static void messageview_update		(MessageView	*msgview,
    141 					 MsgInfo	*old_msginfo);
    142 static gboolean messageview_update_msg	(gpointer source, gpointer data);
    143 
    144 static void save_part_as_cb(GtkAction *action, gpointer data);
    145 static void view_part_as_text_cb(GtkAction *action, gpointer data);
    146 static void open_part_cb(GtkAction *action, gpointer data);
    147 static void open_part_with_cb(GtkAction *action, gpointer data);
    148 static void goto_next_part_cb(GtkAction *action, gpointer data);
    149 static void goto_prev_part_cb(GtkAction *action, gpointer data);
    150 
    151 static void messageview_nothing_cb	   (GtkAction *action, gpointer data)
    152 {
    153 }
    154 
    155 static GList *msgview_list = NULL;
    156 static GtkActionEntry msgview_entries[] =
    157 {
    158 	{"Menu",                                     NULL, "Menu", NULL, NULL, NULL },
    159 /* menus */
    160 	{"File",                                     NULL, N_("_File"), NULL, NULL, NULL },
    161 	{"Edit",                                     NULL, N_("_Edit"), NULL, NULL, NULL },
    162 	{"View",                                     NULL, N_("_View"), NULL, NULL, NULL },
    163 	{"Message",                                  NULL, N_("_Message"), NULL, NULL, NULL },
    164 	{"Tools",                                    NULL, N_("_Tools"), NULL, NULL, NULL },
    165 	{"Help",                                     NULL, N_("_Help"), NULL, NULL, NULL },
    166 	{"PlaceHolder",                              NULL, "Placeholder", NULL, NULL, G_CALLBACK(messageview_nothing_cb) },
    167 
    168 /* File menu */
    169 	{"File/SaveAs",                              NULL, N_("_Save email as..."), "<control>S", NULL, G_CALLBACK(save_as_cb) },
    170 	{"File/SavePartAs",                          NULL, N_("_Save part as..."), "Y", NULL, G_CALLBACK(save_part_as_cb) },
    171 	{"File/---",                                 NULL, "---", NULL, NULL, NULL },
    172 	{"File/Close",                               NULL, N_("_Close"), "<control>W", NULL, G_CALLBACK(close_cb) },
    173 
    174 /* Edit menu */
    175 	{"Edit/Copy",                                NULL, N_("_Copy"), "<control>C", NULL, G_CALLBACK(copy_cb) },
    176 	{"Edit/SelectAll",                           NULL, N_("_Select all"), "<control>A", NULL, G_CALLBACK(allsel_cb) },
    177 	{"Edit/---",                                 NULL, "---", NULL, NULL, NULL },
    178 	{"Edit/Find",                                NULL, N_("_Find"), "<control>F", NULL, G_CALLBACK(search_cb) },
    179 
    180 /* View menu */
    181 	{"View/Goto",                                NULL, N_("_Go to"), NULL, NULL, NULL },
    182 	{"View/Goto/Prev",                           NULL, N_("_Previous message"), "P", NULL, G_CALLBACK(prev_cb) },
    183 	{"View/Goto/Next",                           NULL, N_("_Next message"), "N", NULL, G_CALLBACK(next_cb) },
    184 	{"View/Goto/---",                            NULL, "---", NULL, NULL, NULL },
    185 	{"View/Goto/PrevUnread",                     NULL, N_("P_revious unread message"), "<shift>P", NULL, G_CALLBACK(prev_unread_cb) },
    186 	{"View/Goto/NextUnread",                     NULL, N_("N_ext unread message"), "<shift>N", NULL, G_CALLBACK(next_unread_cb) },
    187 	/* {"View/Goto/---",                         NULL, "---", NULL, NULL, NULL }, */
    188 	{"View/Goto/PrevNew",                        NULL, N_("Previous ne_w message"), NULL, NULL, G_CALLBACK(prev_new_cb) },
    189 	{"View/Goto/NextNew",                        NULL, N_("Ne_xt new message"), NULL, NULL, G_CALLBACK(next_new_cb) },
    190 	/* {"View/Goto/---",                         NULL, "---", NULL, NULL, NULL }, */
    191 	{"View/Goto/PrevMarked",                     NULL, N_("Previous _marked message"), NULL, NULL, G_CALLBACK(prev_marked_cb) },
    192 	{"View/Goto/NextMarked",                     NULL, N_("Next m_arked message"), NULL, NULL, G_CALLBACK(next_marked_cb) },
    193 	/* {"View/Goto/---",                         NULL, "---", NULL, NULL, NULL }, */
    194 	{"View/Goto/PrevLabeled",                    NULL, N_("Previous _labeled message"), NULL, NULL, G_CALLBACK(prev_labeled_cb) },
    195 	{"View/Goto/NextLabeled",                    NULL, N_("Next la_beled message"), NULL, NULL, G_CALLBACK(next_labeled_cb) },
    196 	/* {"View/Goto/---",                         NULL, "---", NULL, NULL, NULL }, */
    197 	{"View/Goto/PrevHistory",                    NULL, N_("Previously opened message"), "<alt>Left", NULL, G_CALLBACK(prev_history_cb) },
    198 	{"View/Goto/NextHistory",                    NULL, N_("Next opened message"), "<alt>Right", NULL, G_CALLBACK(next_history_cb) },
    199 	/* {"View/Goto/---",                         NULL, "---", NULL, NULL, NULL }, */
    200 	{"View/Goto/ParentMessage",                  NULL, N_("Parent message"), "<control>Up", NULL, G_CALLBACK(parent_cb) },
    201 	/* {"View/Goto/---",                         NULL, "---", NULL, NULL, NULL }, */
    202 	{"View/Goto/NextUnreadFolder",               NULL, N_("Next unread _folder"), "<shift>G", NULL, G_CALLBACK(goto_unread_folder_cb) },
    203 	{"View/Goto/Folder",                         NULL, N_("F_older..."), "G", NULL, G_CALLBACK(goto_folder_cb) },
    204 	/* {"View/Goto/---",                         NULL, "---", NULL, NULL, NULL }, */
    205 	{"View/Goto/NextPart",                       NULL, N_("Next part"), "A", NULL, G_CALLBACK(goto_next_part_cb) },
    206 	{"View/Goto/PrevPart",                       NULL, N_("Previous part"), "Z", NULL, G_CALLBACK(goto_prev_part_cb) },
    207 
    208 	{"View/Encoding",                            NULL, N_("Character _encoding"), NULL, NULL, NULL }, /* set_charset_cb */
    209 	{"View/Encoding/---",                        NULL, "---", NULL, NULL, NULL },
    210 #define ENC_ACTION(cs_char,c_char,string) \
    211 	{ "View/Encoding/" cs_char, NULL, N_(string), NULL, NULL, c_char }
    212 
    213 	{"View/Encoding/Western",                    NULL, N_("Western European"), NULL, NULL, NULL },
    214 	{"View/Encoding/Baltic",                     NULL, N_("Baltic"), NULL, NULL, NULL },
    215 	{"View/Encoding/Hebrew",                     NULL, N_("Hebrew"), NULL, NULL, NULL },
    216 	{"View/Encoding/Arabic",                     NULL, N_("Arabic"), NULL, NULL, NULL },
    217 	{"View/Encoding/Cyrillic",                   NULL, N_("Cyrillic"), NULL, NULL, NULL },
    218 	{"View/Encoding/Japanese",                   NULL, N_("Japanese"), NULL, NULL, NULL },
    219 	{"View/Encoding/Chinese",                    NULL, N_("Chinese"), NULL, NULL, NULL },
    220 	{"View/Encoding/Korean",                     NULL, N_("Korean"), NULL, NULL, NULL },
    221 	{"View/Encoding/Thai",                       NULL, N_("Thai"), NULL, NULL, NULL },
    222 
    223 	{"View/Decode",                              NULL, N_("Decode"), NULL, NULL, NULL }, /* set_decode_cb */
    224 	{"View/Decode/---",                          NULL, "---", NULL, NULL, NULL },
    225 
    226 #define DEC_ACTION(cs_type,c_type,string) \
    227 	{ "View/Decode/" cs_type, NULL, N_(string), NULL, NULL, c_type }
    228 
    229 	{"View/---",                                 NULL, "---", NULL, NULL, NULL },
    230 	{"View/MessageSource",                       NULL, N_("Mess_age source"), "<control>U", NULL, G_CALLBACK(view_source_cb) },
    231 	{"View/Part",                                NULL, N_("Message part"), NULL, NULL, NULL },
    232 	{"View/Part/AsText",                         NULL, N_("View as text"), "T", NULL, G_CALLBACK(view_part_as_text_cb) },
    233 	{"View/Part/Open",                           NULL, N_("Open"), "L", NULL, G_CALLBACK(open_part_cb) },
    234 	{"View/Part/OpenWith",                       NULL, N_("Open with..."), "O", NULL, G_CALLBACK(open_part_with_cb) },
    235 
    236 	{"View/Quotes",                              NULL, N_("Quotes"), NULL, NULL, NULL },
    237 
    238 /* Message menu */
    239 	{"Message/Compose",                          NULL, N_("Write _new message"), "<control>M", NULL, G_CALLBACK(compose_cb) },
    240 	{"Message/---",                              NULL, "---", NULL, NULL, NULL },
    241 
    242 	{"Message/Reply",                            NULL, N_("_Reply"), "<control>R", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY */
    243 	{"Message/ReplyTo",                          NULL, N_("Repl_y to"), NULL, NULL, NULL },
    244 	{"Message/ReplyTo/All",                      NULL, N_("_All"), "<control><shift>R", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY_TO_ALL */
    245 	{"Message/ReplyTo/Sender",                   NULL, N_("_Sender"), NULL, NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY_TO_SENDER */
    246 	{"Message/ReplyTo/List",                     NULL, N_("Mailing _list"), "<control>L", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY_TO_LIST */
    247 	/* {"Message/---",                           NULL, "---", NULL, NULL, NULL }, */
    248 
    249 	{"Message/Forward",                          NULL, N_("_Forward"), "<control><alt>F", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_FORWARD_INLINE */
    250 	{"Message/ForwardAtt",                       NULL, N_("For_ward as attachment"), NULL, NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_FORWARD_AS_ATTACH */
    251 	{"Message/Redirect",                         NULL, N_("Redirec_t"), NULL, NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REDIRECT */
    252 
    253 /* Tools menu */
    254 	{"Tools/AddressBook",                        NULL, N_("_Address book"), "<control><shift>A", NULL, G_CALLBACK(addressbook_open_cb) },
    255 	{"Tools/AddSenderToAB",                      NULL, N_("Add sender to address boo_k"), NULL, NULL, G_CALLBACK(add_address_cb) },
    256 	{"Tools/---",                                NULL, "---", NULL, NULL, NULL },
    257 
    258 	/* {"Tools/---",                             NULL, "---", NULL, NULL, NULL }, */
    259 	{"Tools/Actions",                            NULL, N_("Actio_ns"), NULL, NULL, NULL },
    260 	{"Tools/Actions/PlaceHolder",                NULL, "Placeholder", NULL, NULL, G_CALLBACK(messageview_nothing_cb) },
    261 };
    262 
    263 static GtkToggleActionEntry msgview_toggle_entries[] =
    264 {
    265 	{"View/AllHeaders",         NULL, N_("Show all _headers"), "<control>H", NULL, G_CALLBACK(show_all_header_cb), FALSE }, /* toggle */
    266 	{"View/Quotes/CollapseAll", NULL, N_("_Collapse all"), "<control><shift>Q", NULL, G_CALLBACK(msg_hide_quotes_cb), FALSE }, /* 1 toggle */
    267 	{"View/Quotes/Collapse2",   NULL, N_("Collapse from level _2"), NULL, NULL, G_CALLBACK(msg_hide_quotes_cb), FALSE }, /* 2 toggle */
    268 	{"View/Quotes/Collapse3",   NULL, N_("Collapse from level _3"), NULL, NULL, G_CALLBACK(msg_hide_quotes_cb), FALSE }, /* 3 toggle */
    269 };
    270 
    271 static GtkRadioActionEntry msgview_radio_enc_entries[] =
    272 {
    273 	ENC_ACTION(CS_AUTO, C_AUTO, N_("_Automatic")), /* RADIO set_charset_cb */
    274 	ENC_ACTION(CS_US_ASCII, C_US_ASCII, N_("7bit ASCII (US-ASC_II)")), /* RADIO set_charset_cb */
    275 	ENC_ACTION(CS_UTF_8, C_UTF_8, N_("Unicode (_UTF-8)")), /* RADIO set_charset_cb */
    276 	ENC_ACTION("Western/"CS_ISO_8859_1, C_ISO_8859_1, "ISO-8859-_1"), /* RADIO set_charset_cb */
    277 	ENC_ACTION("Western/"CS_ISO_8859_15, C_ISO_8859_15, "ISO-8859-15"), /* RADIO set_charset_cb */
    278 	ENC_ACTION("Western/"CS_WINDOWS_1252, C_WINDOWS_1252, "Windows-1252"), /* RADIO set_charset_cb */
    279 	ENC_ACTION(CS_ISO_8859_2, C_ISO_8859_2, N_("Central European (ISO-8859-_2)")), /* RADIO set_charset_cb */
    280 	ENC_ACTION("Baltic/"CS_ISO_8859_13, C_ISO_8859_13, "ISO-8859-13"), /* RADIO set_charset_cb */
    281 	ENC_ACTION("Baltic/"CS_ISO_8859_4, C_ISO_8859_14, "ISO-8859-_4"), /* RADIO set_charset_cb */
    282 	ENC_ACTION(CS_ISO_8859_7, C_ISO_8859_7, N_("Greek (ISO-8859-_7)")), /* RADIO set_charset_cb */
    283 	ENC_ACTION("Hebrew/"CS_ISO_8859_8, C_ISO_8859_8, "ISO-8859-_8"), /* RADIO set_charset_cb */
    284 	ENC_ACTION("Hebrew/"CS_WINDOWS_1255, C_WINDOWS_1255, "Windows-1255"), /* RADIO set_charset_cb */
    285 	ENC_ACTION("Arabic/"CS_ISO_8859_6, C_ISO_8859_6, "ISO-8859-_6"), /* RADIO set_charset_cb */
    286 	ENC_ACTION("Arabic/"CS_WINDOWS_1256, C_WINDOWS_1256, "Windows-1256"), /* RADIO set_charset_cb */
    287 	ENC_ACTION(CS_ISO_8859_9, C_ISO_8859_9, N_("Turkish (ISO-8859-_9)")), /* RADIO set_charset_cb */
    288 	ENC_ACTION("Cyrillic/"CS_ISO_8859_5, C_ISO_8859_5, "ISO-8859-_5"), /* RADIO set_charset_cb */
    289 	ENC_ACTION("Cyrillic/"CS_KOI8_R, C_KOI8_R, "KOI8-_R"), /* RADIO set_charset_cb */
    290 	ENC_ACTION("Cyrillic/"CS_MACCYR, C_MACCYR, "MAC_CYR"), /* RADIO set_charset_cb */
    291 	ENC_ACTION("Cyrillic/"CS_KOI8_U, C_KOI8_U, "KOI8-_U"), /* RADIO set_charset_cb */
    292 	ENC_ACTION("Cyrillic/"CS_WINDOWS_1251, C_WINDOWS_1251, "Windows-1251"), /* RADIO set_charset_cb */
    293 	ENC_ACTION("Japanese/"CS_ISO_2022_JP, C_ISO_2022_JP, "ISO-2022-_JP"), /* RADIO set_charset_cb */
    294 	ENC_ACTION("Japanese/"CS_ISO_2022_JP_2, C_ISO_2022_JP_2, "ISO-2022-JP-_2"), /* RADIO set_charset_cb */
    295 	ENC_ACTION("Japanese/"CS_EUC_JP, C_EUC_JP, "_EUC-JP"), /* RADIO set_charset_cb */
    296 	ENC_ACTION("Japanese/"CS_SHIFT_JIS, C_SHIFT_JIS, "_Shift-JIS"), /* RADIO set_charset_cb */
    297 	ENC_ACTION("Chinese/"CS_GB18030, C_GB18030, "_GB18030"), /* RADIO set_charset_cb */
    298 	ENC_ACTION("Chinese/"CS_GB2312, C_GB2312, "_GB2312"), /* RADIO set_charset_cb */
    299 	ENC_ACTION("Chinese/"CS_GBK, C_GBK, "GB_K"), /* RADIO set_charset_cb */
    300 	ENC_ACTION("Chinese/"CS_BIG5, C_BIG5, "_Big5-JP"), /* RADIO set_charset_cb */
    301 	ENC_ACTION("Chinese/"CS_EUC_TW, C_EUC_TW, "EUC-_TW"), /* RADIO set_charset_cb */
    302 	ENC_ACTION("Korean/"CS_EUC_KR, C_EUC_KR, "_EUC-KR"), /* RADIO set_charset_cb */
    303 	ENC_ACTION("Korean/"CS_ISO_2022_KR, C_ISO_2022_KR, "_ISO-2022-KR"), /* RADIO set_charset_cb */
    304 	ENC_ACTION("Thai/"CS_TIS_620, C_TIS_620, "_TIS-620-KR"), /* RADIO set_charset_cb */
    305 	ENC_ACTION("Thai/"CS_WINDOWS_874, C_WINDOWS_874, "_Windows-874"), /* RADIO set_charset_cb */
    306 };
    307 
    308 static GtkRadioActionEntry msgview_radio_dec_entries[] =
    309 {
    310 	DEC_ACTION("AutoDetect", 0, N_("_Auto detect")),	/* set_decode_cb */
    311 	/* --- */
    312 	DEC_ACTION("8bit", ENC_8BIT, "_8bit"),
    313 	DEC_ACTION("QP", ENC_QUOTED_PRINTABLE, "_Quoted printable"),
    314 	DEC_ACTION("B64", ENC_BASE64, "_Base64"),
    315 	DEC_ACTION("Uuencode", ENC_X_UUENCODE, "_Uuencode"),
    316 };
    317 
    318 MessageView *messageview_create(MainWindow *mainwin)
    319 {
    320 	MessageView *messageview = g_new0(MessageView, 1);
    321 
    322 	MimeView *mimeview = mimeview_create(mainwin);
    323 	mimeview->textview = textview_create();
    324 	mimeview->textview->messageview = messageview;
    325 	mimeview->messageview = messageview;
    326 
    327 	GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    328 	gtk_widget_set_name(GTK_WIDGET(vbox), "messageview");
    329 	gtk_box_pack_start(GTK_BOX(vbox),
    330                            GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
    331 	gtk_widget_show(vbox);
    332 
    333 	messageview->vbox        = vbox;
    334 	messageview->new_window  = FALSE;
    335 	messageview->window      = NULL;
    336 	messageview->mimeview    = mimeview;
    337 	messageview->mainwin    = mainwin;
    338 
    339 	messageview->statusbar     = NULL;
    340 	messageview->statusbar_cid = 0;
    341 
    342 	messageview->show_full_text= FALSE;
    343 	messageview->update_needed = FALSE;
    344 
    345 	messageview->msginfo_update_callback_id =
    346 		hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, messageview_update_msg, (gpointer) messageview);
    347 
    348 	return messageview;
    349 }
    350 
    351 const GList *messageview_get_msgview_list(void)
    352 {
    353 	return msgview_list;
    354 }
    355 
    356 void messageview_update_actions_menu(MessageView *msgview)
    357 {
    358 	/* Messages opened in a new window do not have a menu bar */
    359 	if (msgview->menubar == NULL)
    360 		return;
    361 	action_update_msgview_menu(msgview->ui_manager, "/Menu/Tools/Actions", msgview);
    362 }
    363 
    364 static void messageview_add_toolbar(MessageView *msgview, GtkWidget *window)
    365 {
    366  	GtkWidget *handlebox;
    367 	GtkWidget *vbox;
    368 	GtkWidget *menubar;
    369 	GtkWidget *statusbar = NULL;
    370 	GtkActionGroup *action_group;
    371 
    372 	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    373 	gtk_widget_show(vbox);
    374 	gtk_container_add(GTK_CONTAINER(window), vbox);
    375 
    376 	msgview->ui_manager = gtk_ui_manager_new();
    377 	action_group = cm_menu_create_action_group_full(msgview->ui_manager,"Menu", msgview_entries,
    378 			G_N_ELEMENTS(msgview_entries), (gpointer)msgview);
    379 	gtk_action_group_add_toggle_actions(action_group, msgview_toggle_entries,
    380 			G_N_ELEMENTS(msgview_toggle_entries), (gpointer)msgview);
    381 	gtk_action_group_add_radio_actions(action_group, msgview_radio_enc_entries,
    382 			G_N_ELEMENTS(msgview_radio_enc_entries), C_AUTO, G_CALLBACK(set_charset_cb), (gpointer)msgview);
    383 	gtk_action_group_add_radio_actions(action_group, msgview_radio_dec_entries,
    384 			G_N_ELEMENTS(msgview_radio_dec_entries), C_AUTO, G_CALLBACK(set_decode_cb), (gpointer)msgview);
    385 
    386 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_MENUBAR)
    387 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "File", "File", GTK_UI_MANAGER_MENU)
    388 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "Edit", "Edit", GTK_UI_MANAGER_MENU)
    389 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "View", "View", GTK_UI_MANAGER_MENU)
    390 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "Message", "Message", GTK_UI_MANAGER_MENU)
    391 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "Tools", "Tools", GTK_UI_MANAGER_MENU)
    392 
    393 /* File menu */
    394 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "SaveAs", "File/SaveAs", GTK_UI_MANAGER_MENUITEM)
    395 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "SavePartAs", "File/SavePartAs", GTK_UI_MANAGER_MENUITEM)
    396 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "Separator1", "File/---", GTK_UI_MANAGER_SEPARATOR)
    397 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "Separator2", "File/---", GTK_UI_MANAGER_SEPARATOR)
    398 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "Close", "File/Close", GTK_UI_MANAGER_MENUITEM)
    399 
    400 /* Edit menu */
    401 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "Copy", "Edit/Copy", GTK_UI_MANAGER_MENUITEM)
    402 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "SelectAll", "Edit/SelectAll", GTK_UI_MANAGER_MENUITEM)
    403 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "Separator1", "Edit/---", GTK_UI_MANAGER_SEPARATOR)
    404 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "Find", "Edit/Find", GTK_UI_MANAGER_MENUITEM)
    405 
    406 /* View menu */
    407 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Goto", "View/Goto", GTK_UI_MANAGER_MENU)
    408 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Prev", "View/Goto/Prev", GTK_UI_MANAGER_MENUITEM)
    409 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Next", "View/Goto/Next", GTK_UI_MANAGER_MENUITEM)
    410 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator1", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    411 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevUnread", "View/Goto/PrevUnread", GTK_UI_MANAGER_MENUITEM)
    412 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextUnread", "View/Goto/NextUnread", GTK_UI_MANAGER_MENUITEM)
    413 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator2", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    414 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevNew", "View/Goto/PrevNew", GTK_UI_MANAGER_MENUITEM)
    415 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextNew", "View/Goto/NextNew", GTK_UI_MANAGER_MENUITEM)
    416 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator3", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    417 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevMarked", "View/Goto/PrevMarked", GTK_UI_MANAGER_MENUITEM)
    418 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextMarked", "View/Goto/NextMarked", GTK_UI_MANAGER_MENUITEM)
    419 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator4", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    420 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevLabeled", "View/Goto/PrevLabeled", GTK_UI_MANAGER_MENUITEM)
    421 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextLabeled", "View/Goto/NextLabeled", GTK_UI_MANAGER_MENUITEM)
    422 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator5", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    423 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevHistory", "View/Goto/PrevHistory", GTK_UI_MANAGER_MENUITEM)
    424 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextHistory", "View/Goto/NextHistory", GTK_UI_MANAGER_MENUITEM)
    425 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator6", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    426 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "ParentMessage", "View/Goto/ParentMessage", GTK_UI_MANAGER_MENUITEM)
    427 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator7", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    428 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextUnreadFolder", "View/Goto/NextUnreadFolder", GTK_UI_MANAGER_MENUITEM)
    429 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Folder", "View/Goto/Folder", GTK_UI_MANAGER_MENUITEM)
    430 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator8", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
    431 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextPart", "View/Goto/NextPart", GTK_UI_MANAGER_MENUITEM)
    432 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevPart", "View/Goto/PrevPart", GTK_UI_MANAGER_MENUITEM)
    433 
    434 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Separator1", "View/---", GTK_UI_MANAGER_SEPARATOR)
    435 
    436 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Encoding", "View/Encoding", GTK_UI_MANAGER_MENU)
    437 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_AUTO, "View/Encoding/"CS_AUTO, GTK_UI_MANAGER_MENUITEM)
    438 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Separator1", "View/Encoding/---", GTK_UI_MANAGER_SEPARATOR)
    439 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_US_ASCII, "View/Encoding/"CS_US_ASCII, GTK_UI_MANAGER_MENUITEM)
    440 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_UTF_8, "View/Encoding/"CS_UTF_8, GTK_UI_MANAGER_MENUITEM)
    441 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Separator2", "View/Encoding/---", GTK_UI_MANAGER_SEPARATOR)
    442 
    443 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Western", "View/Encoding/Western", GTK_UI_MANAGER_MENU)
    444 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Western", CS_ISO_8859_1, "View/Encoding/Western/"CS_ISO_8859_1, GTK_UI_MANAGER_MENUITEM)
    445 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Western", CS_ISO_8859_15, "View/Encoding/Western/"CS_ISO_8859_15, GTK_UI_MANAGER_MENUITEM)
    446 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Western", CS_WINDOWS_1252, "View/Encoding/Western/"CS_WINDOWS_1252, GTK_UI_MANAGER_MENUITEM)
    447 
    448 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_ISO_8859_2, "View/Encoding/"CS_ISO_8859_2, GTK_UI_MANAGER_MENUITEM)
    449 
    450 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Baltic", "View/Encoding/Baltic", GTK_UI_MANAGER_MENU)
    451 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Baltic", CS_ISO_8859_13, "View/Encoding/Baltic/"CS_ISO_8859_13, GTK_UI_MANAGER_MENUITEM)
    452 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Baltic", CS_ISO_8859_4, "View/Encoding/Baltic/"CS_ISO_8859_4, GTK_UI_MANAGER_MENUITEM)
    453 
    454 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_ISO_8859_7, "View/Encoding/"CS_ISO_8859_7, GTK_UI_MANAGER_MENUITEM)
    455 
    456 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Hebrew", "View/Encoding/Hebrew", GTK_UI_MANAGER_MENU)
    457 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Hebrew", CS_ISO_8859_8, "View/Encoding/Hebrew/"CS_ISO_8859_8, GTK_UI_MANAGER_MENUITEM)
    458 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Hebrew", CS_WINDOWS_1255, "View/Encoding/Hebrew/"CS_WINDOWS_1255, GTK_UI_MANAGER_MENUITEM)
    459 
    460 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Arabic", "View/Encoding/Arabic", GTK_UI_MANAGER_MENU)
    461 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Arabic", CS_ISO_8859_6, "View/Encoding/Arabic/"CS_ISO_8859_6, GTK_UI_MANAGER_MENUITEM)
    462 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Arabic", CS_WINDOWS_1256, "View/Encoding/Arabic/"CS_WINDOWS_1256, GTK_UI_MANAGER_MENUITEM)
    463 
    464 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_ISO_8859_9, "View/Encoding/"CS_ISO_8859_9, GTK_UI_MANAGER_MENUITEM)
    465 
    466 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Cyrillic", "View/Encoding/Cyrillic", GTK_UI_MANAGER_MENU)
    467 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_ISO_8859_5, "View/Encoding/Cyrillic/"CS_ISO_8859_5, GTK_UI_MANAGER_MENUITEM)
    468 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_KOI8_R, "View/Encoding/Cyrillic/"CS_KOI8_R, GTK_UI_MANAGER_MENUITEM)
    469 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_MACCYR, "View/Encoding/Cyrillic/"CS_MACCYR, GTK_UI_MANAGER_MENUITEM)
    470 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_KOI8_U, "View/Encoding/Cyrillic/"CS_KOI8_U, GTK_UI_MANAGER_MENUITEM)
    471 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_WINDOWS_1251, "View/Encoding/Cyrillic/"CS_WINDOWS_1251, GTK_UI_MANAGER_MENUITEM)
    472 
    473 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Japanese", "View/Encoding/Japanese", GTK_UI_MANAGER_MENU)
    474 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Japanese", CS_ISO_2022_JP, "View/Encoding/Japanese/"CS_ISO_2022_JP, GTK_UI_MANAGER_MENUITEM)
    475 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Japanese", CS_ISO_2022_JP_2, "View/Encoding/Japanese/"CS_ISO_2022_JP_2, GTK_UI_MANAGER_MENUITEM)
    476 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Japanese", CS_EUC_JP, "View/Encoding/Japanese/"CS_EUC_JP, GTK_UI_MANAGER_MENUITEM)
    477 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Japanese", CS_SHIFT_JIS, "View/Encoding/Japanese/"CS_SHIFT_JIS, GTK_UI_MANAGER_MENUITEM)
    478 
    479 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Chinese", "View/Encoding/Chinese", GTK_UI_MANAGER_MENU)
    480 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_GB18030, "View/Encoding/Chinese/"CS_GB18030, GTK_UI_MANAGER_MENUITEM)
    481 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_GB2312, "View/Encoding/Chinese/"CS_GB2312, GTK_UI_MANAGER_MENUITEM)
    482 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_GBK, "View/Encoding/Chinese/"CS_GBK, GTK_UI_MANAGER_MENUITEM)
    483 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_BIG5, "View/Encoding/Chinese/"CS_BIG5, GTK_UI_MANAGER_MENUITEM)
    484 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_EUC_TW, "View/Encoding/Chinese/"CS_EUC_TW, GTK_UI_MANAGER_MENUITEM)
    485 
    486 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Korean", "View/Encoding/Korean", GTK_UI_MANAGER_MENU)
    487 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Korean", CS_EUC_KR, "View/Encoding/Korean/"CS_EUC_KR, GTK_UI_MANAGER_MENUITEM)
    488 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Korean", CS_ISO_2022_KR, "View/Encoding/Korean/"CS_ISO_2022_KR, GTK_UI_MANAGER_MENUITEM)
    489 
    490 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Thai", "View/Encoding/Thai", GTK_UI_MANAGER_MENU)
    491 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Thai", CS_TIS_620, "View/Encoding/Thai/"CS_TIS_620, GTK_UI_MANAGER_MENUITEM)
    492 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Thai", CS_WINDOWS_874, "View/Encoding/Thai/"CS_WINDOWS_874, GTK_UI_MANAGER_MENUITEM)
    493 
    494 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Decode", "View/Decode", GTK_UI_MANAGER_MENU)
    495 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "AutoDetect", "View/Decode/AutoDetect", GTK_UI_MANAGER_MENUITEM)
    496 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "Separator1", "View/Decode/---", GTK_UI_MANAGER_SEPARATOR)
    497 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "8bit", "View/Decode/8bit", GTK_UI_MANAGER_MENUITEM)
    498 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "QP", "View/Decode/QP", GTK_UI_MANAGER_MENUITEM)
    499 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "B64", "View/Decode/B64", GTK_UI_MANAGER_MENUITEM)
    500 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "Uuencode", "View/Decode/Uuencode", GTK_UI_MANAGER_MENUITEM)
    501 
    502 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Separator2", "View/---", GTK_UI_MANAGER_SEPARATOR)
    503 
    504 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "MessageSource", "View/MessageSource", GTK_UI_MANAGER_MENUITEM)
    505 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "AllHeaders", "View/AllHeaders", GTK_UI_MANAGER_MENUITEM)
    506 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Quotes", "View/Quotes", GTK_UI_MANAGER_MENU)
    507 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Quotes", "CollapseAll", "View/Quotes/CollapseAll", GTK_UI_MANAGER_MENUITEM)
    508 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Quotes", "Collapse2", "View/Quotes/Collapse2", GTK_UI_MANAGER_MENUITEM)
    509 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Quotes", "Collapse3", "View/Quotes/Collapse3", GTK_UI_MANAGER_MENUITEM)
    510 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Part", "View/Part", GTK_UI_MANAGER_MENU)
    511 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Part", "AsText", "View/Part/AsText", GTK_UI_MANAGER_MENUITEM)
    512 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Part", "Open", "View/Part/Open", GTK_UI_MANAGER_MENUITEM)
    513 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Part", "OpenWith", "View/Part/OpenWith", GTK_UI_MANAGER_MENUITEM)
    514 
    515 /* Message menu */
    516 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Compose", "Message/Compose", GTK_UI_MANAGER_MENUITEM)
    517 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Separator1", "Message/---", GTK_UI_MANAGER_SEPARATOR)
    518 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Reply", "Message/Reply", GTK_UI_MANAGER_MENUITEM)
    519 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "ReplyTo", "Message/ReplyTo", GTK_UI_MANAGER_MENU)
    520 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message/ReplyTo", "All", "Message/ReplyTo/All", GTK_UI_MANAGER_MENUITEM)
    521 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message/ReplyTo", "Sender", "Message/ReplyTo/Sender", GTK_UI_MANAGER_MENUITEM)
    522 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message/ReplyTo", "List", "Message/ReplyTo/List", GTK_UI_MANAGER_MENUITEM)
    523 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Separator2", "Message/---", GTK_UI_MANAGER_SEPARATOR)
    524 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Forward", "Message/Forward", GTK_UI_MANAGER_MENUITEM)
    525 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "ForwardAtt", "Message/ForwardAtt", GTK_UI_MANAGER_MENUITEM)
    526 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Redirect", "Message/Redirect", GTK_UI_MANAGER_MENUITEM)
    527 
    528 /* Tools menu */
    529 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "AddressBook", "Tools/AddressBook", GTK_UI_MANAGER_MENUITEM)
    530 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "AddSenderToAB", "Tools/AddSenderToAB", GTK_UI_MANAGER_MENUITEM)
    531 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "Separator1", "Tools/---", GTK_UI_MANAGER_SEPARATOR)
    532 
    533 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "Separator2", "Tools/---", GTK_UI_MANAGER_SEPARATOR)
    534 
    535 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "Actions", "Tools/Actions", GTK_UI_MANAGER_MENU)
    536 	MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/Actions", "PlaceHolder", "Tools/Actions/PlaceHolder", GTK_UI_MANAGER_MENUITEM)
    537 
    538 	menubar = gtk_ui_manager_get_widget(msgview->ui_manager, "/Menu");
    539 	gtk_widget_show_all(menubar);
    540 	gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(msgview->ui_manager));
    541 
    542 	gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
    543 
    544 	cm_toggle_menu_set_active_full(msgview->ui_manager, "Menu/View/AllHeaders",
    545 					prefs_common.show_all_headers);
    546 
    547 	handlebox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    548 	gtk_box_pack_start(GTK_BOX(vbox), handlebox, FALSE, FALSE, 0);
    549 	gtk_widget_realize(handlebox);
    550 	msgview->toolbar = toolbar_create(TOOLBAR_MSGVIEW, handlebox,
    551 					  (gpointer)msgview);
    552 	statusbar = gtk_statusbar_new();
    553 	gtk_widget_show(statusbar);
    554 	gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
    555 	msgview->statusbar = statusbar;
    556 	msgview->statusbar_cid = gtk_statusbar_get_context_id
    557 		(GTK_STATUSBAR(statusbar), "Message View");
    558 
    559 
    560 	msgview->handlebox = handlebox;
    561 	msgview->menubar   = menubar;
    562 
    563 	gtk_container_add(GTK_CONTAINER(vbox),
    564 			  GTK_WIDGET_PTR(msgview));
    565 
    566 	messageview_update_actions_menu(msgview);
    567 
    568 	msgview_list = g_list_append(msgview_list, msgview);
    569 }
    570 
    571 static MessageView *messageview_create_with_new_window_visible(MainWindow *mainwin, gboolean show)
    572 {
    573 	MessageView *msgview;
    574 	GtkWidget *window;
    575 	static GdkGeometry geometry;
    576 
    577 	window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "messageview");
    578 	gtk_window_set_title(GTK_WINDOW(window), _("Claws Mail - Message View"));
    579 	gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
    580 
    581 	gtk_window_set_default_size(GTK_WINDOW(window), prefs_common.msgwin_width,
    582 			prefs_common.msgwin_height);
    583 
    584 	if (!geometry.min_height) {
    585 		geometry.min_width = 320;
    586 		geometry.min_height = 200;
    587 	}
    588 	gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
    589 				      GDK_HINT_MIN_SIZE);
    590 
    591 	msgview = messageview_create(mainwin);
    592 
    593 	g_signal_connect(G_OBJECT(window), "size_allocate",
    594 			 G_CALLBACK(messageview_size_allocate_cb),
    595 			 msgview);
    596 	g_signal_connect(G_OBJECT(window), "delete_event",
    597 			 G_CALLBACK(messageview_delete_cb), msgview);
    598 	g_signal_connect(G_OBJECT(window), "key_press_event",
    599 			 G_CALLBACK(key_pressed), msgview);
    600 	messageview_add_toolbar(msgview, window);
    601 
    602 	if (show) {
    603 		gtk_widget_show(window);
    604 	} else {
    605 		gtk_widget_realize(window);
    606 	}
    607 
    608 	msgview->new_window = TRUE;
    609 	msgview->window = window;
    610 	msgview->visible = TRUE;
    611 
    612 	toolbar_set_style(msgview->toolbar->toolbar, msgview->handlebox,
    613 			  prefs_common.toolbar_style);
    614 	messageview_init(msgview);
    615 
    616 	if (show) {
    617 		GTK_EVENTS_FLUSH();
    618 		gtk_widget_grab_focus(msgview->mimeview->textview->text);
    619 	}
    620 
    621 	return msgview;
    622 }
    623 
    624 MessageView *messageview_create_with_new_window(MainWindow *mainwin)
    625 {
    626 	return messageview_create_with_new_window_visible(mainwin, TRUE);
    627 }
    628 void messageview_init(MessageView *messageview)
    629 {
    630 	mimeview_init(messageview->mimeview);
    631 }
    632 
    633 static gboolean find_broken_func(GNode *node, gpointer data)
    634 {
    635 	MimeInfo *mimeinfo = (MimeInfo *) node->data;
    636 	MimeInfo **brokeninfo = (MimeInfo **) data;
    637 
    638 	if (mimeinfo->broken) {
    639 		*brokeninfo = mimeinfo;
    640 		return TRUE;
    641 	}
    642 
    643 	return FALSE;
    644 }
    645 
    646 static MimeInfo *find_broken_part(MimeInfo *rootinfo)
    647 {
    648 	MimeInfo *brokeninfo = NULL;
    649 
    650 	g_node_traverse(rootinfo->node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
    651 		find_broken_func, &brokeninfo);
    652 
    653 	return brokeninfo;
    654 }
    655 
    656 static void messageview_register_nav(MessageView *messageview)
    657 {
    658 	gchar *id;
    659 	gint pos = -1;
    660 	GList *existing;
    661 
    662 	cm_return_if_fail(messageview);
    663 	cm_return_if_fail(messageview->msginfo);
    664 
    665 	id = procmsg_msginfo_get_identifier(messageview->msginfo);
    666 	existing = g_list_find_custom(messageview->trail, id, (GCompareFunc)g_strcmp0);
    667 
    668 	if (existing != NULL)
    669 		pos = g_list_position(messageview->trail, existing);
    670 	else
    671 		pos = -1;
    672 
    673 	if (pos != -1) {
    674 		messageview->trail_pos = pos;
    675 		g_free(id);
    676 	} else {
    677 		/* Cut the end of the list */
    678 		GList *end = g_list_nth(messageview->trail, messageview->trail_pos + 1);
    679 		if (end) {
    680 			if (end->prev) {
    681 				end->prev->next = NULL;
    682 				end->prev = NULL;
    683 				list_free_strings_full(end);
    684 			} else {
    685 				list_free_strings_full(messageview->trail);
    686 				messageview->trail = NULL;
    687 			}
    688 		}
    689 		messageview->trail = g_list_append(messageview->trail, id);
    690 		messageview->trail_pos = (gint)g_list_length(messageview->trail) - 1;
    691 
    692 		/* Cut the beginning if needed */
    693 		while (messageview->trail_pos > prefs_common.nav_history_length) {
    694 			g_free(messageview->trail->data);
    695 			messageview->trail = g_list_delete_link(messageview->trail,
    696 						messageview->trail);
    697 			messageview->trail_pos--;
    698 		}
    699 	}
    700 	messageview_set_menu_sensitive(messageview);
    701 }
    702 
    703 gboolean messageview_nav_has_prev(MessageView *messageview) {
    704 	return messageview != NULL && messageview->trail != NULL
    705 		&& messageview->trail_pos > 0;
    706 }
    707 
    708 gboolean messageview_nav_has_next(MessageView *messageview) {
    709 	if (!messageview || !messageview->trail)
    710 		return FALSE;
    711 
    712 	return sc_g_list_bigger(messageview->trail, messageview->trail_pos + 1);
    713 }
    714 
    715 MsgInfo *messageview_nav_get_prev(MessageView *messageview) {
    716 	GList *item;
    717 	MsgInfo *info;
    718 
    719 	cm_return_val_if_fail(messageview, NULL);
    720 	cm_return_val_if_fail(messageview->trail, NULL);
    721 
    722 	do {
    723 		if (!messageview_nav_has_prev(messageview))
    724 			return NULL;
    725 
    726 		item = g_list_nth(messageview->trail, messageview->trail_pos - 1);
    727 		cm_return_val_if_fail(item != NULL, NULL);
    728 
    729 		info = procmsg_get_msginfo_from_identifier((const gchar *)item->data);
    730 		if (info != NULL)
    731 			break;
    732 
    733 		g_free(item->data);
    734 		messageview->trail = g_list_delete_link(messageview->trail, item);
    735 		if (messageview->trail_pos > 0)
    736 			messageview->trail_pos--;
    737 	} while (info == NULL);
    738 
    739 	return info;
    740 }
    741 
    742 MsgInfo *messageview_nav_get_next(MessageView *messageview) {
    743 	GList *item;
    744 	MsgInfo *info;
    745 
    746 	cm_return_val_if_fail(messageview, NULL);
    747 	cm_return_val_if_fail(messageview->trail, NULL);
    748 
    749 	do {
    750 		if (!messageview_nav_has_next(messageview))
    751 			return NULL;
    752 
    753 		item = g_list_nth(messageview->trail, messageview->trail_pos + 1);
    754 		cm_return_val_if_fail(item != NULL, NULL);
    755 
    756 		info = procmsg_get_msginfo_from_identifier((const gchar *)item->data);
    757 		if (info != NULL)
    758 			break;
    759 
    760 		g_free(item->data);
    761 		messageview->trail = g_list_delete_link(messageview->trail, item);
    762 	} while (info == NULL);
    763 
    764 	return info;
    765 }
    766 
    767 static gboolean messageview_try_select_mimeinfo(MessageView *messageview, MsgInfo *msginfo, MimeInfo *mimeinfo)
    768 {
    769 	if (mimeinfo->type == MIMETYPE_TEXT) {
    770 		if (!strcasecmp(mimeinfo->subtype, "calendar")
    771 				&& mimeview_has_viewer_for_content_type(messageview->mimeview, "text/calendar")) {
    772 			mimeview_select_mimepart_icon(messageview->mimeview, mimeinfo);
    773 			return TRUE;
    774 		}
    775 	}
    776 	return FALSE;
    777 }
    778 
    779 static void messageview_find_part_depth_first(MimeInfoSearch *context, MimeMediaType type, const gchar *subtype)
    780 {
    781 	MimeInfo * mimeinfo = context->current;
    782 
    783 	if (!mimeinfo)
    784 		return;
    785 
    786 	debug_print("found part %d/%s\n", mimeinfo->type, mimeinfo->subtype);
    787 
    788 	if (mimeinfo->type == type
    789 			&& !strcasecmp(mimeinfo->subtype, subtype)) {
    790 		context->found = mimeinfo;
    791 	} else if (mimeinfo->type == MIMETYPE_MULTIPART) {
    792 		if (!strcasecmp(mimeinfo->subtype, "alternative")
    793 				|| !strcasecmp(mimeinfo->subtype, "related")) {
    794 			context->found = procmime_mimeinfo_next(mimeinfo);
    795 			while (context->found && context->found != context->parent) {
    796 				if (context->found->type == type
    797 					&& !strcasecmp(context->found->subtype, subtype))
    798 						break;
    799 				context->found = procmime_mimeinfo_next(context->found);
    800 			}
    801 			if (context->found == context->parent)
    802 				context->found = NULL;
    803 		}
    804 		if (!context->found
    805 			&& (!strcasecmp(mimeinfo->subtype, "related")
    806 				|| !strcasecmp(mimeinfo->subtype, "mixed"))) {
    807 			context->parent = mimeinfo;
    808 			context->current = procmime_mimeinfo_next(mimeinfo);
    809 			messageview_find_part_depth_first(context, type, subtype);
    810 		}
    811 	}
    812 }
    813 
    814 gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
    815 		      gboolean all_headers)
    816 {
    817 	gchar *file;
    818 	MimeInfo *mimeinfo, *root;
    819 	gchar *subject = NULL;
    820 	cm_return_val_if_fail(msginfo != NULL, -1);
    821 
    822 	if (msginfo != messageview->msginfo)
    823 		messageview->show_full_text = FALSE;
    824 
    825 	if (messageview->mimeview->textview &&
    826 	    messageview->mimeview->textview->loading) {
    827 		messageview->mimeview->textview->stop_loading = TRUE;
    828 		return 0;
    829 	}
    830 
    831 	mimeview_clear(messageview->mimeview);
    832 	messageview->updating = TRUE;
    833 
    834 	if (msginfo->size > 1024*1024)
    835 		statusbar_print_all(_("Fetching message (%s)..."),
    836 			to_human_readable(msginfo->size));
    837 
    838 	file = procmsg_get_message_file_path(msginfo);
    839 
    840 	if (msginfo->size > 1024*1024)
    841 		statusbar_pop_all();
    842 
    843 	if (!file) {
    844 		g_warning("can't get message file path");
    845 		textview_show_error(messageview->mimeview->textview);
    846 		return -1;
    847 	}
    848 
    849 	if (!folder_has_parent_of_type(msginfo->folder, F_QUEUE) &&
    850 	    !folder_has_parent_of_type(msginfo->folder, F_DRAFT))
    851 		mimeinfo = procmime_scan_file(file);
    852 	else
    853 		mimeinfo = procmime_scan_queue_file(file);
    854 
    855 	messageview->updating = FALSE;
    856 
    857 	if (messageview->deferred_destroy) {
    858 		g_free(file);
    859 		messageview_destroy(messageview);
    860 		return 0;
    861 	}
    862 
    863 	if (!mimeinfo) {
    864 		textview_show_error(messageview->mimeview->textview);
    865 		return -1;
    866 	}
    867 
    868 	if (messageview->msginfo != msginfo) {
    869 		procmsg_msginfo_free(&(messageview->msginfo));
    870 		messageview->msginfo = NULL;
    871 		messageview_set_menu_sensitive(messageview);
    872 		messageview->msginfo =
    873 			procmsg_msginfo_get_full_info_from_file(msginfo, file);
    874 		if (!messageview->msginfo)
    875 			messageview->msginfo = procmsg_msginfo_copy(msginfo);
    876 	} else {
    877 		messageview->msginfo = NULL;
    878 		messageview_set_menu_sensitive(messageview);
    879 		messageview->msginfo = msginfo;
    880 	}
    881 
    882 	messageview_register_nav(messageview);
    883 	messageview_set_position(messageview, 0);
    884 
    885 	if (messageview->window) {
    886 		gtk_window_set_title(GTK_WINDOW(messageview->window),
    887 				_("Claws Mail - Message View"));
    888 		GTK_EVENTS_FLUSH();
    889 	}
    890 	mimeview_show_message(messageview->mimeview, mimeinfo, file);
    891 
    892 	summary_open_msg(messageview->mainwin->summaryview, FALSE, TRUE);
    893 
    894 	messageview_set_position(messageview, 0);
    895 
    896 	if (messageview->window && msginfo->subject) {
    897 		subject = g_strdup(msginfo->subject);
    898 		if (!g_utf8_validate(subject, -1, NULL)) {
    899 			g_free(subject);
    900 			subject = g_malloc(strlen(msginfo->subject)*2 +1);
    901 			conv_localetodisp(subject, strlen(msginfo->subject)*2 +1,
    902 				msginfo->subject);
    903 		}
    904 		if (g_utf8_validate(subject, -1, NULL))
    905 			gtk_window_set_title(GTK_WINDOW(messageview->window),
    906 				subject);
    907 		g_free(subject);
    908 	}
    909 
    910 	if (msginfo->folder) {
    911 		msginfo->folder->last_seen = msginfo->msgnum;
    912 	}
    913 
    914 	main_create_mailing_list_menu(messageview->mainwin, messageview->msginfo);
    915 
    916 	if (find_broken_part(mimeinfo) != NULL) {
    917 		GtkDialogFlags flag = GTK_DIALOG_DESTROY_WITH_PARENT;
    918 		GtkWidget *dialog = gtk_message_dialog_new(messageview->mainwin, flag, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Broken MIME part");
    919 		g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog);
    920 		gtk_widget_show(dialog);
    921 	}
    922 
    923 	root = mimeinfo;
    924 	mimeinfo = procmime_mimeinfo_next(mimeinfo);
    925 	if (!all_headers && mimeinfo
    926 			&& (mimeinfo->type != MIMETYPE_TEXT
    927 				|| strcasecmp(mimeinfo->subtype, "plain"))
    928 			&& (mimeinfo->type != MIMETYPE_MULTIPART
    929 				|| strcasecmp(mimeinfo->subtype, "signed"))) {
    930 		if (strcasecmp(mimeinfo->subtype, "html")) {
    931 			MimeInfoSearch context = {
    932 				.parent = root,
    933 				.current = mimeinfo,
    934 				.found = NULL
    935 			};
    936 			if (mimeview_has_viewer_for_content_type(messageview->mimeview, "text/calendar")) {
    937 				MimeInfoSearch cal_context = context;
    938 				messageview_find_part_depth_first(&cal_context, MIMETYPE_TEXT, "calendar");
    939 				if (cal_context.found) { /* calendar found */
    940 					mimeinfo = cal_context.found;
    941 					if (messageview_try_select_mimeinfo(messageview, msginfo, mimeinfo))
    942 						goto done;
    943 				}
    944 			}
    945 			messageview_find_part_depth_first(&context, MIMETYPE_TEXT, "html");
    946 			mimeinfo = root;
    947 			if (!mimeview_show_part(messageview->mimeview, mimeinfo))
    948 				mimeview_select_mimepart_icon(messageview->mimeview, root);
    949 			goto done;
    950 		}
    951 	}
    952 	if (!all_headers && mimeinfo &&
    953 	    mimeinfo->type == MIMETYPE_MULTIPART &&
    954 	    mimeview_has_viewer_for_content_type(messageview->mimeview, "text/calendar")) {
    955 		/* look for a calendar part or it looks really strange */
    956 		while (mimeinfo) {
    957 			if (mimeinfo->type == MIMETYPE_TEXT &&
    958 			    !strcasecmp(mimeinfo->subtype, "calendar")) {
    959 				mimeview_select_mimepart_icon(messageview->mimeview, mimeinfo);
    960 				goto done;
    961 			}
    962 			mimeinfo = procmime_mimeinfo_next(mimeinfo);
    963 		}
    964 	}
    965 
    966 	mimeview_select_mimepart_icon(messageview->mimeview, root);
    967 done:
    968 	messageview_set_menu_sensitive(messageview);
    969 	g_free(file);
    970 
    971 	return 0;
    972 }
    973 
    974 void messageview_reflect_prefs_pixmap_theme(void)
    975 {
    976 	GList *cur;
    977 	MessageView *msgview;
    978 
    979 	for (cur = msgview_list; cur != NULL; cur = cur->next) {
    980 		msgview = (MessageView*)cur->data;
    981 		toolbar_update(TOOLBAR_MSGVIEW, msgview);
    982 		mimeview_update(msgview->mimeview);
    983 	}
    984 }
    985 
    986 void messageview_clear(MessageView *messageview)
    987 {
    988 	if (!messageview)
    989 		return;
    990 	procmsg_msginfo_free(&(messageview->msginfo));
    991 	messageview->msginfo = NULL;
    992 	messageview->filtered = FALSE;
    993 
    994 	if (messageview->window) {
    995 		gtk_window_set_title(GTK_WINDOW(messageview->window),
    996 				_("Claws Mail - Message View"));
    997 		GTK_EVENTS_FLUSH();
    998 	}
    999 
   1000 	mimeview_clear(messageview->mimeview);
   1001 }
   1002 
   1003 void messageview_destroy(MessageView *messageview)
   1004 {
   1005 	debug_print("destroy messageview\n");
   1006 	messageview_list = g_list_remove(messageview_list, messageview);
   1007 
   1008 	if (messageview->mainwin->summaryview->messageview == messageview) {
   1009 		messageview->mainwin->summaryview->displayed = NULL;
   1010 		messageview->mainwin->summaryview->messageview = NULL;
   1011 	}
   1012 	if (messageview->mainwin->summaryview->ext_messageview == messageview) {
   1013 		messageview->mainwin->summaryview->displayed = NULL;
   1014 		messageview->mainwin->summaryview->ext_messageview = NULL;
   1015 	}
   1016 	if (!messageview->deferred_destroy)
   1017 		hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST,
   1018 			      messageview->msginfo_update_callback_id);
   1019 
   1020 	if (messageview->updating) {
   1021 		debug_print("uh oh, better not touch that now (fetching)\n");
   1022 		messageview->deferred_destroy = TRUE;
   1023 		gtk_widget_hide(messageview->window);
   1024 		return;
   1025 	}
   1026 
   1027 	if (messageview->mimeview->textview
   1028 	&&  messageview->mimeview->textview->loading) {
   1029 		debug_print("uh oh, better not touch that now (loading text)\n");
   1030 		messageview->deferred_destroy = TRUE;
   1031 		messageview->mimeview->textview->stop_loading = TRUE;
   1032 		gtk_widget_hide(messageview->window);
   1033 		return;
   1034 	}
   1035 
   1036 	mimeview_destroy(messageview->mimeview);
   1037 
   1038 	procmsg_msginfo_free(&(messageview->msginfo));
   1039 	toolbar_clear_list(TOOLBAR_MSGVIEW);
   1040 	if (messageview->toolbar) {
   1041 		toolbar_destroy(messageview->toolbar);
   1042 		g_free(messageview->toolbar);
   1043 	}
   1044 
   1045 	message_search_close(messageview);
   1046 
   1047 	list_free_strings_full(messageview->trail);
   1048 	msgview_list = g_list_remove(msgview_list, messageview);
   1049 
   1050 	if (messageview->window)
   1051 		gtk_widget_destroy(messageview->window);
   1052 	g_free(messageview);
   1053 }
   1054 
   1055 void messageview_delete(MessageView *msgview)
   1056 {
   1057 	MsgInfo *msginfo = NULL;
   1058 	FolderItem *trash = NULL;
   1059 	PrefsAccount *ac = NULL;
   1060 
   1061 	if (msgview->msginfo && msgview->mainwin && msgview->mainwin->summaryview)
   1062 		msginfo = summary_get_selected_msg(msgview->mainwin->summaryview);
   1063 
   1064 	/* need a procmsg_msginfo_equal() */
   1065 	if (msginfo && msgview->msginfo &&
   1066 	    msginfo->msgnum == msgview->msginfo->msgnum &&
   1067 	    msginfo->folder == msgview->msginfo->folder) {
   1068 		summary_delete_trash(msgview->mainwin->summaryview);
   1069 	} else {
   1070 		msginfo = msgview->msginfo;
   1071 
   1072 		cm_return_if_fail(msginfo != NULL);
   1073 
   1074 		/* We will need to access the original message's msginfo
   1075 		 * later, so we add our own reference. */
   1076 		procmsg_msginfo_new_ref(msginfo);
   1077 
   1078 		/* to get the trash folder, we have to choose either
   1079 		 * the folder's or account's trash default - we prefer
   1080 		 * the one in the account prefs */
   1081 		if (msginfo->folder) {
   1082 			if (NULL != (ac = account_find_from_item(msginfo->folder)))
   1083 				trash = account_get_special_folder(ac, F_TRASH);
   1084 			if (!trash && msginfo->folder->folder)
   1085 				trash = msginfo->folder->folder->trash;
   1086 			/* if still not found, use the default */
   1087 			if (!trash)
   1088 				trash =	folder_get_default_trash();
   1089 		}
   1090 
   1091 		cm_return_if_fail(trash != NULL);
   1092 
   1093 		if (prefs_common.immediate_exec)
   1094 			/* TODO: Delete from trash */
   1095 			folder_item_move_msg(trash, msginfo);
   1096 		else {
   1097 			procmsg_msginfo_set_to_folder(msginfo, trash);
   1098 			procmsg_msginfo_set_flags(msginfo, MSG_DELETED, 0);
   1099 			/* NOTE: does not update to next message in summaryview */
   1100 		}
   1101 
   1102 		procmsg_msginfo_free(&msginfo);
   1103 	}
   1104 }
   1105 
   1106 /*
   1107  * \brief update messageview with currently selected message in summaryview
   1108  *        leave unchanged if summaryview is empty
   1109  * \param pointer to MessageView
   1110  */
   1111 static void messageview_update(MessageView *msgview, MsgInfo *old_msginfo)
   1112 {
   1113 	SummaryView *summaryview = (SummaryView*)msgview->mainwin->summaryview;
   1114 
   1115 	cm_return_if_fail(summaryview != NULL);
   1116 
   1117 	if (summaryview->selected) {
   1118 		MsgInfo *msginfo = summary_get_selected_msg(summaryview);
   1119 		if (msginfo == NULL || msginfo == old_msginfo)
   1120 			return;
   1121 
   1122 		messageview_show(msgview, msginfo,
   1123 				 msgview->all_headers);
   1124 	}
   1125 }
   1126 
   1127 TextView *messageview_get_current_textview(MessageView *messageview)
   1128 {
   1129 	TextView *text = NULL;
   1130 
   1131 	text = messageview->mimeview->textview;
   1132 
   1133 	return text;
   1134 }
   1135 
   1136 MimeInfo *messageview_get_selected_mime_part(MessageView *messageview)
   1137 {
   1138 	return mimeview_get_selected_part(messageview->mimeview);
   1139 }
   1140 
   1141 void messageview_copy_clipboard(MessageView *messageview)
   1142 {
   1143 	gchar *text = messageview_get_selection(messageview);
   1144 	if (text) {
   1145 		gtk_clipboard_set_text(
   1146 			gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
   1147 			text, -1);
   1148 	}
   1149 	g_free(text);
   1150 }
   1151 
   1152 void messageview_select_all(MessageView *messageview)
   1153 {
   1154 	TextView *text;
   1155 
   1156 	text = messageview_get_current_textview(messageview);
   1157 	if (text) {
   1158 		GtkTextView *textview = GTK_TEXT_VIEW(text->text);
   1159 		GtkTextBuffer *buffer;
   1160 		GtkTextIter start, end;
   1161 
   1162 		buffer = gtk_text_view_get_buffer(textview);
   1163 		gtk_text_buffer_get_bounds(buffer, &start, &end);
   1164 		gtk_text_buffer_select_range(buffer, &start, &end);
   1165 	}
   1166 }
   1167 
   1168 void messageview_set_position(MessageView *messageview, gint pos)
   1169 {
   1170 	TextView *text;
   1171 
   1172 	text = messageview_get_current_textview(messageview);
   1173 	if (text)
   1174 		textview_set_position(text, pos);
   1175 }
   1176 
   1177 gboolean messageview_search_string(MessageView *messageview, const gchar *str,
   1178 				   gboolean case_sens)
   1179 {
   1180 	TextView *text;
   1181 
   1182 	if (messageview->mimeview->type == MIMEVIEW_VIEWER) {
   1183 		MimeViewer *viewer = messageview->mimeview->mimeviewer;
   1184 		if (viewer && viewer->text_search) {
   1185 			return viewer->text_search(viewer, FALSE, str, case_sens);
   1186 		}
   1187 	}
   1188 
   1189 	text = messageview_get_current_textview(messageview);
   1190 	if (text)
   1191 		return textview_search_string(text, str, case_sens);
   1192 	return FALSE;
   1193 }
   1194 
   1195 gboolean messageview_search_string_backward(MessageView *messageview,
   1196 					    const gchar *str,
   1197 					    gboolean case_sens)
   1198 {
   1199 	TextView *text;
   1200 
   1201 	if (messageview->mimeview->type == MIMEVIEW_VIEWER) {
   1202 		MimeViewer *viewer = messageview->mimeview->mimeviewer;
   1203 		if (viewer && viewer->text_search) {
   1204 			return viewer->text_search(viewer, TRUE, str, case_sens);
   1205 		}
   1206 	}
   1207 
   1208 	text = messageview_get_current_textview(messageview);
   1209 	if (text)
   1210 		return textview_search_string_backward(text,
   1211 						       str, case_sens);
   1212 	return FALSE;
   1213 }
   1214 
   1215 gboolean messageview_is_visible(MessageView *messageview)
   1216 {
   1217 	if (messageview == NULL)
   1218 		return FALSE;
   1219 	return messageview->visible;
   1220 }
   1221 
   1222 static gint messageview_delete_cb(GtkWidget *widget, GdkEventAny *event,
   1223 				  MessageView *messageview)
   1224 {
   1225 	messageview_destroy(messageview);
   1226 	return TRUE;
   1227 }
   1228 
   1229 static void messageview_size_allocate_cb(GtkWidget *widget,
   1230 					 GtkAllocation *allocation)
   1231 {
   1232 	cm_return_if_fail(allocation != NULL);
   1233 
   1234 	gtk_window_get_size(GTK_WINDOW(widget),
   1235 		&prefs_common.msgwin_width, &prefs_common.msgwin_height);
   1236 }
   1237 
   1238 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
   1239 			MessageView *messageview)
   1240 {
   1241 	if (event && (event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0)
   1242 		return FALSE;
   1243 	if (event && (event->state & GDK_SHIFT_MASK) && event->keyval != GDK_KEY_space)
   1244 		return FALSE;
   1245 
   1246 	if (event && (event->keyval == GDK_KEY_KP_Enter || event->keyval ==  GDK_KEY_Return) &&
   1247 	    messageview->window) {
   1248 		MsgInfo *new_msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1249 		messageview_show(messageview, new_msginfo, messageview->all_headers);
   1250 	}
   1251 	return FALSE;
   1252 }
   1253 
   1254 /*
   1255  * \brief return selected messageview text, when nothing is
   1256  * 	  selected and message was filtered, return complete text
   1257  *
   1258  * \param  pointer to Messageview
   1259  *
   1260  * \return pointer to text (needs to be free'd by calling func)
   1261  */
   1262 gchar *messageview_get_selection(MessageView *msgview)
   1263 {
   1264 	TextView *textview;
   1265 	gchar *text = NULL;
   1266 	GtkTextView *edit = NULL;
   1267 	GtkTextBuffer *textbuf;
   1268 	gint body_pos = 0;
   1269 	GtkTextIter start_iter, end_iter;
   1270 	GtkTextMark *body_start, *body_end;
   1271 
   1272 	cm_return_val_if_fail(msgview != NULL, NULL);
   1273 
   1274 	if (msgview->mimeview->type == MIMEVIEW_VIEWER) {
   1275 		MimeViewer *viewer = msgview->mimeview->mimeviewer;
   1276 		if (viewer && viewer->get_selection) {
   1277 			text = viewer->get_selection(viewer);
   1278 			if (text)
   1279 				return text;
   1280 		}
   1281 	}
   1282 
   1283 	textview = messageview_get_current_textview(msgview);
   1284 	cm_return_val_if_fail(textview != NULL, NULL);
   1285 
   1286 	edit = GTK_TEXT_VIEW(textview->text);
   1287 	cm_return_val_if_fail(edit != NULL, NULL);
   1288 	body_pos = textview->body_pos;
   1289 
   1290 	textbuf = gtk_text_view_get_buffer(edit);
   1291 
   1292 	if (gtk_text_buffer_get_selection_bounds(textbuf, NULL, NULL)) {
   1293 		return gtkut_text_view_get_selection(edit);
   1294 	} else {
   1295 		if (msgview->filtered) {
   1296 			gtk_text_buffer_get_iter_at_offset(textbuf, &start_iter, body_pos);
   1297 			gtk_text_buffer_get_end_iter(textbuf, &end_iter);
   1298 		} else {
   1299 			body_start = gtk_text_buffer_get_mark(textbuf, "body_start");
   1300 
   1301 			/* If there is no body_start mark, an attachment is likely
   1302 			 * selected, and we're looking at instructions on what to do
   1303 			 * with it. No point in quoting that, so we'll just return NULL,
   1304 			 * so that original message body is quoted instead down the line.
   1305 			 */
   1306 			if (body_start == NULL) {
   1307 				return NULL;
   1308 			}
   1309 
   1310 			gtk_text_buffer_get_iter_at_mark(textbuf, &start_iter, body_start);
   1311 
   1312 			body_end = gtk_text_buffer_get_mark(textbuf, "body_end");
   1313 			if (body_end != NULL) /* Just in case */
   1314 				gtk_text_buffer_get_iter_at_mark(textbuf, &end_iter, body_end);
   1315 			else
   1316 				gtk_text_buffer_get_end_iter(textbuf, &end_iter);
   1317 		}
   1318 
   1319 		return gtk_text_buffer_get_text(textbuf, &start_iter, &end_iter, FALSE);
   1320 	}
   1321 
   1322 	return text;
   1323 }
   1324 
   1325 static void save_as_cb(GtkAction *action, gpointer data)
   1326 {
   1327 	messageview_save_as((MessageView *)data);
   1328 }
   1329 
   1330 void messageview_save_as(MessageView *messageview)
   1331 {
   1332 	gchar *filename = NULL;
   1333 	gchar *src, *dest;
   1334 	gchar *tmp;
   1335 	gchar *filedir = NULL;
   1336 	gchar *converted_filename = NULL;
   1337 	gchar * filepath = NULL;
   1338 	AlertValue aval = 0;
   1339 
   1340 	if (!messageview->msginfo) return;
   1341 
   1342 	if (messageview->msginfo->subject) {
   1343 		Xstrdup_a(filename, messageview->msginfo->subject, return);
   1344 		subst_for_filename(filename);
   1345 	}
   1346 
   1347 	if (filename && !g_utf8_validate(filename, -1, NULL)) {
   1348 		converted_filename = conv_codeset_strdup(filename,
   1349 					       conv_get_locale_charset_str(),
   1350 					       CS_UTF_8);
   1351 		if (!converted_filename)
   1352 			g_warning("messageview_save_as(): failed to convert character set");
   1353 		else
   1354 			filename = converted_filename;
   1355 	}
   1356 	if (!filename)
   1357 		return;
   1358 
   1359 	if (prefs_common.attach_save_dir && *prefs_common.attach_save_dir)
   1360 		filepath = g_strconcat(prefs_common.attach_save_dir, G_DIR_SEPARATOR_S,
   1361 				       filename, NULL);
   1362 	dest = filesel_select_file_save(_("Save as"), filepath ? filepath : filename);
   1363 	if (filepath)
   1364 		g_free(filepath);
   1365 	if (converted_filename)
   1366 		g_free(converted_filename);
   1367 	if (!dest)
   1368 		return;
   1369 
   1370 	if (is_file_exist(dest)) {
   1371 		aval = alertpanel(_("Append or Overwrite"),
   1372 				  _("Append or overwrite existing file?"),
   1373 				  NULL, _("_Append"), NULL, _("_Overwrite"),
   1374 				  NULL, _("_Cancel"), ALERTFOCUS_FIRST);
   1375 		if (aval != 0 && aval != 1)
   1376 			return;
   1377 	}
   1378 
   1379 	src = procmsg_get_message_file(messageview->msginfo);
   1380 	tmp = g_path_get_basename(dest);
   1381 
   1382 	if (aval == 0) {
   1383 		if (append_file(src, dest, TRUE) < 0)
   1384 			alertpanel_error(_("Couldn't save the file '%s'."), tmp);
   1385 	} else {
   1386 		if (copy_file(src, dest, TRUE) < 0)
   1387 			alertpanel_error(_("Couldn't save the file '%s'."), tmp);
   1388 	}
   1389 	g_free(src);
   1390 
   1391 	filedir = g_path_get_dirname(dest);
   1392 	if (filedir) {
   1393 		if (strcmp(filedir, ".")) {
   1394 			g_free(prefs_common.attach_save_dir);
   1395 			prefs_common.attach_save_dir = g_filename_to_utf8(filedir, -1, NULL, NULL, NULL);
   1396 		}
   1397 		g_free(filedir);
   1398 	}
   1399 	g_free(dest);
   1400 	g_free(tmp);
   1401 }
   1402 
   1403 static void close_cb(GtkAction *action, gpointer data)
   1404 {
   1405 	MessageView *messageview = (MessageView *)data;
   1406 	messageview_destroy(messageview);
   1407 }
   1408 
   1409 static void copy_cb(GtkAction *action, gpointer data)
   1410 {
   1411 	MessageView *messageview = (MessageView *)data;
   1412 	messageview_copy_clipboard(messageview);
   1413 }
   1414 
   1415 static void allsel_cb(GtkAction *action, gpointer data)
   1416 {
   1417 	MessageView *messageview = (MessageView *)data;
   1418 	messageview_select_all(messageview);
   1419 }
   1420 
   1421 static void search_cb(GtkAction *action, gpointer data)
   1422 {
   1423 	MessageView *messageview = (MessageView *)data;
   1424 	message_search(messageview);
   1425 }
   1426 
   1427 static void prev_cb(GtkAction *action, gpointer data)
   1428 {
   1429 	MessageView *messageview = (MessageView *)data;
   1430 	messageview->updating = TRUE;
   1431 	summary_select_prev(messageview->mainwin->summaryview);
   1432 	messageview->updating = FALSE;
   1433 
   1434 	if (messageview->deferred_destroy) {
   1435 		debug_print("messageview got away!\n");
   1436 		messageview_destroy(messageview);
   1437 		return;
   1438 	}
   1439 	if (messageview->mainwin->summaryview->selected) {
   1440 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1441 
   1442 		if (msginfo)
   1443 			messageview_show(messageview, msginfo,
   1444 					 messageview->all_headers);
   1445 	} else {
   1446 		gtk_widget_destroy(messageview->window);
   1447 	}
   1448 }
   1449 
   1450 static void next_cb(GtkAction *action, gpointer data)
   1451 {
   1452 	MessageView *messageview = (MessageView *)data;
   1453 	messageview->updating = TRUE;
   1454 	summary_select_next(messageview->mainwin->summaryview);
   1455 	messageview->updating = FALSE;
   1456 
   1457 	if (messageview->deferred_destroy) {
   1458 		debug_print("messageview got away!\n");
   1459 		messageview_destroy(messageview);
   1460 		return;
   1461 	}
   1462 	if (messageview->mainwin->summaryview->selected) {
   1463 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1464 
   1465 		if (msginfo)
   1466 			messageview_show(messageview, msginfo,
   1467 					 messageview->all_headers);
   1468 	} else {
   1469 		gtk_widget_destroy(messageview->window);
   1470 	}
   1471 }
   1472 
   1473 static void prev_unread_cb(GtkAction *action, gpointer data)
   1474 {
   1475 	MessageView *messageview = (MessageView *)data;
   1476 	messageview->updating = TRUE;
   1477 	summary_select_prev_unread(messageview->mainwin->summaryview);
   1478 	messageview->updating = FALSE;
   1479 
   1480 	if (messageview->deferred_destroy) {
   1481 		debug_print("messageview got away!\n");
   1482 		messageview_destroy(messageview);
   1483 		return;
   1484 	}
   1485 	if (messageview->mainwin->summaryview->selected) {
   1486 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1487 
   1488 		if (msginfo)
   1489 			messageview_show(messageview, msginfo,
   1490 					 messageview->all_headers);
   1491 	} else {
   1492 		gtk_widget_destroy(messageview->window);
   1493 	}
   1494 }
   1495 
   1496 static void next_unread_cb(GtkAction *action, gpointer data)
   1497 {
   1498 	MessageView *messageview = (MessageView *)data;
   1499 	messageview->updating = TRUE;
   1500 	summary_select_next_unread(messageview->mainwin->summaryview);
   1501 	messageview->updating = FALSE;
   1502 
   1503 	if (messageview->deferred_destroy) {
   1504 		debug_print("messageview got away!\n");
   1505 		messageview_destroy(messageview);
   1506 		return;
   1507 	}
   1508 	if (messageview->mainwin->summaryview->selected) {
   1509 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1510 
   1511 		if (msginfo)
   1512 			messageview_show(messageview, msginfo,
   1513 					 messageview->all_headers);
   1514 	} else {
   1515 		gtk_widget_destroy(messageview->window);
   1516 	}
   1517 }
   1518 
   1519 static void prev_new_cb(GtkAction *action, gpointer data)
   1520 {
   1521 	MessageView *messageview = (MessageView *)data;
   1522 	messageview->updating = TRUE;
   1523 	summary_select_prev_new(messageview->mainwin->summaryview);
   1524 	messageview->updating = FALSE;
   1525 
   1526 	if (messageview->deferred_destroy) {
   1527 		debug_print("messageview got away!\n");
   1528 		messageview_destroy(messageview);
   1529 		return;
   1530 	}
   1531 	if (messageview->mainwin->summaryview->selected) {
   1532 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1533 
   1534 		if (msginfo)
   1535 			messageview_show(messageview, msginfo,
   1536 					 messageview->all_headers);
   1537 	} else {
   1538 		gtk_widget_destroy(messageview->window);
   1539 	}
   1540 }
   1541 
   1542 static void next_new_cb(GtkAction *action, gpointer data)
   1543 {
   1544 	MessageView *messageview = (MessageView *)data;
   1545 	messageview->updating = TRUE;
   1546 	summary_select_next_new(messageview->mainwin->summaryview);
   1547 	messageview->updating = FALSE;
   1548 
   1549 	if (messageview->deferred_destroy) {
   1550 		debug_print("messageview got away!\n");
   1551 		messageview_destroy(messageview);
   1552 		return;
   1553 	}
   1554 	if (messageview->mainwin->summaryview->selected) {
   1555 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1556 
   1557 		if (msginfo)
   1558 			messageview_show(messageview, msginfo,
   1559 					 messageview->all_headers);
   1560 	} else {
   1561 		gtk_widget_destroy(messageview->window);
   1562 	}
   1563 }
   1564 
   1565 static void prev_marked_cb(GtkAction *action, gpointer data)
   1566 {
   1567 	MessageView *messageview = (MessageView *)data;
   1568 	messageview->updating = TRUE;
   1569 	summary_select_prev_marked(messageview->mainwin->summaryview);
   1570 	messageview->updating = FALSE;
   1571 
   1572 	if (messageview->deferred_destroy) {
   1573 		debug_print("messageview got away!\n");
   1574 		messageview_destroy(messageview);
   1575 		return;
   1576 	}
   1577 	if (messageview->mainwin->summaryview->selected) {
   1578 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1579 
   1580 		if (msginfo)
   1581 			messageview_show(messageview, msginfo,
   1582 					 messageview->all_headers);
   1583 	} else {
   1584 		gtk_widget_destroy(messageview->window);
   1585 	}
   1586 }
   1587 
   1588 static void next_marked_cb(GtkAction *action, gpointer data)
   1589 {
   1590 	MessageView *messageview = (MessageView *)data;
   1591 	messageview->updating = TRUE;
   1592 	summary_select_next_marked(messageview->mainwin->summaryview);
   1593 	messageview->updating = FALSE;
   1594 
   1595 	if (messageview->deferred_destroy) {
   1596 		debug_print("messageview got away!\n");
   1597 		messageview_destroy(messageview);
   1598 		return;
   1599 	}
   1600 	if (messageview->mainwin->summaryview->selected) {
   1601 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1602 
   1603 		if (msginfo)
   1604 			messageview_show(messageview, msginfo,
   1605 					 messageview->all_headers);
   1606 	} else {
   1607 		gtk_widget_destroy(messageview->window);
   1608 	}
   1609 }
   1610 
   1611 static void prev_labeled_cb(GtkAction *action, gpointer data)
   1612 {
   1613 	MessageView *messageview = (MessageView *)data;
   1614 	messageview->updating = TRUE;
   1615 	summary_select_prev_labeled(messageview->mainwin->summaryview);
   1616 	messageview->updating = FALSE;
   1617 
   1618 	if (messageview->deferred_destroy) {
   1619 		debug_print("messageview got away!\n");
   1620 		messageview_destroy(messageview);
   1621 		return;
   1622 	}
   1623 	if (messageview->mainwin->summaryview->selected) {
   1624 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1625 
   1626 		if (msginfo)
   1627 			messageview_show(messageview, msginfo,
   1628 					 messageview->all_headers);
   1629 	} else {
   1630 		gtk_widget_destroy(messageview->window);
   1631 	}
   1632 }
   1633 
   1634 static void next_labeled_cb(GtkAction *action, gpointer data)
   1635 {
   1636 	MessageView *messageview = (MessageView *)data;
   1637 	messageview->updating = TRUE;
   1638 	summary_select_next_labeled(messageview->mainwin->summaryview);
   1639 	messageview->updating = FALSE;
   1640 
   1641 	if (messageview->deferred_destroy) {
   1642 		debug_print("messageview got away!\n");
   1643 		messageview_destroy(messageview);
   1644 		return;
   1645 	}
   1646 	if (messageview->mainwin->summaryview->selected) {
   1647 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1648 
   1649 		if (msginfo)
   1650 			messageview_show(messageview, msginfo,
   1651 					 messageview->all_headers);
   1652 	} else {
   1653 		gtk_widget_destroy(messageview->window);
   1654 	}
   1655 }
   1656 
   1657 static void prev_history_cb(GtkAction *action, gpointer data)
   1658 {
   1659 	MessageView *messageview = (MessageView *)data;
   1660 	MsgInfo *info = messageview_nav_get_prev(messageview);
   1661 	if (info) {
   1662 		messageview->updating = TRUE;
   1663 		messageview_show(messageview, info,
   1664 					 messageview->all_headers);
   1665 		messageview->updating = FALSE;
   1666 		procmsg_msginfo_free(&info);
   1667 		if (messageview->deferred_destroy) {
   1668 			debug_print("messageview got away!\n");
   1669 			messageview_destroy(messageview);
   1670 			return;
   1671 		}
   1672 	}
   1673 }
   1674 
   1675 static void next_history_cb(GtkAction *action, gpointer data)
   1676 {
   1677 	MessageView *messageview = (MessageView *)data;
   1678 	MsgInfo *info = messageview_nav_get_next(messageview);
   1679 	if (info) {
   1680 		messageview->updating = TRUE;
   1681 		messageview_show(messageview, info,
   1682 					 messageview->all_headers);
   1683 		messageview->updating = FALSE;
   1684 		procmsg_msginfo_free(&info);
   1685 		if (messageview->deferred_destroy) {
   1686 			debug_print("messageview got away!\n");
   1687 			messageview_destroy(messageview);
   1688 			return;
   1689 		}
   1690 	}
   1691 }
   1692 
   1693 static void parent_cb(GtkAction *action, gpointer data)
   1694 {
   1695 	MessageView *messageview = (MessageView *)data;
   1696 	messageview->updating = TRUE;
   1697 	summary_select_parent(messageview->mainwin->summaryview);
   1698 	messageview->updating = FALSE;
   1699 
   1700 	if (messageview->deferred_destroy) {
   1701 		debug_print("messageview got away!\n");
   1702 		messageview_destroy(messageview);
   1703 		return;
   1704 	}
   1705 	if (messageview->mainwin->summaryview->selected) {
   1706 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1707 
   1708 		if (msginfo)
   1709 			messageview_show(messageview, msginfo,
   1710 					 messageview->all_headers);
   1711 	} else {
   1712 		gtk_widget_destroy(messageview->window);
   1713 	}
   1714 }
   1715 
   1716 static void goto_unread_folder_cb(GtkAction *action, gpointer data)
   1717 {
   1718 	MessageView *messageview = (MessageView *)data;
   1719 
   1720 	messageview->updating = TRUE;
   1721 	folderview_select_next_with_flag(messageview->mainwin->folderview, MSG_UNREAD);
   1722 	messageview->updating = FALSE;
   1723 
   1724 	if (messageview->deferred_destroy) {
   1725 		debug_print("messageview got away!\n");
   1726 		messageview_destroy(messageview);
   1727 		return;
   1728 	}
   1729 	if (messageview->mainwin->summaryview->selected) {
   1730 		MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1731 
   1732 		if (msginfo)
   1733 			messageview_show(messageview, msginfo,
   1734 					 messageview->all_headers);
   1735 	} else {
   1736 		gtk_widget_destroy(messageview->window);
   1737 	}
   1738 }
   1739 
   1740 static void goto_folder_cb(GtkAction *action, gpointer data)
   1741 {
   1742 	MessageView *messageview = (MessageView *)data;
   1743 	FolderItem *to_folder;
   1744 
   1745 	to_folder = foldersel_folder_sel(NULL, FOLDER_SEL_ALL, NULL, FALSE,
   1746 			_("Select folder to go to"));
   1747 
   1748 	if (to_folder) {
   1749 		folderview_select(messageview->mainwin->folderview, to_folder);
   1750 
   1751 		if (messageview->deferred_destroy) {
   1752 			debug_print("messageview got away!\n");
   1753 			messageview_destroy(messageview);
   1754 			return;
   1755 		}
   1756 		if (messageview->mainwin->summaryview->selected) {
   1757 			MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
   1758 
   1759 			if (msginfo)
   1760 				messageview_show(messageview, msginfo,
   1761 						 messageview->all_headers);
   1762 		} else {
   1763 			gtk_widget_destroy(messageview->window);
   1764 		}
   1765 	}
   1766 }
   1767 
   1768 static void set_charset_cb(GtkAction *action, GtkRadioAction *current, gpointer data)
   1769 {
   1770 	MessageView *messageview = (MessageView *)data;
   1771 	gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current));
   1772 	gint value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (current));
   1773 	const gchar *charset;
   1774 
   1775 	if (active) {
   1776 		charset = conv_get_charset_str((CharSet)value);
   1777 		g_free(messageview->forced_charset);
   1778 		messageview->forced_charset = g_strdup(charset);
   1779 		procmime_force_charset(charset);
   1780 
   1781 		messageview_show(messageview, messageview->msginfo, FALSE);
   1782 	}
   1783 }
   1784 
   1785 static void set_decode_cb(GtkAction *action, GtkRadioAction *current, gpointer data)
   1786 {
   1787 	MessageView *messageview = (MessageView *)data;
   1788 	gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current));
   1789 	gint value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (current));
   1790 
   1791 	if (active) {
   1792 		messageview->forced_encoding = (EncodingType)value;
   1793 
   1794 		messageview_show(messageview, messageview->msginfo, FALSE);
   1795 		debug_print("forced encoding: %d\n", value);
   1796 	}
   1797 }
   1798 
   1799 
   1800 static void view_source_cb(GtkAction *action, gpointer data)
   1801 {
   1802 	MessageView *messageview = (MessageView *)data;
   1803 	SourceWindow *srcwin;
   1804 
   1805 	if (!messageview->msginfo) return;
   1806 
   1807 	srcwin = source_window_create();
   1808 	source_window_show(srcwin);
   1809 	source_window_show_msg(srcwin, messageview->msginfo);
   1810 }
   1811 
   1812 static void show_all_header_cb(GtkToggleAction *action, gpointer data)
   1813 {
   1814 	MessageView *messageview = (MessageView *)data;
   1815 	MsgInfo *msginfo = messageview->msginfo;
   1816 
   1817 	if (messageview->mimeview->textview &&
   1818 	    messageview->mimeview->textview->loading) {
   1819 		return;
   1820 	}
   1821 	if (messageview->updating)
   1822 		return;
   1823 
   1824 	messageview->all_headers = prefs_common.show_all_headers =
   1825 			gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
   1826 	if (!msginfo) return;
   1827 	messageview->msginfo = NULL;
   1828 	messageview_show(messageview, msginfo, messageview->all_headers);
   1829 	procmsg_msginfo_free(&msginfo);
   1830 	main_window_set_menu_sensitive(messageview->mainwin);
   1831 	summary_redisplay_msg(messageview->mainwin->summaryview);
   1832 }
   1833 
   1834 static void msg_hide_quotes_cb(GtkToggleAction *action, gpointer data)
   1835 {
   1836 	MessageView *messageview = (MessageView *)data;
   1837 	MsgInfo *msginfo = messageview->msginfo;
   1838 	static gboolean updating_menu = FALSE;
   1839 
   1840 	if (updating_menu)
   1841 		return;
   1842 	if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
   1843 		const gchar *a_name = gtk_action_get_name(GTK_ACTION(action));
   1844 		if (!strcmp(a_name, "View/Quotes/CollapseAll")) prefs_common.hide_quotes = 1;
   1845 		else if (!strcmp(a_name, "View/Quotes/Collapse2")) prefs_common.hide_quotes = 2;
   1846 		else if (!strcmp(a_name, "View/Quotes/Collapse3")) prefs_common.hide_quotes = 3;
   1847 	} else
   1848 		prefs_common.hide_quotes = 0;
   1849 
   1850 	updating_menu=TRUE;
   1851 
   1852 	cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/CollapseAll", (prefs_common.hide_quotes == 1));
   1853 	cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse2", (prefs_common.hide_quotes == 2));
   1854 	cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse3", (prefs_common.hide_quotes == 3));
   1855 
   1856 	updating_menu=FALSE;
   1857 	if (!msginfo) return;
   1858 	messageview->msginfo = NULL;
   1859 	messageview_show(messageview, msginfo,
   1860 			 messageview->all_headers);
   1861 	procmsg_msginfo_free(&msginfo);
   1862 
   1863 	/* update main window */
   1864 	main_window_set_menu_sensitive(messageview->mainwin);
   1865 	summary_redisplay_msg(messageview->mainwin->summaryview);
   1866 }
   1867 #undef SET_CHECK_MENU_ACTIVE
   1868 
   1869 static void compose_cb(GtkAction *action, gpointer data)
   1870 {
   1871 	MessageView *messageview = (MessageView *)data;
   1872 	PrefsAccount *ac = NULL;
   1873 	FolderItem *item = NULL;
   1874 
   1875 	if (messageview->msginfo)
   1876 		item = messageview->msginfo->folder;
   1877 	if (item)
   1878 		ac = account_find_from_item(item);
   1879 
   1880 	compose_new(ac, NULL, NULL);
   1881 }
   1882 
   1883 #define DO_ACTION(name, act)	{ if (!strcmp(a_name, name)) action = act; }
   1884 
   1885 static void reply_cb(GtkAction *gaction, gpointer data)
   1886 {
   1887 	MessageView *messageview = (MessageView *)data;
   1888 	GSList *msginfo_list = NULL;
   1889 	gint action = COMPOSE_REPLY;
   1890 	const gchar *a_name = gtk_action_get_name(gaction);
   1891 
   1892 	cm_return_if_fail(messageview->msginfo);
   1893 
   1894 	DO_ACTION("Message/Reply", COMPOSE_REPLY);
   1895 	DO_ACTION("Message/ReplyTo/All", COMPOSE_REPLY_TO_ALL);
   1896 	DO_ACTION("Message/ReplyTo/Sender", COMPOSE_REPLY_TO_SENDER);
   1897 	DO_ACTION("Message/ReplyTo/List", COMPOSE_REPLY_TO_LIST);
   1898 	DO_ACTION("Message/Forward", COMPOSE_FORWARD_INLINE);
   1899 	DO_ACTION("Message/ForwardAtt", COMPOSE_FORWARD_AS_ATTACH);
   1900 	DO_ACTION("Message/Redirect", COMPOSE_REDIRECT);
   1901 
   1902 	msginfo_list = g_slist_append(msginfo_list, messageview->msginfo);
   1903 	compose_reply_from_messageview(messageview, msginfo_list, action);
   1904 	g_slist_free(msginfo_list);
   1905 }
   1906 
   1907 static void addressbook_open_cb(GtkAction *action, gpointer data)
   1908 {
   1909 	addressbook_open(NULL);
   1910 }
   1911 
   1912 static void add_address_cb(GtkAction *action, gpointer data)
   1913 {
   1914 	MessageView *messageview = (MessageView *)data;
   1915 	MsgInfo *msginfo, *full_msginfo;
   1916 	gchar *from;
   1917 
   1918 	if (!messageview->msginfo || !messageview->msginfo->from)
   1919 		return;
   1920 
   1921 	msginfo = messageview->msginfo;
   1922 	Xstrdup_a(from, msginfo->from, return);
   1923 	eliminate_address_comment(from);
   1924 	extract_address(from);
   1925 
   1926 	full_msginfo = procmsg_msginfo_get_full_info(msginfo);
   1927 
   1928 	procmsg_msginfo_free(&full_msginfo);
   1929 
   1930 	addressbook_add_contact(msginfo->fromname, from, NULL, NULL);
   1931 }
   1932 
   1933 static gboolean messageview_update_msg(gpointer source, gpointer data)
   1934 {
   1935 	MsgInfoUpdate *msginfo_update = (MsgInfoUpdate *) source;
   1936 	MessageView *messageview = (MessageView *)data;
   1937 	MsgInfo *old_msginfo = messageview->msginfo;
   1938 
   1939 	if (messageview->msginfo != msginfo_update->msginfo)
   1940 		return FALSE;
   1941 
   1942 	if ((msginfo_update->flags & MSGINFO_UPDATE_DELETED) ||
   1943 	    MSG_IS_DELETED(old_msginfo->flags)) {
   1944 		if (messageview->new_window) {
   1945 			if (old_msginfo->folder && old_msginfo->folder->total_msgs == 0) {
   1946 				messageview_clear(messageview);
   1947 				textview_show_info(messageview->mimeview->textview,
   1948 					_("\n  There are no messages in this folder"));
   1949 				return FALSE;
   1950 			}
   1951 
   1952  			if (!OPEN_SELECTED_ON_DELETEMOVE && !OPEN_SELECTED_ON_PREVNEXT) {
   1953  				messageview_clear(messageview);
   1954   				textview_show_info(messageview->mimeview->textview,
   1955   					MSG_IS_DELETED(old_msginfo->flags) ?
   1956   					_("\n  Message has been deleted") :
   1957   					_("\n  Message has been deleted or moved to another folder"));
   1958 			} else
   1959 				messageview->update_needed = TRUE;
   1960 		} else {
   1961 			messageview_clear(messageview);
   1962 			messageview_update(messageview, old_msginfo);
   1963 		}
   1964 	}
   1965 
   1966 	return FALSE;
   1967 }
   1968 
   1969 void messageview_set_menu_sensitive(MessageView *messageview)
   1970 {
   1971 	if (!messageview || !messageview->ui_manager)
   1972 		return;
   1973 
   1974 	cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/CollapseAll", (prefs_common.hide_quotes == 1));
   1975 	cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse2", (prefs_common.hide_quotes == 2));
   1976 	cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse3", (prefs_common.hide_quotes == 3));
   1977 	cm_menu_set_sensitive_full(messageview->ui_manager, "Menu/View/Goto/PrevHistory", messageview_nav_has_prev(messageview));
   1978 	cm_menu_set_sensitive_full(messageview->ui_manager, "Menu/View/Goto/NextHistory", messageview_nav_has_next(messageview));
   1979 }
   1980 
   1981 static void save_part_as_cb(GtkAction *action, gpointer data)
   1982 {
   1983 	MessageView *messageview = (MessageView *)data;
   1984 
   1985 	if (messageview->mimeview)
   1986 		mimeview_save_as(messageview->mimeview);
   1987 }
   1988 
   1989 static void view_part_as_text_cb(GtkAction *action, gpointer data)
   1990 {
   1991 	MessageView *messageview = (MessageView *)data;
   1992 
   1993 	if (messageview->mimeview)
   1994 		mimeview_display_as_text(messageview->mimeview);
   1995 }
   1996 
   1997 static void open_part_cb(GtkAction *action, gpointer data)
   1998 {
   1999 	MessageView *messageview = (MessageView *)data;
   2000 
   2001 	if (messageview->mimeview)
   2002 		mimeview_launch(messageview->mimeview, NULL);
   2003 }
   2004 
   2005 static void open_part_with_cb(GtkAction *action, gpointer data)
   2006 {
   2007 	MessageView *messageview = (MessageView *)data;
   2008 
   2009 	if (messageview->mimeview)
   2010 		mimeview_open_with(messageview->mimeview);
   2011 }
   2012 
   2013 static void goto_next_part_cb(GtkAction *action, gpointer data)
   2014 {
   2015 	MessageView *messageview = (MessageView *)data;
   2016 
   2017 	if (messageview->mimeview)
   2018 		mimeview_select_next_part(messageview->mimeview);
   2019 }
   2020 
   2021 static void goto_prev_part_cb(GtkAction *action, gpointer data)
   2022 {
   2023 	MessageView *messageview = (MessageView *)data;
   2024 
   2025 	if (messageview->mimeview)
   2026 		mimeview_select_prev_part(messageview->mimeview);
   2027 }
   2028