Statistics
| Revision:

root / src / messageview.c @ 710

History | View | Annotate | Download (26.5 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2005 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 <stdio.h>
35
#include <ctype.h>
36
#include <string.h>
37
38
#include "main.h"
39
#include "messageview.h"
40
#include "message_search.h"
41
#include "headerview.h"
42
#include "textview.h"
43
#include "imageview.h"
44
#include "mimeview.h"
45
#include "menu.h"
46
#include "about.h"
47
#include "filesel.h"
48
#include "sourcewindow.h"
49
#include "addressbook.h"
50
#include "alertpanel.h"
51
#include "inputdialog.h"
52
#include "manage_window.h"
53
#include "procmsg.h"
54
#include "procheader.h"
55
#include "procmime.h"
56
#include "account.h"
57
#include "action.h"
58
#include "prefs_common.h"
59
#include "prefs_account.h"
60
#include "prefs_filter.h"
61
#include "filter.h"
62
#include "gtkutils.h"
63
#include "utils.h"
64
#include "rfc2015.h"
65
66
static GList *messageview_list = NULL;
67
68
static void messageview_change_view_type(MessageView                *messageview,
69
                                         MessageType                 type);
70
static gint messageview_delete_cb        (GtkWidget                *widget,
71
                                         GdkEventAny                *event,
72
                                         MessageView                *messageview);
73
static void messageview_size_allocate_cb(GtkWidget                *widget,
74
                                         GtkAllocation                *allocation);
75
static void messageview_switch_page_cb        (GtkNotebook                *notebook,
76
                                         GtkNotebookPage        *page,
77
                                         guint                         page_num,
78
                                         MessageView                *messageview);
79
static gboolean key_pressed                (GtkWidget                *widget,
80
                                         GdkEventKey                *event,
81
                                         MessageView                *messageview);
82
83
static void save_as_cb                        (gpointer         data,
84
                                         guint                 action,
85
                                         GtkWidget        *widget);
86
static void print_cb                        (gpointer         data,
87
                                         guint                 action,
88
                                         GtkWidget        *widget);
89
static void close_cb                        (gpointer         data,
90
                                         guint                 action,
91
                                         GtkWidget        *widget);
92
static void copy_cb                        (gpointer         data,
93
                                         guint                 action,
94
                                         GtkWidget        *widget);
95
static void allsel_cb                        (gpointer         data,
96
                                         guint                 action,
97
                                         GtkWidget        *widget);
98
static void search_cb                        (gpointer         data,
99
                                         guint                 action,
100
                                         GtkWidget        *widget);
101
102
static void set_charset_cb                (gpointer         data,
103
                                         guint                 action,
104
                                         GtkWidget        *widget);
105
static void view_source_cb                (gpointer         data,
106
                                         guint                 action,
107
                                         GtkWidget        *widget);
108
static void show_all_header_cb                (gpointer         data,
109
                                         guint                 action,
110
                                         GtkWidget        *widget);
111
112
static void compose_cb                        (gpointer         data,
113
                                         guint                 action,
114
                                         GtkWidget        *widget);
115
static void reply_cb                        (gpointer         data,
116
                                         guint                 action,
117
                                         GtkWidget        *widget);
118
static void reedit_cb                        (gpointer         data,
119
                                         guint                 action,
120
                                         GtkWidget        *widget);
121
122
static void addressbook_open_cb                (gpointer         data,
123
                                         guint                 action,
124
                                         GtkWidget        *widget);
125
static void add_address_cb                (gpointer         data,
126
                                         guint                 action,
127
                                         GtkWidget        *widget);
128
static void create_filter_cb                (gpointer         data,
129
                                         guint                 action,
130
                                         GtkWidget        *widget);
131
132
static void about_cb                        (gpointer         data,
133
                                         guint                 action,
134
                                         GtkWidget        *widget);
135
136
static GtkItemFactoryEntry msgview_entries[] =
137
{
138
        {N_("/_File"),                        NULL, NULL, 0, "<Branch>"},
139
        {N_("/_File/_Save as..."),        NULL, save_as_cb, 0, NULL},
140
        {N_("/_File/_Print..."),        NULL, print_cb, 0, NULL},
141
        {N_("/_File/---"),                NULL, NULL, 0, "<Separator>"},
142
        {N_("/_File/_Close"),                NULL, close_cb, 0, NULL},
143
144
        {N_("/_Edit"),                        NULL, NULL, 0, "<Branch>"},
145
        {N_("/_Edit/_Copy"),                NULL, copy_cb, 0, NULL},
146
        {N_("/_Edit/Select _all"),        NULL, allsel_cb, 0, NULL},
147
        {N_("/_Edit/---"),                NULL, NULL, 0, "<Separator>"},
148
        {N_("/_Edit/_Find in current message..."),
149
                                        NULL, search_cb, 0, NULL},
150
151
        {N_("/_View"),                        NULL, NULL, 0, "<Branch>"},
152
153
#define ENC_SEPARATOR \
154
        {N_("/_View/Character _encoding/---"),        NULL, NULL, 0, "<Separator>"}
155
#define ENC_ACTION(action) \
156
        NULL, set_charset_cb, action, "/View/Character encoding/Auto detect"
157
158
        {N_("/_View/Character _encoding"),        NULL, NULL, 0, "<Branch>"},
159
        {N_("/_View/Character _encoding/_Auto detect"),
160
                                        NULL, set_charset_cb, C_AUTO, "<RadioItem>"},
161
        ENC_SEPARATOR,
162
        {N_("/_View/Character _encoding/7bit ascii (US-ASC_II)"),
163
         ENC_ACTION(C_US_ASCII)},
164
165
        {N_("/_View/Character _encoding/Unicode (_UTF-8)"),
166
         ENC_ACTION(C_UTF_8)},
167
        ENC_SEPARATOR,
168
        {N_("/_View/Character _encoding/Western European (ISO-8859-_1)"),
169
         ENC_ACTION(C_ISO_8859_1)},
170
        {N_("/_View/Character _encoding/Western European (ISO-8859-15)"),
171
         ENC_ACTION(C_ISO_8859_15)},
172
        ENC_SEPARATOR,
173
        {N_("/_View/Character _encoding/Central European (ISO-8859-_2)"),
174
         ENC_ACTION(C_ISO_8859_2)},
175
        ENC_SEPARATOR,
176
        {N_("/_View/Character _encoding/_Baltic (ISO-8859-13)"),
177
         ENC_ACTION(C_ISO_8859_13)},
178
        {N_("/_View/Character _encoding/Baltic (ISO-8859-_4)"),
179
         ENC_ACTION(C_ISO_8859_4)},
180
        ENC_SEPARATOR,
181
        {N_("/_View/Character _encoding/Greek (ISO-8859-_7)"),
182
         ENC_ACTION(C_ISO_8859_7)},
183
        ENC_SEPARATOR,
184
        {N_("/_View/Character _encoding/Hebrew (ISO-8859-_8)"),
185
         ENC_ACTION(C_ISO_8859_8)},
186
        {N_("/_View/Character _encoding/Hebrew (Windows-1255)"),
187
         ENC_ACTION(C_CP1255)},
188
        ENC_SEPARATOR,
189
        {N_("/_View/Character _encoding/Turkish (ISO-8859-_9)"),
190
         ENC_ACTION(C_ISO_8859_9)},
191
        ENC_SEPARATOR,
192
        {N_("/_View/Character _encoding/Cyrillic (ISO-8859-_5)"),
193
         ENC_ACTION(C_ISO_8859_5)},
194
        {N_("/_View/Character _encoding/Cyrillic (KOI8-_R)"),
195
         ENC_ACTION(C_KOI8_R)},
196
        {N_("/_View/Character _encoding/Cyrillic (KOI8-U)"),
197
         ENC_ACTION(C_KOI8_U)},
198
        {N_("/_View/Character _encoding/Cyrillic (Windows-1251)"),
199
         ENC_ACTION(C_CP1251)},
200
        ENC_SEPARATOR,
201
        {N_("/_View/Character _encoding/Japanese (ISO-2022-_JP)"),
202
         ENC_ACTION(C_ISO_2022_JP)},
203
        {N_("/_View/Character _encoding/Japanese (ISO-2022-JP-2)"),
204
         ENC_ACTION(C_ISO_2022_JP_2)},
205
        {N_("/_View/Character _encoding/Japanese (_EUC-JP)"),
206
         ENC_ACTION(C_EUC_JP)},
207
        {N_("/_View/Character _encoding/Japanese (_Shift__JIS)"),
208
         ENC_ACTION(C_SHIFT_JIS)},
209
        ENC_SEPARATOR,
210
        {N_("/_View/Character _encoding/Simplified Chinese (_GB2312)"),
211
         ENC_ACTION(C_GB2312)},
212
        {N_("/_View/Character _encoding/Simplified Chinese (GBK)"),
213
         ENC_ACTION(C_GBK)},
214
        {N_("/_View/Character _encoding/Traditional Chinese (_Big5)"),
215
         ENC_ACTION(C_BIG5)},
216
        {N_("/_View/Character _encoding/Traditional Chinese (EUC-_TW)"),
217
         ENC_ACTION(C_EUC_TW)},
218
        {N_("/_View/Character _encoding/Chinese (ISO-2022-_CN)"),
219
         ENC_ACTION(C_ISO_2022_CN)},
220
        ENC_SEPARATOR,
221
        {N_("/_View/Character _encoding/Korean (EUC-_KR)"),
222
         ENC_ACTION(C_EUC_KR)},
223
        {N_("/_View/Character _encoding/Korean (ISO-2022-KR)"),
224
         ENC_ACTION(C_ISO_2022_KR)},
225
        ENC_SEPARATOR,
226
        {N_("/_View/Character _encoding/Thai (TIS-620)"),
227
         ENC_ACTION(C_TIS_620)},
228
        {N_("/_View/Character _encoding/Thai (Windows-874)"),
229
         ENC_ACTION(C_WINDOWS_874)},
230
231
#undef ENC_SEPARATOR
232
#undef ENC_ACTION
233
234
        {N_("/_View/---"),                NULL, NULL, 0, "<Separator>"},
235
        {N_("/_View/Mess_age source"),        NULL, view_source_cb, 0, NULL},
236
        {N_("/_View/Show all _header"),        NULL, show_all_header_cb, 0, "<ToggleItem>"},
237
238
        {N_("/_Message"),                NULL, NULL, 0, "<Branch>"},
239
        {N_("/_Message/Compose _new message"),
240
                                        NULL, compose_cb, 0, NULL},
241
        {N_("/_Message/---"),                NULL, NULL, 0, "<Separator>"},
242
        {N_("/_Message/_Reply"),        NULL, reply_cb, COMPOSE_REPLY, NULL},
243
        {N_("/_Message/Repl_y to/_all"),
244
                                        NULL, reply_cb, COMPOSE_REPLY_TO_ALL, NULL},
245
        {N_("/_Message/Repl_y to/_sender"),
246
                                        NULL, reply_cb, COMPOSE_REPLY_TO_SENDER, NULL},
247
        {N_("/_Message/Repl_y to/mailing _list"),
248
                                        NULL, reply_cb, COMPOSE_REPLY_TO_LIST, NULL},
249
        {N_("/_Message/---"),                NULL, NULL, 0, "<Separator>"},
250
        {N_("/_Message/_Forward"),        NULL, reply_cb, COMPOSE_FORWARD, NULL},
251
        {N_("/_Message/For_ward as attachment"),
252
                                        NULL, reply_cb, COMPOSE_FORWARD_AS_ATTACH, NULL},
253
        {N_("/_Message/Redirec_t"),        NULL, reply_cb, COMPOSE_REDIRECT, NULL},
254
        {N_("/_Message/---"),                NULL, NULL, 0, "<Separator>"},
255
        {N_("/_Message/Re-_edit"),        NULL, reedit_cb, 0, NULL},
256
257
        {N_("/_Tools"),                        NULL, NULL, 0, "<Branch>"},
258
        {N_("/_Tools/_Address book"),        NULL, addressbook_open_cb, 0, NULL},
259
        {N_("/_Tools/Add sender to address boo_k"),
260
                                        NULL, add_address_cb, 0, NULL},
261
        {N_("/_Tools/---"),                NULL, NULL, 0, "<Separator>"},
262
        {N_("/_Tools/_Create filter rule"),
263
                                        NULL, NULL, 0, "<Branch>"},
264
        {N_("/_Tools/_Create filter rule/_Automatically"),
265
                                        NULL, create_filter_cb, FLT_BY_AUTO, NULL},
266
        {N_("/_Tools/_Create filter rule/by _From"),
267
                                        NULL, create_filter_cb, FLT_BY_FROM, NULL},
268
        {N_("/_Tools/_Create filter rule/by _To"),
269
                                        NULL, create_filter_cb, FLT_BY_TO, NULL},
270
        {N_("/_Tools/_Create filter rule/by _Subject"),
271
                                        NULL, create_filter_cb, FLT_BY_SUBJECT, NULL},
272
        {N_("/_Tools/---"),                NULL, NULL, 0, "<Separator>"},
273
        {N_("/_Tools/Actio_ns"),        NULL, NULL, 0, "<Branch>"},
274
275
        {N_("/_Help"),                        NULL, NULL, 0, "<Branch>"},
276
        {N_("/_Help/_About"),                NULL, about_cb, 0, NULL}
277
};
278
279
280
MessageView *messageview_create(void)
281
{
282
        MessageView *messageview;
283
        GtkWidget *vbox;
284
        GtkWidget *notebook;
285
        HeaderView *headerview;
286
        TextView *textview;
287
        MimeView *mimeview;
288
289
        debug_print(_("Creating message view...\n"));
290
        messageview = g_new0(MessageView, 1);
291
292
        messageview->type = MVIEW_TEXT;
293
294
        headerview = headerview_create();
295
296
        textview = textview_create();
297
        textview->messageview = messageview;
298
299
        mimeview = mimeview_create();
300
        mimeview->textview = textview_create();
301
        mimeview->textview->messageview = messageview;
302
        mimeview->imageview = imageview_create();
303
        mimeview->imageview->messageview = messageview;
304
        mimeview->messageview = messageview;
305
306
        notebook = gtk_notebook_new();
307
        gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
308
        gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
309
        gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
310
        gtk_widget_show(notebook);
311
312
        gtk_container_add(GTK_CONTAINER(notebook), GTK_WIDGET_PTR(textview));
313
        gtk_notebook_set_tab_label_text
314
                (GTK_NOTEBOOK(notebook), GTK_WIDGET_PTR(textview), _("Text"));
315
316
        gtk_container_add(GTK_CONTAINER(notebook), GTK_WIDGET_PTR(mimeview));
317
        gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(notebook),
318
                                        GTK_WIDGET_PTR(mimeview),
319
                                        _("Attachments"));
320
321
        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
322
        gtk_widget_show_all(notebook);
323
324
        vbox = gtk_vbox_new(FALSE, 0);
325
        gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(headerview),
326
                           FALSE, FALSE, 0);
