Statistics
| Revision:

root / src / messageview.c @ 1

History | View | Annotate | Download (24.8 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2004 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 <gdk/gdkkeysyms.h>
24
#include <gtk/gtkvbox.h>
25
#include <gtk/gtkcontainer.h>
26
#include <gtk/gtkeditable.h>
27
#include <gtk/gtkwindow.h>
28
#include <gtk/gtktextview.h>
29
#include <gtk/gtkmenu.h>
30
#include <gtk/gtkmenuitem.h>
31
#include <stdio.h>
32
#include <ctype.h>
33
#include <string.h>
34

    
35
#include "intl.h"
36
#include "main.h"
37
#include "messageview.h"
38
#include "message_search.h"
39
#include "headerview.h"
40
#include "textview.h"
41
#include "imageview.h"
42
#include "mimeview.h"
43
#include "menu.h"
44
#include "about.h"
45
#include "filesel.h"
46
#include "sourcewindow.h"
47
#include "addressbook.h"
48
#include "alertpanel.h"
49
#include "inputdialog.h"
50
#include "manage_window.h"
51
#include "procmsg.h"
52
#include "procheader.h"
53
#include "procmime.h"
54
#include "account.h"
55
#include "action.h"
56
#include "prefs_common.h"
57
#include "prefs_account.h"
58
#include "prefs_filter.h"
59
#include "gtkutils.h"
60
#include "utils.h"
61
#include "rfc2015.h"
62

    
63
static GList *messageview_list = NULL;
64

    
65
static void messageview_change_view_type(MessageView        *messageview,
66
                                         MessageType         type);
67
static void messageview_destroy_cb        (GtkWidget        *widget,
68
                                         MessageView        *messageview);
69
static void messageview_size_allocate_cb(GtkWidget        *widget,
70
                                         GtkAllocation        *allocation);
71
static gboolean key_pressed                (GtkWidget        *widget,
72
                                         GdkEventKey        *event,
73
                                         MessageView        *messageview);
74

    
75
static void save_as_cb                        (gpointer         data,
76
                                         guint                 action,
77
                                         GtkWidget        *widget);
78
static void print_cb                        (gpointer         data,
79
                                         guint                 action,
80
                                         GtkWidget        *widget);
81
static void close_cb                        (gpointer         data,
82
                                         guint                 action,
83
                                         GtkWidget        *widget);
84
static void copy_cb                        (gpointer         data,
85
                                         guint                 action,
86
                                         GtkWidget        *widget);
87
static void allsel_cb                        (gpointer         data,
88
                                         guint                 action,
89
                                         GtkWidget        *widget);
90
static void search_cb                        (gpointer         data,
91
                                         guint                 action,
92
                                         GtkWidget        *widget);
93

    
94
static void set_charset_cb                (gpointer         data,
95
                                         guint                 action,
96
                                         GtkWidget        *widget);
97
static void view_source_cb                (gpointer         data,
98
                                         guint                 action,
99
                                         GtkWidget        *widget);
100
static void show_all_header_cb                (gpointer         data,
101
                                         guint                 action,
102
                                         GtkWidget        *widget);
103

    
104
static void compose_cb                        (gpointer         data,
105
                                         guint                 action,
106
                                         GtkWidget        *widget);
107
static void reply_cb                        (gpointer         data,
108
                                         guint                 action,
109
                                         GtkWidget        *widget);
110
static void reedit_cb                        (gpointer         data,
111
                                         guint                 action,
112
                                         GtkWidget        *widget);
113

    
114
static void addressbook_open_cb                (gpointer         data,
115
                                         guint                 action,
116
                                         GtkWidget        *widget);
117
static void add_address_cb                (gpointer         data,
118
                                         guint                 action,
119
                                         GtkWidget        *widget);
120
static void create_filter_cb                (gpointer         data,
121
                                         guint                 action,
122
                                         GtkWidget        *widget);
123

    
124
static void about_cb                        (gpointer         data,
125
                                         guint                 action,
126
                                         GtkWidget        *widget);
127

    
128
static GtkItemFactoryEntry msgview_entries[] =
129
{
130
        {N_("/_File"),                        NULL, NULL, 0, "<Branch>"},
131
        {N_("/_File/_Save as..."),        NULL, save_as_cb, 0, NULL},
132
        {N_("/_File/_Print..."),        NULL, print_cb, 0, NULL},
133
        {N_("/_File/---"),                NULL, NULL, 0, "<Separator>"},
134
        {N_("/_File/_Close"),                NULL, close_cb, 0, NULL},
135

    
136
        {N_("/_Edit"),                        NULL, NULL, 0, "<Branch>"},
137
        {N_("/_Edit/_Copy"),                NULL, copy_cb, 0, NULL},
138
        {N_("/_Edit/Select _all"),        NULL, allsel_cb, 0, NULL},
139
        {N_("/_Edit/---"),                NULL, NULL, 0, "<Separator>"},
140
        {N_("/_Edit/_Find in current message..."),
141
                                        NULL, search_cb, 0, NULL},
142

    
143
        {N_("/_View"),                        NULL, NULL, 0, "<Branch>"},
144

    
145
#define CODESET_SEPARATOR \
146
        {N_("/_View/_Code set/---"),        NULL, NULL, 0, "<Separator>"}
147
#define CODESET_ACTION(action) \
148
        NULL, set_charset_cb, action, "/View/Code set/Auto detect"
149

    
150
        {N_("/_View/_Code set"),        NULL, NULL, 0, "<Branch>"},
151
        {N_("/_View/_Code set/_Auto detect"),
152
                                        NULL, set_charset_cb, C_AUTO, "<RadioItem>"},
153
        CODESET_SEPARATOR,
154
        {N_("/_View/_Code set/7bit ascii (US-ASC_II)"),
155
         CODESET_ACTION(C_US_ASCII)},
156

    
157
#if HAVE_ICONV
158
        {N_("/_View/_Code set/Unicode (_UTF-8)"),
159
         CODESET_ACTION(C_UTF_8)},
160
        CODESET_SEPARATOR,
161
#endif
162
        {N_("/_View/_Code set/Western European (ISO-8859-_1)"),
163
         CODESET_ACTION(C_ISO_8859_1)},
164
        {N_("/_View/_Code set/Western European (ISO-8859-15)"),
165
         CODESET_ACTION(C_ISO_8859_15)},
166
        CODESET_SEPARATOR,
167
#if HAVE_ICONV
168
        {N_("/_View/_Code set/Central European (ISO-8859-_2)"),
169
         CODESET_ACTION(C_ISO_8859_2)},
170
        CODESET_SEPARATOR,
171
        {N_("/_View/_Code set/_Baltic (ISO-8859-13)"),
172
         CODESET_ACTION(C_ISO_8859_13)},
173
        {N_("/_View/_Code set/Baltic (ISO-8859-_4)"),
174
         CODESET_ACTION(C_ISO_8859_4)},
175
        CODESET_SEPARATOR,
176
        {N_("/_View/_Code set/Greek (ISO-8859-_7)"),
177
         CODESET_ACTION(C_ISO_8859_7)},
178
        CODESET_SEPARATOR,
179
        {N_("/_View/_Code set/Turkish (ISO-8859-_9)"),
180
         CODESET_ACTION(C_ISO_8859_9)},
181
        CODESET_SEPARATOR,
182
        {N_("/_View/_Code set/Cyrillic (ISO-8859-_5)"),
183
         CODESET_ACTION(C_ISO_8859_5)},
184
        {N_("/_View/_Code set/Cyrillic (KOI8-_R)"),
185
         CODESET_ACTION(C_KOI8_R)},
186
        {N_("/_View/_Code set/Cyrillic (KOI8-U)"),
187
         CODESET_ACTION(C_KOI8_U)},
188
        {N_("/_View/_Code set/Cyrillic (Windows-1251)"),
189
         CODESET_ACTION(C_CP1251)},
190
        CODESET_SEPARATOR,
191
#endif
192
        {N_("/_View/_Code set/Japanese (ISO-2022-_JP)"),
193
         CODESET_ACTION(C_ISO_2022_JP)},
194
#if HAVE_ICONV
195
        {N_("/_View/_Code set/Japanese (ISO-2022-JP-2)"),
196
         CODESET_ACTION(C_ISO_2022_JP_2)},
197
#endif
198
        {N_("/_View/_Code set/Japanese (_EUC-JP)"),
199
         CODESET_ACTION(C_EUC_JP)},
200
        {N_("/_View/_Code set/Japanese (_Shift__JIS)"),
201
         CODESET_ACTION(C_SHIFT_JIS)},
202
#if HAVE_ICONV
203
        CODESET_SEPARATOR,
204
        {N_("/_View/_Code set/Simplified Chinese (_GB2312)"),
205
         CODESET_ACTION(C_GB2312)},
206
        {N_("/_View/_Code set/Traditional Chinese (_Big5)"),
207
         CODESET_ACTION(C_BIG5)},
208
        {N_("/_View/_Code set/Traditional Chinese (EUC-_TW)"),
209
         CODESET_ACTION(C_EUC_TW)},
210
        {N_("/_View/_Code set/Chinese (ISO-2022-_CN)"),
211
         CODESET_ACTION(C_ISO_2022_CN)},
212
        CODESET_SEPARATOR,
213
        {N_("/_View/_Code set/Korean (EUC-_KR)"),
214
         CODESET_ACTION(C_EUC_KR)},
215
        {N_("/_View/_Code set/Korean (ISO-2022-KR)"),
216
         CODESET_ACTION(C_ISO_2022_KR)},
217
        CODESET_SEPARATOR,
218
        {N_("/_View/_Code set/Thai (TIS-620)"),
219
         CODESET_ACTION(C_TIS_620)},
220
        {N_("/_View/_Code set/Thai (Windows-874)"),
221
         CODESET_ACTION(C_WINDOWS_874)},
222
#endif
223

    
224
#undef CODESET_SEPARATOR
225
#undef CODESET_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
        HeaderView *headerview;
278
        TextView *textview;
279
        MimeView *mimeview;
280

    
281
        debug_print(_("Creating message view...\n"));
282
        messageview = g_new0(MessageView, 1);
283

    
284
        messageview->type = MVIEW_TEXT;
285

    
286
        headerview = headerview_create();
287

    
288
        textview = textview_create();
289
        textview->messageview = messageview;
290

    
291
        mimeview = mimeview_create();
292
        mimeview->textview = textview_create();
293
        mimeview->textview->messageview = messageview;
294
        mimeview->imageview = imageview_create();
295
        mimeview->imageview->messageview = messageview;
296
        mimeview->messageview = messageview;
297

    
298
        vbox = gtk_vbox_new(FALSE, 0);
299
        gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(headerview),
300
                           FALSE, FALSE, 0);
301
        gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(textview),
302
                           TRUE, TRUE, 0);
