Statistics
| Revision:

root / src / messageview.c @ 3254

History | View | Annotate | Download (36.6 KB)

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

    
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

    
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

    
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

    
559
void messageview_reflect_prefs(MessageView *messageview)
560
{
561
        if (messageview->type == MVIEW_MIME)
562
                messageview_set_mime_view_layout(messageview);
563
}
564

    
565
GList *messageview_get_window_list(void)
566
{
567
        return messageview_list;
568
}
569

    
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

    
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

    
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

    
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

    
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

    
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

    
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

    
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

    
819
void messageview_quote_color_set(void)
820
{
821
}
822

    
823
void messageview_set_font(MessageView *messageview)
824
{
825
        textview_set_font(messageview->textview, NULL);
826
}
827

    
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

    
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

    
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

    
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

    
885
void messageview_set_position(MessageView *messageview, gint pos)
886
{
887
        textview_set_position(messageview->textview, pos);
888
}
889

    
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

    
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

    
906
gboolean messageview_is_visible(MessageView *messageview)
907
{
908
        return messageview->visible;
909
}
910

    
911
void messageview_save_as(MessageView *messageview)
912
{
913
        gchar *filename = NULL;
914
        MsgInfo *msginfo;
915
        gchar *src, *dest;
916
        GSList *types;
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 = g_slist_append(NULL, _("Original (EML/RFC 822)"));
932
        types = g_slist_append(types, _("Text"));
933
        types = g_slist_append(types, _("Text (UTF-8)"));
934
        dest = filesel_save_as_type(filename, types, 0, &selected_type);
935
        g_slist_free(types);
936

    
937
        g_free(filename);
938
        if (!dest)
939
                return;
940

    
941
        all_headers = messageview->textview->show_all_headers;
942

    
943
        if (selected_type == 1) {
944
                result = procmsg_save_message_as_text(msginfo, dest, conv_get_locale_charset_str(), all_headers);
945
        } else if (selected_type == 2) {
946
                result = procmsg_save_message_as_text(msginfo, dest, NULL, all_headers);
947
        } else {
948
                src = procmsg_get_message_file(msginfo);
949
                result = copy_file(src, dest, TRUE);
950
                g_free(src);
951
        }
952

    
953
        if (result < 0) {
954
                gchar *utf8_dest;
955

    
956
                utf8_dest = conv_filename_to_utf8(dest);
957
                alertpanel_error(_("Can't save the file `%s'."),
958
                                 g_basename(utf8_dest));
959
                g_free(utf8_dest);
960
        }
961

    
962
        g_free(dest);
963
}
964

    
965
static gint messageview_delete_cb(GtkWidget *widget, GdkEventAny *event,
966
                                  MessageView *messageview)
967
{
968
        messageview_destroy(messageview);
969
        return TRUE;
970
}
971

    
972
static void messageview_size_allocate_cb(GtkWidget *widget,
973
                                         GtkAllocation *allocation)
974
{
975
        g_return_if_fail(allocation != NULL);
976

    
977
        prefs_common.msgwin_width  = allocation->width;
978
        prefs_common.msgwin_height = allocation->height;
979
}
980

    
981
static void messageview_toggle_attach_cb(GtkToggleButton *toggle,
982
                                         MessageView *messageview)
983
{
984
        if (gtk_toggle_button_get_active(toggle))
985
                gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->notebook), 1);
986
        else
987
                gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->notebook), 0);
988
}
989

    
990
static void messageview_switch_page_cb(GtkNotebook *notebook,
991
                                       GtkNotebookPage *page, guint page_num,
992
                                       MessageView *messageview)
993
{
994
        if (messageview->current_page != page_num) {
995
                messageview->current_page = page_num;
996
                if (page_num == 0)
997
                        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(messageview->mime_toggle_btn), FALSE);
998
                else
999
                        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(messageview->mime_toggle_btn), TRUE);
1000
        }
1001
}
1002

    
1003
static gint messageview_menu_tool_btn_pressed(GtkWidget *widget,
1004
                                              GdkEventButton *event,
1005
                                              MessageView *messageview)
1006
{
1007
        if (!event)
1008
                return FALSE;
1009

    
1010
        gtk_menu_popup(GTK_MENU(messageview->tool_menu), NULL, NULL, 
1011
                       menu_button_position, messageview->mime_toggle_btn,
1012
                       event->button, event->time);
1013

    
1014
        return TRUE;
1015
}
1016

    
1017
static void messageview_open_file_cb(GtkWidget *widget, MessageView *messageview)
1018
{
1019
        MimeInfo *partinfo;
1020

    
1021
        partinfo = g_object_get_data(G_OBJECT(widget), "tool-menu-mimeinfo");
1022
        if (partinfo)
1023
                mimeview_launch_part(messageview->mimeview, partinfo);
1024
}
1025

    
1026
static void messageview_save_all_cb(GtkWidget *widget, MessageView *messageview)
1027
{
1028
        mimeview_save_all(messageview->mimeview);
1029
}
1030

    
1031
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
1032
                            MessageView *messageview)
