Statistics
| Revision:

root / src / messageview.c @ 237

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