local account without SMTP
[claws.git] / src / messageview.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999,2000 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/gtktext.h>
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <string.h>
32
33 #include "intl.h"
34 #include "main.h"
35 #include "messageview.h"
36 #include "headerview.h"
37 #include "textview.h"
38 #include "imageview.h"
39 #include "mimeview.h"
40 #include "procmsg.h"
41 #include "procheader.h"
42 #include "procmime.h"
43 #include "prefs_common.h"
44 #include "gtkutils.h"
45 #include "utils.h"
46 #include "rfc2015.h"
47
48 static void messageview_change_view_type(MessageView    *messageview,
49                                          MessageType     type);
50 static void messageview_destroy_cb      (GtkWidget      *widget,
51                                          MessageView    *messageview);
52 static void messageview_size_allocate_cb(GtkWidget      *widget,
53                                          GtkAllocation  *allocation);
54 static void key_pressed                 (GtkWidget      *widget,
55                                          GdkEventKey    *event,
56                                          MessageView    *messageview);
57
58 MessageView *messageview_create(void)
59 {
60         MessageView *messageview;
61         GtkWidget *vbox;
62         HeaderView *headerview;
63         TextView *textview;
64         ImageView *imageview;
65         MimeView *mimeview;
66
67         debug_print(_("Creating message view...\n"));
68         messageview = g_new0(MessageView, 1);
69
70         messageview->type = MVIEW_TEXT;
71
72         headerview = headerview_create();
73
74         textview = textview_create();
75         textview->messageview = messageview;
76
77         imageview = imageview_create();
78         imageview->messageview = messageview;
79
80         mimeview = mimeview_create();
81         mimeview->textview = textview;
82         mimeview->imageview = imageview;
83         mimeview->messageview = messageview;
84
85         vbox = gtk_vbox_new(FALSE, 0);
86         gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(headerview),
87                            FALSE, FALSE, 0);
88         gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(textview),
89                            TRUE, TRUE, 0);
90
91         /* to remove without destroyed */
92         gtk_widget_ref(GTK_WIDGET_PTR(textview));
93         gtk_widget_ref(GTK_WIDGET_PTR(imageview));
94         gtk_widget_ref(GTK_WIDGET_PTR(mimeview));
95
96         messageview->vbox       = vbox;
97         messageview->new_window = FALSE;
98         messageview->window     = NULL;
99         messageview->headerview = headerview;
100         messageview->textview   = textview;
101         messageview->imageview  = imageview;
102         messageview->mimeview   = mimeview;
103
104         return messageview;
105 }
106
107 MessageView *messageview_create_with_new_window(void)
108 {
109         GtkWidget *window;
110         MessageView *msgview;
111
112         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
113         gtk_window_set_title(GTK_WINDOW(window), "Message");
114         gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
115         gtk_widget_set_usize(window, prefs_common.msgwin_width,
116                              prefs_common.msgwin_height);
117
118         msgview = messageview_create();
119
120         gtk_signal_connect(GTK_OBJECT(window), "size_allocate",
121                            GTK_SIGNAL_FUNC(messageview_size_allocate_cb),
122                            msgview);
123         gtk_signal_connect(GTK_OBJECT(window), "destroy",
124                            GTK_SIGNAL_FUNC(messageview_destroy_cb), msgview);
125         gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
126                            GTK_SIGNAL_FUNC(key_pressed), msgview);
127
128         gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET_PTR(msgview));
129         gtk_widget_grab_focus(msgview->textview->text);
130         gtk_widget_show_all(window);
131
132         msgview->new_window = TRUE;
133         msgview->window = window;
134
135         messageview_init(msgview);
136
137         return msgview;
138 }
139
140 void messageview_init(MessageView *messageview)
141 {
142         headerview_init(messageview->headerview);
143         textview_init(messageview->textview);
144         imageview_init(messageview->imageview);
145         mimeview_init(messageview->mimeview);
146         //messageview_set_font(messageview);
147 }
148
149 void messageview_show(MessageView *messageview, MsgInfo *msginfo)
150 {
151         FILE *fp;
152         gchar *file;
153         MimeInfo *mimeinfo;
154         MsgInfo *tmpmsginfo;
155
156         g_return_if_fail(msginfo != NULL);
157
158 #if USE_GPGME
159         for (;;) {
160                 if ((fp = procmsg_open_message(msginfo)) == NULL) return;
161                 mimeinfo = procmime_scan_mime_header(fp);
162                 if (!mimeinfo) break;
163
164                 if (!MSG_IS_ENCRYPTED(msginfo->flags) &&
165                     rfc2015_is_encrypted(mimeinfo)) {
166                         MSG_SET_FLAGS(msginfo->flags, MSG_ENCRYPTED);
167                 }
168                 if (MSG_IS_ENCRYPTED(msginfo->flags) &&
169                     !msginfo->plaintext_file  &&
170                     !msginfo->decryption_failed) {
171                         /* This is an encrypted message but it has not yet
172                          * been decrypted and there was no unsuccessful
173                          * decryption attempt */
174                         rfc2015_decrypt_message(msginfo, mimeinfo, fp);
175                         if (msginfo->plaintext_file &&
176                             !msginfo->decryption_failed) {
177                                 fclose(fp);
178                                 continue;
179                         }
180                 }
181
182                 break;
183         }
184 #else /* !USE_GPGME */
185         if ((fp = procmsg_open_message(msginfo)) == NULL) return;
186         mimeinfo = procmime_scan_mime_header(fp);
187 #endif /* USE_GPGME */
188         fclose(fp);
189         if (!mimeinfo) return;
190
191         file = procmsg_get_message_file_path(msginfo);
192         g_return_if_fail(file != NULL);
193
194         tmpmsginfo = procheader_parse(file, msginfo->flags, TRUE);
195         headerview_show(messageview->headerview, tmpmsginfo);
196         procmsg_msginfo_free(tmpmsginfo);
197
198         if (mimeinfo->mime_type != MIME_TEXT) {
199                 messageview_change_view_type(messageview, MVIEW_MIME);
200                 mimeview_show_message(messageview->mimeview, mimeinfo, file);
201         } else {
202                 messageview_change_view_type(messageview, MVIEW_TEXT);
203                 textview_show_message(messageview->textview, mimeinfo, file);
204                 procmime_mimeinfo_free(mimeinfo);
205         }
206
207         g_free(file);
208 }
209
210 static void messageview_change_view_type(MessageView *messageview,
211                                          MessageType type)
212 {
213         TextView *textview = messageview->textview;
214         ImageView *imageview = messageview->imageview;
215         MimeView *mimeview = messageview->mimeview;
216
217         if (messageview->type == type) return;
218
219         if (type == MVIEW_MIME) {
220                 gtk_container_remove
221                         (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
222                          GTK_WIDGET_PTR(textview));
223                 gtk_box_pack_start(GTK_BOX(messageview->vbox),
224                                    GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
225                 gtk_container_add(GTK_CONTAINER(mimeview->vbox),
226                                   GTK_WIDGET_PTR(textview));
227                 mimeview->type = MIMEVIEW_TEXT;
228         } else if (type == MVIEW_TEXT) {
229                 gtk_container_remove
230                         (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
231                          GTK_WIDGET_PTR(mimeview));
232
233                 if (mimeview->vbox == GTK_WIDGET_PTR(textview)->parent) {
234                         gtk_container_remove(GTK_CONTAINER(mimeview->vbox),
235                                              GTK_WIDGET_PTR(textview));
236                 } else {
237                         gtk_container_remove(GTK_CONTAINER(mimeview->vbox),
238                                              GTK_WIDGET_PTR(imageview));
239                 }
240
241                 gtk_box_pack_start(GTK_BOX(messageview->vbox),
242                                    GTK_WIDGET_PTR(textview), TRUE, TRUE, 0);
243         } else
244                 return;
245
246         messageview->type = type;
247 }
248
249 void messageview_clear(MessageView *messageview)
250 {
251         messageview_change_view_type(messageview, MVIEW_TEXT);
252         headerview_clear(messageview->headerview);
253         textview_clear(messageview->textview);
254 }
255
256 void messageview_destroy(MessageView *messageview)
257 {
258         GtkWidget *textview  = GTK_WIDGET_PTR(messageview->textview);
259         GtkWidget *imageview = GTK_WIDGET_PTR(messageview->imageview);
260         GtkWidget *mimeview  = GTK_WIDGET_PTR(messageview->mimeview);
261
262         headerview_destroy(messageview->headerview);
263         textview_destroy(messageview->textview);
264         imageview_destroy(messageview->imageview);
265         mimeview_destroy(messageview->mimeview);
266
267         g_free(messageview);
268
269         gtk_widget_unref(textview);
270         gtk_widget_unref(imageview);
271         gtk_widget_unref(mimeview);
272 }
273
274 void messageview_quote_color_set(void)
275 {
276 }
277
278 void messageview_set_font(MessageView *messageview)
279 {
280         textview_set_font(messageview->textview, NULL);
281 }
282
283 void messageview_copy_clipboard(MessageView *messageview)
284 {
285         if (messageview->type == MVIEW_TEXT)
286                 gtk_editable_copy_clipboard
287                         (GTK_EDITABLE(messageview->textview->text));
288 }
289
290 void messageview_select_all(MessageView *messageview)
291 {
292         if (messageview->type == MVIEW_TEXT)
293                 gtk_editable_select_region
294                         (GTK_EDITABLE(messageview->textview->text), 0, -1);
295 }
296
297 GtkWidget *messageview_get_text_widget(MessageView *messageview)
298 {
299         return messageview->textview->text;
300 }
301
302 static void messageview_destroy_cb(GtkWidget *widget, MessageView *messageview)
303 {
304         messageview_destroy(messageview);
305 }
306
307 static void messageview_size_allocate_cb(GtkWidget *widget,
308                                          GtkAllocation *allocation)
309 {
310         g_return_if_fail(allocation != NULL);
311
312         prefs_common.msgwin_width  = allocation->width;
313         prefs_common.msgwin_height = allocation->height;
314 }
315
316 static void key_pressed(GtkWidget *widget, GdkEventKey *event,
317                         MessageView *messageview)
318 {
319         if (event && event->keyval == GDK_Escape && messageview->window)
320                 gtk_widget_destroy(messageview->window);
321 }