303
        gtk_widget_show(vbox);
304

    
305
        /* to remove without destroyed */
306
        gtk_widget_ref(GTK_WIDGET_PTR(textview));
307
        gtk_widget_ref(GTK_WIDGET_PTR(mimeview));
308
        gtk_widget_ref(GTK_WIDGET_PTR(mimeview->textview));
309
        gtk_widget_ref(GTK_WIDGET_PTR(mimeview->imageview));
310

    
311
        messageview->vbox        = vbox;
312
        messageview->new_window  = FALSE;
313
        messageview->window      = NULL;
314
        messageview->window_vbox = NULL;
315
        messageview->headerview  = headerview;
316
        messageview->textview    = textview;
317
        messageview->mimeview    = mimeview;
318

    
319
        messageview->statusbar     = NULL;
320
        messageview->statusbar_cid = 0;
321

    
322
        return messageview;
323
}
324

    
325
MessageView *messageview_create_with_new_window(void)
326
{
327
        MessageView *msgview;
328
        GtkWidget *window;
329
        GtkWidget *window_vbox;
330
        GtkWidget *body_vbox;
331
        GtkWidget *menubar;
332
        GtkItemFactory *ifactory;
333
        GtkWidget *statusbar;
334
        guint n_menu_entries;
335

    
336
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
337
        gtk_window_set_title(GTK_WINDOW(window), _("Sylpheed - Message View"));
338
        gtk_window_set_wmclass(GTK_WINDOW(window), "message_view", "Sylpheed");
339
        gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
340
        gtk_widget_set_size_request(window, prefs_common.msgwin_width,
341
                                    prefs_common.msgwin_height);
342

    
343
        msgview = messageview_create();
344

    
345
        window_vbox = gtk_vbox_new(FALSE, 0);
346
        gtk_container_add(GTK_CONTAINER(window), window_vbox);
347

    
348
        g_signal_connect(G_OBJECT(window), "size_allocate",
349
                         G_CALLBACK(messageview_size_allocate_cb),
350
                         msgview);
351
        g_signal_connect(G_OBJECT(window), "destroy",
352
                         G_CALLBACK(messageview_destroy_cb), msgview);
353
        g_signal_connect(G_OBJECT(window), "key_press_event",
354
                         G_CALLBACK(key_pressed), msgview);
355
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
356

    
357
        n_menu_entries = sizeof(msgview_entries) / sizeof (msgview_entries[0]);
358
        menubar = menubar_create(window, msgview_entries, n_menu_entries,
359
                                 "<MessageView>", msgview);
360
#warning FIXME_GTK2
361
#if 0
362
        menu_factory_copy_rc("<Main>", "<MessageView>");
363
#endif
364
        gtk_box_pack_start(GTK_BOX(window_vbox), menubar, FALSE, TRUE, 0);
365

    
366
        body_vbox = gtk_vbox_new(FALSE, BORDER_WIDTH);
367
        gtk_container_set_border_width(GTK_CONTAINER(body_vbox), BORDER_WIDTH);
368
        gtk_box_pack_start(GTK_BOX(window_vbox), body_vbox, TRUE, TRUE, 0);
369

    
370
        gtk_box_pack_start(GTK_BOX(body_vbox), GTK_WIDGET_PTR(msgview),
371
                           TRUE, TRUE, 0);
372
        gtk_widget_grab_focus(msgview->textview->text);
373

    
374
        statusbar = gtk_statusbar_new();
375
        gtk_box_pack_end(GTK_BOX(body_vbox), statusbar, FALSE, FALSE, 0);
376
        msgview->statusbar = statusbar;
377
        msgview->statusbar_cid = gtk_statusbar_get_context_id
378
                (GTK_STATUSBAR(statusbar), "Message View");
379

    
380
        gtk_widget_show_all(window);
381

    
382
        msgview->new_window = TRUE;
383
        msgview->window = window;
384
        msgview->window_vbox = window_vbox;
385
        msgview->body_vbox = body_vbox;
386
        msgview->visible = TRUE;
387

    
388
        messageview_init(msgview);
389

    
390
        ifactory = gtk_item_factory_from_widget(menubar);
391
        action_update_msgview_menu(ifactory, msgview);
392

    
393
        messageview_list = g_list_append(messageview_list, msgview);
394

    
395
        return msgview;
396
}
397

    
398
void messageview_init(MessageView *messageview)
399
{
400
        headerview_init(messageview->headerview);
401
        textview_init(messageview->textview);
402
        mimeview_init(messageview->mimeview);
403
        /* messageview_set_font(messageview); */
404
}
405

    
406
GList *messageview_get_window_list(void)
407
{
408
        return messageview_list;
409
}
410

    
411
gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
412
                      gboolean all_headers)
