2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999,2000 Hiroyuki Yamamoto
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.
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.
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.
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>
35 #include "messageview.h"
36 #include "headerview.h"
38 #include "imageview.h"
41 #include "procheader.h"
43 #include "prefs_common.h"
48 #include "alertpanel.h"
51 static void messageview_change_view_type(MessageView *messageview,
53 static void messageview_destroy_cb (GtkWidget *widget,
54 MessageView *messageview);
55 static void messageview_size_allocate_cb(GtkWidget *widget,
56 GtkAllocation *allocation);
57 static void key_pressed (GtkWidget *widget,
59 MessageView *messageview);
61 MessageView *messageview_create(void)
63 MessageView *messageview;
65 HeaderView *headerview;
70 debug_print(_("Creating message view...\n"));
71 messageview = g_new0(MessageView, 1);
73 messageview->type = MVIEW_TEXT;
75 headerview = headerview_create();
77 textview = textview_create();
78 textview->messageview = messageview;
80 imageview = imageview_create();
81 imageview->messageview = messageview;
83 mimeview = mimeview_create();
84 mimeview->textview = textview;
85 mimeview->imageview = imageview;
86 mimeview->messageview = messageview;
88 vbox = gtk_vbox_new(FALSE, 0);
89 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(headerview),
91 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(textview),
94 /* to remove without destroyed */
95 gtk_widget_ref(GTK_WIDGET_PTR(textview));
96 gtk_widget_ref(GTK_WIDGET_PTR(imageview));
97 gtk_widget_ref(GTK_WIDGET_PTR(mimeview));
99 messageview->vbox = vbox;
100 messageview->new_window = FALSE;
101 messageview->window = NULL;
102 messageview->headerview = headerview;
103 messageview->textview = textview;
104 messageview->imageview = imageview;
105 messageview->mimeview = mimeview;
110 MessageView *messageview_create_with_new_window(void)
113 MessageView *msgview;
115 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
116 gtk_window_set_title(GTK_WINDOW(window), "Message");
117 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
118 gtk_widget_set_usize(window, prefs_common.msgwin_width,
119 prefs_common.msgwin_height);
121 msgview = messageview_create();
123 gtk_signal_connect(GTK_OBJECT(window), "size_allocate",
124 GTK_SIGNAL_FUNC(messageview_size_allocate_cb),
126 gtk_signal_connect(GTK_OBJECT(window), "destroy",
127 GTK_SIGNAL_FUNC(messageview_destroy_cb), msgview);
128 gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
129 GTK_SIGNAL_FUNC(key_pressed), msgview);
131 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET_PTR(msgview));
132 gtk_widget_grab_focus(msgview->textview->text);
133 gtk_widget_show_all(window);
135 msgview->new_window = TRUE;
136 msgview->window = window;
138 messageview_init(msgview);
143 void messageview_init(MessageView *messageview)
145 headerview_init(messageview->headerview);
146 textview_init(messageview->textview);
147 imageview_init(messageview->imageview);
148 mimeview_init(messageview->mimeview);
149 //messageview_set_font(messageview);
152 static void notification_convert_header(gchar *dest, gint len, gchar *src,
155 g_return_if_fail(src != NULL);
156 g_return_if_fail(dest != NULL);
162 if (is_ascii_str(src)) {
163 strncpy2(dest, src, len);
164 dest[len - 1] = '\0';
167 conv_encode_header(dest, len, src, header_len);
170 static gint dispotition_notification_send(MsgInfo * msginfo)
173 gchar tmp[MAXPATHLEN + 1];
178 if ((!msginfo->returnreceiptto) &&
179 (!msginfo->dispositionnotificationto))
182 /* write to temporary file */
183 g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg%d",
184 get_rc_dir(), G_DIR_SEPARATOR, (gint)msginfo);
186 if ((fp = fopen(tmp, "w")) == NULL) {
187 FILE_OP_ERROR(tmp, "fopen");
191 /* chmod for security */
192 if (change_file_mode_rw(fp, tmp) < 0) {
193 FILE_OP_ERROR(tmp, "chmod");
194 g_warning(_("can't change file mode\n"));
198 get_rfc822_date(buf, sizeof(buf));
199 fprintf(fp, "Date: %s\n", buf);
202 if (cur_account->name && *cur_account->name) {
203 notification_convert_header
204 (buf, sizeof(buf), cur_account->name,
206 fprintf(fp, "From: %s <%s>\n", buf, cur_account->address);
208 fprintf(fp, "From: %s\n", cur_account->address);
211 if (msginfo->dispositionnotificationto)
212 fprintf(fp, "To: %s\n", msginfo->dispositionnotificationto);
214 fprintf(fp, "To: %s\n", msginfo->returnreceiptto);
217 notification_convert_header(buf, sizeof(buf), msginfo->subject,
218 strlen("Subject: "));
219 fprintf(fp, "Subject: Disposition notification: %s\n", buf);
221 if (fclose(fp) == EOF) {
222 FILE_OP_ERROR(tmp, "fclose");
227 to_list = address_list_append(NULL, msginfo->dispositionnotificationto);
228 ok = send_message(tmp, cur_account, to_list);
230 if (unlink(tmp) < 0) FILE_OP_ERROR(tmp, "unlink");
235 void messageview_show(MessageView *messageview, MsgInfo *msginfo)
242 g_return_if_fail(msginfo != NULL);
246 if ((fp = procmsg_open_message(msginfo)) == NULL) return;
247 mimeinfo = procmime_scan_mime_header(fp);
248 if (!mimeinfo) break;
250 if (!MSG_IS_ENCRYPTED(msginfo->flags) &&
251 rfc2015_is_encrypted(mimeinfo)) {
252 MSG_SET_FLAGS(msginfo->flags, MSG_ENCRYPTED);
254 if (MSG_IS_ENCRYPTED(msginfo->flags) &&
255 !msginfo->plaintext_file &&
256 !msginfo->decryption_failed) {
257 /* This is an encrypted message but it has not yet
258 * been decrypted and there was no unsuccessful
259 * decryption attempt */
260 rfc2015_decrypt_message(msginfo, mimeinfo, fp);
261 if (msginfo->plaintext_file &&
262 !msginfo->decryption_failed) {
270 #else /* !USE_GPGME */
271 if ((fp = procmsg_open_message(msginfo)) == NULL) return;
272 mimeinfo = procmime_scan_mime_header(fp);
273 #endif /* USE_GPGME */
275 if (!mimeinfo) return;
277 file = procmsg_get_message_file_path(msginfo);
278 g_return_if_fail(file != NULL);
280 tmpmsginfo = procheader_parse(file, msginfo->flags, TRUE);
282 if (prefs_common.return_receipt
283 && (tmpmsginfo->dispositionnotificationto
284 || tmpmsginfo->returnreceiptto)
285 && (MSG_IS_UNREAD(msginfo->flags))) {
288 if (alertpanel(_("Return Receipt"), _("Send return receipt ?"),
289 _("Yes"), _("No"), NULL) == G_ALERTDEFAULT) {
290 ok = dispotition_notification_send(tmpmsginfo);
292 alertpanel_error(_("Error occurred while sending notification."));
296 headerview_show(messageview->headerview, tmpmsginfo);
297 procmsg_msginfo_free(tmpmsginfo);
299 if (mimeinfo->mime_type != MIME_TEXT) {
300 messageview_change_view_type(messageview, MVIEW_MIME);
301 mimeview_show_message(messageview->mimeview, mimeinfo, file);
303 messageview_change_view_type(messageview, MVIEW_TEXT);
304 textview_show_message(messageview->textview, mimeinfo, file);
305 procmime_mimeinfo_free(mimeinfo);
311 static void messageview_change_view_type(MessageView *messageview,
314 TextView *textview = messageview->textview;
315 ImageView *imageview = messageview->imageview;
316 MimeView *mimeview = messageview->mimeview;
318 if (messageview->type == type) return;
320 if (type == MVIEW_MIME) {
322 (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
323 GTK_WIDGET_PTR(textview));
324 gtk_box_pack_start(GTK_BOX(messageview->vbox),
325 GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
326 gtk_container_add(GTK_CONTAINER(mimeview->vbox),
327 GTK_WIDGET_PTR(textview));
328 mimeview->type = MIMEVIEW_TEXT;
329 } else if (type == MVIEW_TEXT) {
331 (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
332 GTK_WIDGET_PTR(mimeview));
334 if (mimeview->vbox == GTK_WIDGET_PTR(textview)->parent) {
335 gtk_container_remove(GTK_CONTAINER(mimeview->vbox),
336 GTK_WIDGET_PTR(textview));
338 gtk_container_remove(GTK_CONTAINER(mimeview->vbox),
339 GTK_WIDGET_PTR(imageview));
342 gtk_box_pack_start(GTK_BOX(messageview->vbox),
343 GTK_WIDGET_PTR(textview), TRUE, TRUE, 0);
347 messageview->type = type;
350 void messageview_clear(MessageView *messageview)
352 messageview_change_view_type(messageview, MVIEW_TEXT);
353 headerview_clear(messageview->headerview);
354 textview_clear(messageview->textview);
357 void messageview_destroy(MessageView *messageview)
359 GtkWidget *textview = GTK_WIDGET_PTR(messageview->textview);
360 GtkWidget *imageview = GTK_WIDGET_PTR(messageview->imageview);
361 GtkWidget *mimeview = GTK_WIDGET_PTR(messageview->mimeview);
363 headerview_destroy(messageview->headerview);
364 textview_destroy(messageview->textview);
365 imageview_destroy(messageview->imageview);
366 mimeview_destroy(messageview->mimeview);
370 gtk_widget_unref(textview);
371 gtk_widget_unref(imageview);
372 gtk_widget_unref(mimeview);
375 void messageview_quote_color_set(void)
379 void messageview_set_font(MessageView *messageview)
381 textview_set_font(messageview->textview, NULL);
384 void messageview_copy_clipboard(MessageView *messageview)
386 if (messageview->type == MVIEW_TEXT)
387 gtk_editable_copy_clipboard
388 (GTK_EDITABLE(messageview->textview->text));
391 void messageview_select_all(MessageView *messageview)
393 if (messageview->type == MVIEW_TEXT)
394 gtk_editable_select_region
395 (GTK_EDITABLE(messageview->textview->text), 0, -1);
398 GtkWidget *messageview_get_text_widget(MessageView *messageview)
400 return messageview->textview->text;
403 static void messageview_destroy_cb(GtkWidget *widget, MessageView *messageview)
405 messageview_destroy(messageview);
408 static void messageview_size_allocate_cb(GtkWidget *widget,
409 GtkAllocation *allocation)
411 g_return_if_fail(allocation != NULL);
413 prefs_common.msgwin_width = allocation->width;
414 prefs_common.msgwin_height = allocation->height;
417 static void key_pressed(GtkWidget *widget, GdkEventKey *event,
418 MessageView *messageview)
420 if (event && event->keyval == GDK_Escape && messageview->window)
421 gtk_widget_destroy(messageview->window);