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"
50 static void messageview_change_view_type(MessageView *messageview,
52 static void messageview_destroy_cb (GtkWidget *widget,
53 MessageView *messageview);
54 static void messageview_size_allocate_cb(GtkWidget *widget,
55 GtkAllocation *allocation);
56 static void key_pressed (GtkWidget *widget,
58 MessageView *messageview);
60 MessageView *messageview_create(void)
62 MessageView *messageview;
64 HeaderView *headerview;
69 debug_print(_("Creating message view...\n"));
70 messageview = g_new0(MessageView, 1);
72 messageview->type = MVIEW_TEXT;
74 headerview = headerview_create();
76 textview = textview_create();
77 textview->messageview = messageview;
79 imageview = imageview_create();
80 imageview->messageview = messageview;
82 mimeview = mimeview_create();
83 mimeview->textview = textview;
84 mimeview->imageview = imageview;
85 mimeview->messageview = messageview;
87 vbox = gtk_vbox_new(FALSE, 0);
88 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(headerview),
90 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET_PTR(textview),
93 /* to remove without destroyed */
94 gtk_widget_ref(GTK_WIDGET_PTR(textview));
95 gtk_widget_ref(GTK_WIDGET_PTR(imageview));
96 gtk_widget_ref(GTK_WIDGET_PTR(mimeview));
98 messageview->vbox = vbox;
99 messageview->new_window = FALSE;
100 messageview->window = NULL;
101 messageview->headerview = headerview;
102 messageview->textview = textview;
103 messageview->imageview = imageview;
104 messageview->mimeview = mimeview;
109 MessageView *messageview_create_with_new_window(void)
112 MessageView *msgview;
114 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
115 gtk_window_set_title(GTK_WINDOW(window), "Message");
116 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
117 gtk_widget_set_usize(window, prefs_common.msgwin_width,
118 prefs_common.msgwin_height);
120 msgview = messageview_create();
122 gtk_signal_connect(GTK_OBJECT(window), "size_allocate",
123 GTK_SIGNAL_FUNC(messageview_size_allocate_cb),
125 gtk_signal_connect(GTK_OBJECT(window), "destroy",
126 GTK_SIGNAL_FUNC(messageview_destroy_cb), msgview);
127 gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
128 GTK_SIGNAL_FUNC(key_pressed), msgview);
130 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET_PTR(msgview));
131 gtk_widget_grab_focus(msgview->textview->text);
132 gtk_widget_show_all(window);
134 msgview->new_window = TRUE;
135 msgview->window = window;
137 messageview_init(msgview);
142 void messageview_init(MessageView *messageview)
144 headerview_init(messageview->headerview);
145 textview_init(messageview->textview);
146 imageview_init(messageview->imageview);
147 mimeview_init(messageview->mimeview);
148 //messageview_set_font(messageview);
151 static void notification_convert_header(gchar *dest, gint len, gchar *src,
154 g_return_if_fail(src != NULL);
155 g_return_if_fail(dest != NULL);
161 if (is_ascii_str(src)) {
162 strncpy2(dest, src, len);
163 dest[len - 1] = '\0';
166 conv_encode_header(dest, len, src, header_len);
169 static gint dispotition_notification_send(MsgInfo * msginfo)
172 gchar tmp[MAXPATHLEN + 1];
177 /* write to temporary file */
178 g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg%d",
179 get_rc_dir(), G_DIR_SEPARATOR, (gint)msginfo);
181 if ((fp = fopen(tmp, "w")) == NULL) {
182 FILE_OP_ERROR(tmp, "fopen");
186 /* chmod for security */
187 if (change_file_mode_rw(fp, tmp) < 0) {
188 FILE_OP_ERROR(tmp, "chmod");
189 g_warning(_("can't change file mode\n"));
193 get_rfc822_date(buf, sizeof(buf));
194 fprintf(fp, "Date: %s\n", buf);
197 if (cur_account->name && *cur_account->name) {
198 notification_convert_header
199 (buf, sizeof(buf), cur_account->name,
201 fprintf(fp, "From: %s <%s>\n", buf, cur_account->address);
203 fprintf(fp, "From: %s\n", cur_account->address);
206 fprintf(fp, "To: %s\n", msginfo->dispositionnotificationto);
209 notification_convert_header(buf, sizeof(buf), msginfo->subject,
210 strlen("Subject: "));
211 fprintf(fp, "Subject: Disposition notification: %s\n", buf);
213 if (fclose(fp) == EOF) {
214 FILE_OP_ERROR(tmp, "fclose");
219 to_list = address_list_append(NULL, msginfo->dispositionnotificationto);
220 ok = send_message(tmp, cur_account, to_list);
222 if (unlink(tmp) < 0) FILE_OP_ERROR(tmp, "unlink");
227 void messageview_show(MessageView *messageview, MsgInfo *msginfo)
234 g_return_if_fail(msginfo != NULL);
238 if ((fp = procmsg_open_message(msginfo)) == NULL) return;
239 mimeinfo = procmime_scan_mime_header(fp);
240 if (!mimeinfo) break;
242 if (!MSG_IS_ENCRYPTED(msginfo->flags) &&
243 rfc2015_is_encrypted(mimeinfo)) {
244 MSG_SET_FLAGS(msginfo->flags, MSG_ENCRYPTED);
246 if (MSG_IS_ENCRYPTED(msginfo->flags) &&
247 !msginfo->plaintext_file &&
248 !msginfo->decryption_failed) {
249 /* This is an encrypted message but it has not yet
250 * been decrypted and there was no unsuccessful
251 * decryption attempt */
252 rfc2015_decrypt_message(msginfo, mimeinfo, fp);
253 if (msginfo->plaintext_file &&
254 !msginfo->decryption_failed) {
262 #else /* !USE_GPGME */
263 if ((fp = procmsg_open_message(msginfo)) == NULL) return;
264 mimeinfo = procmime_scan_mime_header(fp);
265 #endif /* USE_GPGME */
267 if (!mimeinfo) return;
269 file = procmsg_get_message_file_path(msginfo);
270 g_return_if_fail(file != NULL);
272 tmpmsginfo = procheader_parse(file, msginfo->flags, TRUE);
274 if (prefs_common.return_receipt
275 && tmpmsginfo->dispositionnotificationto
276 && (MSG_IS_UNREAD(msginfo->flags))) {
279 if (alertpanel(_("Return Receipt"), _("Send return receipt ?"),
280 _("Yes"), _("No"), NULL) == G_ALERTDEFAULT) {
281 ok = dispotition_notification_send(tmpmsginfo);
283 alertpanel_error(_("Error occurred while sending notification."));
287 headerview_show(messageview->headerview, tmpmsginfo);
288 procmsg_msginfo_free(tmpmsginfo);
290 if (mimeinfo->mime_type != MIME_TEXT) {
291 messageview_change_view_type(messageview, MVIEW_MIME);
292 mimeview_show_message(messageview->mimeview, mimeinfo, file);
294 messageview_change_view_type(messageview, MVIEW_TEXT);
295 textview_show_message(messageview->textview, mimeinfo, file);
296 procmime_mimeinfo_free(mimeinfo);
302 static void messageview_change_view_type(MessageView *messageview,
305 TextView *textview = messageview->textview;
306 ImageView *imageview = messageview->imageview;
307 MimeView *mimeview = messageview->mimeview;
309 if (messageview->type == type) return;
311 if (type == MVIEW_MIME) {
313 (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
314 GTK_WIDGET_PTR(textview));
315 gtk_box_pack_start(GTK_BOX(messageview->vbox),
316 GTK_WIDGET_PTR(mimeview), TRUE, TRUE, 0);
317 gtk_container_add(GTK_CONTAINER(mimeview->vbox),
318 GTK_WIDGET_PTR(textview));
319 mimeview->type = MIMEVIEW_TEXT;
320 } else if (type == MVIEW_TEXT) {
322 (GTK_CONTAINER(GTK_WIDGET_PTR(messageview)),
323 GTK_WIDGET_PTR(mimeview));
325 if (mimeview->vbox == GTK_WIDGET_PTR(textview)->parent) {
326 gtk_container_remove(GTK_CONTAINER(mimeview->vbox),
327 GTK_WIDGET_PTR(textview));
329 gtk_container_remove(GTK_CONTAINER(mimeview->vbox),
330 GTK_WIDGET_PTR(imageview));
333 gtk_box_pack_start(GTK_BOX(messageview->vbox),
334 GTK_WIDGET_PTR(textview), TRUE, TRUE, 0);
338 messageview->type = type;
341 void messageview_clear(MessageView *messageview)
343 messageview_change_view_type(messageview, MVIEW_TEXT);
344 headerview_clear(messageview->headerview);
345 textview_clear(messageview->textview);
348 void messageview_destroy(MessageView *messageview)
350 GtkWidget *textview = GTK_WIDGET_PTR(messageview->textview);
351 GtkWidget *imageview = GTK_WIDGET_PTR(messageview->imageview);
352 GtkWidget *mimeview = GTK_WIDGET_PTR(messageview->mimeview);
354 headerview_destroy(messageview->headerview);
355 textview_destroy(messageview->textview);
356 imageview_destroy(messageview->imageview);
357 mimeview_destroy(messageview->mimeview);
361 gtk_widget_unref(textview);
362 gtk_widget_unref(imageview);
363 gtk_widget_unref(mimeview);
366 void messageview_quote_color_set(void)
370 void messageview_set_font(MessageView *messageview)
372 textview_set_font(messageview->textview, NULL);
375 void messageview_copy_clipboard(MessageView *messageview)
377 if (messageview->type == MVIEW_TEXT)
378 gtk_editable_copy_clipboard
379 (GTK_EDITABLE(messageview->textview->text));
382 void messageview_select_all(MessageView *messageview)
384 if (messageview->type == MVIEW_TEXT)
385 gtk_editable_select_region
386 (GTK_EDITABLE(messageview->textview->text), 0, -1);
389 GtkWidget *messageview_get_text_widget(MessageView *messageview)
391 return messageview->textview->text;
394 static void messageview_destroy_cb(GtkWidget *widget, MessageView *messageview)
396 messageview_destroy(messageview);
399 static void messageview_size_allocate_cb(GtkWidget *widget,
400 GtkAllocation *allocation)
402 g_return_if_fail(allocation != NULL);
404 prefs_common.msgwin_width = allocation->width;
405 prefs_common.msgwin_height = allocation->height;
408 static void key_pressed(GtkWidget *widget, GdkEventKey *event,
409 MessageView *messageview)
411 if (event && event->keyval == GDK_Escape && messageview->window)
412 gtk_widget_destroy(messageview->window);