1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 Hiroyuki Yamamoto
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include "defs.h"
21
22 #include <glib.h>
23 #include <glib/gi18n.h>
24 #include <gdk/gdkkeysyms.h>
25 #include <gtk/gtknotebook.h>
26 #include <gtk/gtkvbox.h>
27 #include <gtk/gtkcontainer.h>
28 #include <gtk/gtkwindow.h>
29 #include <gtk/gtktextview.h>
30 #include <gtk/gtkmenu.h>
31 #include <gtk/gtkmenuitem.h>
32 #include <gtk/gtkcheckmenuitem.h>
33 #include <gtk/gtkstatusbar.h>
34 #include <gtk/gtktooltips.h>
35 #include <gtk/gtkarrow.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <string.h>
39
40 #include "main.h"
41 #include "messageview.h"
42 #include "message_search.h"
43 #include "headerview.h"
44 #include "textview.h"
45 #include "imageview.h"
46 #include "mimeview.h"
47 #include "menu.h"
48 #include "about.h"
49 #include "filesel.h"
50 #include "sourcewindow.h"
51 #include "addressbook.h"
52 #include "alertpanel.h"
53 #include "inputdialog.h"
54 #include "manage_window.h"
55 #include "printing.h"
56 #include "procmsg.h"
57 #include "procheader.h"
58 #include "procmime.h"
59 #include "account.h"
60 #include "action.h"
61 #include "prefs_common.h"
62 #include "prefs_account.h"
63 #include "prefs_filter.h"
64 #include "filter.h"
65 #include "gtkutils.h"
66 #include "utils.h"
67 #include "rfc2015.h"
68 #include "plugin.h"
69
70 static GList *messageview_list = NULL;
71
72 static void messageview_set_mime_view_layout
73 (MessageView *messageview);
74 static void messageview_change_view_type(MessageView *messageview,
75 MessageType type);
76 static void messageview_set_tool_menu (MessageView *messageview,
77 MimeInfo *mimeinfo);
78 static void messageview_set_menu_state (MessageView *messageview);
79
80 static void messageview_set_encoding_menu
81 (MessageView *messageview);
82
83 static gint messageview_delete_cb (GtkWidget *widget,
84 GdkEventAny *event,
85 MessageView *messageview);
86 static void messageview_size_allocate_cb(GtkWidget *widget,
87 GtkAllocation *allocation);
88 static void messageview_toggle_attach_cb(GtkToggleButton *toggle,
89 MessageView *messageview);
90 static void messageview_switch_page_cb (GtkNotebook *notebook,
91 GtkNotebookPage *page,
92 guint page_num,
93 MessageView *messageview);
94 static gint messageview_menu_tool_btn_pressed
95 (GtkWidget *widget,
96 GdkEventButton *event,
97 MessageView *messageview);
98 static void messageview_open_file_cb (GtkWidget *widget,
99 MessageView *messageview);
100 static void messageview_save_all_cb (GtkWidget *widget,
101 MessageView *messageview);
102 static gboolean key_pressed (GtkWidget *widget,
103 GdkEventKey *event,
104 MessageView *messageview);
105
106 static void save_as_cb (gpointer data,
107 guint action,
108 GtkWidget *widget);
109 #if GTK_CHECK_VERSION(2, 10, 0)
110 static void page_setup_cb (gpointer data,
111 guint action,
112 GtkWidget *widget);
113 #endif
114 static void print_cb (gpointer data,
115 guint action,
116 GtkWidget *widget);
117 static void close_cb (gpointer data,
118 guint action,
119 GtkWidget *widget);
120 static void copy_cb (gpointer data,
121 guint action,
122 GtkWidget *widget);
123 static void allsel_cb (gpointer data,
124 guint action,
125 GtkWidget *widget);
126 static void search_cb (gpointer data,
127 guint action,
128 GtkWidget *widget);
129
130 static void set_charset_cb (gpointer data,
131 guint action,
132 GtkWidget *widget);
133 static void view_source_cb (gpointer data,
134 guint action,
135 GtkWidget *widget);
136 static void show_all_header_cb (gpointer data,
137 guint action,
138 GtkWidget *widget);
139
140 static void compose_cb (gpointer data,
141 guint action,
142 GtkWidget *widget);
143 static void reply_cb (gpointer data,
144 guint action,
145 GtkWidget *widget);
146 static void reedit_cb (gpointer data,
147 guint action,
148 GtkWidget *widget);
149
150 static void addressbook_open_cb (gpointer data,
151 guint action,
152 GtkWidget *widget);
153 static void add_address_cb (gpointer data,
154 guint action,
155 GtkWidget *widget);
156 static void create_filter_cb (gpointer data,
157 guint action,
158 GtkWidget *widget);
159
160 static void about_cb (gpointer data,
161 guint action,
162 GtkWidget *widget);
163
164 static GtkItemFactoryEntry msgview_entries[] =
165 {
166 {N_("/_File"), NULL, NULL, 0, "<Branch>"},
167 {N_("/_File/_Save as..."), NULL, save_as_cb, 0, NULL},
168 {N_("/_File/---"), NULL, NULL, 0, "<Separator>"},
169 #if GTK_CHECK_VERSION(2, 10, 0)
170 {N_("/_File/Page set_up..."), NULL, page_setup_cb, 0, NULL},
171 #endif
172 {N_("/_File/_Print..."), NULL, print_cb, 0, NULL},
173 {N_("/_File/---"), NULL, NULL, 0, "<Separator>"},
174 {N_("/_File/_Close"), NULL, close_cb, 0, NULL},
175
176 {N_("/_Edit"), NULL, NULL, 0, "<Branch>"},
177 {N_("/_Edit/_Copy"), NULL, copy_cb, 0, NULL},
178 {N_("/_Edit/Select _all"), NULL, allsel_cb, 0, NULL},
179 {N_("/_Edit/---"), NULL, NULL, 0, "<Separator>"},
180 {N_("/_Edit/_Find in current message..."),
181 NULL, search_cb, 0, NULL},
182
183 {N_("/_View"), NULL, NULL, 0, "<Branch>"},
184
185 #define ENC_SEPARATOR \
186 {N_("/_View/Character _encoding/---"), NULL, NULL, 0, "<Separator>"}
187 #define ENC_ACTION(action) \
188 NULL, set_charset_cb, action, "/View/Character encoding/Auto detect"
189
190 {N_("/_View/Character _encoding"), NULL, NULL, 0, "<Branch>"},
191 {N_("/_View/Character _encoding/_Auto detect"),
192 NULL, set_charset_cb, C_AUTO, "<RadioItem>"},
193 ENC_SEPARATOR,
194 {N_("/_View/Character _encoding/7bit ascii (US-ASC_II)"),
195 ENC_ACTION(C_US_ASCII)},
196
197 {N_("/_View/Character _encoding/Unicode (_UTF-8)"),
198 ENC_ACTION(C_UTF_8)},
199 ENC_SEPARATOR,
200 {N_("/_View/Character _encoding/Western European (ISO-8859-_1)"),
201 ENC_ACTION(C_ISO_8859_1)},
202 {N_("/_View/Character _encoding/Western European (ISO-8859-15)"),
203 ENC_ACTION(C_ISO_8859_15)},
204 {N_("/_View/Character _encoding/Western European (Windows-1252)"),
205 ENC_ACTION(C_WINDOWS_1252)},
206 ENC_SEPARATOR,
207 {N_("/_View/Character _encoding/Central European (ISO-8859-_2)"),
208 ENC_ACTION(C_ISO_8859_2)},
209 ENC_SEPARATOR,
210 {N_("/_View/Character _encoding/_Baltic (ISO-8859-13)"),
211 ENC_ACTION(C_ISO_8859_13)},
212 {N_("/_View/Character _encoding/Baltic (ISO-8859-_4)"),
213 ENC_ACTION(C_ISO_8859_4)},
214 {N_("/_View/Character _encoding/Baltic (Windows-1257)"),
215 ENC_ACTION(C_WINDOWS_1257)},
216 ENC_SEPARATOR,
217 {N_("/_View/Character _encoding/Greek (ISO-8859-_7)"),
218 ENC_ACTION(C_ISO_8859_7)},
219 ENC_SEPARATOR,
220 {N_("/_View/Character _encoding/Arabic (ISO-8859-_6)"),
221 ENC_ACTION(C_ISO_8859_6)},
222 {N_("/_View/Character _encoding/Arabic (Windows-1256)"),
223 ENC_ACTION(C_CP1256)},
224 ENC_SEPARATOR,
225 {N_("/_View/Character _encoding/Hebrew (ISO-8859-_8)"),
226 ENC_ACTION(C_ISO_8859_8)},
227 {N_("/_View/Character _encoding/Hebrew (Windows-1255)"),
228 ENC_ACTION(C_CP1255)},
229 ENC_SEPARATOR,
230 {N_("/_View/Character _encoding/Turkish (ISO-8859-_9)"),
231 ENC_ACTION(C_ISO_8859_9)},
232 ENC_SEPARATOR,
233 {N_("/_View/Character _encoding/Cyrillic (ISO-8859-_5)"),
234 ENC_ACTION(C_ISO_8859_5)},
235 {N_("/_View/Character _encoding/Cyrillic (KOI8-_R)"),
236 ENC_ACTION(C_KOI8_R)},
237 {N_("/_View/Character _encoding/Cyrillic (KOI8-U)"),
238 ENC_ACTION(C_KOI8_U)},
239 {N_("/_View/Character _encoding/Cyrillic (Windows-1251)"),
240 ENC_ACTION(C_CP1251)},
241 ENC_SEPARATOR,
242 {N_("/_View/Character _encoding/Japanese (ISO-2022-_JP)"),
243 ENC_ACTION(C_ISO_2022_JP)},
244 {N_("/_View/Character _encoding/Japanese (ISO-2022-JP-2)"),
245 ENC_ACTION(C_ISO_2022_JP_2)},
246 {N_("/_View/Character _encoding/Japanese (_EUC-JP)"),
247 ENC_ACTION(C_EUC_JP)},
248 {N_("/_View/Character _encoding/Japanese (_Shift__JIS)"),
249 ENC_ACTION(C_SHIFT_JIS)},
250 ENC_SEPARATOR,
251 {N_("/_View/Character _encoding/Simplified Chinese (_GB2312)"),
252 ENC_ACTION(C_GB2312)},
253 {N_("/_View/Character _encoding/Simplified Chinese (GBK)"),
254 ENC_ACTION(C_GBK)},
255 {N_("/_View/Character _encoding/Traditional Chinese (_Big5)"),
256 ENC_ACTION(C_BIG5)},
257 {N_("/_View/Character _encoding/Traditional Chinese (EUC-_TW)"),
258 ENC_ACTION(C_EUC_TW)},
259 {N_("/_View/Character _encoding/Chinese (ISO-2022-_CN)"),
260 ENC_ACTION(C_ISO_2022_CN)},
261 ENC_SEPARATOR,
262 {N_("/_View/Character _encoding/Korean (EUC-_KR)"),
263 ENC_ACTION(C_EUC_KR)},
264 {N_("/_View/Character _encoding/Korean (ISO-2022-KR)"),
265 ENC_ACTION(C_ISO_2022_KR)},
266 ENC_SEPARATOR,
267 {N_("/_View/Character _encoding/Thai (TIS-620)"),
268 ENC_ACTION(C_TIS_620)},
269 {N_("/_View/Character _encoding/Thai (Windows-874)"),
270 ENC_ACTION(C_WINDOWS_874)},
271
272 #undef ENC_SEPARATOR
273 #undef ENC_ACTION
274
275 {N_("/_View/---"), NULL, NULL, 0, "<Separator>"},
276 {N_("/_View/Mess_age source"), NULL, view_source_cb, 0, NULL},
277 {N_("/_View/All _headers"),
278 NULL, show_all_header_cb, 0, "<ToggleItem>"},
279
280 {N_("/_Message"), NULL, NULL, 0, "<Branch>"},
281 {N_("/_Message/Compose _new message"),
282 NULL, compose_cb, 0, NULL},
283 {N_("/_Message/---"), NULL, NULL, 0, "<Separator>"},
284 {N_("/_Message/_Reply"), NULL, reply_cb, COMPOSE_REPLY, NULL},
285 {N_("/_Message/Repl_y to/_all"),
286 NULL, reply_cb, COMPOSE_REPLY_TO_ALL, NULL},
287 {N_("/_Message/Repl_y to/_sender"),
288 NULL, reply_cb, COMPOSE_REPLY_TO_SENDER, NULL},
289 {N_("/_Message/Repl_y to/mailing _list"),
290 NULL, reply_cb, COMPOSE_REPLY_TO_LIST, NULL},
291 {N_("/_Message/---"), NULL, NULL, 0, "<Separator>"},
292 {N_("/_Message/_Forward"), NULL, reply_cb, COMPOSE_FORWARD, NULL},
293 {N_("/_Message/For_ward as attachment"),
294 NULL, reply_cb, COMPOSE_FORWARD_AS_ATTACH, NULL},
295 {N_("/_Message/Redirec_t"), NULL, reply_cb, COMPOSE_REDIRECT, NULL},
296 {N_("/_Message/---"), NULL, NULL, 0, "<Separator>"},
297 {N_("/_Message/Re-_edit"), NULL, reedit_cb, 0, NULL},
298
299 {N_("/_Tools"), NULL, NULL, 0, "<Branch>"},
300 {N_("/_Tools/_Address book"), NULL, addressbook_open_cb, 0, NULL},
301 {N_("/_Tools/Add sender to address boo_k"),
302 NULL, add_address_cb, 0, NULL},
303 {N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
304 {N_("/_Tools/_Create filter rule"),
305 NULL, NULL, 0, "<Branch>"},
306 {N_("/_Tools/_Create filter rule/_Automatically"),
307 NULL, create_filter_cb, FLT_BY_AUTO, NULL},
308 {N_("/_Tools/_Create filter rule/by _From"),
309 NULL, create_filter_cb, FLT_BY_FROM, NULL},
310 {N_("/_Tools/_Create filter rule/by _To"),
311 NULL, create_filter_cb, FLT_BY_TO, NULL},
312 {N_("/_Tools/_Create filter rule/by _Subject"),
313 NULL, create_filter_cb, FLT_BY_SUBJECT, NULL},
314 #ifndef G_OS_WIN32
315 {N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
316 {N_("/_Tools/Actio_ns"), NULL, NULL, 0, "<Branch>"},
317 #endif
318
319 {N_("/_Help"), NULL, NULL, 0, "<Branch>"},
320 {N_("/_Help/_About"), NULL, about_cb, 0, NULL}
321 };
322
323
messageview_create(void)324 MessageView *messageview_create(void)
325 {
326 MessageView *messageview;
327 GtkWidget *vbox;
328 GtkWidget *notebook;
329 GtkWidget *hbox;
330 GtkWidget *toolbar_vbox;
331 GtkWidget *toolbar_hbox;
332 GtkWidget *image;
333 GtkWidget *arrow;
334 GtkWidget *mime_toggle_btn;
335 GtkWidget *menu_tool_btn;
336 GtkWidget *tool_menu;
337 GtkWidget *menuitem;
338 HeaderView *headerview;
339 TextView *textview;
340 MimeView *mimeview;
341 GtkTooltips *tip;
342
343 debug_print(_("Creating message view...\n"));
344 messageview = g_new0(MessageView, 1);
345
346 messageview->type = MVIEW_TEXT;
347
348 headerview = headerview_create();
349
350 textview = textview_create();
351 textview->messageview = messageview;
352
353 mimeview = mimeview_create();
354 mimeview->textview = textview_create();
355 mimeview->textview->messageview = messageview;
356 mimeview->imageview = imageview_create();
357 mimeview->imageview->messageview = messageview;
358 mimeview->messageview = messageview;
359
360 notebook = gtk_notebook_new();
361 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
362 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
363 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
364 gtk_widget_show(notebook);
365
366 gtk_container_add(GTK_CONTAINER(notebook), GTK_WIDGET_PTR(textview));
367 gtk_notebook_set_tab_label_text
368 (GTK_NOTEBOOK(notebook), GTK_WIDGET_PTR(textview), _("Text"));
369
370 gtk_container_add(GTK_CONTAINER(notebook), GTK_WIDGET_PTR(mimeview));
371 gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(notebook),
372 GTK_WIDGET_PTR(mimeview),
373 _("Attachments"));
374
375 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
376 gtk_widget_show_all(notebook);
377
378 /* Attachment toolbar */
379 toolbar_vbox = gtk_vbox_new(FALSE, 0);
380 gtk_widget_show(toolbar_vbox);
381
382 toolbar_hbox = gtk_hbox_new(FALSE, 0);
383 gtk_widget_show(toolbar_hbox);
384 gtk_box_pack_start(GTK_BOX(toolbar_vbox), toolbar_hbox, TRUE, FALSE, 0);
385
386 mime_toggle_btn = gtk_toggle_button_new();
387 gtk_widget_show(mime_toggle_btn);
388 gtk_box_pack_start(GTK_BOX(toolbar_hbox), mime_toggle_btn,
389 FALSE, FALSE, 0);
390 g_signal_connect(G_OBJECT(mime_toggle_btn), "toggled",
391 G_CALLBACK(messageview_toggle_attach_cb), messageview);
392
393 image = stock_pixbuf_widget_scale(NULL, STOCK_PIXMAP_MAIL_ATTACH, 18, 18);
394 gtk_widget_show(image);
395 gtk_container_add(GTK_CONTAINER(mime_toggle_btn), image);
396
397 tip = gtk_tooltips_new();
398 gtk_tooltips_set_tip(tip, mime_toggle_btn,
399 _("Switch to attachment list view"), NULL);
400
401 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
402 gtk_widget_show(arrow);
403 gtk_widget_set_size_request(arrow, 5, -1);
404
405 menu_tool_btn = gtk_button_new();
406 gtk_container_add(GTK_CONTAINER(menu_tool_btn), arrow);
407 GTK_WIDGET_UNSET_FLAGS(menu_tool_btn, GTK_CAN_FOCUS);
408 gtk_widget_show(menu_tool_btn);
409 gtk_box_pack_start(GTK_BOX(toolbar_hbox), menu_tool_btn,
410 FALSE, FALSE, 0);
411 g_signal_connect(G_OBJECT(menu_tool_btn), "button_press_event",
412 G_CALLBACK(messageview_menu_tool_btn_pressed),
413 messageview);
414
415 tool_menu = gtk_menu_new();
416 MENUITEM_ADD(tool_menu, menuitem, NULL, 0);
417 MENUITEM_ADD_WITH_MNEMONIC(tool_menu, menuitem, _("Save _all attachments..."), 0);
418 g_signal_connect(G_OBJECT(menuitem), "activate",
419 G_CALLBACK(messageview_save_all_cb), messageview);
420 gtk_widget_show_all(tool_menu);
421
422 gtk_widget_hide(toolbar_vbox);
423
424 hbox = gtk_hbox_new(FALSE, 0);
425 gtk_widget_show(hbox);
426 gtk_box_pack_start(GTK_BOX(hbox), toolbar_vbox, FALSE, FALSE, 0);
427 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET_PTR(headerview), TRUE, TRUE, 0);
428
429 vbox = gtk_vbox_new(FALSE, 0);
430 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
431 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
432 gtk_widget_show(vbox);
433
434 /* to remove without destroyed */
435 gtk_widget_ref(GTK_WIDGET_PTR(mimeview->textview));
436 gtk_widget_ref(GTK_WIDGET_PTR(mimeview->imageview));
437
438 g_signal_connect(G_OBJECT(notebook), "switch_page",
439 G_CALLBACK(messageview_switch_page_cb), messageview);
440
441 messageview->vbox = vbox;
442
443 messageview->notebook = notebook;
444
445 messageview->hbox = hbox;
446 messageview->toolbar_vbox = toolbar_vbox;
447 messageview->mime_toggle_btn = mime_toggle_btn;
448 messageview->menu_tool_btn = menu_tool_btn;
449 messageview->tool_menu = tool_menu;
450
451 messageview->new_window = FALSE;
452 messageview->window = NULL;
453 messageview->window_vbox = NULL;
454 messageview->body_vbox = NULL;
455
456 messageview->headerview = headerview;
457 messageview->textview = textview;
458 messageview->mimeview = mimeview;
459
460 messageview->statusbar = NULL;
461 messageview->statusbar_cid = 0;
462
463 messageview->current_page = 0;
464
465 return messageview;
466 }
467
messageview_create_with_new_window(void)468 MessageView *messageview_create_with_new_window(void)
469 {
470 MessageView *msgview;
471 GtkWidget *window;
472 GtkWidget *window_vbox;
473 GtkWidget *body_vbox;
474 GtkWidget *vspacer;
475 GtkWidget *menubar;
476 GtkItemFactory *ifactory;
477 GtkWidget *statusbar;
478 guint n_menu_entries;
479
480 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
481 gtk_window_set_title(GTK_WINDOW(window), _("Message View - Sylpheed"));
482 gtk_window_set_wmclass(GTK_WINDOW(window), "message_view", "Sylpheed");
483 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
484 gtk_widget_set_size_request(window, prefs_common.msgwin_width,
485 prefs_common.msgwin_height);
486
487 msgview = messageview_create();
488
489 window_vbox = gtk_vbox_new(FALSE, 0);
490 gtk_container_add(GTK_CONTAINER(window), window_vbox);
491
492 g_signal_connect(G_OBJECT(window), "size_allocate",
493 G_CALLBACK(messageview_size_allocate_cb),
494 msgview);
495 g_signal_connect(G_OBJECT(window), "delete_event",
496 G_CALLBACK(messageview_delete_cb), msgview);
497 g_signal_connect(G_OBJECT(window), "key_press_event",
498 G_CALLBACK(key_pressed), msgview);
499 MANAGE_WINDOW_SIGNALS_CONNECT(window);
500
501 n_menu_entries = sizeof(msgview_entries) / sizeof (msgview_entries[0]);
502 menubar = menubar_create(window, msgview_entries, n_menu_entries,
503 "<MessageView>", msgview);
504 #if 0
505 menu_factory_copy_rc("<Main>", "<MessageView>");
506 #endif
507 gtk_box_pack_start(GTK_BOX(window_vbox), menubar, FALSE, TRUE, 0);
508
509 vspacer = gtk_vbox_new(FALSE, 0);
510 gtk_box_pack_start(GTK_BOX(window_vbox), vspacer, FALSE, TRUE,
511 BORDER_WIDTH);
512
513 body_vbox = gtk_vbox_new(FALSE, BORDER_WIDTH);
514 gtk_box_pack_start(GTK_BOX(window_vbox), body_vbox, TRUE, TRUE, 0);
515
516 gtk_box_pack_start(GTK_BOX(body_vbox), GTK_WIDGET_PTR(msgview),
517 TRUE, TRUE, 0);
518 gtk_widget_grab_focus(msgview->textview->text);
519
520 statusbar = gtk_statusbar_new();
521 gtk_box_pack_end(GTK_BOX(body_vbox), statusbar, FALSE, FALSE, 0);
522 msgview->statusbar = statusbar;
523 msgview->statusbar_cid = gtk_statusbar_get_context_id
524 (GTK_STATUSBAR(statusbar), "Message View");
525
526 msgview->new_window = TRUE;
527 msgview->window = window;
528 msgview->window_vbox = window_vbox;
529 msgview->body_vbox = body_vbox;
530 msgview->menubar = menubar;
531 msgview->menu_locked = FALSE;
532 msgview->visible = TRUE;
533
534 gtk_widget_show_all(window);
535 gtk_widget_hide(msgview->toolbar_vbox);
536
537 messageview_init(msgview);
538
539 messageview_set_encoding_menu(msgview);
540
541 ifactory = gtk_item_factory_from_widget(menubar);
542 #ifndef G_OS_WIN32
543 action_update_msgview_menu(ifactory, msgview);
544 #endif
545
546 messageview_list = g_list_append(messageview_list, msgview);
547
548 return msgview;
549 }
550
messageview_init(MessageView * messageview)551 void messageview_init(MessageView *messageview)
552 {
553 headerview_init(messageview->headerview);
554 textview_init(messageview->textview);
555 mimeview_init(messageview->mimeview);
556 /* messageview_set_font(messageview); */
557 }
558
messageview_reflect_prefs(MessageView * messageview)559 void messageview_reflect_prefs(MessageView *messageview)
560 {
561 if (messageview->type == MVIEW_MIME)
562 messageview_set_mime_view_layout(messageview);
563 }
564
messageview_get_window_list(void)565 GList *messageview_get_window_list(void)
566 {
567 return messageview_list;
568 }
569
messageview_show(MessageView * messageview,MsgInfo * msginfo,gboolean all_headers)570 gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
571 gboolean all_headers)
572 {
573 gchar *file;
574 MimeInfo *mimeinfo;
575
576 g_return_val_if_fail(msginfo != NULL, -1);
577
578 mimeinfo = procmime_scan_message(msginfo);
579 if (!mimeinfo) {
580 messageview_change_view_type(messageview, MVIEW_TEXT);
581 textview_show_error(messageview->textview);
582 return -1;
583 }
584
585 file = procmsg_get_message_file_path(msginfo);
586 if (!file) {
587 g_warning("can't get message file path.\n");
588 procmime_mimeinfo_free_all(mimeinfo);
589 messageview_change_view_type(messageview, MVIEW_TEXT);
590 textview_show_error(messageview->textview);
591 return -1;
592 }
593
594 if (messageview->msginfo != msginfo) {
595 procmsg_msginfo_free(messageview->msginfo);
596 messageview->msginfo = procmsg_msginfo_get_full_info(msginfo);
597 if (!messageview->msginfo)
598 messageview->msginfo = procmsg_msginfo_copy(msginfo);
599 }
600 procmime_mimeinfo_free_all(messageview->mimeinfo);
601 messageview->mimeinfo = mimeinfo;
602 g_free(messageview->file);
603 messageview->file = file;
604
605 if (messageview->window && msginfo->subject) {
606 gchar *title;
607
608 title = g_strconcat(msginfo->subject, " - Sylpheed", NULL);
609 gtk_window_set_title(GTK_WINDOW(messageview->window), title);
610 g_free(title);
611 }
612 headerview_show(messageview->headerview, messageview->msginfo);
613
614 textview_set_all_headers(messageview->textview, all_headers);
615 textview_set_all_headers(messageview->mimeview->textview, all_headers);
616
617 if (mimeinfo->mime_type != MIME_TEXT &&
618 (prefs_common.html_only_as_attach ||
619 mimeinfo->mime_type != MIME_TEXT_HTML)) {
620 messageview_change_view_type(messageview, MVIEW_MIME);
621 mimeview_show_message(messageview->mimeview, mimeinfo, file);
622 messageview_set_tool_menu(messageview, mimeinfo);
623 } else {
624 messageview_change_view_type(messageview, MVIEW_TEXT);
625 textview_show_message(messageview->textview, mimeinfo, file);
626 }
627
628 if (messageview->new_window)
629 messageview_set_menu_state(messageview);
630
631 syl_plugin_signal_emit("messageview-show", messageview, msginfo,
632 all_headers);
633
634 return 0;
635 }
636
messageview_set_mime_view_layout(MessageView * messageview)637 static void messageview_set_mime_view_layout(MessageView *messageview)
638 {
639 if (prefs_common.attach_toolbutton_pos == 0)
640 gtk_box_set_child_packing(GTK_BOX(messageview->hbox), messageview->toolbar_vbox, FALSE, FALSE, 0, GTK_PACK_START);
641 else
642 gtk_box_set_child_packing(GTK_BOX(messageview->hbox), messageview->toolbar_vbox, FALSE, FALSE, 0, GTK_PACK_END);
643
644 if (prefs_common.show_attach_tab)
645 gtk_widget_hide(messageview->toolbar_vbox);
646 else
647 gtk_widget_show(messageview->toolbar_vbox);
648
649 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(messageview->notebook),
650 prefs_common.show_attach_tab);
651 }
652
messageview_change_view_type(MessageView * messageview,MessageType type)653 static void messageview_change_view_type(MessageView *messageview,
654 MessageType type)
655 {
656 GtkWidget *notebook = messageview->notebook;
657
658 if (messageview->type == type) return;
659
660 if (type == MVIEW_MIME) {
661 messageview_set_mime_view_layout(messageview);
662 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),
663 messageview->current_page);
664 if (messageview->current_page == 0)
665 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(messageview->mime_toggle_btn), FALSE);
666 else
667 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(messageview->mime_toggle_btn), TRUE);
668 } else if (type == MVIEW_TEXT) {
669 gint current_page = messageview->current_page;
670
671 gtk_widget_hide(messageview->toolbar_vbox);
672 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
673 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
674 messageview->current_page = current_page;
675 mimeview_clear(messageview->mimeview);
676 } else
677 return;
678
679 messageview->type = type;
680 }
681
messageview_set_tool_menu(MessageView * messageview,MimeInfo * mimeinfo)682 static void messageview_set_tool_menu(MessageView *messageview,
683 MimeInfo *mimeinfo)
684 {
685 MimeInfo *partinfo;
686 const gchar *name;
687 GtkWidget *menuitem;
688 GList *cur_item, *next = NULL;
689 gint pos = 0;
690 gboolean exist;
691
692 cur_item = GTK_MENU_SHELL(messageview->tool_menu)->children;
693 while (cur_item != NULL) {
694 next = cur_item->next;
695 if (GTK_BIN(cur_item->data)->child == NULL)
696 break;
697 gtk_widget_destroy(GTK_WIDGET(cur_item->data));
698 cur_item = next;
699 }
700
701 for (partinfo = mimeinfo; partinfo != NULL;
702 partinfo = procmime_mimeinfo_next(partinfo)) {
703 if (partinfo->filename || partinfo->name) {
704 name = g_basename(partinfo->filename ? partinfo->filename : partinfo->name);
705 if (*name == '\0')
706 name = "mimetmp";
707 menuitem = gtk_menu_item_new_with_label(name);
708 gtk_widget_show(menuitem);
709 gtk_menu_shell_insert(GTK_MENU_SHELL(messageview->tool_menu), menuitem, pos++);
710 g_object_set_data(G_OBJECT(menuitem), "tool-menu-mimeinfo", partinfo);
711 g_signal_connect(G_OBJECT(menuitem), "activate",
712 G_CALLBACK(messageview_open_file_cb),
713 messageview);
714 }
715 }
716
717 exist = (pos != 0);
718 for (cur_item = next; cur_item != NULL; cur_item = cur_item->next) {
719 menuitem = GTK_WIDGET(cur_item->data);
720 gtk_widget_set_sensitive(menuitem, exist);
721 }
722 }
723
messageview_set_menu_state(MessageView * messageview)724 static void messageview_set_menu_state(MessageView *messageview)
725 {
726 GtkItemFactory *ifactory;
727 GtkWidget *menuitem;
728
729 messageview->menu_locked = TRUE;
730
731 ifactory = gtk_item_factory_from_widget(messageview->menubar);
732 menuitem = gtk_item_factory_get_widget
733 (ifactory, "/View/All headers");
734 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
735 messageview->textview->show_all_headers);
736
737 if (messageview->msginfo &&
738 FOLDER_ITEM_IS_SENT_FOLDER(messageview->msginfo->folder))
739 menu_set_sensitive(ifactory, "/Message/Re-edit", TRUE);
740 else
741 menu_set_sensitive(ifactory, "/Message/Re-edit", FALSE);
742
743 messageview->menu_locked = FALSE;
744 }
745
messageview_set_encoding_menu(MessageView * messageview)746 static void messageview_set_encoding_menu(MessageView *messageview)
747 {
748 GtkItemFactoryEntry *entry;
749 GtkItemFactory *ifactory;
750 CharSet encoding;
751 gchar *path, *p, *q;
752 GtkWidget *item;
753
754 encoding = conv_get_charset_from_str(prefs_common.force_charset);
755 ifactory = gtk_item_factory_from_widget(messageview->menubar);
756
757 for (entry = msgview_entries; entry->callback != view_source_cb;
758 entry++) {
759 if (entry->callback == set_charset_cb &&
760 (CharSet)entry->callback_action == encoding) {
761 p = q = path = g_strdup(entry->path);
762 while (*p) {
763 if (*p == '_') {
764 if (p[1] == '_') {
765 p++;
766 *q++ = '_';
767 }
768 } else
769 *q++ = *p;
770 p++;
771 }
772 *q = '\0';
773 item = gtk_item_factory_get_item(ifactory, path);
774 gtk_widget_activate(item);
775 g_free(path);
776 break;
777 }
778 }
779 }
780
messageview_clear(MessageView * messageview)781 void messageview_clear(MessageView *messageview)
782 {
783 messageview_set_tool_menu(messageview, NULL);
784 g_free(messageview->file);
785 messageview->file = NULL;
786 procmime_mimeinfo_free_all(messageview->mimeinfo);
787 messageview->mimeinfo = NULL;
788 procmsg_msginfo_free(messageview->msginfo);
789 messageview->msginfo = NULL;
790 messageview_change_view_type(messageview, MVIEW_TEXT);
791 headerview_clear(messageview->headerview);
792 textview_clear(messageview->textview);
793 mimeview_clear(messageview->mimeview);
794 }
795
messageview_destroy(MessageView * messageview)796 void messageview_destroy(MessageView *messageview)
797 {
798 GtkWidget *textview = GTK_WIDGET_PTR(messageview->mimeview->textview);
799 GtkWidget *imageview = GTK_WIDGET_PTR(messageview->mimeview->imageview);
800
801 messageview_list = g_list_remove(messageview_list, messageview);
802
803 headerview_destroy(messageview->headerview);
804 textview_destroy(messageview->textview);
805 mimeview_destroy(messageview->mimeview);
806
807 procmsg_msginfo_free(messageview->msginfo);
808
809 gtk_widget_destroy(messageview->tool_menu);
810 if (messageview->window)
811 gtk_widget_destroy(messageview->window);
812
813 g_free(messageview);
814
815 gtk_widget_unref(textview);
816 gtk_widget_unref(imageview);
817 }
818
messageview_quote_color_set(void)819 void messageview_quote_color_set(void)
820 {
821 }
822
messageview_set_font(MessageView * messageview)823 void messageview_set_font(MessageView *messageview)
824 {
825 textview_set_font(messageview->textview, NULL);
826 }
827
messageview_get_current_textview(MessageView * messageview)828 TextView *messageview_get_current_textview(MessageView *messageview)
829 {
830 TextView *text = NULL;
831
832 if (messageview->type == MVIEW_TEXT)
833 text = messageview->textview;
834 else if (messageview->type == MVIEW_MIME) {
835 if (gtk_notebook_get_current_page
836 (GTK_NOTEBOOK(messageview->notebook)) == 0)
837 text = messageview->textview;
838 else if (messageview->mimeview->type == MIMEVIEW_TEXT)
839 text = messageview->mimeview->textview;
840 }
841
842 return text;
843 }
844
messageview_get_selected_mime_part(MessageView * messageview)845 MimeInfo *messageview_get_selected_mime_part(MessageView *messageview)
846 {
847 if (messageview->type == MVIEW_MIME)
848 return mimeview_get_selected_part(messageview->mimeview);
849
850 return NULL;
851 }
852
messageview_copy_clipboard(MessageView * messageview)853 void messageview_copy_clipboard(MessageView *messageview)
854 {
855 TextView *text;
856
857 text = messageview_get_current_textview(messageview);
858 if (text) {
859 GtkTextView *textview = GTK_TEXT_VIEW(text->text);
860 GtkTextBuffer *buffer;
861 GtkClipboard *clipboard;
862
863 buffer = gtk_text_view_get_buffer(textview);
864 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
865 gtk_text_buffer_copy_clipboard(buffer, clipboard);
866 }
867 }
868
messageview_select_all(MessageView * messageview)869 void messageview_select_all(MessageView *messageview)
870 {
871 TextView *text;
872
873 text = messageview_get_current_textview(messageview);
874 if (text) {
875 GtkTextView *textview = GTK_TEXT_VIEW(text->text);
876 GtkTextBuffer *buffer;
877 GtkTextIter start, end;
878
879 buffer = gtk_text_view_get_buffer(textview);
880 gtk_text_buffer_get_bounds(buffer, &start, &end);
881 gtk_text_buffer_select_range(buffer, &start, &end);
882 }
883 }
884
messageview_set_position(MessageView * messageview,gint pos)885 void messageview_set_position(MessageView *messageview, gint pos)
886 {
887 textview_set_position(messageview->textview, pos);
888 }
889
messageview_search_string(MessageView * messageview,const gchar * str,gboolean case_sens)890 gboolean messageview_search_string(MessageView *messageview, const gchar *str,
891 gboolean case_sens)
892 {
893 return textview_search_string(messageview->textview, str, case_sens);
894 return FALSE;
895 }
896
messageview_search_string_backward(MessageView * messageview,const gchar * str,gboolean case_sens)897 gboolean messageview_search_string_backward(MessageView *messageview,
898 const gchar *str,
899 gboolean case_sens)
900 {
901 return textview_search_string_backward(messageview->textview,
902 str, case_sens);
903 return FALSE;
904 }
905
messageview_is_visible(MessageView * messageview)906 gboolean messageview_is_visible(MessageView *messageview)
907 {
908 return messageview->visible;
909 }
910
messageview_save_as(MessageView * messageview)911 void messageview_save_as(MessageView *messageview)
912 {
913 gchar *filename = NULL;
914 MsgInfo *msginfo;
915 gchar *src, *dest;
916 FileselFileType types[4] = {{NULL, NULL}};
917 gint selected_type = 0;
918 gint result;
919 gboolean all_headers;
920
921 if (!messageview->msginfo) return;
922 msginfo = messageview->msginfo;
923
924 if (msginfo->subject && *msginfo->subject) {
925 filename = g_strdup_printf("%s.eml", msginfo->subject);
926 } else {
927 filename = g_strdup_printf("%u.eml", msginfo->msgnum);
928 }
929 subst_for_filename(filename);
930
931 types[0].type = _("Original (EML/RFC 822)");
932 types[0].ext = "eml";
933 types[1].type = _("Text");
934 types[1].ext = "txt";
935 types[2].type = _("Text (UTF-8)");
936 types[2].ext = "txt";
937 dest = filesel_save_as_type(filename, types, prefs_common.save_file_type, &selected_type);
938
939 g_free(filename);
940 if (!dest)
941 return;
942
943 all_headers = messageview->textview->show_all_headers;
944
945 if (selected_type == 1) {
946 result = procmsg_save_message_as_text(msginfo, dest, conv_get_locale_charset_str(), all_headers);
947 } else if (selected_type == 2) {
948 result = procmsg_save_message_as_text(msginfo, dest, NULL, all_headers);
949 } else {
950 src = procmsg_get_message_file(msginfo);
951 result = copy_file(src, dest, TRUE);
952 g_free(src);
953 }
954
955 if (result < 0) {
956 gchar *utf8_dest;
957
958 utf8_dest = conv_filename_to_utf8(dest);
959 alertpanel_error(_("Can't save the file `%s'."),
960 g_basename(utf8_dest));
961 g_free(utf8_dest);
962 }
963
964 g_free(dest);
965
966 prefs_common.save_file_type = selected_type;
967 }
968
messageview_delete_cb(GtkWidget * widget,GdkEventAny * event,MessageView * messageview)969 static gint messageview_delete_cb(GtkWidget *widget, GdkEventAny *event,
970 MessageView *messageview)
971 {
972 messageview_destroy(messageview);
973 return TRUE;
974 }
975
messageview_size_allocate_cb(GtkWidget * widget,GtkAllocation * allocation)976 static void messageview_size_allocate_cb(GtkWidget *widget,
977 GtkAllocation *allocation)
978 {
979 g_return_if_fail(allocation != NULL);
980
981 prefs_common.msgwin_width = allocation->width;
982 prefs_common.msgwin_height = allocation->height;
983 }
984
messageview_toggle_attach_cb(GtkToggleButton * toggle,MessageView * messageview)985 static void messageview_toggle_attach_cb(GtkToggleButton *toggle,
986 MessageView *messageview)
987 {
988 if (gtk_toggle_button_get_active(toggle))
989 gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->notebook), 1);
990 else
991 gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->notebook), 0);
992 }
993
messageview_switch_page_cb(GtkNotebook * notebook,GtkNotebookPage * page,guint page_num,MessageView * messageview)994 static void messageview_switch_page_cb(GtkNotebook *notebook,
995 GtkNotebookPage *page, guint page_num,
996 MessageView *messageview)
997 {
998 if (messageview->current_page != page_num) {
999 messageview->current_page = page_num;
1000 if (page_num == 0)
1001 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(messageview->mime_toggle_btn), FALSE);
1002 else
1003 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(messageview->mime_toggle_btn), TRUE);
1004 }
1005 }
1006
messageview_menu_tool_btn_pressed(GtkWidget * widget,GdkEventButton * event,MessageView * messageview)1007 static gint messageview_menu_tool_btn_pressed(GtkWidget *widget,
1008 GdkEventButton *event,
1009 MessageView *messageview)
1010 {
1011 if (!event)
1012 return FALSE;
1013
1014 gtk_menu_popup(GTK_MENU(messageview->tool_menu), NULL, NULL,
1015 menu_button_position, messageview->mime_toggle_btn,
1016 event->button, event->time);
1017
1018 return TRUE;
1019 }
1020
messageview_open_file_cb(GtkWidget * widget,MessageView * messageview)1021 static void messageview_open_file_cb(GtkWidget *widget, MessageView *messageview)
1022 {
1023 MimeInfo *partinfo;
1024
1025 partinfo = g_object_get_data(G_OBJECT(widget), "tool-menu-mimeinfo");
1026 if (partinfo)
1027 mimeview_launch_part(messageview->mimeview, partinfo);
1028 }
1029
messageview_save_all_cb(GtkWidget * widget,MessageView * messageview)1030 static void messageview_save_all_cb(GtkWidget *widget, MessageView *messageview)
1031 {
1032 mimeview_save_all(messageview->mimeview);
1033 }
1034
key_pressed(GtkWidget * widget,GdkEventKey * event,MessageView * messageview)1035 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
1036 MessageView *messageview)
1037 {
1038 if (event && event->keyval == GDK_Escape && messageview->window) {
1039 messageview_destroy(messageview);
1040 return TRUE;
1041 }
1042 return FALSE;
1043 }
1044
save_as_cb(gpointer data,guint action,GtkWidget * widget)1045 static void save_as_cb(gpointer data, guint action, GtkWidget *widget)
1046 {
1047 MessageView *messageview = (MessageView *)data;
1048 messageview_save_as(messageview);
1049 }
1050
1051 #if GTK_CHECK_VERSION(2, 10, 0)
page_setup_cb(gpointer data,guint action,GtkWidget * widget)1052 static void page_setup_cb(gpointer data, guint action, GtkWidget *widget)
1053 {
1054 printing_page_setup_gtk();
1055 }
1056 #endif
1057
print_cb(gpointer data,guint action,GtkWidget * widget)1058 static void print_cb(gpointer data, guint action, GtkWidget *widget)
1059 {
1060 MessageView *messageview = (MessageView *)data;
1061
1062 if (!messageview->msginfo) return;
1063
1064 printing_print_message(messageview->msginfo,
1065 messageview->textview->show_all_headers);
1066 }
1067
close_cb(gpointer data,guint action,GtkWidget * widget)1068 static void close_cb(gpointer data, guint action, GtkWidget *widget)
1069 {
1070 MessageView *messageview = (MessageView *)data;
1071 messageview_destroy(messageview);
1072 }
1073
copy_cb(gpointer data,guint action,GtkWidget * widget)1074 static void copy_cb(gpointer data, guint action, GtkWidget *widget)
1075 {
1076 MessageView *messageview = (MessageView *)data;
1077 messageview_copy_clipboard(messageview);
1078 }
1079
allsel_cb(gpointer data,guint action,GtkWidget * widget)1080 static void allsel_cb(gpointer data, guint action, GtkWidget *widget)
1081 {
1082 MessageView *messageview = (MessageView *)data;
1083 messageview_select_all(messageview);
1084 }
1085
search_cb(gpointer data,guint action,GtkWidget * widget)1086 static void search_cb(gpointer data, guint action, GtkWidget *widget)
1087 {
1088 MessageView *messageview = (MessageView *)data;
1089 message_search(messageview);
1090 }
1091
set_charset_cb(gpointer data,guint action,GtkWidget * widget)1092 static void set_charset_cb(gpointer data, guint action, GtkWidget *widget)
1093 {
1094 MessageView *messageview = (MessageView *)data;
1095 const gchar *charset;
1096
1097 if (GTK_CHECK_MENU_ITEM(widget)->active) {
1098 charset = conv_get_charset_str((CharSet)action);
1099 g_free(messageview->forced_charset);
1100 messageview->forced_charset = g_strdup(charset);
1101 if (messageview->msginfo)
1102 messageview_show(messageview, messageview->msginfo,
1103 FALSE);
1104 }
1105 }
1106
view_source_cb(gpointer data,guint action,GtkWidget * widget)1107 static void view_source_cb(gpointer data, guint action, GtkWidget *widget)
1108 {
1109 MessageView *messageview = (MessageView *)data;
1110 SourceWindow *srcwin;
1111
1112 if (!messageview->msginfo) return;
1113
1114 srcwin = source_window_create();
1115 source_window_show_msg(srcwin, messageview->msginfo);
1116 source_window_show(srcwin);
1117 }
1118
show_all_header_cb(gpointer data,guint action,GtkWidget * widget)1119 static void show_all_header_cb(gpointer data, guint action, GtkWidget *widget)
1120 {
1121 MessageView *messageview = (MessageView *)data;
1122 MsgInfo *msginfo = messageview->msginfo;
1123
1124 if (!msginfo) return;
1125 if (messageview->menu_locked) return;
1126
1127 messageview->msginfo = NULL;
1128 messageview_show(messageview, msginfo,
1129 GTK_CHECK_MENU_ITEM(widget)->active);
1130 procmsg_msginfo_free(msginfo);
1131 }
1132
compose_cb(gpointer data,guint action,GtkWidget * widget)1133 static void compose_cb(gpointer data, guint action, GtkWidget *widget)
1134 {
1135 MessageView *messageview = (MessageView *)data;
1136 PrefsAccount *ac = NULL;
1137 FolderItem *item = NULL;
1138
1139 if (messageview->msginfo)
1140 item = messageview->msginfo->folder;
1141
1142 if (item) {
1143 ac = account_find_from_item(item);
1144 if (ac && ac->protocol == A_NNTP &&
1145 FOLDER_TYPE(item->folder) == F_NEWS) {
1146 compose_new(ac, item, item->path, NULL);
1147 return;
1148 }
1149 }
1150
1151 compose_new(ac, item, NULL, NULL);
1152 }
1153
reply_cb(gpointer data,guint action,GtkWidget * widget)1154 static void reply_cb(gpointer data, guint action, GtkWidget *widget)
1155 {
1156 MessageView *messageview = (MessageView *)data;
1157 GSList *mlist = NULL;
1158 MsgInfo *msginfo;
1159 gchar *text = NULL;
1160 ComposeMode mode = (ComposeMode)action;
1161 gchar *prev_force_charset;
1162
1163 msginfo = messageview->msginfo;
1164 mlist = g_slist_append(NULL, msginfo);
1165
1166 text = gtkut_text_view_get_selection
1167 (GTK_TEXT_VIEW(messageview->textview->text));
1168 if (text && *text == '\0') {
1169 g_free(text);
1170 text = NULL;
1171 }
1172
1173 if (!COMPOSE_QUOTE_MODE(mode))
1174 mode |= prefs_common.reply_with_quote
1175 ? COMPOSE_WITH_QUOTE : COMPOSE_WITHOUT_QUOTE;
1176
1177 prev_force_charset = prefs_common.force_charset;
1178 prefs_common.force_charset = messageview->forced_charset;
1179
1180 switch (COMPOSE_MODE(mode)) {
1181 case COMPOSE_REPLY:
1182 case COMPOSE_REPLY_TO_SENDER:
1183 case COMPOSE_REPLY_TO_ALL:
1184 case COMPOSE_REPLY_TO_LIST:
1185 compose_reply(msginfo, msginfo->folder, mode, text);
1186 break;
1187 case COMPOSE_FORWARD:
1188 compose_forward(mlist, msginfo->folder, FALSE, text);
1189 break;
1190 case COMPOSE_FORWARD_AS_ATTACH:
1191 compose_forward(mlist, msginfo->folder, TRUE, NULL);
1192 break;
1193 case COMPOSE_REDIRECT:
1194 compose_redirect(msginfo, msginfo->folder);
1195 break;
1196 default:
1197 g_warning("messageview.c: reply_cb(): invalid mode: %d\n",
1198 mode);
1199 }
1200
1201 prefs_common.force_charset = prev_force_charset;
1202
1203 /* summary_set_marks_selected(summaryview); */
1204 g_free(text);
1205 g_slist_free(mlist);
1206 }
1207
reedit_cb(gpointer data,guint action,GtkWidget * widget)1208 static void reedit_cb(gpointer data, guint action, GtkWidget *widget)
1209 {
1210 MessageView *messageview = (MessageView *)data;
1211 MsgInfo *msginfo;
1212
1213 if (!messageview->msginfo) return;
1214 msginfo = messageview->msginfo;
1215 if (!msginfo->folder) return;
1216 if (msginfo->folder->stype != F_OUTBOX &&
1217 msginfo->folder->stype != F_DRAFT &&
1218 msginfo->folder->stype != F_QUEUE) return;
1219
1220 compose_reedit(msginfo);
1221 }
1222
addressbook_open_cb(gpointer data,guint action,GtkWidget * widget)1223 static void addressbook_open_cb(gpointer data, guint action, GtkWidget *widget)
1224 {
1225 addressbook_open(NULL);
1226 }
1227
add_address_cb(gpointer data,guint action,GtkWidget * widget)1228 static void add_address_cb(gpointer data, guint action, GtkWidget *widget)
1229 {
1230 MessageView *messageview = (MessageView *)data;
1231 MsgInfo *msginfo;
1232 gchar *from;
1233
1234 if (!messageview->msginfo) return;
1235 msginfo = messageview->msginfo;
1236 from = g_strdup(msginfo->from);
1237 eliminate_address_comment(from);
1238 extract_address(from);
1239 addressbook_add_contact(msginfo->fromname, from, NULL);
1240 g_free(from);
1241 }
1242
create_filter_cb(gpointer data,guint action,GtkWidget * widget)1243 static void create_filter_cb(gpointer data, guint action, GtkWidget *widget)
1244 {
1245 MessageView *messageview = (MessageView *)data;
1246 gchar *header = NULL;
1247 gchar *key = NULL;
1248
1249 if (!messageview->msginfo) return;
1250
1251 filter_get_keyword_from_msg(messageview->msginfo, &header, &key,
1252 (FilterCreateType)action);
1253 prefs_filter_open(messageview->msginfo, header, key);
1254
1255 g_free(header);
1256 g_free(key);
1257 }
1258
about_cb(gpointer data,guint action,GtkWidget * widget)1259 static void about_cb(gpointer data, guint action, GtkWidget *widget)
1260 {
1261 about_show();
1262 }
1263