413
{
414
        gchar *file;
415
        MimeInfo *mimeinfo;
416

    
417
        g_return_val_if_fail(msginfo != NULL, -1);
418

    
419
        mimeinfo = procmime_scan_message(msginfo);
420
        if (!mimeinfo) {
421
                messageview_change_view_type(messageview, MVIEW_TEXT);
422
                textview_show_error(messageview->textview);
423
                return -1;
424
        }
425

    
426
        file = procmsg_get_message_file_path(msginfo);
427
        if (!file) {
428
                g_warning("can't get message file path.\n");
429
                procmime_mimeinfo_free_all(mimeinfo);
430
                messageview_change_view_type(messageview, MVIEW_TEXT);
431
                textview_show_error(messageview->textview);
432
                return -1;
433
        }
434

    
435
        if (messageview->msginfo != msginfo) {
436
                procmsg_msginfo_free(messageview->msginfo);
437
                messageview->msginfo = procmsg_msginfo_get_full_info(msginfo);
438
        }
439
        headerview_show(messageview->headerview, messageview->msginfo);
440

    
441
        textview_set_all_headers(messageview->textview, all_headers);
442
        textview_set_all_headers(messageview->mimeview->textview, all_headers);
443

    
444
        if (mimeinfo->mime_type != MIME_TEXT &&
445
            mimeinfo->mime_type != MIME_TEXT_HTML) {
446
                messageview_change_view_type(messageview, MVIEW_MIME);
447
                mimeview_show_message(messageview->mimeview, mimeinfo, file);
448
        } else {
449
                messageview_change_view_type(messageview, MVIEW_TEXT);
450
                textview_show_message(messageview->textview, mimeinfo, file);
451
                procmime_mimeinfo_free_all(mimeinfo);
452
        }
453

    
454
        g_free(file);
455

    
456
        return 0;
457
}
458

    
459
static void messageview_change_view_type(MessageView *messageview,
460
                                         MessageType type)