327
        gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
328
        gtk_widget_show(vbox);
329
330
        /* to remove without destroyed */
331
        gtk_widget_ref(GTK_WIDGET_PTR(mimeview->textview));
332
        gtk_widget_ref(GTK_WIDGET_PTR(mimeview->imageview));
333
334
        g_signal_connect(G_OBJECT(notebook), "switch_page",
335
                         G_CALLBACK(messageview_switch_page_cb), messageview);
336
337
        messageview->vbox        = vbox;
338
        messageview->notebook    = notebook;
339
340
        messageview->new_window  = FALSE;
341
        messageview->window      = NULL;
342
        messageview->window_vbox = NULL;
343
        messageview->body_vbox   = NULL;
344
345
        messageview->headerview  = headerview;
346
        messageview->textview    = textview;
347
        messageview->mimeview    = mimeview;
348
349
        messageview->statusbar     = NULL;
350
        messageview->statusbar_cid = 0;
351
352
        messageview->current_page = 0;
353
354
        return messageview;
355
}
356
357
MessageView *messageview_create_with_new_window(void)
358
{
359
        MessageView *msgview;
360
        GtkWidget *window;
361
        GtkWidget *window_vbox;
362
        GtkWidget *body_vbox;
363
        GtkWidget *menubar;
364
        GtkItemFactory *ifactory;
365
        GtkWidget *statusbar;
366
        guint n_menu_entries;
367
368
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
369
        gtk_window_set_title(GTK_WINDOW(window), _("Message View - Sylpheed"));
370
        gtk_window_set_wmclass(GTK_WINDOW(window), "message_view", "Sylpheed");
371
        gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
372
        gtk_widget_set_size_request(window, prefs_common.msgwin_width,
373
                                    prefs_common.msgwin_height);
374
375
        msgview = messageview_create();
376
377
        window_vbox = gtk_vbox_new(FALSE, 0);
378
        gtk_container_add(GTK_CONTAINER(window), window_vbox);
379
380
        g_signal_connect(G_OBJECT(window), "size_allocate",
381
                         G_CALLBACK(messageview_size_allocate_cb),
382
                         msgview);
383
        g_signal_connect(G_OBJECT(window), "delete_event",
384
                         G_CALLBACK(messageview_delete_cb), msgview);
385
        g_signal_connect(G_OBJECT(window), "key_press_event",
386
                         G_CALLBACK(key_pressed), msgview);
387
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
388
389
        n_menu_entries = sizeof(msgview_entries) / sizeof (msgview_entries[0]);
390
        menubar = menubar_create(window, msgview_entries, n_menu_entries,
391
                                 "<MessageView>", msgview);
392
#if 0
393
        menu_factory_copy_rc("<Main>", "<MessageView>");
394
#endif
395
        gtk_box_pack_start(GTK_BOX(window_vbox), menubar, FALSE, TRUE, 0);
396
397
        body_vbox = gtk_vbox_new(FALSE, BORDER_WIDTH);
398
        gtk_container_set_border_width(GTK_CONTAINER(body_vbox), BORDER_WIDTH);
399
        gtk_box_pack_start(GTK_BOX(window_vbox), body_vbox, TRUE, TRUE, 0);
400
401
        gtk_box_pack_start(GTK_BOX(body_vbox), GTK_WIDGET_PTR(msgview),
402
                           TRUE, TRUE, 0);
403
        gtk_widget_grab_focus(msgview->textview->text);
404
405
        statusbar = gtk_statusbar_new();
406
        gtk_box_pack_end(GTK_BOX(body_vbox), statusbar, FALSE, FALSE, 0);
407
        msgview->statusbar = statusbar;
408
        msgview->statusbar_cid = gtk_statusbar_get_context_id
409
                (GTK_STATUSBAR(statusbar), "Message View");
410
411
        gtk_widget_show_all(window);
412
413
        msgview->new_window = TRUE;
414
        msgview->window = window;
415
        msgview->window_vbox = window_vbox;
416
        msgview->body_vbox = body_vbox;
417
        msgview->visible = TRUE;
418
419
        messageview_init(msgview);
420
421
        ifactory = gtk_item_factory_from_widget(menubar);
422
        action_update_msgview_menu(ifactory, msgview);
423
424
        messageview_list = g_list_append(messageview_list, msgview);
425
426
        return msgview;
427
}
428
429
void messageview_init(MessageView *messageview)
430
{
431
        headerview_init(messageview->headerview);
432
        textview_init(messageview->textview);
433
        mimeview_init(messageview->mimeview);
434
        /* messageview_set_font(messageview); */
435
}
436
437
GList *messageview_get_window_list(void)
438
{
439
        return messageview_list;
440
}
441
442
gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
443
                      gboolean all_headers)
