2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2016 Hiroyuki Yamamoto and the Claws Mail team
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.
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.
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/>.
22 #include <glib/gi18n.h>
23 #include <gdk/gdkkeysyms.h>
30 #include "messageview.h"
31 #include "message_search.h"
32 #include "headerview.h"
33 #include "summaryview.h"
39 #include "foldersel.h"
40 #include "sourcewindow.h"
41 #include "alertpanel.h"
42 #include "inputdialog.h"
43 #include "mainwindow.h"
44 #include "manage_window.h"
46 #include "procheader.h"
50 #include "prefs_common.h"
51 #include "prefs_account.h"
54 #include "send_message.h"
55 #include "stock_pixmap.h"
57 #include "filtering.h"
58 #include "partial_download.h"
59 #include "uri_opener.h"
65 #include "quoted-printable.h"
67 #include "statusbar.h"
68 #include "folder_item_prefs.h"
70 #ifndef USE_ALT_ADDRBOOK
71 #include "addressbook.h"
73 #include "addressadd.h"
74 #include "addressbook-dbus.h"
76 static GList *messageview_list = NULL;
78 static gint messageview_delete_cb (GtkWidget *widget,
80 MessageView *messageview);
81 static void messageview_size_allocate_cb(GtkWidget *widget,
82 GtkAllocation *allocation);
83 static gboolean key_pressed (GtkWidget *widget,
85 MessageView *messageview);
86 static void return_receipt_show (NoticeView *noticeview,
88 static void return_receipt_send_clicked (NoticeView *noticeview,
90 static void partial_recv_show (NoticeView *noticeview,
92 static void partial_recv_dload_clicked (NoticeView *noticeview,
94 static void partial_recv_del_clicked (NoticeView *noticeview,
96 static void partial_recv_unmark_clicked (NoticeView *noticeview,
98 static void save_as_cb (GtkAction *action,
100 static void page_setup_cb (GtkAction *action,
102 static void print_cb (GtkAction *action,
104 static void close_cb (GtkAction *action,
106 static void copy_cb (GtkAction *action,
108 static void allsel_cb (GtkAction *action,
110 static void search_cb (GtkAction *action,
113 static void prev_cb (GtkAction *action,
115 static void next_cb (GtkAction *action,
117 static void prev_unread_cb (GtkAction *action,
119 static void next_unread_cb (GtkAction *action,
121 static void prev_new_cb (GtkAction *action,
123 static void next_new_cb (GtkAction *action,
125 static void prev_marked_cb (GtkAction *action,
127 static void next_marked_cb (GtkAction *action,
129 static void prev_labeled_cb (GtkAction *action,
131 static void next_labeled_cb (GtkAction *action,
133 static void prev_history_cb (GtkAction *action,
135 static void next_history_cb (GtkAction *action,
137 static void parent_cb (GtkAction *action,
139 static void goto_unread_folder_cb (GtkAction *action,
141 static void goto_folder_cb (GtkAction *action,
144 static void scroll_prev_line_cb (GtkAction *action,
146 static void scroll_next_line_cb (GtkAction *action,
148 static void scroll_next_page_cb (GtkAction *action,
150 static void scroll_prev_page_cb (GtkAction *action,
153 static void set_charset_cb (GtkAction *action, GtkRadioAction *current, gpointer data);
154 static void set_decode_cb (GtkAction *action, GtkRadioAction *current, gpointer data);
156 static void view_source_cb (GtkAction *action,
159 static void show_all_header_cb (GtkToggleAction *action,
161 static void msg_hide_quotes_cb (GtkToggleAction *action,
164 static void compose_cb (GtkAction *action,
166 static void reply_cb (GtkAction *action,
169 static PrefsAccount *select_account_from_list
171 static void addressbook_open_cb (GtkAction *action,
173 static void add_address_cb (GtkAction *action,
175 static void create_filter_cb (GtkAction *action,
177 static void create_processing_cb (GtkAction *action,
179 static void open_urls_cb (GtkAction *action,
182 static void about_cb (GtkAction *action,
184 static void messageview_update (MessageView *msgview,
185 MsgInfo *old_msginfo);
186 static gboolean messageview_update_msg (gpointer source, gpointer data);
188 static void save_part_as_cb(GtkAction *action, gpointer data);
189 static void view_part_as_text_cb(GtkAction *action, gpointer data);
190 static void open_part_cb(GtkAction *action, gpointer data);
192 static void open_part_with_cb(GtkAction *action, gpointer data);
194 static void check_signature_cb(GtkAction *action, gpointer data);
195 static void goto_next_part_cb(GtkAction *action, gpointer data);
196 static void goto_prev_part_cb(GtkAction *action, gpointer data);
198 static void messageview_nothing_cb (GtkAction *action, gpointer data)
203 static GList *msgview_list = NULL;
204 static GtkActionEntry msgview_entries[] =
206 {"Menu", NULL, "Menu" },
208 {"File", NULL, N_("_File") },
209 {"Edit", NULL, N_("_Edit") },
210 {"View", NULL, N_("_View") },
211 {"Message", NULL, N_("_Message") },
212 {"Tools", NULL, N_("_Tools") },
213 {"Help", NULL, N_("_Help") },
214 {"PlaceHolder", NULL, "Placeholder", NULL, NULL, G_CALLBACK(messageview_nothing_cb) },
217 {"File/SaveAs", NULL, N_("_Save email as..."), "<control>S", NULL, G_CALLBACK(save_as_cb) },
218 {"File/SavePartAs", NULL, N_("_Save part as..."), "Y", NULL, G_CALLBACK(save_part_as_cb) },
219 {"File/PageSetup", NULL, N_("Page setup..."), NULL, NULL, G_CALLBACK(page_setup_cb) },
220 {"File/Print", NULL, N_("_Print..."), "<control>P", NULL, G_CALLBACK(print_cb) },
221 {"File/---", NULL, "---", NULL, NULL, NULL },
222 {"File/Close", NULL, N_("_Close"), "<control>W", NULL, G_CALLBACK(close_cb) },
225 {"Edit/Copy", NULL, N_("_Copy"), "<control>C", NULL, G_CALLBACK(copy_cb) },
226 {"Edit/SelectAll", NULL, N_("_Select all"), "<control>A", NULL, G_CALLBACK(allsel_cb) },
227 {"Edit/---", NULL, "---", NULL, NULL, NULL },
228 {"Edit/Find", NULL, N_("_Find"), "<control>F", NULL, G_CALLBACK(search_cb) },
231 {"View/Goto", NULL, N_("_Go to") },
232 {"View/Goto/Prev", NULL, N_("_Previous message"), "P", NULL, G_CALLBACK(prev_cb) },
233 {"View/Goto/Next", NULL, N_("_Next message"), "N", NULL, G_CALLBACK(next_cb) },
234 {"View/Goto/---", NULL, "---", NULL, NULL, NULL },
235 {"View/Goto/PrevUnread", NULL, N_("P_revious unread message"), "<shift>P", NULL, G_CALLBACK(prev_unread_cb) },
236 {"View/Goto/NextUnread", NULL, N_("N_ext unread message"), "<shift>N", NULL, G_CALLBACK(next_unread_cb) },
237 /* {"View/Goto/---", NULL, "---", NULL, NULL, NULL }, */
238 {"View/Goto/PrevNew", NULL, N_("Previous ne_w message"), NULL, NULL, G_CALLBACK(prev_new_cb) },
239 {"View/Goto/NextNew", NULL, N_("Ne_xt new message"), NULL, NULL, G_CALLBACK(next_new_cb) },
240 /* {"View/Goto/---", NULL, "---", NULL, NULL, NULL }, */
241 {"View/Goto/PrevMarked", NULL, N_("Previous _marked message"), NULL, NULL, G_CALLBACK(prev_marked_cb) },
242 {"View/Goto/NextMarked", NULL, N_("Next m_arked message"), NULL, NULL, G_CALLBACK(next_marked_cb) },
243 /* {"View/Goto/---", NULL, "---", NULL, NULL, NULL }, */
244 {"View/Goto/PrevLabeled", NULL, N_("Previous _labeled message"), NULL, NULL, G_CALLBACK(prev_labeled_cb) },
245 {"View/Goto/NextLabeled", NULL, N_("Next la_beled message"), NULL, NULL, G_CALLBACK(next_labeled_cb) },
246 /* {"View/Goto/---", NULL, "---", NULL, NULL, NULL }, */
247 {"View/Goto/PrevHistory", NULL, N_("Previous opened message"), "<alt>Left", NULL, G_CALLBACK(prev_history_cb) },
248 {"View/Goto/NextHistory", NULL, N_("Next opened message"), "<alt>Right", NULL, G_CALLBACK(next_history_cb) },
249 /* {"View/Goto/---", NULL, "---", NULL, NULL, NULL }, */
250 {"View/Goto/ParentMessage", NULL, N_("Parent message"), "<control>Up", NULL, G_CALLBACK(parent_cb) },
251 /* {"View/Goto/---", NULL, "---", NULL, NULL, NULL }, */
252 {"View/Goto/NextUnreadFolder", NULL, N_("Next unread _folder"), "<shift>G", NULL, G_CALLBACK(goto_unread_folder_cb) },
253 {"View/Goto/Folder", NULL, N_("F_older..."), "G", NULL, G_CALLBACK(goto_folder_cb) },
254 /* {"View/Goto/---", NULL, "---", NULL, NULL, NULL }, */
255 {"View/Goto/NextPart", NULL, N_("Next part"), "A", NULL, G_CALLBACK(goto_next_part_cb) },
256 {"View/Goto/PrevPart", NULL, N_("Previous part"), "Z", NULL, G_CALLBACK(goto_prev_part_cb) },
257 {"View/Scroll", NULL, N_("Message scroll") },
258 {"View/Scroll/PrevLine", NULL, N_("Previous line"), NULL, NULL, G_CALLBACK(scroll_prev_line_cb) },
259 {"View/Scroll/NextLine", NULL, N_("Next line"), NULL, NULL, G_CALLBACK(scroll_next_line_cb) },
260 {"View/Scroll/PrevPage", NULL, N_("Previous page"), NULL, NULL, G_CALLBACK(scroll_prev_page_cb) },
261 {"View/Scroll/NextPage", NULL, N_("Next page"), NULL, NULL, G_CALLBACK(scroll_next_page_cb) },
262 /* {"View/Scroll/---", NULL, "---", NULL, NULL, NULL }, */
264 {"View/Encoding", NULL, N_("Character _encoding") }, /* set_charset_cb */
265 {"View/Encoding/---", NULL, "---" },
266 #define ENC_ACTION(cs_char,c_char,string) \
267 { "View/Encoding/" cs_char, NULL, N_(string), NULL, NULL, c_char }
269 {"View/Encoding/Western", NULL, N_("Western European") },
270 {"View/Encoding/Baltic", NULL, N_("Baltic") },
271 {"View/Encoding/Hebrew", NULL, N_("Hebrew") },
272 {"View/Encoding/Arabic", NULL, N_("Arabic") },
273 {"View/Encoding/Cyrillic", NULL, N_("Cyrillic") },
274 {"View/Encoding/Japanese", NULL, N_("Japanese") },
275 {"View/Encoding/Chinese", NULL, N_("Chinese") },
276 {"View/Encoding/Korean", NULL, N_("Korean") },
277 {"View/Encoding/Thai", NULL, N_("Thai") },
279 {"View/Decode", NULL, N_("Decode") }, /* set_decode_cb */
280 {"View/Decode/---", NULL, "---" },
282 #define DEC_ACTION(cs_type,c_type,string) \
283 { "View/Decode/" cs_type, NULL, N_(string), NULL, NULL, c_type }
285 {"View/---", NULL, "---", NULL, NULL, NULL },
286 {"View/MessageSource", NULL, N_("Mess_age source"), "<control>U", NULL, G_CALLBACK(view_source_cb) },
287 {"View/Part", NULL, N_("Message part") },
288 {"View/Part/AsText", NULL, N_("View as text"), "T", NULL, G_CALLBACK(view_part_as_text_cb) },
289 {"View/Part/Open", NULL, N_("Open"), "L", NULL, G_CALLBACK(open_part_cb) },
291 {"View/Part/OpenWith", NULL, N_("Open with..."), "O", NULL, G_CALLBACK(open_part_with_cb) },
294 {"View/Quotes", NULL, N_("Quotes") },
297 {"Message/Compose", NULL, N_("Compose _new message"), "<control>M", NULL, G_CALLBACK(compose_cb) },
298 {"Message/---", NULL, "---", NULL, NULL, NULL },
300 {"Message/Reply", NULL, N_("_Reply"), "<control>R", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY */
301 {"Message/ReplyTo", NULL, N_("Repl_y to") },
302 {"Message/ReplyTo/All", NULL, N_("_All"), "<control><shift>R", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY_TO_ALL */
303 {"Message/ReplyTo/Sender", NULL, N_("_Sender"), NULL, NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY_TO_SENDER */
304 {"Message/ReplyTo/List", NULL, N_("Mailing _list"), "<control>L", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REPLY_TO_LIST */
305 /* {"Message/---", NULL, "---", NULL, NULL, NULL }, */
307 {"Message/Forward", NULL, N_("_Forward"), "<control><alt>F", NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_FORWARD_INLINE */
308 {"Message/ForwardAtt", NULL, N_("For_ward as attachment"), NULL, NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_FORWARD_AS_ATTACH */
309 {"Message/Redirect", NULL, N_("Redirec_t"), NULL, NULL, G_CALLBACK(reply_cb) }, /* COMPOSE_REDIRECT */
310 {"Message/CheckSignature", NULL, N_("Check signature"), "C", NULL, G_CALLBACK(check_signature_cb) },
313 {"Tools/AddressBook", NULL, N_("_Address book"), "<control><shift>A", NULL, G_CALLBACK(addressbook_open_cb) },
314 {"Tools/AddSenderToAB", NULL, N_("Add sender to address boo_k"), NULL, NULL, G_CALLBACK(add_address_cb) },
315 {"Tools/---", NULL, "---", NULL, NULL, NULL },
317 {"Tools/CreateFilterRule", NULL, N_("_Create filter rule") },
318 {"Tools/CreateFilterRule/Automatically", NULL, N_("_Automatically"), NULL, NULL, G_CALLBACK(create_filter_cb) }, /* FILTER_BY_AUTO */
319 {"Tools/CreateFilterRule/ByFrom", NULL, N_("By _From"), NULL, NULL, G_CALLBACK(create_filter_cb) }, /* FILTER_BY_FROM */
320 {"Tools/CreateFilterRule/ByTo", NULL, N_("By _To"), NULL, NULL, G_CALLBACK(create_filter_cb) }, /* FILTER_BY_TO */
321 {"Tools/CreateFilterRule/BySubject", NULL, N_("By _Subject"), NULL, NULL, G_CALLBACK(create_filter_cb) }, /* FILTER_BY_SUBJECT */
323 {"Tools/CreateProcessingRule", NULL, N_("Create processing rule") },
324 {"Tools/CreateProcessingRule/Automatically", NULL, N_("_Automatically"), NULL, NULL, G_CALLBACK(create_processing_cb) },
325 {"Tools/CreateProcessingRule/ByFrom", NULL, N_("By _From"), NULL, NULL, G_CALLBACK(create_processing_cb) },
326 {"Tools/CreateProcessingRule/ByTo", NULL, N_("By _To"), NULL, NULL, G_CALLBACK(create_processing_cb) },
327 {"Tools/CreateProcessingRule/BySubject", NULL, N_("By _Subject"), NULL, NULL, G_CALLBACK(create_processing_cb) },
329 /* {"Tools/---", NULL, "---", NULL, NULL, NULL }, */
331 {"Tools/ListUrls", NULL, N_("List _URLs..."), "<control><shift>U", NULL, G_CALLBACK(open_urls_cb) },
333 /* {"Tools/---", NULL, "---", NULL, NULL, NULL }, */
334 {"Tools/Actions", NULL, N_("Actio_ns") },
335 {"Tools/Actions/PlaceHolder", NULL, "Placeholder", NULL, NULL, G_CALLBACK(messageview_nothing_cb) },
338 {"Help/About", NULL, N_("_About"), NULL, NULL, G_CALLBACK(about_cb) },
341 static GtkToggleActionEntry msgview_toggle_entries[] =
343 {"View/AllHeaders", NULL, N_("Show all _headers"), "<control>H", NULL, G_CALLBACK(show_all_header_cb) }, /* toggle */
344 {"View/Quotes/CollapseAll", NULL, N_("_Collapse all"), "<control><shift>Q", NULL, G_CALLBACK(msg_hide_quotes_cb) }, /* 1 toggle */
345 {"View/Quotes/Collapse2", NULL, N_("Collapse from level _2"), NULL, NULL, G_CALLBACK(msg_hide_quotes_cb) }, /* 2 toggle */
346 {"View/Quotes/Collapse3", NULL, N_("Collapse from level _3"), NULL, NULL, G_CALLBACK(msg_hide_quotes_cb) }, /* 3 toggle */
349 static GtkRadioActionEntry msgview_radio_enc_entries[] =
351 ENC_ACTION(CS_AUTO, C_AUTO, N_("_Automatic")), /* RADIO set_charset_cb */
352 ENC_ACTION(CS_US_ASCII, C_US_ASCII, N_("7bit ASCII (US-ASC_II)")), /* RADIO set_charset_cb */
353 ENC_ACTION(CS_UTF_8, C_UTF_8, N_("Unicode (_UTF-8)")), /* RADIO set_charset_cb */
354 ENC_ACTION("Western/"CS_ISO_8859_1, C_ISO_8859_1, "ISO-8859-_1"), /* RADIO set_charset_cb */
355 ENC_ACTION("Western/"CS_ISO_8859_15, C_ISO_8859_15, "ISO-8859-15"), /* RADIO set_charset_cb */
356 ENC_ACTION("Western/"CS_WINDOWS_1252, C_WINDOWS_1252, "Windows-1252"), /* RADIO set_charset_cb */
357 ENC_ACTION(CS_ISO_8859_2, C_ISO_8859_2, N_("Central European (ISO-8859-_2)")), /* RADIO set_charset_cb */
358 ENC_ACTION("Baltic/"CS_ISO_8859_13, C_ISO_8859_13, "ISO-8859-13"), /* RADIO set_charset_cb */
359 ENC_ACTION("Baltic/"CS_ISO_8859_4, C_ISO_8859_14, "ISO-8859-_4"), /* RADIO set_charset_cb */
360 ENC_ACTION(CS_ISO_8859_7, C_ISO_8859_7, N_("Greek (ISO-8859-_7)")), /* RADIO set_charset_cb */
361 ENC_ACTION("Hebrew/"CS_ISO_8859_8, C_ISO_8859_8, "ISO-8859-_8"), /* RADIO set_charset_cb */
362 ENC_ACTION("Hebrew/"CS_WINDOWS_1255, C_WINDOWS_1255, "Windows-1255"), /* RADIO set_charset_cb */
363 ENC_ACTION("Arabic/"CS_ISO_8859_6, C_ISO_8859_6, "ISO-8859-_6"), /* RADIO set_charset_cb */
364 ENC_ACTION("Arabic/"CS_WINDOWS_1256, C_WINDOWS_1256, "Windows-1256"), /* RADIO set_charset_cb */
365 ENC_ACTION(CS_ISO_8859_9, C_ISO_8859_9, N_("Turkish (ISO-8859-_9)")), /* RADIO set_charset_cb */
366 ENC_ACTION("Cyrillic/"CS_ISO_8859_5, C_ISO_8859_5, "ISO-8859-_5"), /* RADIO set_charset_cb */
367 ENC_ACTION("Cyrillic/"CS_KOI8_R, C_KOI8_R, "KOI8-_R"), /* RADIO set_charset_cb */
368 ENC_ACTION("Cyrillic/"CS_MACCYR, C_MACCYR, "MAC_CYR"), /* RADIO set_charset_cb */
369 ENC_ACTION("Cyrillic/"CS_KOI8_U, C_KOI8_U, "KOI8-_U"), /* RADIO set_charset_cb */
370 ENC_ACTION("Cyrillic/"CS_WINDOWS_1251, C_WINDOWS_1251, "Windows-1251"), /* RADIO set_charset_cb */
371 ENC_ACTION("Japanese/"CS_ISO_2022_JP, C_ISO_2022_JP, "ISO-2022-_JP"), /* RADIO set_charset_cb */
372 ENC_ACTION("Japanese/"CS_ISO_2022_JP_2, C_ISO_2022_JP_2, "ISO-2022-JP-_2"), /* RADIO set_charset_cb */
373 ENC_ACTION("Japanese/"CS_EUC_JP, C_EUC_JP, "_EUC-JP"), /* RADIO set_charset_cb */
374 ENC_ACTION("Japanese/"CS_SHIFT_JIS, C_SHIFT_JIS, "_Shift-JIS"), /* RADIO set_charset_cb */
375 ENC_ACTION("Chinese/"CS_GB18030, C_GB18030, "_GB18030"), /* RADIO set_charset_cb */
376 ENC_ACTION("Chinese/"CS_GB2312, C_GB2312, "_GB2312"), /* RADIO set_charset_cb */
377 ENC_ACTION("Chinese/"CS_GBK, C_GBK, "GB_K"), /* RADIO set_charset_cb */
378 ENC_ACTION("Chinese/"CS_BIG5, C_BIG5, "_Big5-JP"), /* RADIO set_charset_cb */
379 ENC_ACTION("Chinese/"CS_EUC_TW, C_EUC_TW, "EUC-_TW"), /* RADIO set_charset_cb */
380 ENC_ACTION("Korean/"CS_EUC_KR, C_EUC_KR, "_EUC-KR"), /* RADIO set_charset_cb */
381 ENC_ACTION("Korean/"CS_ISO_2022_KR, C_ISO_2022_KR, "_ISO-2022-KR"), /* RADIO set_charset_cb */
382 ENC_ACTION("Thai/"CS_TIS_620, C_TIS_620, "_TIS-620-KR"), /* RADIO set_charset_cb */
383 ENC_ACTION("Thai/"CS_WINDOWS_874, C_WINDOWS_874, "_Windows-874"), /* RADIO set_charset_cb */
386 static GtkRadioActionEntry msgview_radio_dec_entries[] =
388 DEC_ACTION("AutoDetect", 0, N_("_Auto detect")), /* set_decode_cb */
390 DEC_ACTION("8bit", ENC_8BIT, "_8bit"),
391 DEC_ACTION("QP", ENC_QUOTED_PRINTABLE, "_Quoted printable"),
392 DEC_ACTION("B64", ENC_BASE64, "_Base64"),
393 DEC_ACTION("Uuencode", ENC_X_UUENCODE, "_Uuencode"),
396 MessageView *messageview_create(MainWindow *mainwin)
398 MessageView *messageview;
400 HeaderView *headerview;
402 NoticeView *noticeview;
404 debug_print("Creating message view...\n");
405 messageview = g_new0(MessageView, 1);
407 headerview = headerview_create();
409 noticeview = noticeview_create(mainwin);
411 mimeview = mimeview_create(mainwin);
412 mimeview->textview = textview_create();
413 mimeview->textview->messageview = messageview;
414 mimeview->messageview = messageview;
416 vbox = gtk_vbox_new(FALSE, 0);
417 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(headerview),
419 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(noticeview),
421 gtk_box_pack_start(GTK_BOX(vbox),
422 GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
423 gtk_widget_show(vbox);
425 messageview->vbox = vbox;
426 messageview->new_window = FALSE;
427 messageview->window = NULL;
428 messageview->headerview = headerview;
429 messageview->mimeview = mimeview;
430 messageview->noticeview = noticeview;
431 messageview->mainwin = mainwin;
433 messageview->statusbar = NULL;
434 messageview->statusbar_cid = 0;
436 messageview->show_full_text= FALSE;
437 messageview->update_needed = FALSE;
439 messageview->msginfo_update_callback_id =
440 hooks_register_hook(MSGINFO_UPDATE_HOOKLIST, messageview_update_msg, (gpointer) messageview);
445 const GList *messageview_get_msgview_list(void)
450 void messageview_update_actions_menu(MessageView *msgview)
452 /* Messages opened in a new window do not have a menu bar */
453 if (msgview->menubar == NULL)
455 action_update_msgview_menu(msgview->ui_manager, "/Menu/Tools/Actions", msgview);
458 static void messageview_add_toolbar(MessageView *msgview, GtkWidget *window)
460 GtkWidget *handlebox;
464 GtkWidget *statusbar = NULL;
466 GtkActionGroup *action_group;
469 vbox = gtk_vbox_new(FALSE, 0);
470 gtk_widget_show(vbox);
471 gtk_container_add(GTK_CONTAINER(window), vbox);
473 msgview->ui_manager = gtk_ui_manager_new();
474 action_group = cm_menu_create_action_group_full(msgview->ui_manager,"Menu", msgview_entries,
475 G_N_ELEMENTS(msgview_entries), (gpointer)msgview);
476 gtk_action_group_add_toggle_actions(action_group, msgview_toggle_entries,
477 G_N_ELEMENTS(msgview_toggle_entries), (gpointer)msgview);
478 gtk_action_group_add_radio_actions(action_group, msgview_radio_enc_entries,
479 G_N_ELEMENTS(msgview_radio_enc_entries), C_AUTO, G_CALLBACK(set_charset_cb), (gpointer)msgview);
480 gtk_action_group_add_radio_actions(action_group, msgview_radio_dec_entries,
481 G_N_ELEMENTS(msgview_radio_dec_entries), C_AUTO, G_CALLBACK(set_decode_cb), (gpointer)msgview);
483 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_MENUBAR)
484 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "File", "File", GTK_UI_MANAGER_MENU)
485 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "Edit", "Edit", GTK_UI_MANAGER_MENU)
486 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "View", "View", GTK_UI_MANAGER_MENU)
487 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "Message", "Message", GTK_UI_MANAGER_MENU)
488 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "Tools", "Tools", GTK_UI_MANAGER_MENU)
489 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu", "Help", "Help", GTK_UI_MANAGER_MENU)
492 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "SaveAs", "File/SaveAs", GTK_UI_MANAGER_MENUITEM)
493 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "SavePartAs", "File/SavePartAs", GTK_UI_MANAGER_MENUITEM)
494 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "Separator1", "File/---", GTK_UI_MANAGER_SEPARATOR)
495 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "PageSetup", "File/PageSetup", GTK_UI_MANAGER_MENUITEM)
496 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "Print", "File/Print", GTK_UI_MANAGER_MENUITEM)
497 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "Separator2", "File/---", GTK_UI_MANAGER_SEPARATOR)
498 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/File", "Close", "File/Close", GTK_UI_MANAGER_MENUITEM)
501 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "Copy", "Edit/Copy", GTK_UI_MANAGER_MENUITEM)
502 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "SelectAll", "Edit/SelectAll", GTK_UI_MANAGER_MENUITEM)
503 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "Separator1", "Edit/---", GTK_UI_MANAGER_SEPARATOR)
504 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Edit", "Find", "Edit/Find", GTK_UI_MANAGER_MENUITEM)
507 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Goto", "View/Goto", GTK_UI_MANAGER_MENU)
508 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Prev", "View/Goto/Prev", GTK_UI_MANAGER_MENUITEM)
509 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Next", "View/Goto/Next", GTK_UI_MANAGER_MENUITEM)
510 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator1", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
511 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevUnread", "View/Goto/PrevUnread", GTK_UI_MANAGER_MENUITEM)
512 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextUnread", "View/Goto/NextUnread", GTK_UI_MANAGER_MENUITEM)
513 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator2", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
514 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevNew", "View/Goto/PrevNew", GTK_UI_MANAGER_MENUITEM)
515 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextNew", "View/Goto/NextNew", GTK_UI_MANAGER_MENUITEM)
516 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator3", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
517 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevMarked", "View/Goto/PrevMarked", GTK_UI_MANAGER_MENUITEM)
518 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextMarked", "View/Goto/NextMarked", GTK_UI_MANAGER_MENUITEM)
519 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator4", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
520 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevLabeled", "View/Goto/PrevLabeled", GTK_UI_MANAGER_MENUITEM)
521 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextLabeled", "View/Goto/NextLabeled", GTK_UI_MANAGER_MENUITEM)
522 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator5", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
523 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevHistory", "View/Goto/PrevHistory", GTK_UI_MANAGER_MENUITEM)
524 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextHistory", "View/Goto/NextHistory", GTK_UI_MANAGER_MENUITEM)
525 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator6", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
526 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "ParentMessage", "View/Goto/ParentMessage", GTK_UI_MANAGER_MENUITEM)
527 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator7", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
528 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextUnreadFolder", "View/Goto/NextUnreadFolder", GTK_UI_MANAGER_MENUITEM)
529 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Folder", "View/Goto/Folder", GTK_UI_MANAGER_MENUITEM)
530 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "Separator8", "View/Goto/---", GTK_UI_MANAGER_SEPARATOR)
531 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "NextPart", "View/Goto/NextPart", GTK_UI_MANAGER_MENUITEM)
532 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Goto", "PrevPart", "View/Goto/PrevPart", GTK_UI_MANAGER_MENUITEM)
534 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Scroll", "View/Scroll", GTK_UI_MANAGER_MENU)
535 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Scroll", "PrevLine", "View/Scroll/PrevLine", GTK_UI_MANAGER_MENUITEM)
536 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Scroll", "NextLine", "View/Scroll/NextLine", GTK_UI_MANAGER_MENUITEM)
537 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Scroll", "PrevPage", "View/Scroll/PrevPage", GTK_UI_MANAGER_MENUITEM)
538 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Scroll", "NextPage", "View/Scroll/NextPage", GTK_UI_MANAGER_MENUITEM)
540 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Separator1", "View/---", GTK_UI_MANAGER_SEPARATOR)
542 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Encoding", "View/Encoding", GTK_UI_MANAGER_MENU)
543 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_AUTO, "View/Encoding/"CS_AUTO, GTK_UI_MANAGER_MENUITEM)
544 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Separator1", "View/Encoding/---", GTK_UI_MANAGER_SEPARATOR)
545 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_US_ASCII, "View/Encoding/"CS_US_ASCII, GTK_UI_MANAGER_MENUITEM)
546 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_UTF_8, "View/Encoding/"CS_UTF_8, GTK_UI_MANAGER_MENUITEM)
547 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Separator2", "View/Encoding/---", GTK_UI_MANAGER_SEPARATOR)
549 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Western", "View/Encoding/Western", GTK_UI_MANAGER_MENU)
550 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)
551 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)
552 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Western", CS_WINDOWS_1252, "View/Encoding/Western/"CS_WINDOWS_1252, GTK_UI_MANAGER_MENUITEM)
554 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_ISO_8859_2, "View/Encoding/"CS_ISO_8859_2, GTK_UI_MANAGER_MENUITEM)
556 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Baltic", "View/Encoding/Baltic", GTK_UI_MANAGER_MENU)
557 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)
558 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)
560 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_ISO_8859_7, "View/Encoding/"CS_ISO_8859_7, GTK_UI_MANAGER_MENUITEM)
562 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Hebrew", "View/Encoding/Hebrew", GTK_UI_MANAGER_MENU)
563 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)
564 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Hebrew", CS_WINDOWS_1255, "View/Encoding/Hebrew/"CS_WINDOWS_1255, GTK_UI_MANAGER_MENUITEM)
566 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Arabic", "View/Encoding/Arabic", GTK_UI_MANAGER_MENU)
567 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)
568 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Arabic", CS_WINDOWS_1256, "View/Encoding/Arabic/"CS_WINDOWS_1256, GTK_UI_MANAGER_MENUITEM)
570 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", CS_ISO_8859_9, "View/Encoding/"CS_ISO_8859_9, GTK_UI_MANAGER_MENUITEM)
572 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Cyrillic", "View/Encoding/Cyrillic", GTK_UI_MANAGER_MENU)
573 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)
574 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_KOI8_R, "View/Encoding/Cyrillic/"CS_KOI8_R, GTK_UI_MANAGER_MENUITEM)
575 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_MACCYR, "View/Encoding/Cyrillic/"CS_MACCYR, GTK_UI_MANAGER_MENUITEM)
576 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_KOI8_U, "View/Encoding/Cyrillic/"CS_KOI8_U, GTK_UI_MANAGER_MENUITEM)
577 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Cyrillic", CS_WINDOWS_1251, "View/Encoding/Cyrillic/"CS_WINDOWS_1251, GTK_UI_MANAGER_MENUITEM)
579 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Japanese", "View/Encoding/Japanese", GTK_UI_MANAGER_MENU)
580 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)
581 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)
582 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Japanese", CS_EUC_JP, "View/Encoding/Japanese/"CS_EUC_JP, GTK_UI_MANAGER_MENUITEM)
583 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Japanese", CS_SHIFT_JIS, "View/Encoding/Japanese/"CS_SHIFT_JIS, GTK_UI_MANAGER_MENUITEM)
585 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Chinese", "View/Encoding/Chinese", GTK_UI_MANAGER_MENU)
586 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_GB18030, "View/Encoding/Chinese/"CS_GB18030, GTK_UI_MANAGER_MENUITEM)
587 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_GB2312, "View/Encoding/Chinese/"CS_GB2312, GTK_UI_MANAGER_MENUITEM)
588 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_GBK, "View/Encoding/Chinese/"CS_GBK, GTK_UI_MANAGER_MENUITEM)
589 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_BIG5, "View/Encoding/Chinese/"CS_BIG5, GTK_UI_MANAGER_MENUITEM)
590 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Chinese", CS_EUC_TW, "View/Encoding/Chinese/"CS_EUC_TW, GTK_UI_MANAGER_MENUITEM)
592 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Korean", "View/Encoding/Korean", GTK_UI_MANAGER_MENU)
593 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Korean", CS_EUC_KR, "View/Encoding/Korean/"CS_EUC_KR, GTK_UI_MANAGER_MENUITEM)
594 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)
596 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding", "Thai", "View/Encoding/Thai", GTK_UI_MANAGER_MENU)
597 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Thai", CS_TIS_620, "View/Encoding/Thai/"CS_TIS_620, GTK_UI_MANAGER_MENUITEM)
598 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Encoding/Thai", CS_WINDOWS_874, "View/Encoding/Thai/"CS_WINDOWS_874, GTK_UI_MANAGER_MENUITEM)
600 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Decode", "View/Decode", GTK_UI_MANAGER_MENU)
601 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "AutoDetect", "View/Decode/AutoDetect", GTK_UI_MANAGER_MENUITEM)
602 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "Separator1", "View/Decode/---", GTK_UI_MANAGER_SEPARATOR)
603 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "8bit", "View/Decode/8bit", GTK_UI_MANAGER_MENUITEM)
604 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "QP", "View/Decode/QP", GTK_UI_MANAGER_MENUITEM)
605 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "B64", "View/Decode/B64", GTK_UI_MANAGER_MENUITEM)
606 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Decode", "Uuencode", "View/Decode/Uuencode", GTK_UI_MANAGER_MENUITEM)
608 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Separator2", "View/---", GTK_UI_MANAGER_SEPARATOR)
610 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "MessageSource", "View/MessageSource", GTK_UI_MANAGER_MENUITEM)
611 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "AllHeaders", "View/AllHeaders", GTK_UI_MANAGER_MENUITEM)
612 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Quotes", "View/Quotes", GTK_UI_MANAGER_MENU)
613 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Quotes", "CollapseAll", "View/Quotes/CollapseAll", GTK_UI_MANAGER_MENUITEM)
614 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Quotes", "Collapse2", "View/Quotes/Collapse2", GTK_UI_MANAGER_MENUITEM)
615 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Quotes", "Collapse3", "View/Quotes/Collapse3", GTK_UI_MANAGER_MENUITEM)
616 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View", "Part", "View/Part", GTK_UI_MANAGER_MENU)
617 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Part", "AsText", "View/Part/AsText", GTK_UI_MANAGER_MENUITEM)
618 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Part", "Open", "View/Part/Open", GTK_UI_MANAGER_MENUITEM)
620 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/View/Part", "OpenWith", "View/Part/OpenWith", GTK_UI_MANAGER_MENUITEM)
624 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Compose", "Message/Compose", GTK_UI_MANAGER_MENUITEM)
625 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Separator1", "Message/---", GTK_UI_MANAGER_SEPARATOR)
626 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Reply", "Message/Reply", GTK_UI_MANAGER_MENUITEM)
627 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "ReplyTo", "Message/ReplyTo", GTK_UI_MANAGER_MENU)
628 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message/ReplyTo", "All", "Message/ReplyTo/All", GTK_UI_MANAGER_MENUITEM)
629 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message/ReplyTo", "Sender", "Message/ReplyTo/Sender", GTK_UI_MANAGER_MENUITEM)
630 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message/ReplyTo", "List", "Message/ReplyTo/List", GTK_UI_MANAGER_MENUITEM)
631 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Separator2", "Message/---", GTK_UI_MANAGER_SEPARATOR)
632 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Forward", "Message/Forward", GTK_UI_MANAGER_MENUITEM)
633 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "ForwardAtt", "Message/ForwardAtt", GTK_UI_MANAGER_MENUITEM)
634 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "Redirect", "Message/Redirect", GTK_UI_MANAGER_MENUITEM)
635 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Message", "CheckSignature", "Message/CheckSignature", GTK_UI_MANAGER_MENUITEM)
638 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "AddressBook", "Tools/AddressBook", GTK_UI_MANAGER_MENUITEM)
639 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "AddSenderToAB", "Tools/AddSenderToAB", GTK_UI_MANAGER_MENUITEM)
640 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "Separator1", "Tools/---", GTK_UI_MANAGER_SEPARATOR)
642 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "CreateFilterRule", "Tools/CreateFilterRule", GTK_UI_MANAGER_MENU)
643 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateFilterRule", "Automatically", "Tools/CreateFilterRule/Automatically", GTK_UI_MANAGER_MENUITEM)
644 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateFilterRule", "ByFrom", "Tools/CreateFilterRule/ByFrom", GTK_UI_MANAGER_MENUITEM)
645 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateFilterRule", "ByTo", "Tools/CreateFilterRule/ByTo", GTK_UI_MANAGER_MENUITEM)
646 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateFilterRule", "BySubject", "Tools/CreateFilterRule/BySubject", GTK_UI_MANAGER_MENUITEM)
648 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "CreateProcessingRule", "Tools/CreateProcessingRule", GTK_UI_MANAGER_MENU)
649 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateProcessingRule", "Automatically", "Tools/CreateProcessingRule/Automatically", GTK_UI_MANAGER_MENUITEM)
650 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateProcessingRule", "ByFrom", "Tools/CreateProcessingRule/ByFrom", GTK_UI_MANAGER_MENUITEM)
651 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateProcessingRule", "ByTo", "Tools/CreateProcessingRule/ByTo", GTK_UI_MANAGER_MENUITEM)
652 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/CreateProcessingRule", "BySubject", "Tools/CreateProcessingRule/BySubject", GTK_UI_MANAGER_MENUITEM)
653 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "Separator2", "Tools/---", GTK_UI_MANAGER_SEPARATOR)
655 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "ListUrls", "Tools/ListUrls", GTK_UI_MANAGER_MENUITEM)
656 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "Separator3", "Tools/---", GTK_UI_MANAGER_SEPARATOR)
658 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools", "Actions", "Tools/Actions", GTK_UI_MANAGER_MENU)
659 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Tools/Actions", "PlaceHolder", "Tools/Actions/PlaceHolder", GTK_UI_MANAGER_MENUITEM)
662 MENUITEM_ADDUI_MANAGER(msgview->ui_manager, "/Menu/Help", "About", "Help/About", GTK_UI_MANAGER_MENUITEM)
664 menubar = gtk_ui_manager_get_widget(msgview->ui_manager, "/Menu");
665 gtk_widget_show_all(menubar);
666 gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(msgview->ui_manager));
668 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
670 cm_toggle_menu_set_active_full(msgview->ui_manager, "Menu/View/AllHeaders",
671 prefs_common.show_all_headers);
673 if (prefs_common.toolbar_detachable) {
674 handlebox = gtk_handle_box_new();
676 handlebox = gtk_hbox_new(FALSE, 0);
678 gtk_box_pack_start(GTK_BOX(vbox), handlebox, FALSE, FALSE, 0);
679 gtk_widget_realize(handlebox);
680 msgview->toolbar = toolbar_create(TOOLBAR_MSGVIEW, handlebox,
683 statusbar = gtk_statusbar_new();
684 gtk_widget_show(statusbar);
685 gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
686 msgview->statusbar = statusbar;
687 msgview->statusbar_cid = gtk_statusbar_get_context_id
688 (GTK_STATUSBAR(statusbar), "Message View");
690 msgview->statusbar = NULL;
691 msgview->statusbar_cid = 0;
695 msgview->handlebox = handlebox;
696 msgview->menubar = menubar;
698 gtk_container_add(GTK_CONTAINER(vbox),
699 GTK_WIDGET_PTR(msgview));
701 messageview_update_actions_menu(msgview);
703 msgview_list = g_list_append(msgview_list, msgview);
706 static MessageView *messageview_create_with_new_window_visible(MainWindow *mainwin, gboolean show)
708 MessageView *msgview;
710 static GdkGeometry geometry;
712 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "messageview");
713 gtk_window_set_title(GTK_WINDOW(window), _("Claws Mail - Message View"));
714 gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
716 if (!geometry.min_height) {
717 geometry.min_width = 320;
718 geometry.min_height = 200;
720 gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
723 gtk_widget_set_size_request(window, prefs_common.msgwin_width,
724 prefs_common.msgwin_height);
726 gtk_window_move(GTK_WINDOW(window), 48, 48);
729 msgview = messageview_create(mainwin);
731 g_signal_connect(G_OBJECT(window), "size_allocate",
732 G_CALLBACK(messageview_size_allocate_cb),
734 g_signal_connect(G_OBJECT(window), "delete_event",
735 G_CALLBACK(messageview_delete_cb), msgview);
736 g_signal_connect(G_OBJECT(window), "key_press_event",
737 G_CALLBACK(key_pressed), msgview);
738 messageview_add_toolbar(msgview, window);
741 gtk_widget_show(window);
743 gtk_widget_realize(window);
746 msgview->new_window = TRUE;
747 msgview->window = window;
748 msgview->visible = TRUE;
750 toolbar_set_style(msgview->toolbar->toolbar, msgview->handlebox,
751 prefs_common.toolbar_style);
752 messageview_init(msgview);
756 gtk_widget_grab_focus(msgview->mimeview->textview->text);
762 MessageView *messageview_create_with_new_window(MainWindow *mainwin)
764 return messageview_create_with_new_window_visible(mainwin, TRUE);
766 void messageview_init(MessageView *messageview)
768 headerview_init(messageview->headerview);
769 mimeview_init(messageview->mimeview);
770 /*messageview_set_font(messageview);*/
772 noticeview_hide(messageview->noticeview);
775 static void notification_convert_header(gchar *dest, gint len,
781 cm_return_if_fail(src_ != NULL);
782 cm_return_if_fail(dest != NULL);
786 Xstrndup_a(src, src_, len, return);
790 if (is_ascii_str(src)) {
791 strncpy2(dest, src, len);
792 dest[len - 1] = '\0';
795 conv_encode_header(dest, len, src, header_len, FALSE);
798 static gint disposition_notification_send(MsgInfo *msginfo)
801 gchar tmp[MAXPATHLEN + 1];
804 PrefsAccount *account = NULL;
807 FolderItem *queue, *outbox;
813 gboolean queued_removed = FALSE;
814 gchar *boundary = NULL;
816 gchar *orig_to = NULL;
817 gchar *enc_sub = NULL;
819 if (!msginfo->extradata)
821 if (!msginfo->extradata->returnreceiptto &&
822 !msginfo->extradata->dispositionnotificationto)
825 /* RFC2298: Test for Return-Path */
826 if (msginfo->extradata->dispositionnotificationto)
827 to = msginfo->extradata->dispositionnotificationto;
829 to = msginfo->extradata->returnreceiptto;
831 ok = procheader_get_header_from_msginfo(msginfo, buf, sizeof(buf),
834 gchar *to_addr = g_strdup(to);
835 extract_address(to_addr);
836 extract_address(buf);
837 ok = strcasecmp(to_addr, buf);
840 g_strlcpy(buf, _("<No Return-Path found>"),
847 message = g_markup_printf_escaped(
848 _("The notification address to which the return receipt is\n"
849 "to be sent does not correspond to the return path:\n"
850 "Notification address: %s\n"
852 "It is advised to not send the return receipt."),
854 val = alertpanel_full(_("Warning"), message,
855 _("_Don't Send"), _("_Send"), NULL, FALSE,
856 NULL, ALERT_WARNING, G_ALERTDEFAULT);
858 if (val != G_ALERTALTERNATE)
862 ac_list = account_find_all_from_address(NULL, msginfo->to);
863 ac_list = account_find_all_from_address(ac_list, msginfo->cc);
865 if (ac_list == NULL) {
867 alertpanel_full(_("Warning"),
868 _("This message is asking for a return receipt notification\n"
869 "but according to its 'To' and 'Cc' headers it was not\n"
870 "officially addressed to you.\n"
871 "It is advised to not send the return receipt."),
872 _("_Don't Send"), _("_Send"), NULL, FALSE,
873 NULL, ALERT_WARNING, G_ALERTDEFAULT);
874 if (val != G_ALERTALTERNATE)
878 if (g_list_length(ac_list) > 1) {
879 if ((account = select_account_from_list(ac_list)) == NULL)
882 else if (ac_list != NULL)
883 account = (PrefsAccount *) ac_list->data;
884 g_list_free(ac_list);
887 account = account_get_default();
888 if (!account || account->protocol == A_NNTP) {
889 alertpanel_error(_("Account for sending mail is not specified.\n"
890 "Please select a mail account before sending."));
894 /* write to temporary file */
895 g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg%p",
896 get_rc_dir(), G_DIR_SEPARATOR, msginfo);
898 if ((fp = g_fopen(tmp, "wb")) == NULL) {
899 FILE_OP_ERROR(tmp, "fopen");
903 /* chmod for security */
904 if (change_file_mode_rw(fp, tmp) < 0) {
905 FILE_OP_ERROR(tmp, "chmod");
906 g_warning("can't change file mode");
911 extract_address(addr);
914 /* write queue headers */
915 ok = fprintf(fp, "AF:\n"
930 account->smtp_server?account->smtp_server:"",
937 /* check whether we need to save the message */
938 outbox = account_get_special_folder(account, F_OUTBOX);
939 if (folder_get_default_outbox() == outbox && !prefs_common.savemsg)
942 path = folder_item_get_identifier(outbox);
943 ok = fprintf(fp, "SCF:%s\n", path);
950 if (fprintf(fp, "X-Claws-End-Special-Headers: 1\n") < 0)
954 get_rfc822_date(buf, sizeof(buf));
955 if (fprintf(fp, "Date: %s\n", buf) < 0)
959 if (account->name && *account->name) {
960 notification_convert_header
961 (buf, sizeof(buf), account->name,
963 if (fprintf(fp, "From: %s <%s>\n", buf, account->address) < 0)
966 if (fprintf(fp, "From: %s\n", account->address) < 0)
969 if (fprintf(fp, "To: %s\n", to) < 0)
973 notification_convert_header(buf, sizeof(buf), msginfo->subject,
974 strlen("Subject: "));
975 if (fprintf(fp, "Subject: Disposition notification: %s\n", buf) < 0)
979 if (account->gen_msgid) {
980 gchar *addr = prefs_account_generate_msgid(account);
981 if (fprintf(fp, "Message-ID: <%s>\n", addr) < 0) {
988 boundary = generate_mime_boundary("DN");
989 get_rfc822_date(buf, sizeof(buf));
990 date = g_strdup(buf);
992 orig_to = g_strdup(msginfo->to);
993 extract_address(orig_to);
995 if (msginfo->subject && *(msginfo->subject)) {
996 enc_sub = g_malloc0(strlen(msginfo->subject)*8);
997 qp_encode_line(enc_sub, (const guchar *)msginfo->subject);
1000 ok = fprintf(fp,"MIME-Version: 1.0\n"
1001 "Content-Type: multipart/report; report-type=disposition-notification;\n"
1002 " boundary=\"%s\"\n"
1005 "Content-Type: text/plain; charset=UTF-8\n"
1006 "Content-Transfer-Encoding: quoted-printable\n"
1008 "The message sent on: %s\n"
1010 "With subject: \"%s\"\n"
1011 "has been displayed at %s.\n"
1013 "There is no guarantee that the message has been read or understood.\n"
1016 "Content-Type: message/disposition-notification\n"
1018 "Reporting-UA: %s\n"
1019 "Original-Recipient: rfc822;%s\n"
1020 "Final-Recipient: rfc822;%s\n"
1021 "Original-Message-ID: <%s>\n"
1022 "Disposition: manual-action/MDN-sent-manually; displayed\n"
1025 "Content-Type: application/octet-stream\n"
1027 "Reporting-UA: %s\n"
1028 "Original-Recipient: rfc822;%s\n"
1029 "Final-Recipient: rfc822;%s\n"
1030 "Original-Message-ID: <%s>\n"
1031 "Disposition: manual-action/MDN-sent-manually; displayed\n"
1037 orig_to?orig_to:"No To:",
1038 enc_sub?enc_sub:"No subject",
1042 orig_to?orig_to:"No To:",
1044 msginfo->msgid?msginfo->msgid:"NO MESSAGE ID",
1047 orig_to?orig_to:"No To:",
1049 msginfo->msgid?msginfo->msgid:"NO MESSAGE ID",
1060 if (fclose(fp) == EOF) {
1061 FILE_OP_ERROR(tmp, "fclose");
1066 /* put it in queue */
1067 queue = account_get_special_folder(account, F_QUEUE);
1068 if (!queue) queue = folder_get_default_queue();
1070 g_warning("can't find queue folder");
1074 folder_item_scan(queue);
1075 if ((num = folder_item_add_msg(queue, tmp, NULL, TRUE)) < 0) {
1076 g_warning("can't queue the message");
1081 if (prefs_common.work_offline &&
1082 !inc_offline_should_override(TRUE,
1083 _("Claws Mail needs network access in order "
1084 "to send this email.")))
1088 path = folder_item_fetch_msg(queue, num);
1089 ok = procmsg_send_message_queue_with_lock(path, &foo, queue, num, &queued_removed);
1092 if (ok == 0 && !queued_removed)
1093 folder_item_remove_msg(queue, num);
1103 static gboolean find_encrypted_func(GNode *node, gpointer data)
1105 MimeInfo *mimeinfo = (MimeInfo *) node->data;
1106 MimeInfo **encinfo = (MimeInfo **) data;
1108 if (privacy_mimeinfo_is_encrypted(mimeinfo)) {
1109 *encinfo = mimeinfo;
1116 static MimeInfo *find_encrypted_part(MimeInfo *rootinfo)
1118 MimeInfo *encinfo = NULL;
1120 g_node_traverse(rootinfo->node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
1121 find_encrypted_func, &encinfo);
1126 static gboolean find_broken_func(GNode *node, gpointer data)
1128 MimeInfo *mimeinfo = (MimeInfo *) node->data;
1129 MimeInfo **brokeninfo = (MimeInfo **) data;
1131 if (mimeinfo->broken) {
1132 *brokeninfo = mimeinfo;
1139 static MimeInfo *find_broken_part(MimeInfo *rootinfo)
1141 MimeInfo *brokeninfo = NULL;
1143 g_node_traverse(rootinfo->node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
1144 find_broken_func, &brokeninfo);
1149 static void messageview_register_nav(MessageView *messageview)
1155 cm_return_if_fail(messageview);
1156 cm_return_if_fail(messageview->msginfo);
1158 id = procmsg_msginfo_get_identifier(messageview->msginfo);
1159 existing = g_list_find_custom(messageview->trail, id, (GCompareFunc)g_strcmp0);
1161 if (existing != NULL)
1162 pos = g_list_position(messageview->trail, existing);
1167 messageview->trail_pos = pos;
1170 /* Cut the end of the list */
1171 GList *end = g_list_nth(messageview->trail, messageview->trail_pos + 1);
1174 end->prev->next = NULL;
1176 list_free_strings(end);
1179 list_free_strings(messageview->trail);
1180 g_list_free(messageview->trail);
1181 messageview->trail = NULL;
1184 messageview->trail = g_list_append(messageview->trail, id);
1185 messageview->trail_pos = g_list_length(messageview->trail) - 1;
1187 /* Cut the beginning if needed */
1188 while (messageview->trail_pos > prefs_common.nav_history_length) {
1189 g_free(messageview->trail->data);
1190 messageview->trail = g_list_delete_link(messageview->trail,
1191 messageview->trail);
1192 messageview->trail_pos--;
1195 messageview_set_menu_sensitive(messageview);
1198 gboolean messageview_nav_has_prev(MessageView *messageview) {
1199 return messageview != NULL && messageview->trail != NULL
1200 && messageview->trail_pos > 0;
1203 gboolean messageview_nav_has_next(MessageView *messageview) {
1204 if (!messageview || !messageview->trail)
1207 return sc_g_list_bigger(messageview->trail, messageview->trail_pos + 1);
1210 MsgInfo *messageview_nav_get_prev(MessageView *messageview) {
1214 cm_return_val_if_fail(messageview, NULL);
1215 cm_return_val_if_fail(messageview->trail, NULL);
1218 if (!messageview_nav_has_prev(messageview))
1221 item = g_list_nth(messageview->trail, messageview->trail_pos - 1);
1222 cm_return_val_if_fail(item != NULL, NULL);
1224 info = procmsg_get_msginfo_from_identifier((const gchar *)item->data);
1229 messageview->trail = g_list_delete_link(messageview->trail, item);
1230 if (messageview->trail_pos > 0)
1231 messageview->trail_pos--;
1232 } while (info == NULL);
1237 MsgInfo *messageview_nav_get_next(MessageView *messageview) {
1241 cm_return_val_if_fail(messageview, NULL);
1242 cm_return_val_if_fail(messageview->trail, NULL);
1245 if (!messageview_nav_has_next(messageview))
1248 item = g_list_nth(messageview->trail, messageview->trail_pos + 1);
1249 cm_return_val_if_fail(item != NULL, NULL);
1251 info = procmsg_get_msginfo_from_identifier((const gchar *)item->data);
1256 messageview->trail = g_list_delete_link(messageview->trail, item);
1257 } while (info == NULL);
1262 static gboolean messageview_try_select_mimeinfo(MessageView *messageview, MsgInfo *msginfo, MimeInfo *mimeinfo)
1264 if (mimeinfo->type == MIMETYPE_TEXT) {
1265 if (!strcasecmp(mimeinfo->subtype, "calendar")
1266 && mimeview_has_viewer_for_content_type(messageview->mimeview, "text/calendar")) {
1267 mimeview_select_mimepart_icon(messageview->mimeview, mimeinfo);
1269 } else if (!strcasecmp(mimeinfo->subtype, "html")
1270 && mimeinfo->disposition != DISPOSITIONTYPE_ATTACHMENT
1271 && (msginfo->folder->prefs->promote_html_part == HTML_PROMOTE_ALWAYS
1272 || (msginfo->folder->prefs->promote_html_part == HTML_PROMOTE_DEFAULT
1273 && prefs_common.promote_html_part))) {
1274 mimeview_select_mimepart_icon(messageview->mimeview, mimeinfo);
1281 static void messageview_find_part_depth_first(MimeInfoSearch *context, MimeMediaType type, const gchar *subtype)
1283 MimeInfo * mimeinfo = context->current;
1288 debug_print("found part %d/%s\n", mimeinfo->type, mimeinfo->subtype);
1290 if (mimeinfo->type == type
1291 && !strcasecmp(mimeinfo->subtype, subtype)) {
1292 context->found = mimeinfo;
1293 } else if (mimeinfo->type == MIMETYPE_MULTIPART) {
1294 if (!strcasecmp(mimeinfo->subtype, "alternative")
1295 || !strcasecmp(mimeinfo->subtype, "related")) {
1296 context->found = procmime_mimeinfo_next(mimeinfo);
1297 while (context->found && context->found != context->parent) {
1298 if (context->found->type == type
1299 && !strcasecmp(context->found->subtype, subtype))
1301 context->found = procmime_mimeinfo_next(context->found);
1303 if (context->found == context->parent)
1304 context->found = NULL;
1307 && (!strcasecmp(mimeinfo->subtype, "related")
1308 || !strcasecmp(mimeinfo->subtype, "mixed"))) {
1309 context->parent = mimeinfo;
1310 context->current = procmime_mimeinfo_next(mimeinfo);
1311 messageview_find_part_depth_first(context, type, subtype);
1316 gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
1317 gboolean all_headers)
1321 MimeInfo *mimeinfo, *encinfo, *root;
1322 gchar *subject = NULL;
1323 cm_return_val_if_fail(msginfo != NULL, -1);
1325 if (msginfo != messageview->msginfo)
1326 messageview->show_full_text = FALSE;
1328 if (messageview->mimeview->textview &&
1329 messageview->mimeview->textview->loading) {
1330 messageview->mimeview->textview->stop_loading = TRUE;
1334 if (messageview->toolbar)
1335 toolbar_set_learn_button
1336 (messageview->toolbar,
1337 MSG_IS_SPAM(msginfo->flags)?LEARN_HAM:LEARN_SPAM);
1339 toolbar_set_learn_button
1340 (messageview->mainwin->toolbar,
1341 MSG_IS_SPAM(msginfo->flags)?LEARN_HAM:LEARN_SPAM);
1343 if (messageview->toolbar) {
1344 if (messageview->toolbar->learn_spam_btn) {
1345 gboolean can_learn = FALSE;
1346 if (procmsg_spam_can_learn() &&
1348 msginfo->folder->folder->klass->type != F_UNKNOWN &&
1349 msginfo->folder->folder->klass->type != F_NEWS))
1352 gtk_widget_set_sensitive(
1353 messageview->toolbar->learn_spam_btn,
1358 noticeview_hide(messageview->noticeview);
1359 mimeview_clear(messageview->mimeview);
1360 messageview->updating = TRUE;
1362 if (msginfo->size > 1024*1024)
1363 statuswindow_print_all(_("Fetching message (%s)..."),
1364 to_human_readable(msginfo->size));
1366 file = procmsg_get_message_file_path(msginfo);
1368 if (msginfo->size > 1024*1024)
1369 statuswindow_pop_all();
1372 g_warning("can't get message file path.");
1373 textview_show_error(messageview->mimeview->textview);
1377 if (!folder_has_parent_of_type(msginfo->folder, F_QUEUE) &&
1378 !folder_has_parent_of_type(msginfo->folder, F_DRAFT))
1379 mimeinfo = procmime_scan_file(file);
1381 mimeinfo = procmime_scan_queue_file(file);
1383 messageview->updating = FALSE;
1385 if (messageview->deferred_destroy) {
1387 messageview_destroy(messageview);
1392 textview_show_error(messageview->mimeview->textview);
1396 while ((encinfo = find_encrypted_part(mimeinfo)) != NULL) {
1397 debug_print("decrypting message part\n");
1398 if (privacy_mimeinfo_decrypt(encinfo) < 0) {
1399 text = g_strdup_printf(_("Couldn't decrypt: %s"),
1400 privacy_get_error());
1401 noticeview_show(messageview->noticeview);
1402 noticeview_set_icon(messageview->noticeview,
1403 STOCK_PIXMAP_NOTICE_WARN);
1404 noticeview_set_text(messageview->noticeview, text);
1405 gtk_widget_hide(messageview->noticeview->button);
1406 gtk_widget_hide(messageview->noticeview->button2);
1412 if (messageview->msginfo != msginfo) {
1413 procmsg_msginfo_free(&(messageview->msginfo));
1414 messageview->msginfo = NULL;
1415 messageview_set_menu_sensitive(messageview);
1416 messageview->msginfo =
1417 procmsg_msginfo_get_full_info_from_file(msginfo, file);
1418 if (!messageview->msginfo)
1419 messageview->msginfo = procmsg_msginfo_copy(msginfo);
1421 messageview->msginfo = NULL;
1422 messageview_set_menu_sensitive(messageview);
1423 messageview->msginfo = msginfo;
1425 if (prefs_common.display_header_pane)
1426 headerview_show(messageview->headerview, messageview->msginfo);
1428 messageview_register_nav(messageview);
1429 messageview_set_position(messageview, 0);
1431 if (messageview->window) {
1432 gtk_window_set_title(GTK_WINDOW(messageview->window),
1433 _("Claws Mail - Message View"));
1436 mimeview_show_message(messageview->mimeview, mimeinfo, file);
1438 #ifndef GENERIC_UMPC
1439 messageview_set_position(messageview, 0);
1442 if (messageview->window && msginfo->subject) {
1443 subject = g_strdup(msginfo->subject);
1444 if (!g_utf8_validate(subject, -1, NULL)) {
1446 subject = g_malloc(strlen(msginfo->subject)*2 +1);
1447 conv_localetodisp(subject, strlen(msginfo->subject)*2 +1,
1450 if (g_utf8_validate(subject, -1, NULL))
1451 gtk_window_set_title(GTK_WINDOW(messageview->window),
1456 if (msginfo && msginfo->folder) {
1457 msginfo->folder->last_seen = msginfo->msgnum;
1460 main_create_mailing_list_menu(messageview->mainwin, messageview->msginfo);
1462 if (messageview->msginfo && messageview->msginfo->extradata
1463 && messageview->msginfo->extradata->partial_recv
1464 && !noticeview_is_visible(messageview->noticeview))
1465 partial_recv_show(messageview->noticeview,
1466 messageview->msginfo);
1467 else if (messageview->msginfo && messageview->msginfo->extradata &&
1468 (messageview->msginfo->extradata->dispositionnotificationto ||
1469 messageview->msginfo->extradata->returnreceiptto) &&
1470 !MSG_IS_RETRCPT_SENT(messageview->msginfo->flags) &&
1471 !prefs_common.never_send_retrcpt &&
1472 !noticeview_is_visible(messageview->noticeview))
1473 return_receipt_show(messageview->noticeview,
1474 messageview->msginfo);
1476 if (find_broken_part(mimeinfo) != NULL) {
1477 noticeview_set_icon(messageview->noticeview,
1478 STOCK_PIXMAP_NOTICE_WARN);
1479 if (!noticeview_is_visible(messageview->noticeview)) {
1480 noticeview_set_text(messageview->noticeview, _("Message doesn't conform to MIME standard. "
1481 "It may render wrongly."));
1482 gtk_widget_hide(messageview->noticeview->button);
1483 gtk_widget_hide(messageview->noticeview->button2);
1485 gchar *full = g_strconcat(
1486 gtk_label_get_text(GTK_LABEL(messageview->noticeview->text)),
1488 _("Message doesn't conform to MIME standard. "
1489 "It may render wrongly."), NULL);
1490 noticeview_set_text(messageview->noticeview, full);
1493 noticeview_show(messageview->noticeview);
1497 mimeinfo = procmime_mimeinfo_next(mimeinfo);
1498 if (!all_headers && mimeinfo
1499 && (mimeinfo->type != MIMETYPE_TEXT
1500 || strcasecmp(mimeinfo->subtype, "plain"))
1501 && (mimeinfo->type != MIMETYPE_MULTIPART
1502 || strcasecmp(mimeinfo->subtype, "signed"))) {
1503 if (strcasecmp(mimeinfo->subtype, "html")) {
1504 MimeInfoSearch context = {
1506 .current = mimeinfo,
1509 if (mimeview_has_viewer_for_content_type(messageview->mimeview, "text/calendar")) {
1510 MimeInfoSearch cal_context = context;
1511 messageview_find_part_depth_first(&cal_context, MIMETYPE_TEXT, "calendar");
1512 if (cal_context.found) { /* calendar found */
1513 mimeinfo = cal_context.found;
1514 if (messageview_try_select_mimeinfo(messageview, msginfo, mimeinfo))
1518 messageview_find_part_depth_first(&context, MIMETYPE_TEXT, "html");
1519 if (context.found &&
1520 (msginfo->folder->prefs->promote_html_part == HTML_PROMOTE_ALWAYS ||
1521 (msginfo->folder->prefs->promote_html_part == HTML_PROMOTE_DEFAULT &&
1522 prefs_common.promote_html_part))) { /* html found */
1523 mimeinfo = context.found;
1524 if (messageview_try_select_mimeinfo(messageview, msginfo, mimeinfo))
1527 mimeinfo = root; /* nothing found */
1529 if (!mimeview_show_part(messageview->mimeview, mimeinfo))
1530 mimeview_select_mimepart_icon(messageview->mimeview, root);
1532 } else if (prefs_common.invoke_plugin_on_html) {
1533 mimeview_select_mimepart_icon(messageview->mimeview, mimeinfo);
1537 if (!all_headers && mimeinfo &&
1538 mimeinfo->type == MIMETYPE_MULTIPART &&
1539 mimeview_has_viewer_for_content_type(messageview->mimeview, "text/calendar")) {
1540 /* look for a calendar part or it looks really strange */
1542 if (mimeinfo->type == MIMETYPE_TEXT &&
1543 !strcasecmp(mimeinfo->subtype, "calendar")) {
1544 mimeview_select_mimepart_icon(messageview->mimeview, mimeinfo);
1547 mimeinfo = procmime_mimeinfo_next(mimeinfo);
1551 mimeview_select_mimepart_icon(messageview->mimeview, root);
1553 messageview_set_menu_sensitive(messageview);
1554 /* plugins may hook in here to work with the message view */
1555 hooks_invoke(MESSAGE_VIEW_SHOW_DONE_HOOKLIST, messageview);
1562 void messageview_reflect_prefs_pixmap_theme(void)
1565 MessageView *msgview;
1567 for (cur = msgview_list; cur != NULL; cur = cur->next) {
1568 msgview = (MessageView*)cur->data;
1569 toolbar_update(TOOLBAR_MSGVIEW, msgview);
1570 mimeview_update(msgview->mimeview);
1574 void messageview_clear(MessageView *messageview)
1578 procmsg_msginfo_free(&(messageview->msginfo));
1579 messageview->msginfo = NULL;
1580 messageview->filtered = FALSE;
1582 if (messageview->window) {
1583 gtk_window_set_title(GTK_WINDOW(messageview->window),
1584 _("Claws Mail - Message View"));
1588 mimeview_clear(messageview->mimeview);
1589 headerview_clear(messageview->headerview);
1590 noticeview_hide(messageview->noticeview);
1593 void messageview_destroy(MessageView *messageview)
1595 debug_print("destroy messageview\n");
1596 messageview_list = g_list_remove(messageview_list, messageview);
1598 if (messageview->mainwin->summaryview->messageview == messageview) {
1599 messageview->mainwin->summaryview->displayed = NULL;
1600 messageview->mainwin->summaryview->messageview = NULL;
1602 if (messageview->mainwin->summaryview->ext_messageview == messageview) {
1603 messageview->mainwin->summaryview->displayed = NULL;
1604 messageview->mainwin->summaryview->ext_messageview = NULL;
1606 if (!messageview->deferred_destroy)
1607 hooks_unregister_hook(MSGINFO_UPDATE_HOOKLIST,
1608 messageview->msginfo_update_callback_id);
1610 if (messageview->updating) {
1611 debug_print("uh oh, better not touch that now (fetching)\n");
1612 messageview->deferred_destroy = TRUE;
1613 gtk_widget_hide(messageview->window);
1617 if (messageview->mimeview->textview
1618 && messageview->mimeview->textview->loading) {
1619 debug_print("uh oh, better not touch that now (loading text)\n");
1620 messageview->deferred_destroy = TRUE;
1621 messageview->mimeview->textview->stop_loading = TRUE;
1622 gtk_widget_hide(messageview->window);
1626 headerview_destroy(messageview->headerview);
1627 mimeview_destroy(messageview->mimeview);
1628 noticeview_destroy(messageview->noticeview);
1630 procmsg_msginfo_free(&(messageview->msginfo));
1631 toolbar_clear_list(TOOLBAR_MSGVIEW);
1632 if (messageview->toolbar) {
1633 toolbar_destroy(messageview->toolbar);
1634 g_free(messageview->toolbar);
1637 list_free_strings(messageview->trail);
1638 g_list_free(messageview->trail);
1639 msgview_list = g_list_remove(msgview_list, messageview);
1641 if (messageview->window)
1642 gtk_widget_destroy(messageview->window);
1643 g_free(messageview);
1646 void messageview_delete(MessageView *msgview)
1648 MsgInfo *msginfo = NULL;
1649 FolderItem *trash = NULL;
1650 PrefsAccount *ac = NULL;
1652 if (msgview->msginfo && msgview->mainwin && msgview->mainwin->summaryview)
1653 msginfo = summary_get_selected_msg(msgview->mainwin->summaryview);
1655 /* need a procmsg_msginfo_equal() */
1656 if (msginfo && msgview->msginfo &&
1657 msginfo->msgnum == msgview->msginfo->msgnum &&
1658 msginfo->folder == msgview->msginfo->folder) {
1659 summary_delete_trash(msgview->mainwin->summaryview);
1661 msginfo = msgview->msginfo;
1663 cm_return_if_fail(msginfo != NULL);
1665 /* to get the trash folder, we have to choose either
1666 * the folder's or account's trash default - we prefer
1667 * the one in the account prefs */
1668 if (msginfo->folder) {
1669 if (NULL != (ac = account_find_from_item(msginfo->folder)))
1670 trash = account_get_special_folder(ac, F_TRASH);
1671 if (!trash && msginfo->folder->folder)
1672 trash = msginfo->folder->folder->trash;
1673 /* if still not found, use the default */
1675 trash = folder_get_default_trash();
1678 cm_return_if_fail(trash != NULL);
1680 if (prefs_common.immediate_exec)
1681 /* TODO: Delete from trash */
1682 folder_item_move_msg(trash, msginfo);
1684 procmsg_msginfo_set_to_folder(msginfo, trash);
1685 procmsg_msginfo_set_flags(msginfo, MSG_DELETED, 0);
1686 /* NOTE: does not update to next message in summaryview */
1690 if (msgview->window && !prefs_common.always_show_msg) {
1691 messageview_destroy(msgview);
1697 * \brief update messageview with currently selected message in summaryview
1698 * leave unchanged if summaryview is empty
1699 * \param pointer to MessageView
1701 static void messageview_update(MessageView *msgview, MsgInfo *old_msginfo)
1703 SummaryView *summaryview = (SummaryView*)msgview->mainwin->summaryview;
1705 cm_return_if_fail(summaryview != NULL);
1707 if (summaryview->selected) {
1708 MsgInfo *msginfo = summary_get_selected_msg(summaryview);
1709 if (msginfo == NULL || msginfo == old_msginfo)
1712 messageview_show(msgview, msginfo,
1713 msgview->all_headers);
1717 TextView *messageview_get_current_textview(MessageView *messageview)
1719 TextView *text = NULL;
1721 text = messageview->mimeview->textview;
1726 MimeInfo *messageview_get_selected_mime_part(MessageView *messageview)
1728 return mimeview_get_selected_part(messageview->mimeview);
1731 void messageview_copy_clipboard(MessageView *messageview)
1733 gchar *text = messageview_get_selection(messageview);
1735 gtk_clipboard_set_text(
1736 gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
1742 void messageview_select_all(MessageView *messageview)
1746 text = messageview_get_current_textview(messageview);
1748 GtkTextView *textview = GTK_TEXT_VIEW(text->text);
1749 GtkTextBuffer *buffer;
1750 GtkTextIter start, end;
1752 buffer = gtk_text_view_get_buffer(textview);
1753 gtk_text_buffer_get_bounds(buffer, &start, &end);
1754 gtk_text_buffer_select_range(buffer, &start, &end);
1758 void messageview_set_position(MessageView *messageview, gint pos)
1762 text = messageview_get_current_textview(messageview);
1764 textview_set_position(text, pos);
1767 gboolean messageview_search_string(MessageView *messageview, const gchar *str,
1772 if (messageview->mimeview->type == MIMEVIEW_VIEWER) {
1773 MimeViewer *viewer = messageview->mimeview->mimeviewer;
1774 if (viewer && viewer->text_search) {
1775 return viewer->text_search(viewer, FALSE, str, case_sens);
1779 text = messageview_get_current_textview(messageview);
1781 return textview_search_string(text, str, case_sens);
1785 gboolean messageview_search_string_backward(MessageView *messageview,
1791 if (messageview->mimeview->type == MIMEVIEW_VIEWER) {
1792 MimeViewer *viewer = messageview->mimeview->mimeviewer;
1793 if (viewer && viewer->text_search) {
1794 return viewer->text_search(viewer, TRUE, str, case_sens);
1798 text = messageview_get_current_textview(messageview);
1800 return textview_search_string_backward(text,
1805 gboolean messageview_is_visible(MessageView *messageview)
1807 if (messageview == NULL)
1809 return messageview->visible;
1812 static void messageview_save_as(MessageView *messageview)
1814 gchar *filename = NULL;
1816 gchar *src, *dest, *tmp;
1818 if (!messageview->msginfo) return;
1819 msginfo = messageview->msginfo;
1821 if (msginfo->subject) {
1822 Xstrdup_a(filename, msginfo->subject, return);
1823 subst_for_filename(filename);
1825 if (filename && !g_utf8_validate(filename, -1, NULL)) {
1826 gchar *oldstr = filename;
1827 filename = conv_codeset_strdup(filename,
1828 conv_get_locale_charset_str(),
1831 g_warning("messageview_save_as(): failed to convert character set.");
1832 filename = g_strdup(oldstr);
1834 dest = filesel_select_file_save(_("Save as"), filename);
1837 dest = filesel_select_file_save(_("Save as"), filename);
1839 if (is_file_exist(dest)) {
1842 aval = alertpanel(_("Overwrite"),
1843 _("Overwrite existing file?"),
1844 GTK_STOCK_CANCEL, GTK_STOCK_OK, NULL);
1845 if (G_ALERTALTERNATE != aval) return;
1848 src = procmsg_get_message_file(msginfo);
1849 if (copy_file(src, dest, TRUE) < 0) {
1850 tmp = g_path_get_basename(dest);
1851 alertpanel_error(_("Couldn't save the file '%s'."), tmp);
1858 static gint messageview_delete_cb(GtkWidget *widget, GdkEventAny *event,
1859 MessageView *messageview)
1861 messageview_destroy(messageview);
1865 static void messageview_size_allocate_cb(GtkWidget *widget,
1866 GtkAllocation *allocation)
1868 cm_return_if_fail(allocation != NULL);
1870 prefs_common.msgwin_width = allocation->width;
1871 prefs_common.msgwin_height = allocation->height;
1874 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
1875 MessageView *messageview)
1877 if (event && event->keyval == GDK_KEY_Escape && messageview->window) {
1878 messageview_destroy(messageview);
1882 if (event && (event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0)
1884 if (event && (event->state & GDK_SHIFT_MASK) && event->keyval != GDK_KEY_space)
1887 return mimeview_pass_key_press_event(messageview->mimeview, event);
1890 static void messageview_show_partial_display_cb(NoticeView *noticeview, MessageView *messageview)
1892 messageview->show_full_text = TRUE;
1893 main_window_cursor_wait(mainwindow_get_mainwindow());
1894 noticeview_hide(messageview->noticeview);
1895 messageview->partial_display_shown = FALSE;
1897 mimeview_handle_cmd(messageview->mimeview, "sc://display_as_text", NULL, NULL);
1898 main_window_cursor_normal(mainwindow_get_mainwindow());
1901 void messageview_show_partial_display(MessageView *messageview, MsgInfo *msginfo,
1904 gchar *msg = g_strdup_printf(_("Show all %s."), to_human_readable((goffset)length));
1905 noticeview_set_icon(messageview->noticeview, STOCK_PIXMAP_NOTICE_WARN);
1906 noticeview_set_text(messageview->noticeview, _("Only the first megabyte of text is shown."));
1907 noticeview_set_button_text(messageview->noticeview, msg);
1909 noticeview_set_button_press_callback(messageview->noticeview,
1910 G_CALLBACK(messageview_show_partial_display_cb),
1911 (gpointer) messageview);
1912 noticeview_show(messageview->noticeview);
1913 messageview->partial_display_shown = TRUE;
1916 static void return_receipt_show(NoticeView *noticeview, MsgInfo *msginfo)
1919 gboolean from_me = FALSE;
1921 && (folder_has_parent_of_type(msginfo->folder, F_QUEUE)
1922 || folder_has_parent_of_type(msginfo->folder, F_DRAFT)))
1925 addr = g_strdup(msginfo->from);
1927 extract_address(addr);
1928 if (account_find_from_address(addr, FALSE)) {
1935 noticeview_set_icon(noticeview, STOCK_PIXMAP_NOTICE_WARN);
1936 if (MSG_IS_RETRCPT_GOT(msginfo->flags)) {
1937 noticeview_set_text(noticeview, _("You got a return receipt for this message: "
1938 "it has been displayed by the recipient."));
1940 noticeview_set_text(noticeview, _("You asked for a return receipt in this message."));
1942 noticeview_set_button_text(noticeview, NULL);
1943 noticeview_set_button_press_callback(noticeview, NULL, NULL);
1945 noticeview_set_icon(noticeview, STOCK_PIXMAP_NOTICE_WARN);
1946 noticeview_set_text(noticeview, _("This message asks for a return receipt."));
1947 noticeview_set_button_text(noticeview, _("Send receipt"));
1948 noticeview_set_button_press_callback(noticeview,
1949 G_CALLBACK(return_receipt_send_clicked),
1950 (gpointer) msginfo);
1952 noticeview_show(noticeview);
1955 static void return_receipt_send_clicked(NoticeView *noticeview, MsgInfo *msginfo)
1957 MsgInfo *tmpmsginfo;
1960 file = procmsg_get_message_file_path(msginfo);
1962 g_warning("can't get message file path.");
1966 tmpmsginfo = procheader_parse_file(file, msginfo->flags, TRUE, TRUE);
1967 tmpmsginfo->folder = msginfo->folder;
1968 tmpmsginfo->msgnum = msginfo->msgnum;
1970 if (disposition_notification_send(tmpmsginfo) >= 0) {
1971 procmsg_msginfo_set_flags(msginfo, MSG_RETRCPT_SENT, 0);
1972 noticeview_hide(noticeview);
1975 procmsg_msginfo_free(&tmpmsginfo);
1979 static void partial_recv_show(NoticeView *noticeview, MsgInfo *msginfo)
1982 gchar *button1 = NULL;
1983 gchar *button2 = NULL;
1984 void *button1_cb = NULL;
1985 void *button2_cb = NULL;
1987 if (!msginfo->extradata)
1989 if (!partial_msg_in_uidl_list(msginfo)) {
1990 text = g_strdup_printf(_("This message has been partially "
1991 "retrieved,\nand has been deleted from the "
1994 switch (msginfo->planned_download) {
1995 case POP3_PARTIAL_DLOAD_UNKN:
1996 text = g_strdup_printf(_("This message has been "
1997 "partially retrieved;\nit is %s."),
1999 (goffset)(msginfo->total_size)));
2000 button1 = _("Mark for download");
2001 button2 = _("Mark for deletion");
2002 button1_cb = partial_recv_dload_clicked;
2003 button2_cb = partial_recv_del_clicked;
2005 case POP3_PARTIAL_DLOAD_DLOAD:
2006 text = g_strdup_printf(_("This message has been "
2007 "partially retrieved;\nit is %s and "
2008 "will be downloaded."),
2010 (goffset)(msginfo->total_size)));
2011 button1 = _("Unmark");
2012 button1_cb = partial_recv_unmark_clicked;
2013 button2 = _("Mark for deletion");
2014 button2_cb = partial_recv_del_clicked;
2016 case POP3_PARTIAL_DLOAD_DELE:
2017 text = g_strdup_printf(_("This message has been "
2018 "partially retrieved;\nit is %s and "
2019 "will be deleted."),
2021 (goffset)(msginfo->total_size)));
2022 button1 = _("Mark for download");
2023 button1_cb = partial_recv_dload_clicked;
2024 button2 = _("Unmark");
2025 button2_cb = partial_recv_unmark_clicked;
2032 noticeview_set_icon(noticeview, STOCK_PIXMAP_NOTICE_WARN);
2033 noticeview_set_text(noticeview, text);
2035 noticeview_set_button_text(noticeview, button1);
2036 noticeview_set_button_press_callback(noticeview,
2037 G_CALLBACK(button1_cb), (gpointer) msginfo);
2039 noticeview_set_2ndbutton_text(noticeview, button2);
2040 noticeview_set_2ndbutton_press_callback(noticeview,
2041 G_CALLBACK(button2_cb), (gpointer) msginfo);
2043 noticeview_show(noticeview);
2046 static void partial_recv_dload_clicked(NoticeView *noticeview,
2049 if (partial_mark_for_download(msginfo) == 0) {
2050 partial_recv_show(noticeview, msginfo);
2054 static void partial_recv_del_clicked(NoticeView *noticeview,
2057 if (partial_mark_for_delete(msginfo) == 0) {
2058 partial_recv_show(noticeview, msginfo);
2062 static void partial_recv_unmark_clicked(NoticeView *noticeview,
2065 if (partial_unmark(msginfo) == 0) {
2066 partial_recv_show(noticeview, msginfo);
2070 static void select_account_cb(GtkWidget *w, gpointer data)
2072 *(gint*)data = combobox_get_active_data(GTK_COMBO_BOX(w));
2075 static PrefsAccount *select_account_from_list(GList *ac_list)
2080 cm_return_val_if_fail(ac_list != NULL, NULL);
2081 cm_return_val_if_fail(ac_list->data != NULL, NULL);
2083 optmenu = gtkut_account_menu_new(ac_list,
2084 G_CALLBACK(select_account_cb),
2088 account_id = ((PrefsAccount *) ac_list->data)->account_id;
2089 if (alertpanel_with_widget(
2090 _("Return Receipt Notification"),
2091 _("More than one of your accounts uses the "
2092 "address that this message was sent to.\n"
2093 "Please choose which account you want to "
2094 "use for sending the receipt notification:"),
2095 _("_Cancel"), _("_Send Notification"), NULL,
2096 FALSE, G_ALERTDEFAULT, optmenu) != G_ALERTALTERNATE)
2098 return account_find_from_id(account_id);
2102 * \brief return selected messageview text, when nothing is
2103 * selected and message was filtered, return complete text
2105 * \param pointer to Messageview
2107 * \return pointer to text (needs to be free'd by calling func)
2109 gchar *messageview_get_selection(MessageView *msgview)
2113 GtkTextView *edit = NULL;
2114 GtkTextBuffer *textbuf;
2116 GtkTextIter start_iter, end_iter;
2117 GtkTextMark *body_start, *body_end;
2119 cm_return_val_if_fail(msgview != NULL, NULL);
2121 if (msgview->mimeview->type == MIMEVIEW_VIEWER) {
2122 MimeViewer *viewer = msgview->mimeview->mimeviewer;
2123 if (viewer && viewer->get_selection) {
2124 text = viewer->get_selection(viewer);
2130 textview = messageview_get_current_textview(msgview);
2131 cm_return_val_if_fail(textview != NULL, NULL);
2133 edit = GTK_TEXT_VIEW(textview->text);
2134 cm_return_val_if_fail(edit != NULL, NULL);
2135 body_pos = textview->body_pos;
2137 textbuf = gtk_text_view_get_buffer(edit);
2139 if (gtk_text_buffer_get_selection_bounds(textbuf, NULL, NULL)) {
2140 return gtkut_text_view_get_selection(edit);
2142 if (msgview->filtered) {
2143 gtk_text_buffer_get_iter_at_offset(textbuf, &start_iter, body_pos);
2144 gtk_text_buffer_get_end_iter(textbuf, &end_iter);
2146 body_start = gtk_text_buffer_get_mark(textbuf, "body_start");
2148 /* If there is no body_start mark, an attachment is likely
2149 * selected, and we're looking at instructions on what to do
2150 * with it. No point in quoting that, so we'll just return NULL,
2151 * so that original message body is quoted instead down the line.
2153 if (body_start == NULL) {
2157 gtk_text_buffer_get_iter_at_mark(textbuf, &start_iter, body_start);
2159 body_end = gtk_text_buffer_get_mark(textbuf, "body_end");
2160 if (body_end != NULL) /* Just in case */
2161 gtk_text_buffer_get_iter_at_mark(textbuf, &end_iter, body_end);
2163 gtk_text_buffer_get_end_iter(textbuf, &end_iter);
2166 return gtk_text_buffer_get_text(textbuf, &start_iter, &end_iter, FALSE);
2172 static void save_as_cb(GtkAction *action, gpointer data)
2174 MessageView *messageview = (MessageView *)data;
2175 messageview_save_as(messageview);
2178 static void print_mimeview(MimeView *mimeview, gint sel_start, gint sel_end, gint partnum)
2180 MainWindow *mainwin;
2182 || !mimeview->textview
2183 || !mimeview->textview->text)
2184 alertpanel_warning(_("Cannot print: the message doesn't "
2187 gtk_widget_realize(mimeview->textview->text);
2189 mimeview_select_part_num(mimeview, partnum);
2191 if (mimeview->type == MIMEVIEW_VIEWER) {
2192 MimeViewer *viewer = mimeview->mimeviewer;
2193 if (viewer && viewer->print) {
2194 viewer->print(viewer);
2198 if (sel_start != -1 && sel_end != -1) {
2199 GtkTextIter start, end;
2200 GtkTextView *text = GTK_TEXT_VIEW(mimeview->textview->text);
2201 GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
2203 gtk_text_buffer_get_iter_at_offset(buffer, &start, sel_start);
2204 gtk_text_buffer_get_iter_at_offset(buffer, &end, sel_end);
2205 gtk_text_buffer_select_range(buffer, &start, &end);
2207 /* TODO: Get the real parent window, not the main window */
2208 mainwin = mainwindow_get_mainwindow();
2209 printing_print(GTK_TEXT_VIEW(mimeview->textview->text),
2210 mainwin ? GTK_WINDOW(mainwin->window) : NULL,
2212 (mimeview->textview->image
2213 ? GTK_IMAGE(mimeview->textview->image)
2218 void messageview_print(MsgInfo *msginfo, gboolean all_headers,
2219 gint sel_start, gint sel_end, gint partnum)
2221 PangoFontDescription *font_desc = NULL;
2222 MessageView *tmpview = messageview_create_with_new_window_visible(
2223 mainwindow_get_mainwindow(), FALSE);
2225 if (prefs_common.use_different_print_font) {
2226 font_desc = pango_font_description_from_string
2227 (prefs_common.printfont);
2229 font_desc = pango_font_description_from_string
2230 (prefs_common.textfont);
2233 gtk_widget_modify_font(tmpview->mimeview->textview->text,
2235 pango_font_description_free(font_desc);
2238 tmpview->all_headers = all_headers;
2239 if (msginfo && messageview_show(tmpview, msginfo,
2240 tmpview->all_headers) >= 0) {
2241 print_mimeview(tmpview->mimeview,
2242 sel_start, sel_end, partnum);
2244 messageview_destroy(tmpview);
2247 static void page_setup_cb(GtkAction *action, gpointer data)
2249 MessageView *messageview = (MessageView *)data;
2250 printing_page_setup(messageview ?
2251 GTK_WINDOW(messageview->window) : NULL);
2254 static void print_cb(GtkAction *action, gpointer data)
2256 MessageView *messageview = (MessageView *)data;
2257 gint sel_start = -1, sel_end = -1, partnum = 0;
2259 if (!messageview->msginfo) return;
2261 partnum = mimeview_get_selected_part_num(messageview->mimeview);
2262 textview_get_selection_offsets(messageview->mimeview->textview,
2263 &sel_start, &sel_end);
2264 messageview_print(messageview->msginfo, messageview->all_headers,
2265 sel_start, sel_end, partnum);
2268 static void close_cb(GtkAction *action, gpointer data)
2270 MessageView *messageview = (MessageView *)data;
2271 messageview_destroy(messageview);
2274 static void copy_cb(GtkAction *action, gpointer data)
2276 MessageView *messageview = (MessageView *)data;
2277 messageview_copy_clipboard(messageview);
2280 static void allsel_cb(GtkAction *action, gpointer data)
2282 MessageView *messageview = (MessageView *)data;
2283 messageview_select_all(messageview);
2286 static void search_cb(GtkAction *action, gpointer data)
2288 MessageView *messageview = (MessageView *)data;
2289 message_search(messageview);
2292 static void prev_cb(GtkAction *action, gpointer data)
2294 MessageView *messageview = (MessageView *)data;
2295 messageview->updating = TRUE;
2296 summary_select_prev(messageview->mainwin->summaryview);
2297 messageview->updating = FALSE;
2299 if (messageview->deferred_destroy) {
2300 debug_print("messageview got away!\n");
2301 messageview_destroy(messageview);
2304 if (messageview->mainwin->summaryview->selected) {
2305 #ifndef GENERIC_UMPC
2306 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2309 messageview_show(messageview, msginfo,
2310 messageview->all_headers);
2313 gtk_widget_destroy(messageview->window);
2317 static void next_cb(GtkAction *action, gpointer data)
2319 MessageView *messageview = (MessageView *)data;
2320 messageview->updating = TRUE;
2321 summary_select_next(messageview->mainwin->summaryview);
2322 messageview->updating = FALSE;
2324 if (messageview->deferred_destroy) {
2325 debug_print("messageview got away!\n");
2326 messageview_destroy(messageview);
2329 if (messageview->mainwin->summaryview->selected) {
2330 #ifndef GENERIC_UMPC
2331 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2334 messageview_show(messageview, msginfo,
2335 messageview->all_headers);
2338 gtk_widget_destroy(messageview->window);
2342 static void prev_unread_cb(GtkAction *action, gpointer data)
2344 MessageView *messageview = (MessageView *)data;
2345 messageview->updating = TRUE;
2346 summary_select_prev_unread(messageview->mainwin->summaryview);
2347 messageview->updating = FALSE;
2349 if (messageview->deferred_destroy) {
2350 debug_print("messageview got away!\n");
2351 messageview_destroy(messageview);
2354 if (messageview->mainwin->summaryview->selected) {
2355 #ifndef GENERIC_UMPC
2356 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2359 messageview_show(messageview, msginfo,
2360 messageview->all_headers);
2363 gtk_widget_destroy(messageview->window);
2367 static void next_unread_cb(GtkAction *action, gpointer data)
2369 MessageView *messageview = (MessageView *)data;
2370 messageview->updating = TRUE;
2371 summary_select_next_unread(messageview->mainwin->summaryview);
2372 messageview->updating = FALSE;
2374 if (messageview->deferred_destroy) {
2375 debug_print("messageview got away!\n");
2376 messageview_destroy(messageview);
2379 if (messageview->mainwin->summaryview->selected) {
2380 #ifndef GENERIC_UMPC
2381 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2384 messageview_show(messageview, msginfo,
2385 messageview->all_headers);
2388 gtk_widget_destroy(messageview->window);
2392 static void prev_new_cb(GtkAction *action, gpointer data)
2394 MessageView *messageview = (MessageView *)data;
2395 messageview->updating = TRUE;
2396 summary_select_prev_new(messageview->mainwin->summaryview);
2397 messageview->updating = FALSE;
2399 if (messageview->deferred_destroy) {
2400 debug_print("messageview got away!\n");
2401 messageview_destroy(messageview);
2404 if (messageview->mainwin->summaryview->selected) {
2405 #ifndef GENERIC_UMPC
2406 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2409 messageview_show(messageview, msginfo,
2410 messageview->all_headers);
2413 gtk_widget_destroy(messageview->window);
2417 static void next_new_cb(GtkAction *action, gpointer data)
2419 MessageView *messageview = (MessageView *)data;
2420 messageview->updating = TRUE;
2421 summary_select_next_new(messageview->mainwin->summaryview);
2422 messageview->updating = FALSE;
2424 if (messageview->deferred_destroy) {
2425 debug_print("messageview got away!\n");
2426 messageview_destroy(messageview);
2429 if (messageview->mainwin->summaryview->selected) {
2430 #ifndef GENERIC_UMPC
2431 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2434 messageview_show(messageview, msginfo,
2435 messageview->all_headers);
2438 gtk_widget_destroy(messageview->window);
2442 static void prev_marked_cb(GtkAction *action, gpointer data)
2444 MessageView *messageview = (MessageView *)data;
2445 messageview->updating = TRUE;
2446 summary_select_prev_marked(messageview->mainwin->summaryview);
2447 messageview->updating = FALSE;
2449 if (messageview->deferred_destroy) {
2450 debug_print("messageview got away!\n");
2451 messageview_destroy(messageview);
2454 if (messageview->mainwin->summaryview->selected) {
2455 #ifndef GENERIC_UMPC
2456 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2459 messageview_show(messageview, msginfo,
2460 messageview->all_headers);
2463 gtk_widget_destroy(messageview->window);
2467 static void next_marked_cb(GtkAction *action, gpointer data)
2469 MessageView *messageview = (MessageView *)data;
2470 messageview->updating = TRUE;
2471 summary_select_next_marked(messageview->mainwin->summaryview);
2472 messageview->updating = FALSE;
2474 if (messageview->deferred_destroy) {
2475 debug_print("messageview got away!\n");
2476 messageview_destroy(messageview);
2479 if (messageview->mainwin->summaryview->selected) {
2480 #ifndef GENERIC_UMPC
2481 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2484 messageview_show(messageview, msginfo,
2485 messageview->all_headers);
2488 gtk_widget_destroy(messageview->window);
2492 static void prev_labeled_cb(GtkAction *action, gpointer data)
2494 MessageView *messageview = (MessageView *)data;
2495 messageview->updating = TRUE;
2496 summary_select_prev_labeled(messageview->mainwin->summaryview);
2497 messageview->updating = FALSE;
2499 if (messageview->deferred_destroy) {
2500 debug_print("messageview got away!\n");
2501 messageview_destroy(messageview);
2504 if (messageview->mainwin->summaryview->selected) {
2505 #ifndef GENERIC_UMPC
2506 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2509 messageview_show(messageview, msginfo,
2510 messageview->all_headers);
2513 gtk_widget_destroy(messageview->window);
2517 static void next_labeled_cb(GtkAction *action, gpointer data)
2519 MessageView *messageview = (MessageView *)data;
2520 messageview->updating = TRUE;
2521 summary_select_next_labeled(messageview->mainwin->summaryview);
2522 messageview->updating = FALSE;
2524 if (messageview->deferred_destroy) {
2525 debug_print("messageview got away!\n");
2526 messageview_destroy(messageview);
2529 if (messageview->mainwin->summaryview->selected) {
2530 #ifndef GENERIC_UMPC
2531 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2534 messageview_show(messageview, msginfo,
2535 messageview->all_headers);
2538 gtk_widget_destroy(messageview->window);
2542 static void prev_history_cb(GtkAction *action, gpointer data)
2544 MessageView *messageview = (MessageView *)data;
2545 MsgInfo *info = messageview_nav_get_prev(messageview);
2547 messageview->updating = TRUE;
2548 messageview_show(messageview, info,
2549 messageview->all_headers);
2550 messageview->updating = FALSE;
2551 procmsg_msginfo_free(&info);
2552 if (messageview->deferred_destroy) {
2553 debug_print("messageview got away!\n");
2554 messageview_destroy(messageview);
2560 static void next_history_cb(GtkAction *action, gpointer data)
2562 MessageView *messageview = (MessageView *)data;
2563 MsgInfo *info = messageview_nav_get_next(messageview);
2565 messageview->updating = TRUE;
2566 messageview_show(messageview, info,
2567 messageview->all_headers);
2568 messageview->updating = FALSE;
2569 procmsg_msginfo_free(&info);
2570 if (messageview->deferred_destroy) {
2571 debug_print("messageview got away!\n");
2572 messageview_destroy(messageview);
2578 static void parent_cb(GtkAction *action, gpointer data)
2580 MessageView *messageview = (MessageView *)data;
2581 messageview->updating = TRUE;
2582 summary_select_parent(messageview->mainwin->summaryview);
2583 messageview->updating = FALSE;
2585 if (messageview->deferred_destroy) {
2586 debug_print("messageview got away!\n");
2587 messageview_destroy(messageview);
2590 if (messageview->mainwin->summaryview->selected) {
2591 #ifndef GENERIC_UMPC
2592 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2595 messageview_show(messageview, msginfo,
2596 messageview->all_headers);
2599 gtk_widget_destroy(messageview->window);
2603 static void goto_unread_folder_cb(GtkAction *action, gpointer data)
2605 MessageView *messageview = (MessageView *)data;
2607 messageview->updating = TRUE;
2608 folderview_select_next_with_flag(messageview->mainwin->folderview, MSG_UNREAD);
2609 messageview->updating = FALSE;
2611 if (messageview->deferred_destroy) {
2612 debug_print("messageview got away!\n");
2613 messageview_destroy(messageview);
2616 if (messageview->mainwin->summaryview->selected) {
2617 #ifndef GENERIC_UMPC
2618 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2621 messageview_show(messageview, msginfo,
2622 messageview->all_headers);
2625 gtk_widget_destroy(messageview->window);
2629 static void goto_folder_cb(GtkAction *action, gpointer data)
2631 MessageView *messageview = (MessageView *)data;
2632 FolderItem *to_folder;
2634 to_folder = foldersel_folder_sel(NULL, FOLDER_SEL_ALL, NULL, FALSE);
2637 folderview_select(messageview->mainwin->folderview, to_folder);
2639 if (messageview->deferred_destroy) {
2640 debug_print("messageview got away!\n");
2641 messageview_destroy(messageview);
2644 if (messageview->mainwin->summaryview->selected) {
2645 #ifndef GENERIC_UMPC
2646 MsgInfo * msginfo = summary_get_selected_msg(messageview->mainwin->summaryview);
2649 messageview_show(messageview, msginfo,
2650 messageview->all_headers);
2653 gtk_widget_destroy(messageview->window);
2658 static void scroll_prev_line_cb(GtkAction *action, gpointer data)
2660 MessageView *messageview = (MessageView *)data;
2661 mimeview_scroll_one_line(messageview->mimeview,TRUE);
2664 static void scroll_next_line_cb(GtkAction *action, gpointer data)
2666 MessageView *messageview = (MessageView *)data;
2667 mimeview_scroll_one_line(messageview->mimeview,FALSE);
2670 static void scroll_prev_page_cb(GtkAction *action, gpointer data)
2672 MessageView *messageview = (MessageView *)data;
2673 mimeview_scroll_page(messageview->mimeview,TRUE);
2676 static void scroll_next_page_cb(GtkAction *action, gpointer data)
2678 MessageView *messageview = (MessageView *)data;
2679 mimeview_scroll_page(messageview->mimeview,FALSE);
2682 static void set_charset_cb(GtkAction *action, GtkRadioAction *current, gpointer data)
2684 MessageView *messageview = (MessageView *)data;
2685 gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current));
2686 gint value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (current));
2687 const gchar *charset;
2690 charset = conv_get_charset_str((CharSet)value);
2691 g_free(messageview->forced_charset);
2692 messageview->forced_charset = g_strdup(charset);
2693 procmime_force_charset(charset);
2695 messageview_show(messageview, messageview->msginfo, FALSE);
2699 static void set_decode_cb(GtkAction *action, GtkRadioAction *current, gpointer data)
2701 MessageView *messageview = (MessageView *)data;
2702 gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current));
2703 gint value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (current));
2706 messageview->forced_encoding = (EncodingType)value;
2708 messageview_show(messageview, messageview->msginfo, FALSE);
2709 debug_print("forced encoding: %d\n", value);
2714 static void view_source_cb(GtkAction *action, gpointer data)
2716 MessageView *messageview = (MessageView *)data;
2717 SourceWindow *srcwin;
2719 if (!messageview->msginfo) return;
2721 srcwin = source_window_create();
2722 source_window_show_msg(srcwin, messageview->msginfo);
2723 source_window_show(srcwin);
2726 static void show_all_header_cb(GtkToggleAction *action, gpointer data)
2728 MessageView *messageview = (MessageView *)data;
2729 MsgInfo *msginfo = messageview->msginfo;
2731 if (messageview->mimeview->textview &&
2732 messageview->mimeview->textview->loading) {
2735 if (messageview->updating)
2738 messageview->all_headers = prefs_common.show_all_headers =
2739 gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
2740 if (!msginfo) return;
2741 messageview->msginfo = NULL;
2742 messageview_show(messageview, msginfo, messageview->all_headers);
2743 procmsg_msginfo_free(&msginfo);
2744 main_window_set_menu_sensitive(messageview->mainwin);
2745 summary_redisplay_msg(messageview->mainwin->summaryview);
2748 static void msg_hide_quotes_cb(GtkToggleAction *action, gpointer data)
2750 MessageView *messageview = (MessageView *)data;
2751 MsgInfo *msginfo = messageview->msginfo;
2752 static gboolean updating_menu = FALSE;
2756 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2757 const gchar *a_name = gtk_action_get_name(GTK_ACTION(action));
2758 if (!strcmp(a_name, "View/Quotes/CollapseAll")) prefs_common.hide_quotes = 1;
2759 else if (!strcmp(a_name, "View/Quotes/Collapse2")) prefs_common.hide_quotes = 2;
2760 else if (!strcmp(a_name, "View/Quotes/Collapse3")) prefs_common.hide_quotes = 3;
2762 prefs_common.hide_quotes = 0;
2766 cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/CollapseAll", (prefs_common.hide_quotes == 1));
2767 cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse2", (prefs_common.hide_quotes == 2));
2768 cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse3", (prefs_common.hide_quotes == 3));
2770 updating_menu=FALSE;
2771 if (!msginfo) return;
2772 messageview->msginfo = NULL;
2773 messageview_show(messageview, msginfo,
2774 messageview->all_headers);
2775 procmsg_msginfo_free(&msginfo);
2777 /* update main window */
2778 main_window_set_menu_sensitive(messageview->mainwin);
2779 summary_redisplay_msg(messageview->mainwin->summaryview);
2781 #undef SET_CHECK_MENU_ACTIVE
2783 static void compose_cb(GtkAction *action, gpointer data)
2785 MessageView *messageview = (MessageView *)data;
2786 PrefsAccount *ac = NULL;
2787 FolderItem *item = NULL;
2789 if (messageview->msginfo)
2790 item = messageview->msginfo->folder;
2793 ac = account_find_from_item(item);
2794 if (ac && ac->protocol == A_NNTP &&
2795 FOLDER_TYPE(item->folder) == F_NEWS) {
2796 compose_new(ac, item->path, NULL);
2801 compose_new(ac, NULL, NULL);
2804 #define DO_ACTION(name, act) { if (!strcmp(a_name, name)) action = act; }
2806 static void reply_cb(GtkAction *gaction, gpointer data)
2808 MessageView *messageview = (MessageView *)data;
2809 GSList *msginfo_list = NULL;
2810 gint action = COMPOSE_REPLY;
2811 const gchar *a_name = gtk_action_get_name(gaction);
2813 cm_return_if_fail(messageview->msginfo);
2815 DO_ACTION("Message/Reply", COMPOSE_REPLY);
2816 DO_ACTION("Message/ReplyTo/All", COMPOSE_REPLY_TO_ALL);
2817 DO_ACTION("Message/ReplyTo/Sender", COMPOSE_REPLY_TO_SENDER);
2818 DO_ACTION("Message/ReplyTo/List", COMPOSE_REPLY_TO_LIST);
2819 DO_ACTION("Message/Forward", COMPOSE_FORWARD_INLINE);
2820 DO_ACTION("Message/ForwardAtt", COMPOSE_FORWARD_AS_ATTACH);
2821 DO_ACTION("Message/Redirect", COMPOSE_REDIRECT);
2823 msginfo_list = g_slist_append(msginfo_list, messageview->msginfo);
2824 compose_reply_from_messageview(messageview, msginfo_list, action);
2825 g_slist_free(msginfo_list);
2828 static void addressbook_open_cb(GtkAction *action, gpointer data)
2830 #ifndef USE_ALT_ADDRBOOK
2831 addressbook_open(NULL);
2833 GError* error = NULL;
2835 addressbook_dbus_open(FALSE, &error);
2837 g_warning("Failed to open address book: %s", error->message);
2838 g_error_free(error);
2843 static void add_address_cb(GtkAction *action, gpointer data)
2845 MessageView *messageview = (MessageView *)data;
2846 MsgInfo *msginfo, *full_msginfo;
2848 GdkPixbuf *picture = NULL;
2849 AvatarRender *avatarr;
2851 if (!messageview->msginfo || !messageview->msginfo->from)
2854 msginfo = messageview->msginfo;
2855 Xstrdup_a(from, msginfo->from, return);
2856 eliminate_address_comment(from);
2857 extract_address(from);
2859 full_msginfo = procmsg_msginfo_get_full_info(msginfo);
2861 avatarr = avatars_avatarrender_new(full_msginfo);
2862 hooks_invoke(AVATAR_IMAGE_RENDER_HOOKLIST, avatarr);
2864 procmsg_msginfo_free(&full_msginfo);
2866 if (avatarr->image != NULL)
2867 picture = gtk_image_get_pixbuf(GTK_IMAGE(avatarr->image));
2869 #ifndef USE_ALT_ADDRBOOK
2870 addressbook_add_contact(msginfo->fromname, from, NULL, picture);
2872 if (addressadd_selection(msginfo->fromname, from, NULL, picture)) {
2873 debug_print( "addressbook_add_contact - added\n" );
2876 avatars_avatarrender_free(avatarr);
2879 static void create_filter_cb(GtkAction *gaction, gpointer data)
2881 MessageView *messageview = (MessageView *)data;
2884 const gchar *a_name = gtk_action_get_name(gaction);
2886 if (!messageview->msginfo) return;
2888 DO_ACTION("Tools/CreateFilterRule/Automatically", FILTER_BY_AUTO);
2889 DO_ACTION("Tools/CreateFilterRule/ByFrom", FILTER_BY_FROM);
2890 DO_ACTION("Tools/CreateFilterRule/ByTo", FILTER_BY_TO);
2891 DO_ACTION("Tools/CreateFilterRule/BySubject", FILTER_BY_SUBJECT);
2893 item = messageview->msginfo->folder;
2894 summary_msginfo_filter_open(item, messageview->msginfo,
2895 (PrefsFilterType)action, 0);
2898 static void create_processing_cb(GtkAction *gaction, gpointer data)
2900 MessageView *messageview = (MessageView *)data;
2903 const gchar *a_name = gtk_action_get_name(gaction);
2905 if (!messageview->msginfo) return;
2907 DO_ACTION("Tools/CreateProcessingRule/Automatically", FILTER_BY_AUTO);
2908 DO_ACTION("Tools/CreateProcessingRule/ByFrom", FILTER_BY_FROM);
2909 DO_ACTION("Tools/CreateProcessingRule/ByTo", FILTER_BY_TO);
2910 DO_ACTION("Tools/CreateProcessingRule/BySubject", FILTER_BY_SUBJECT);
2912 item = messageview->msginfo->folder;
2913 summary_msginfo_filter_open(item, messageview->msginfo,
2914 (PrefsFilterType)action, 1);
2917 static void open_urls_cb(GtkAction *action, gpointer data)
2919 MessageView *messageview = (MessageView *)data;
2920 messageview_list_urls(messageview);
2923 static void about_cb(GtkAction *gaction, gpointer data)
2928 static gboolean messageview_update_msg(gpointer source, gpointer data)
2930 MsgInfoUpdate *msginfo_update = (MsgInfoUpdate *) source;
2931 MessageView *messageview = (MessageView *)data;
2932 MsgInfo *old_msginfo = messageview->msginfo;
2934 if (messageview->msginfo != msginfo_update->msginfo)
2937 if ((msginfo_update->flags & MSGINFO_UPDATE_DELETED) ||
2938 MSG_IS_DELETED(old_msginfo->flags))
2940 if (messageview->new_window) {
2941 if (old_msginfo->folder && old_msginfo->folder->total_msgs == 0) {
2942 messageview_clear(messageview);
2943 textview_show_info(messageview->mimeview->textview,
2944 _("\n There are no messages in this folder"));
2948 if (!prefs_common.always_show_msg) {
2949 messageview_clear(messageview);
2950 textview_show_info(messageview->mimeview->textview,
2951 MSG_IS_DELETED(old_msginfo->flags) ?
2952 _("\n Message has been deleted") :
2953 _("\n Message has been deleted or moved to another folder"));
2955 messageview->update_needed = TRUE;
2958 messageview_clear(messageview);
2959 messageview_update(messageview, old_msginfo);
2966 void messageview_set_menu_sensitive(MessageView *messageview)
2968 if (!messageview || !messageview->ui_manager)
2971 cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/CollapseAll", (prefs_common.hide_quotes == 1));
2972 cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse2", (prefs_common.hide_quotes == 2));
2973 cm_toggle_menu_set_active_full(messageview->ui_manager, "Menu/View/Quotes/Collapse3", (prefs_common.hide_quotes == 3));
2974 cm_menu_set_sensitive_full(messageview->ui_manager, "Menu/View/Goto/PrevHistory", messageview_nav_has_prev(messageview));
2975 cm_menu_set_sensitive_full(messageview->ui_manager, "Menu/View/Goto/NextHistory", messageview_nav_has_next(messageview));
2977 cm_menu_set_sensitive_full(messageview->ui_manager, "Menu/Message/CheckSignature", messageview->mimeview->signed_part);
2980 void messageview_learn (MessageView *msgview, gboolean is_spam)
2983 if (procmsg_spam_learner_learn(msgview->msginfo, NULL, TRUE) == 0)
2984 procmsg_msginfo_set_flags(msgview->msginfo, MSG_SPAM, 0);
2986 log_error(LOG_PROTOCOL, _("An error happened while learning.\n"));
2989 if (procmsg_spam_learner_learn(msgview->msginfo, NULL, FALSE) == 0)
2990 procmsg_msginfo_unset_flags(msgview->msginfo, MSG_SPAM, 0);
2992 log_error(LOG_PROTOCOL, _("An error happened while learning.\n"));
2994 if (msgview->toolbar)
2995 toolbar_set_learn_button
2997 MSG_IS_SPAM(msgview->msginfo->flags)?LEARN_HAM:LEARN_SPAM);
2999 toolbar_set_learn_button
3000 (msgview->mainwin->toolbar,
3001 MSG_IS_SPAM(msgview->msginfo->flags)?LEARN_HAM:LEARN_SPAM);
3004 void messageview_list_urls (MessageView *msgview)
3006 GSList *cur = msgview->mimeview->textview->uri_list;
3007 GSList *newlist = NULL;
3008 GHashTable *uri_hashtable;
3011 uri_hashtable = g_hash_table_new_full(g_str_hash, g_str_equal,
3012 (GDestroyNotify) g_free, NULL);
3014 for (; cur; cur = cur->next) {
3015 ClickableText *uri = (ClickableText *)cur->data;
3017 (!g_ascii_strncasecmp(uri->uri, "ftp.", 4) ||
3018 !g_ascii_strncasecmp(uri->uri, "ftp:", 4) ||
3019 !g_ascii_strncasecmp(uri->uri, "www.", 4) ||
3020 !g_ascii_strncasecmp(uri->uri, "http:", 5) ||
3021 !g_ascii_strncasecmp(uri->uri, "https:", 6)))
3023 tmp = g_utf8_strdown(uri->uri, -1);
3025 if (g_hash_table_lookup(uri_hashtable, tmp)) {
3030 newlist = g_slist_prepend(newlist, uri);
3031 g_hash_table_insert(uri_hashtable, tmp,
3032 GUINT_TO_POINTER(g_str_hash(tmp)));
3035 newlist = g_slist_reverse(newlist);
3036 uri_opener_open(msgview, newlist);
3037 g_slist_free(newlist);
3038 g_hash_table_destroy(uri_hashtable);
3041 static void save_part_as_cb(GtkAction *action, gpointer data)
3043 MessageView *messageview = (MessageView *)data;
3045 if (messageview->mimeview)
3046 mimeview_save_as(messageview->mimeview);
3049 static void view_part_as_text_cb(GtkAction *action, gpointer data)
3051 MessageView *messageview = (MessageView *)data;
3053 if (messageview->mimeview)
3054 mimeview_display_as_text(messageview->mimeview);
3057 static void open_part_cb(GtkAction *action, gpointer data)
3059 MessageView *messageview = (MessageView *)data;
3061 if (messageview->mimeview)
3062 mimeview_launch(messageview->mimeview, NULL);
3065 static void open_part_with_cb(GtkAction *action, gpointer data)
3067 MessageView *messageview = (MessageView *)data;
3069 if (messageview->mimeview)
3070 mimeview_open_with(messageview->mimeview);
3073 static void check_signature_cb(GtkAction *action, gpointer data)
3075 MessageView *messageview = (MessageView *)data;
3077 if (messageview->mimeview)
3078 mimeview_check_signature(messageview->mimeview);
3081 static void goto_next_part_cb(GtkAction *action, gpointer data)
3083 MessageView *messageview = (MessageView *)data;
3085 if (messageview->mimeview)
3086 mimeview_select_next_part(messageview->mimeview);
3089 static void goto_prev_part_cb(GtkAction *action, gpointer data)
3091 MessageView *messageview = (MessageView *)data;
3093 if (messageview->mimeview)
3094 mimeview_select_prev_part(messageview->mimeview);