461
{
462
        TextView *textview = messageview->textview;
463
        MimeView *mimeview = messageview->mimeview;
464

    
465
        if (messageview->type == type) return;
466

    
467
        if (type == MVIEW_MIME) {
468
                gtkut_container_remove
469
                        (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
470
                         GTK_WIDGET_PTR(textview));
471
                gtk_box_pack_start(GTK_BOX(messageview->vbox),
472
                                   GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
473
                gtk_container_add(GTK_CONTAINER(mimeview->vbox),
474
                                  GTK_WIDGET_PTR(textview));
475
        } else if (type == MVIEW_TEXT) {
476
                gtkut_container_remove
477
                        (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
478
                         GTK_WIDGET_PTR(mimeview));
479
                mimeview_clear(mimeview);
480

    
481
                if (mimeview->vbox == GTK_WIDGET_PTR(textview)->parent)
482
                        gtkut_container_remove(GTK_CONTAINER(mimeview->vbox),
483
                                                GTK_WIDGET_PTR(textview));
484

    
485
                gtk_box_pack_start(GTK_BOX(messageview->vbox),
486
                                   GTK_WIDGET_PTR(textview), TRUE, TRUE, 0);
487
        } else
488
                return;
489

    
490
        messageview->type = type;
491
}
492

    
493
void messageview_clear(MessageView *messageview)
494
{
495
        procmsg_msginfo_free(messageview->msginfo);
496
        messageview->msginfo = NULL;
497
        messageview_change_view_type(messageview, MVIEW_TEXT);
498
        headerview_clear(messageview->headerview);
499
        textview_clear(messageview->textview);
500
        mimeview_clear(messageview->mimeview);
501
}
502

    
503
void messageview_destroy(MessageView *messageview)
504
{
505
        GtkWidget *textview  = GTK_WIDGET_PTR(messageview->textview);
506
        GtkWidget *imageview = GTK_WIDGET_PTR(messageview->mimeview->imageview);
507
        GtkWidget *mimeview  = GTK_WIDGET_PTR(messageview->mimeview);
508

    
509
        messageview_list = g_list_remove(messageview_list, messageview);
510

    
511
        headerview_destroy(messageview->headerview);
512
        textview_destroy(messageview->textview);
513
        mimeview_destroy(messageview->mimeview);
514

    
515
        procmsg_msginfo_free(messageview->msginfo);
516

    
517
        g_free(messageview);
518

    
519
        gtk_widget_unref(textview);
520
        gtk_widget_unref(imageview);
521
        gtk_widget_unref(mimeview);
522
}
523

    
524
void messageview_quote_color_set(void)
525
{
526
}
527

    
528
void messageview_set_font(MessageView *messageview)
529
{
530
        textview_set_font(messageview->textview, NULL);
531
}
532

    
533
TextView *messageview_get_current_textview(MessageView *messageview)
534
{
535
        TextView *text = NULL;
536

    
537
        if (messageview->type == MVIEW_TEXT)
538
                text = messageview->textview;
539
        else if (messageview->type == MVIEW_MIME) {
540
                if (gtk_notebook_get_current_page
541
                        (GTK_NOTEBOOK(messageview->mimeview->notebook)) == 0)
542
                        text = messageview->textview;
543
                else if (messageview->mimeview->type == MIMEVIEW_TEXT)
544
                        text = messageview->mimeview->textview;
545
        }
546

    
547
        return text;
548
}
549

    
550
MimeInfo *messageview_get_selected_mime_part(MessageView *messageview)
551
{
552
        if (messageview->type == MVIEW_MIME)
553
                return mimeview_get_selected_part(messageview->mimeview);
554

    
555
        return NULL;
556
}
557

    
558
void messageview_copy_clipboard(MessageView *messageview)
559
{
560
        TextView *text;
561

    
562
        text = messageview_get_current_textview(messageview);
563
        if (text) {
564
                GtkTextView *textview = GTK_TEXT_VIEW(text->text);
565
                GtkTextBuffer *buffer;
566
                GtkClipboard *clipboard;
567

    
568
                buffer = gtk_text_view_get_buffer(textview);
569
                clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
570
                gtk_text_buffer_copy_clipboard(buffer, clipboard);
571
        }
572
}
573

    
574
void messageview_select_all(MessageView *messageview)
575
{
576
        TextView *text;
577

    
578
        text = messageview_get_current_textview(messageview);
579
        if (text)
580
                gtk_editable_select_region(GTK_EDITABLE(text->text), 0, -1);
581
}
582

    
583
void messageview_set_position(MessageView *messageview, gint pos)
584
{
585
        textview_set_position(messageview->textview, pos);
586
}
587

    
588
gboolean messageview_search_string(MessageView *messageview, const gchar *str,
589
                                   gboolean case_sens)
590
{
591
        return textview_search_string(messageview->textview, str, case_sens);
592
        return FALSE;
593
}
594

    
595
gboolean messageview_search_string_backward(MessageView *messageview,
596
                                            const gchar *str,
597
                                            gboolean case_sens)
598
{
599
        return textview_search_string_backward(messageview->textview,
600
                                               str, case_sens);
601
        return FALSE;
602
}
603

    
604
gboolean messageview_is_visible(MessageView *messageview)
605
{
606
        return messageview->visible;
607
}
608

    
609
void messageview_save_as(MessageView *messageview)
610
{
611
        gchar *filename = NULL;
612
        MsgInfo *msginfo;
613
        gchar *src, *dest;
614

    
615
        if (!messageview->msginfo) return;
616
        msginfo = messageview->msginfo;
617

    
618
        if (msginfo->subject) {
619
                Xstrdup_a(filename, msginfo->subject, return);
620
                subst_for_filename(filename);
621
        }
622
        dest = filesel_select_file(_("Save as"), filename);
623
        if (!dest) return;
624
        if (is_file_exist(dest)) {
625
                AlertValue aval;
626

    
627
                aval = alertpanel(_("Overwrite"),
628
                                  _("Overwrite existing file?"),
629
                                  _("OK"), _("Cancel"), NULL);
630
                if (G_ALERTDEFAULT != aval) return;
631
        }
632

    
633
        src = procmsg_get_message_file(msginfo);
634
        if (copy_file(src, dest, TRUE) < 0) {
635
                alertpanel_error(_("Can't save the file `%s'."),
636
                                 g_basename(dest));
637
        }
638
        g_free(src);
639
}
640

    
641
static void messageview_destroy_cb(GtkWidget *widget, MessageView *messageview)
642
{
643
        messageview_destroy(messageview);
644
}
645

    
646
static void messageview_size_allocate_cb(GtkWidget *widget,
647
                                         GtkAllocation *allocation)
648
{
649
        g_return_if_fail(allocation != NULL);
650

    
651
        prefs_common.msgwin_width  = allocation->width;
652
        prefs_common.msgwin_height = allocation->height;
653
}
654

    
655
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
656
                            MessageView *messageview)