1033
{
1034
        if (event && event->keyval == GDK_Escape && messageview->window) {
1035
                messageview_destroy(messageview);
1036
                return TRUE;
1037
        }
1038
        return FALSE;
1039
}
1040

    
1041
static void save_as_cb(gpointer data, guint action, GtkWidget *widget)
1042
{
1043
        MessageView *messageview = (MessageView *)data;
1044
        messageview_save_as(messageview);
1045
}
1046

    
1047
#if GTK_CHECK_VERSION(2, 10, 0)
1048
static void page_setup_cb(gpointer data, guint action, GtkWidget *widget)
1049
{
1050
        printing_page_setup_gtk();
1051
}
1052
#endif
1053

    
1054
static void print_cb(gpointer data, guint action, GtkWidget *widget)
1055
{
1056
        MessageView *messageview = (MessageView *)data;
1057

    
1058
        if (!messageview->msginfo) return;
1059

    
1060
        printing_print_message(messageview->msginfo,
1061
                               messageview->textview->show_all_headers);
1062
}
1063

    
1064
static void close_cb(gpointer data, guint action, GtkWidget *widget)
1065
{
1066
        MessageView *messageview = (MessageView *)data;
1067
        messageview_destroy(messageview);
1068
}
1069

    
1070
static void copy_cb(gpointer data, guint action, GtkWidget *widget)
1071
{
1072
        MessageView *messageview = (MessageView *)data;
1073
        messageview_copy_clipboard(messageview);
1074
}
1075

    
1076
static void allsel_cb(gpointer data, guint action, GtkWidget *widget)
1077
{
1078
        MessageView *messageview = (MessageView *)data;
1079
        messageview_select_all(messageview);
1080
}
1081

    
1082
static void search_cb(gpointer data, guint action, GtkWidget *widget)
1083
{
1084
        MessageView *messageview = (MessageView *)data;
1085
        message_search(messageview);
1086
}
1087

    
1088
static void set_charset_cb(gpointer data, guint action, GtkWidget *widget)
1089
{
1090
        MessageView *messageview = (MessageView *)data;
1091
        const gchar *charset;
1092

    
1093
        if (GTK_CHECK_MENU_ITEM(widget)->active) {
1094
                charset = conv_get_charset_str((CharSet)action);
1095
                g_free(messageview->forced_charset);
1096
                messageview->forced_charset = g_strdup(charset);
1097
                if (messageview->msginfo)
1098
                        messageview_show(messageview, messageview->msginfo,
1099
                                         FALSE);
1100
        }
1101
}
1102

    
1103
static void view_source_cb(gpointer data, guint action, GtkWidget *widget)
1104
{
1105
        MessageView *messageview = (MessageView *)data;
1106
        SourceWindow *srcwin;
1107

    
1108
        if (!messageview->msginfo) return;
1109

    
1110
        srcwin = source_window_create();
1111
        source_window_show_msg(srcwin, messageview->msginfo);
1112
        source_window_show(srcwin);
1113
}
1114

    
1115
static void show_all_header_cb(gpointer data, guint action, GtkWidget *widget)
1116
{
1117
        MessageView *messageview = (MessageView *)data;
1118
        MsgInfo *msginfo = messageview->msginfo;
1119

    
1120
        if (!msginfo) return;
1121
        if (messageview->menu_locked) return;
1122

    
1123
        messageview->msginfo = NULL;
1124
        messageview_show(messageview, msginfo,
1125
                         GTK_CHECK_MENU_ITEM(widget)->active);
1126
        procmsg_msginfo_free(msginfo);
1127
}
1128

    
1129
static void compose_cb(gpointer data, guint action, GtkWidget *widget)
1130
{
1131
        MessageView *messageview = (MessageView *)data;
1132
        PrefsAccount *ac = NULL;
1133
        FolderItem *item = NULL;
1134

    
1135
        if (messageview->msginfo)
1136
                item = messageview->msginfo->folder;
1137

    
1138
        if (item) {
1139
                ac = account_find_from_item(item);
1140
                if (ac && ac->protocol == A_NNTP &&
1141
                    FOLDER_TYPE(item->folder) == F_NEWS) {
1142
                        compose_new(ac, item, item->path, NULL);
1143
                        return;
1144
                }
1145
        }
1146

    
1147
        compose_new(ac, item, NULL, NULL);
1148
}
1149

    
1150
static void reply_cb(gpointer data, guint action, GtkWidget *widget)
1151
{
1152
        MessageView *messageview = (MessageView *)data;
1153
        GSList *mlist = NULL;
1154
        MsgInfo *msginfo;
1155
        gchar *text = NULL;
1156
        ComposeMode mode = (ComposeMode)action;
1157
        gchar *prev_force_charset;
1158

    
1159
        msginfo = messageview->msginfo;
1160
        mlist = g_slist_append(NULL, msginfo);
1161

    
1162
        text = gtkut_text_view_get_selection
1163
                (GTK_TEXT_VIEW(messageview->textview->text));
1164
        if (text && *text == '\0') {
1165
                g_free(text);
1166
                text = NULL;
1167
        }
1168

    
1169
        if (!COMPOSE_QUOTE_MODE(mode))
1170
                mode |= prefs_common.reply_with_quote
1171
                        ? COMPOSE_WITH_QUOTE : COMPOSE_WITHOUT_QUOTE;
1172

    
1173
        prev_force_charset = prefs_common.force_charset;
1174
        prefs_common.force_charset = messageview->forced_charset;
1175

    
1176
        switch (COMPOSE_MODE(mode)) {
1177
        case COMPOSE_REPLY:
1178
        case COMPOSE_REPLY_TO_SENDER:
1179
        case COMPOSE_REPLY_TO_ALL:
1180
        case COMPOSE_REPLY_TO_LIST:
1181
                compose_reply(msginfo, msginfo->folder, mode, text);
1182
                break;
1183
        case COMPOSE_FORWARD:
1184
                compose_forward(mlist, msginfo->folder, FALSE, text);
1185
                break;
1186
        case COMPOSE_FORWARD_AS_ATTACH:
1187
                compose_forward(mlist, msginfo->folder, TRUE, NULL);
1188
                break;
1189
        case COMPOSE_REDIRECT:
1190
                compose_redirect(msginfo, msginfo->folder);
1191
                break;
1192
        default:
1193
                g_warning("messageview.c: reply_cb(): invalid mode: %d\n",
1194
                          mode);
1195
        }
1196

    
1197
        prefs_common.force_charset = prev_force_charset;
1198

    
1199
        /* summary_set_marks_selected(summaryview); */
1200
        g_free(text);
1201
        g_slist_free(mlist);
1202
}
1203

    
1204
static void reedit_cb(gpointer data, guint action, GtkWidget *widget)
1205
{
1206
        MessageView *messageview = (MessageView *)data;
1207
        MsgInfo *msginfo;
1208

    
1209
        if (!messageview->msginfo) return;
1210
        msginfo = messageview->msginfo;
1211
        if (!msginfo->folder) return;
1212
        if (msginfo->folder->stype != F_OUTBOX &&
1213
            msginfo->folder->stype != F_DRAFT &&
1214
            msginfo->folder->stype != F_QUEUE) return;
1215

    
1216
        compose_reedit(msginfo);
1217
}
1218

    
1219
static void addressbook_open_cb(gpointer data, guint action, GtkWidget *widget)
1220
{
1221
        addressbook_open(NULL);
1222
}
1223

    
1224
static void add_address_cb(gpointer data, guint action, GtkWidget *widget)
1225
{
1226
        MessageView *messageview = (MessageView *)data;
1227
        MsgInfo *msginfo;
1228
        gchar *from;
1229

    
1230
        if (!messageview->msginfo) return;
1231
        msginfo = messageview->msginfo;
1232
        from = g_strdup(msginfo->from);
1233
        eliminate_address_comment(from);
1234
        extract_address(from);
1235
        addressbook_add_contact(msginfo->fromname, from, NULL);
1236
        g_free(from);
1237
}
1238

    
1239
static void create_filter_cb(gpointer data, guint action, GtkWidget *widget)
1240
{
1241
        MessageView *messageview = (MessageView *)data;
1242
        gchar *header = NULL;
1243
        gchar *key = NULL;
1244

    
1245
        if (!messageview->msginfo) return;
1246

    
1247
        filter_get_keyword_from_msg(messageview->msginfo, &header, &key,
1248
                                    (FilterCreateType)action);
1249
        prefs_filter_open(messageview->msginfo, header, key);
1250

    
1251
        g_free(header);
1252
        g_free(key);
1253
}
1254

    
1255
static void about_cb(gpointer data, guint action, GtkWidget *widget)
1256
{
1257
        about_show();
1258
}