444
{
445
        gchar *file;
446
        MimeInfo *mimeinfo;
447
448
        g_return_val_if_fail(msginfo != NULL, -1);
449
450
        mimeinfo = procmime_scan_message(msginfo);
451
        if (!mimeinfo) {
452
                messageview_change_view_type(messageview, MVIEW_TEXT);
453
                textview_show_error(messageview->textview);
454
                return -1;
455
        }
456
457
        file = procmsg_get_message_file_path(msginfo);
458
        if (!file) {
459
                g_warning("can't get message file path.\n");
460
                procmime_mimeinfo_free_all(mimeinfo);
461
                messageview_change_view_type(messageview, MVIEW_TEXT);
462
                textview_show_error(messageview->textview);
463
                return -1;
464
        }
465
466
        if (messageview->msginfo != msginfo) {
467
                procmsg_msginfo_free(messageview->msginfo);
468
                messageview->msginfo = procmsg_msginfo_get_full_info(msginfo);
469
                if (!messageview->msginfo)
470
                        messageview->msginfo = procmsg_msginfo_copy(msginfo);
471
        }
472
473
        if (messageview->window && msginfo->subject) {
474
                gchar *title;
475
476
                title = g_strconcat(msginfo->subject, " - Sylpheed", NULL);
477
                gtk_window_set_title(GTK_WINDOW(messageview->window), title);
478
                g_free(title);
479
        }
480
        headerview_show(messageview->headerview, messageview->msginfo);
481
482
        textview_set_all_headers(messageview->textview, all_headers);
483
        textview_set_all_headers(messageview->mimeview->textview, all_headers);
484
485
        if (mimeinfo->mime_type != MIME_TEXT &&
486
            mimeinfo->mime_type != MIME_TEXT_HTML) {
487
                messageview_change_view_type(messageview, MVIEW_MIME);
488
                mimeview_show_message(messageview->mimeview, mimeinfo, file);
489
        } else {
490
                messageview_change_view_type(messageview, MVIEW_TEXT);
491
                textview_show_message(messageview->textview, mimeinfo, file);
492
                procmime_mimeinfo_free_all(mimeinfo);
493
        }
494
495
        g_free(file);
496
497
        return 0;
498
}
499
500
static void messageview_change_view_type(MessageView *messageview,
501
                                         MessageType type)