657
{
658
        if (event && event->keyval == GDK_Escape && messageview->window)
659
                gtk_widget_destroy(messageview->window);
660
        return FALSE;
661
}
662

    
663
static void save_as_cb(gpointer data, guint action, GtkWidget *widget)
664
{
665
        MessageView *messageview = (MessageView *)data;
666
        messageview_save_as(messageview);
667
}
668

    
669
static void print_cb(gpointer data, guint action, GtkWidget *widget)
670
{
671
        MessageView *messageview = (MessageView *)data;
672
        gchar *cmdline;
673
        gchar *p;
674

    
675
        if (!messageview->msginfo) return;
676

    
677
        cmdline = input_dialog(_("Print"),
678
                               _("Enter the print command line:\n"
679
                                 "(`%s' will be replaced with file name)"),
680
                               prefs_common.print_cmd);
681
        if (!cmdline) return;
682
        if (!(p = strchr(cmdline, '%')) || *(p + 1) != 's' ||
683
            strchr(p + 2, '%')) {
684
                alertpanel_error(_("Print command line is invalid:\n`%s'"),
685
                                 cmdline);
686
                g_free(cmdline);
687
                return;
688
        }
689

    
690
        procmsg_print_message(messageview->msginfo, cmdline);
691
        g_free(cmdline);
692
}
693

    
694
static void close_cb(gpointer data, guint action, GtkWidget *widget)
695
{
696
        MessageView *messageview = (MessageView *)data;
697
        gtk_widget_destroy(messageview->window);
698
}
699

    
700
static void copy_cb(gpointer data, guint action, GtkWidget *widget)
701
{
702
        MessageView *messageview = (MessageView *)data;
703
        messageview_copy_clipboard(messageview);
704
}
705

    
706
static void allsel_cb(gpointer data, guint action, GtkWidget *widget)
707
{
708
        MessageView *messageview = (MessageView *)data;
709
        messageview_select_all(messageview);
710
}
711

    
712
static void search_cb(gpointer data, guint action, GtkWidget *widget)
713
{
714
        MessageView *messageview = (MessageView *)data;
715
        message_search(messageview);
716
}
717

    
718
static void set_charset_cb(gpointer data, guint action, GtkWidget *widget)
719
{
720
        MessageView *messageview = (MessageView *)data;
721
        const gchar *charset;
722

    
723
        if (GTK_CHECK_MENU_ITEM(widget)->active) {
724
                charset = conv_get_charset_str((CharSet)action);
725
                g_free(messageview->forced_charset);
726
                messageview->forced_charset = g_strdup(charset);
727
                messageview_show(messageview, messageview->msginfo, FALSE);
728
        }
729
}
730

    
731
static void view_source_cb(gpointer data, guint action, GtkWidget *widget)
732
{
733
        MessageView *messageview = (MessageView *)data;
734
        SourceWindow *srcwin;
735

    
736
        if (!messageview->msginfo) return;
737

    
738
        srcwin = source_window_create();
739
        source_window_show_msg(srcwin, messageview->msginfo);
740
        source_window_show(srcwin);
741
}
742

    
743
static void show_all_header_cb(gpointer data, guint action, GtkWidget *widget)
744
{
745
        MessageView *messageview = (MessageView *)data;
746
        MsgInfo *msginfo = messageview->msginfo;
747

    
748
        if (!msginfo) return;
749
        messageview->msginfo = NULL;
750
        messageview_show(messageview, msginfo,
751
                         GTK_CHECK_MENU_ITEM(widget)->active);
752
        procmsg_msginfo_free(msginfo);
753
}
754

    
755
static void compose_cb(gpointer data, guint action, GtkWidget *widget)
756
{
757
        MessageView *messageview = (MessageView *)data;
758
        PrefsAccount *ac = NULL;
759
        FolderItem *item = NULL;
760

    
761
        if (messageview->msginfo)
762
                item = messageview->msginfo->folder;
763

    
764
        if (item) {
765
                ac = account_find_from_item(item);
766
                if (ac && ac->protocol == A_NNTP &&
767
                    FOLDER_TYPE(item->folder) == F_NEWS) {
768
                        compose_new(ac, item, item->path, NULL);
769
                        return;
770
                }
771
        }
772

    
773
        compose_new(ac, item, NULL, NULL);
774
}
775

    
776
static void reply_cb(gpointer data, guint action, GtkWidget *widget)
777
{
778
        MessageView *messageview = (MessageView *)data;
779
        GSList *mlist = NULL;
780
        MsgInfo *msginfo;
781
        gchar *text = NULL;
782
        ComposeMode mode = (ComposeMode)action;
783

    
784
        msginfo = messageview->msginfo;
785
        mlist = g_slist_append(NULL, msginfo);
786

    
787
        text = gtkut_editable_get_selection
788
                (GTK_EDITABLE(messageview->textview->text));
789
        if (text && *text == '\0') {
790
                g_free(text);
791
                text = NULL;
792
        }
793

    
794
        if (!COMPOSE_QUOTE_MODE(mode))
795
                mode |= prefs_common.reply_with_quote
796
                        ? COMPOSE_WITH_QUOTE : COMPOSE_WITHOUT_QUOTE;
797

    
798
        switch (COMPOSE_MODE(mode)) {
799
        case COMPOSE_REPLY:
800
        case COMPOSE_REPLY_TO_SENDER:
801
        case COMPOSE_REPLY_TO_ALL:
802
        case COMPOSE_REPLY_TO_LIST:
803
                compose_reply(msginfo, msginfo->folder, mode, text);
804
                break;
805
        case COMPOSE_FORWARD:
806
                compose_forward(mlist, msginfo->folder, FALSE, text);
807
                break;
808
        case COMPOSE_FORWARD_AS_ATTACH:
809
                compose_forward(mlist, msginfo->folder, TRUE, NULL);
810
                break;
811
        case COMPOSE_REDIRECT:
812
                compose_redirect(msginfo, msginfo->folder);
813
                break;
814
        default:
815
                g_warning("messageview.c: reply_cb(): invalid mode: %d\n",
816
                          mode);
817
        }
818

    
819
        /* summary_set_marks_selected(summaryview); */
820
        g_free(text);
821
        g_slist_free(mlist);
822
}
823

    
824
static void reedit_cb(gpointer data, guint action, GtkWidget *widget)
825
{
826
        MessageView *messageview = (MessageView *)data;
827
        MsgInfo *msginfo;
828

    
829
        if (!messageview->msginfo) return;
830
        msginfo = messageview->msginfo;
831
        if (!msginfo->folder) return;
832
        if (msginfo->folder->stype != F_OUTBOX &&
833
            msginfo->folder->stype != F_DRAFT &&
834
            msginfo->folder->stype != F_QUEUE) return;
835

    
836
        compose_reedit(msginfo);
837
}
838

    
839
static void addressbook_open_cb(gpointer data, guint action, GtkWidget *widget)
840
{
841
        addressbook_open(NULL);
842
}
843

    
844
static void add_address_cb(gpointer data, guint action, GtkWidget *widget)
845
{
846
        MessageView *messageview = (MessageView *)data;
847
        MsgInfo *msginfo;
848
        gchar *from;
849

    
850
        if (!messageview->msginfo) return;
851
        msginfo = messageview->msginfo;
852
        Xstrdup_a(from, msginfo->from, return);
853
        eliminate_address_comment(from);
854
        extract_address(from);
855
        addressbook_add_contact(msginfo->fromname, from, NULL);
856
}
857

    
858
static void create_filter_cb(gpointer data, guint action, GtkWidget *widget)
859
{
860
        MessageView *messageview = (MessageView *)data;
861
        gchar *header = NULL;
862
        gchar *key = NULL;
863

    
864
        if (!messageview->msginfo) return;
865

    
866
        procmsg_get_filter_keyword(messageview->msginfo, &header, &key,
867
                                   (PrefsFilterType)action);
868
        prefs_filter_open(messageview->msginfo, header);
869

    
870
        g_free(header);
871
        g_free(key);
872
}
873

    
874
static void about_cb(gpointer data, guint action, GtkWidget *widget)
875
{
876
        about_show();
877
}