502
{
503
        GtkWidget *notebook = messageview->notebook;
504
505
        if (messageview->type == type) return;
506
507
        if (type == MVIEW_MIME) {
508
                gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), TRUE);
509
                gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),
510
                                              messageview->current_page);
511
        } else if (type == MVIEW_TEXT) {
512
                gint current_page = messageview->current_page;
513
514
                gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
515
                gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
516
                messageview->current_page = current_page;
517
                mimeview_clear(messageview->mimeview);
518
        } else
519
                return;
520
521
        messageview->type = type;
522
}
523
524
void messageview_clear(MessageView *messageview)
525
{
526
        procmsg_msginfo_free(messageview->msginfo);
527
        messageview->msginfo = NULL;
528
        messageview_change_view_type(messageview, MVIEW_TEXT);
529
        headerview_clear(messageview->headerview);
530
        textview_clear(messageview->textview);
531
        mimeview_clear(messageview->mimeview);
532
}
533
534
void messageview_destroy(MessageView *messageview)
535
{
536
        GtkWidget *textview  = GTK_WIDGET_PTR(messageview->mimeview->textview);
537
        GtkWidget *imageview = GTK_WIDGET_PTR(messageview->mimeview->imageview);
538
539
        messageview_list = g_list_remove(messageview_list, messageview);
540
541
        headerview_destroy(messageview->headerview);
542
        textview_destroy(messageview->textview);
543
        mimeview_destroy(messageview->mimeview);
544
545
        procmsg_msginfo_free(messageview->msginfo);
546
547
        if (messageview->window)
548
                gtk_widget_destroy(messageview->window);
549
550
        g_free(messageview);
551
552
        gtk_widget_unref(textview);
553
        gtk_widget_unref(imageview);
554
}
555
556
void messageview_quote_color_set(void)
557
{
558
}
559
560
void messageview_set_font(MessageView *messageview)
561
{
562
        textview_set_font(messageview->textview, NULL);
563
}
564
565
TextView *messageview_get_current_textview(MessageView *messageview)
566
{
567
        TextView *text = NULL;
568
569
        if (messageview->type == MVIEW_TEXT)
570
                text = messageview->textview;
571
        else if (messageview->type == MVIEW_MIME) {
572
                if (gtk_notebook_get_current_page
573
                        (GTK_NOTEBOOK(messageview->notebook)) == 0)
574
                        text = messageview->textview;
575
                else if (messageview->mimeview->type == MIMEVIEW_TEXT)
576
                        text = messageview->mimeview->textview;
577
        }
578
579
        return text;
580
}
581
582
MimeInfo *messageview_get_selected_mime_part(MessageView *messageview)
583
{
584
        if (messageview->type == MVIEW_MIME)
585
                return mimeview_get_selected_part(messageview->mimeview);
586
587
        return NULL;
588
}
589
590
void messageview_copy_clipboard(MessageView *messageview)
591
{
592
        TextView *text;
593
594
        text = messageview_get_current_textview(messageview);
595
        if (text) {
596
                GtkTextView *textview = GTK_TEXT_VIEW(text->text);
597
                GtkTextBuffer *buffer;
598
                GtkClipboard *clipboard;
599
600
                buffer = gtk_text_view_get_buffer(textview);
601
                clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
602
                gtk_text_buffer_copy_clipboard(buffer, clipboard);
603
        }
604
}
605
606
void messageview_select_all(MessageView *messageview)
607
{
608
        TextView *text;
609
610
        text = messageview_get_current_textview(messageview);
611
        if (text) {
612
                GtkTextView *textview = GTK_TEXT_VIEW(text->text);
613
                GtkTextBuffer *buffer;
614
                GtkTextIter start, end;
615
616
                buffer = gtk_text_view_get_buffer(textview);
617
                gtk_text_buffer_get_bounds(buffer, &start, &end);
618
                gtk_text_buffer_select_range(buffer, &start, &end);
619
        }
620
}
621
622
void messageview_set_position(MessageView *messageview, gint pos)
623
{
624
        textview_set_position(messageview->textview, pos);
625
}
626
627
gboolean messageview_search_string(MessageView *messageview, const gchar *str,
628
                                   gboolean case_sens)
629
{
630
        return textview_search_string(messageview->textview, str, case_sens);
631
        return FALSE;
632
}
633
634
gboolean messageview_search_string_backward(MessageView *messageview,
635
                                            const gchar *str,
636
                                            gboolean case_sens)
637
{
638
        return textview_search_string_backward(messageview->textview,
639
                                               str, case_sens);
640
        return FALSE;
641
}
642
643
gboolean messageview_is_visible(MessageView *messageview)
644
{
645
        return messageview->visible;
646
}
647
648
void messageview_save_as(MessageView *messageview)
649
{
650
        gchar *filename = NULL;
651
        MsgInfo *msginfo;
652
        gchar *src, *dest;
653
654
        if (!messageview->msginfo) return;
655
        msginfo = messageview->msginfo;
656
657
        if (msginfo->subject) {
658
                Xstrdup_a(filename, msginfo->subject, return);
659
                subst_for_filename(filename);
660
        }
661
662
        dest = filesel_save_as(filename);
663
        if (!dest) return;
664
665
        src = procmsg_get_message_file(msginfo);
666
        if (copy_file(src, dest, TRUE) < 0) {
667
                alertpanel_error(_("Can't save the file `%s'."),
668
                                 g_basename(dest));
669
        }
670
        g_free(src);
671
672
        g_free(dest);
673
}
674
675
static gint messageview_delete_cb(GtkWidget *widget, GdkEventAny *event,
676
                                  MessageView *messageview)
677
{
678
        messageview_destroy(messageview);
679
        return TRUE;
680
}
681
682
static void messageview_size_allocate_cb(GtkWidget *widget,
683
                                         GtkAllocation *allocation)
684
{
685
        g_return_if_fail(allocation != NULL);
686
687
        prefs_common.msgwin_width  = allocation->width;
688
        prefs_common.msgwin_height = allocation->height;
689
}
690
691
static void messageview_switch_page_cb(GtkNotebook *notebook,
692
                                       GtkNotebookPage *page, guint page_num,
693
                                       MessageView *messageview)
694
{
695
        messageview->current_page = page_num;
696
}
697
698
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
699
                            MessageView *messageview)
700
{
701
        if (event && event->keyval == GDK_Escape && messageview->window) {
702
                messageview_destroy(messageview);
703
                return TRUE;
704
        }
705
        return FALSE;
706
}
707
708
static void save_as_cb(gpointer data, guint action, GtkWidget *widget)
709
{
710
        MessageView *messageview = (MessageView *)data;
711
        messageview_save_as(messageview);
712
}
713
714
static void print_cb(gpointer data, guint action, GtkWidget *widget)
715
{
716
        MessageView *messageview = (MessageView *)data;
717
        const gchar *cmdline;
718
        gchar *msg;
719
        gchar *p;
720
721
        if (!messageview->msginfo) return;
722
723
        cmdline = prefs_common.print_cmd;
724
725
        msg = g_strconcat
726
                (_("The message will be printed with the following command:"),
727
                 "\n\n", cmdline ? cmdline : _("(Default print command)"),
728
                 NULL);
729
        if (alertpanel(_("Print"), msg, GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
730
            != G_ALERTDEFAULT) {
731
                g_free(msg);
732
                return;
733
        }
734
        g_free(msg);
735
736
        if (cmdline && (!(p = strchr(cmdline, '%')) || *(p + 1) != 's' ||
737
                        strchr(p + 2, '%'))) {
738
                alertpanel_error(_("Print command line is invalid:\n`%s'"),
739
                                 cmdline);
740
                return;
741
        }
742
743
        procmsg_print_message(messageview->msginfo, cmdline);
744
}
745
746
static void close_cb(gpointer data, guint action, GtkWidget *widget)
747
{
748
        MessageView *messageview = (MessageView *)data;
749
        messageview_destroy(messageview);
750
}
751
752
static void copy_cb(gpointer data, guint action, GtkWidget *widget)
753
{
754
        MessageView *messageview = (MessageView *)data;
755
        messageview_copy_clipboard(messageview);
756
}
757
758
static void allsel_cb(gpointer data, guint action, GtkWidget *widget)
759
{
760
        MessageView *messageview = (MessageView *)data;
761
        messageview_select_all(messageview);
762
}
763
764
static void search_cb(gpointer data, guint action, GtkWidget *widget)
765
{
766
        MessageView *messageview = (MessageView *)data;
767
        message_search(messageview);
768
}
769
770
static void set_charset_cb(gpointer data, guint action, GtkWidget *widget)
771
{
772
        MessageView *messageview = (MessageView *)data;
773
        const gchar *charset;
774
775
        if (GTK_CHECK_MENU_ITEM(widget)->active) {
776
                charset = conv_get_charset_str((CharSet)action);
777
                g_free(messageview->forced_charset);
778
                messageview->forced_charset = g_strdup(charset);
779
                messageview_show(messageview, messageview->msginfo, FALSE);
780
        }
781
}
782
783
static void view_source_cb(gpointer data, guint action, GtkWidget *widget)
784
{
785
        MessageView *messageview = (MessageView *)data;
786
        SourceWindow *srcwin;
787
788
        if (!messageview->msginfo) return;
789
790
        srcwin = source_window_create();
791
        source_window_show_msg(srcwin, messageview->msginfo);
792
        source_window_show(srcwin);
793
}
794
795
static void show_all_header_cb(gpointer data, guint action, GtkWidget *widget)
796
{
797
        MessageView *messageview = (MessageView *)data;
798
        MsgInfo *msginfo = messageview->msginfo;
799
800
        if (!msginfo) return;
801
        messageview->msginfo = NULL;
802
        messageview_show(messageview, msginfo,
803
                         GTK_CHECK_MENU_ITEM(widget)->active);
804
        procmsg_msginfo_free(msginfo);
805
}
806
807
static void compose_cb(gpointer data, guint action, GtkWidget *widget)
808
{
809
        MessageView *messageview = (MessageView *)data;
810
        PrefsAccount *ac = NULL;
811
        FolderItem *item = NULL;
812
813
        if (messageview->msginfo)
814
                item = messageview->msginfo->folder;
815
816
        if (item) {
817
                ac = account_find_from_item(item);
818
                if (ac && ac->protocol == A_NNTP &&
819
                    FOLDER_TYPE(item->folder) == F_NEWS) {
820
                        compose_new(ac, item, item->path, NULL);
821
                        return;
822
                }
823
        }
824
825
        compose_new(ac, item, NULL, NULL);
826
}
827
828
static void reply_cb(gpointer data, guint action, GtkWidget *widget)
829
{
830
        MessageView *messageview = (MessageView *)data;
831
        GSList *mlist = NULL;
832
        MsgInfo *msginfo;
833
        gchar *text = NULL;
834
        ComposeMode mode = (ComposeMode)action;
835
836
        msginfo = messageview->msginfo;
837
        mlist = g_slist_append(NULL, msginfo);
838
839
        text = gtkut_text_view_get_selection
840
                (GTK_TEXT_VIEW(messageview->textview->text));
841
        if (text && *text == '\0') {
842
                g_free(text);
843
                text = NULL;
844
        }
845
846
        if (!COMPOSE_QUOTE_MODE(mode))
847
                mode |= prefs_common.reply_with_quote
848
                        ? COMPOSE_WITH_QUOTE : COMPOSE_WITHOUT_QUOTE;
849
850
        switch (COMPOSE_MODE(mode)) {
851
        case COMPOSE_REPLY:
852
        case COMPOSE_REPLY_TO_SENDER:
853
        case COMPOSE_REPLY_TO_ALL:
854
        case COMPOSE_REPLY_TO_LIST:
855
                compose_reply(msginfo, msginfo->folder, mode, text);
856
                break;
857
        case COMPOSE_FORWARD:
858
                compose_forward(mlist, msginfo->folder, FALSE, text);
859
                break;
860
        case COMPOSE_FORWARD_AS_ATTACH:
861
                compose_forward(mlist, msginfo->folder, TRUE, NULL);
862
                break;
863
        case COMPOSE_REDIRECT:
864
                compose_redirect(msginfo, msginfo->folder);
865
                break;
866
        default:
867
                g_warning("messageview.c: reply_cb(): invalid mode: %d\n",
868
                          mode);
869
        }
870
871
        /* summary_set_marks_selected(summaryview); */
872
        g_free(text);
873
        g_slist_free(mlist);
874
}
875
876
static void reedit_cb(gpointer data, guint action, GtkWidget *widget)
877
{
878
        MessageView *messageview = (MessageView *)data;
879
        MsgInfo *msginfo;
880
881
        if (!messageview->msginfo) return;
882
        msginfo = messageview->msginfo;
883
        if (!msginfo->folder) return;
884
        if (msginfo->folder->stype != F_OUTBOX &&
885
            msginfo->folder->stype != F_DRAFT &&
886
            msginfo->folder->stype != F_QUEUE) return;
887
888
        compose_reedit(msginfo);
889
}
890
891
static void addressbook_open_cb(gpointer data, guint action, GtkWidget *widget)
892
{
893
        addressbook_open(NULL);
894
}
895
896
static void add_address_cb(gpointer data, guint action, GtkWidget *widget)
897
{
898
        MessageView *messageview = (MessageView *)data;
899
        MsgInfo *msginfo;
900
        gchar *from;
901
902
        if (!messageview->msginfo) return;
903
        msginfo = messageview->msginfo;
904
        Xstrdup_a(from, msginfo->from, return);
905
        eliminate_address_comment(from);
906
        extract_address(from);
907
        addressbook_add_contact(msginfo->fromname, from, NULL);
908
}
909
910
static void create_filter_cb(gpointer data, guint action, GtkWidget *widget)
911
{
912
        MessageView *messageview = (MessageView *)data;
913
        gchar *header = NULL;
914
        gchar *key = NULL;
915
916
        if (!messageview->msginfo) return;
917
918
        filter_get_keyword_from_msg(messageview->msginfo, &header, &key,
919
                                    (FilterCreateType)action);
920
        prefs_filter_open(messageview->msginfo, header);
921
922
        g_free(header);
923
        g_free(key);
924
}
925
926
static void about_cb(gpointer data, guint action, GtkWidget *widget)
927
{
928
        about_show();
929
}