Statistics
| Revision:

root / src / mimeview.c @ 422

History | View | Annotate | Download (31.9 kB)

1 1 hiro
/*
2 1 hiro
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 135 hiro
 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4 1 hiro
 *
5 1 hiro
 * This program is free software; you can redistribute it and/or modify
6 1 hiro
 * it under the terms of the GNU General Public License as published by
7 1 hiro
 * the Free Software Foundation; either version 2 of the License, or
8 1 hiro
 * (at your option) any later version.
9 1 hiro
 *
10 1 hiro
 * This program is distributed in the hope that it will be useful,
11 1 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 1 hiro
 * GNU General Public License for more details.
14 1 hiro
 *
15 1 hiro
 * You should have received a copy of the GNU General Public License
16 1 hiro
 * along with this program; if not, write to the Free Software
17 1 hiro
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 1 hiro
 */
19 1 hiro
20 1 hiro
#ifdef HAVE_CONFIG_H
21 1 hiro
#  include "config.h"
22 1 hiro
#endif
23 1 hiro
24 1 hiro
#include "defs.h"
25 1 hiro
26 1 hiro
#include <glib.h>
27 92 hiro
#include <glib/gi18n.h>
28 1 hiro
#include <gdk/gdkkeysyms.h>
29 1 hiro
#include <gtk/gtkscrolledwindow.h>
30 275 hiro
#include <gtk/gtktreestore.h>
31 275 hiro
#include <gtk/gtktreeview.h>
32 275 hiro
#include <gtk/gtktreeselection.h>
33 275 hiro
#include <gtk/gtkcellrenderertext.h>
34 1 hiro
#include <gtk/gtkvbox.h>
35 1 hiro
#include <gtk/gtkvpaned.h>
36 1 hiro
#include <gtk/gtksignal.h>
37 1 hiro
#include <gtk/gtkmenu.h>
38 1 hiro
#include <gtk/gtkdnd.h>
39 1 hiro
#include <gtk/gtkselection.h>
40 237 hiro
#include <gtk/gtknotebook.h>
41 275 hiro
#include <gtk/gtkvbbox.h>
42 1 hiro
#include <stdio.h>
43 1 hiro
#include <unistd.h>
44 1 hiro
45 1 hiro
#include "main.h"
46 1 hiro
#include "mimeview.h"
47 1 hiro
#include "textview.h"
48 1 hiro
#include "imageview.h"
49 1 hiro
#include "procmime.h"
50 1 hiro
#include "summaryview.h"
51 1 hiro
#include "menu.h"
52 1 hiro
#include "filesel.h"
53 1 hiro
#include "alertpanel.h"
54 1 hiro
#include "inputdialog.h"
55 1 hiro
#include "utils.h"
56 1 hiro
#include "gtkutils.h"
57 1 hiro
#include "prefs_common.h"
58 1 hiro
#include "rfc2015.h"
59 1 hiro
60 275 hiro
enum
61 1 hiro
{
62 275 hiro
        COL_MIMETYPE,
63 275 hiro
        COL_SIZE,
64 275 hiro
        COL_NAME,
65 275 hiro
        COL_MIME_INFO,
66 275 hiro
        N_COLS
67 275 hiro
};
68 1 hiro
69 1 hiro
static void mimeview_set_multipart_tree                (MimeView        *mimeview,
70 1 hiro
                                                 MimeInfo        *mimeinfo,
71 275 hiro
                                                 GtkTreeIter        *parent);
72 275 hiro
static gboolean mimeview_append_part                (MimeView        *mimeview,
73 1 hiro
                                                 MimeInfo        *partinfo,
74 275 hiro
                                                 GtkTreeIter        *iter,
75 275 hiro
                                                 GtkTreeIter        *parent);
76 1 hiro
static void mimeview_show_message_part                (MimeView        *mimeview,
77 1 hiro
                                                 MimeInfo        *partinfo);
78 1 hiro
static void mimeview_show_image_part                (MimeView        *mimeview,
79 1 hiro
                                                 MimeInfo        *partinfo);
80 135 hiro
static void mimeview_show_mime_part                (MimeView        *mimeview,
81 135 hiro
                                                 MimeInfo        *partinfo);
82 135 hiro
#if USE_GPGME
83 135 hiro
static void mimeview_show_signature_part        (MimeView        *mimeview,
84 135 hiro
                                                 MimeInfo        *partinfo);
85 135 hiro
#endif
86 1 hiro
static void mimeview_change_view_type                (MimeView        *mimeview,
87 1 hiro
                                                 MimeViewType         type);
88 1 hiro
89 275 hiro
static void mimeview_selection_changed        (GtkTreeSelection        *selection,
90 275 hiro
                                         MimeView                *mimeview);
91 275 hiro
92 1 hiro
static gint mimeview_button_pressed        (GtkWidget        *widget,
93 1 hiro
                                         GdkEventButton        *event,
94 1 hiro
                                         MimeView        *mimeview);
95 1 hiro
static gint mimeview_key_pressed        (GtkWidget        *widget,
96 1 hiro
                                         GdkEventKey        *event,
97 1 hiro
                                         MimeView        *mimeview);
98 1 hiro
99 275 hiro
static void mimeview_drag_begin         (GtkWidget          *widget,
100 275 hiro
                                         GdkDragContext          *drag_context,
101 275 hiro
                                         MimeView          *mimeview);
102 275 hiro
static void mimeview_drag_end                 (GtkWidget          *widget,
103 275 hiro
                                         GdkDragContext          *drag_context,
104 275 hiro
                                         MimeView          *mimeview);
105 1 hiro
static void mimeview_drag_data_get      (GtkWidget          *widget,
106 1 hiro
                                         GdkDragContext   *drag_context,
107 1 hiro
                                         GtkSelectionData *selection_data,
108 1 hiro
                                         guint                   info,
109 1 hiro
                                         guint                   time,
110 1 hiro
                                         MimeView          *mimeview);
111 1 hiro
112 1 hiro
static void mimeview_display_as_text        (MimeView        *mimeview);
113 1 hiro
static void mimeview_launch                (MimeView        *mimeview);
114 1 hiro
static void mimeview_open_with                (MimeView        *mimeview);
115 1 hiro
static void mimeview_view_file                (const gchar        *filename,
116 1 hiro
                                         MimeInfo        *partinfo,
117 1 hiro
                                         const gchar        *cmdline);
118 1 hiro
#if USE_GPGME
119 1 hiro
static void mimeview_check_signature        (MimeView        *mimeview);
120 1 hiro
#endif
121 1 hiro
122 1 hiro
static GtkItemFactoryEntry mimeview_popup_entries[] =
123 1 hiro
{
124 1 hiro
        {N_("/_Open"),                  NULL, mimeview_launch,          0, NULL},
125 1 hiro
        {N_("/Open _with..."),          NULL, mimeview_open_with,          0, NULL},
126 1 hiro
        {N_("/_Display as text"), NULL, mimeview_display_as_text, 0, NULL},
127 1 hiro
        {N_("/_Save as..."),          NULL, mimeview_save_as,          0, NULL}
128 1 hiro
#if USE_GPGME
129 1 hiro
        ,
130 1 hiro
        {N_("/_Check signature"), NULL, mimeview_check_signature, 0, NULL}
131 1 hiro
#endif
132 1 hiro
};
133 1 hiro
134 1 hiro
static GtkTargetEntry mimeview_mime_types[] =
135 1 hiro
{
136 1 hiro
        {"text/uri-list", 0, 0}
137 1 hiro
};
138 1 hiro
139 1 hiro
MimeView *mimeview_create(void)
140 1 hiro
{
141 1 hiro
        MimeView *mimeview;
142 1 hiro
143 1 hiro
        GtkWidget *paned;
144 1 hiro
        GtkWidget *scrolledwin;
145 275 hiro
        GtkWidget *treeview;
146 275 hiro
        GtkTreeStore *store;
147 275 hiro
        GtkTreeSelection *selection;
148 275 hiro
        GtkTreeViewColumn *column;
149 275 hiro
        GtkCellRenderer *renderer;
150 1 hiro
        GtkWidget *mime_vbox;
151 1 hiro
        GtkWidget *popupmenu;
152 1 hiro
        GtkItemFactory *popupfactory;
153 1 hiro
        gint n_entries;
154 1 hiro
155 1 hiro
        debug_print(_("Creating MIME view...\n"));
156 1 hiro
        mimeview = g_new0(MimeView, 1);
157 1 hiro
158 1 hiro
        scrolledwin = gtk_scrolled_window_new(NULL, NULL);
159 1 hiro
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
160 1 hiro
                                       GTK_POLICY_AUTOMATIC,
161 1 hiro
                                       GTK_POLICY_ALWAYS);
162 275 hiro
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
163 275 hiro
                                            GTK_SHADOW_IN);
164 1 hiro
        gtk_widget_set_size_request(scrolledwin, -1, 80);
165 1 hiro
166 275 hiro
        store = gtk_tree_store_new(N_COLS, G_TYPE_STRING, G_TYPE_STRING,
167 275 hiro
                                   G_TYPE_STRING, G_TYPE_POINTER);
168 1 hiro
169 275 hiro
        treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
170 275 hiro
        g_object_unref(G_OBJECT(store));
171 275 hiro
        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE);
172 275 hiro
        gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
173 275 hiro
        gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), COL_NAME);
174 275 hiro
        gtk_tree_view_set_reorderable(GTK_TREE_VIEW(treeview), FALSE);
175 275 hiro
176 275 hiro
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
177 275 hiro
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
178 275 hiro
179 275 hiro
        gtk_container_add(GTK_CONTAINER(scrolledwin), treeview);
180 275 hiro
181 275 hiro
        renderer = gtk_cell_renderer_text_new();
182 275 hiro
        g_object_set(renderer, "ypad", 0, NULL);
183 275 hiro
        column = gtk_tree_view_column_new_with_attributes
184 275 hiro
                (_("MIME Type"), renderer, "text", COL_MIMETYPE, NULL);
185 275 hiro
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
186 275 hiro
        gtk_tree_view_column_set_resizable(column, TRUE);
187 275 hiro
        gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
188 275 hiro
189 275 hiro
        renderer = gtk_cell_renderer_text_new();
190 275 hiro
        g_object_set(renderer, "xalign", 1.0, "ypad", 0, NULL);
191 275 hiro
        column = gtk_tree_view_column_new_with_attributes
192 275 hiro
                (_("Size"), renderer, "text", COL_SIZE, NULL);
193 275 hiro
        gtk_tree_view_column_set_alignment(column, 1.0);
194 275 hiro
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
195 275 hiro
        gtk_tree_view_column_set_resizable(column, TRUE);
196 275 hiro
        gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
197 275 hiro
198 275 hiro
        renderer = gtk_cell_renderer_text_new();
199 275 hiro
        g_object_set(renderer, "ypad", 0, NULL);
200 275 hiro
        column = gtk_tree_view_column_new_with_attributes
201 275 hiro
                (_("Name"), renderer, "text", COL_NAME, NULL);
202 275 hiro
        gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
203 275 hiro
        gtk_tree_view_column_set_resizable(column, TRUE);
204 275 hiro
        gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
205 275 hiro
206 275 hiro
        gtk_tree_view_enable_model_drag_source
207 275 hiro
                (GTK_TREE_VIEW(treeview), 0, mimeview_mime_types, 1,
208 275 hiro
                 GDK_ACTION_COPY);
209 275 hiro
210 275 hiro
        g_signal_connect(G_OBJECT(selection), "changed",
211 275 hiro
                         G_CALLBACK(mimeview_selection_changed), mimeview);
212 275 hiro
        g_signal_connect(G_OBJECT(treeview), "button_press_event",
213 1 hiro
                         G_CALLBACK(mimeview_button_pressed), mimeview);
214 275 hiro
        g_signal_connect(G_OBJECT(treeview), "key_press_event",
215 1 hiro
                         G_CALLBACK(mimeview_key_pressed), mimeview);
216 275 hiro
217 275 hiro
        g_signal_connect_after(G_OBJECT (treeview),"drag-begin",
218 275 hiro
                               G_CALLBACK (mimeview_drag_begin), mimeview);
219 275 hiro
        g_signal_connect(G_OBJECT (treeview),"drag-end",
220 275 hiro
                         G_CALLBACK (mimeview_drag_end), mimeview);
221 275 hiro
        g_signal_connect(G_OBJECT(treeview), "drag-data-get",
222 1 hiro
                         G_CALLBACK(mimeview_drag_data_get), mimeview);
223 1 hiro
224 1 hiro
        mime_vbox = gtk_vbox_new(FALSE, 0);
225 135 hiro
        gtk_container_set_reallocate_redraws(GTK_CONTAINER(mime_vbox), TRUE);
226 1 hiro
227 1 hiro
        paned = gtk_vpaned_new();
228 1 hiro
        gtk_paned_add1(GTK_PANED(paned), scrolledwin);
229 1 hiro
        gtk_paned_add2(GTK_PANED(paned), mime_vbox);
230 1 hiro
231 1 hiro
        n_entries = sizeof(mimeview_popup_entries) /
232 1 hiro
                sizeof(mimeview_popup_entries[0]);
233 1 hiro
        popupmenu = menu_create_items(mimeview_popup_entries, n_entries,
234 1 hiro
                                      "<MimeView>", &popupfactory, mimeview);
235 1 hiro
236 1 hiro
        mimeview->paned        = paned;
237 1 hiro
        mimeview->scrolledwin  = scrolledwin;
238 275 hiro
        mimeview->treeview     = treeview;
239 275 hiro
        mimeview->store        = store;
240 275 hiro
        mimeview->selection    = selection;
241 1 hiro
        mimeview->mime_vbox    = mime_vbox;
242 1 hiro
        mimeview->popupmenu    = popupmenu;
243 1 hiro
        mimeview->popupfactory = popupfactory;
244 1 hiro
        mimeview->type         = -1;
245 1 hiro
246 1 hiro
        return mimeview;
247 1 hiro
}
248 1 hiro
249 1 hiro
void mimeview_init(MimeView *mimeview)
250 1 hiro
{
251 1 hiro
        textview_init(mimeview->textview);
252 1 hiro
        imageview_init(mimeview->imageview);
253 1 hiro
}
254 1 hiro
255 1 hiro
/*
256 1 hiro
 * Check whether the message is OpenPGP signed
257 1 hiro
 */
258 1 hiro
#if USE_GPGME
259 1 hiro
static gboolean mimeview_is_signed(MimeView *mimeview)
260 1 hiro
{
261 1 hiro
        MimeInfo *partinfo;
262 1 hiro
263 1 hiro
        debug_print("mimeview_is signed of %p\n", mimeview);
264 1 hiro
265 1 hiro
        if (!mimeview) return FALSE;
266 1 hiro
        if (!mimeview->opened) return FALSE;
267 1 hiro
268 1 hiro
        debug_print("mimeview_is_signed: open\n" );
269 1 hiro
270 1 hiro
        if (!mimeview->file) return FALSE;
271 1 hiro
272 1 hiro
        debug_print("mimeview_is_signed: file\n" );
273 1 hiro
274 1 hiro
        partinfo = mimeview_get_selected_part(mimeview);
275 1 hiro
        g_return_val_if_fail(partinfo != NULL, FALSE);
276 1 hiro
277 1 hiro
        /* walk the tree and see whether there is a signature somewhere */
278 1 hiro
        do {
279 1 hiro
                if (rfc2015_has_signature(partinfo))
280 1 hiro
                        return TRUE;
281 1 hiro
        } while ((partinfo = partinfo->parent) != NULL);
282 1 hiro
283 1 hiro
        debug_print("mimeview_is_signed: FALSE\n" );
284 1 hiro
285 1 hiro
        return FALSE;
286 1 hiro
}
287 1 hiro
288 1 hiro
static void set_unchecked_signature(MimeInfo *mimeinfo)
289 1 hiro
{
290 56 hiro
        MimeInfo **signedinfo;
291 1 hiro
292 56 hiro
        signedinfo = rfc2015_find_signature(mimeinfo);
293 56 hiro
        if (signedinfo == NULL) return;
294 1 hiro
295 56 hiro
        g_free(signedinfo[1]->sigstatus);
296 56 hiro
        signedinfo[1]->sigstatus =
297 1 hiro
                g_strdup(_("Select \"Check signature\" to check"));
298 1 hiro
299 56 hiro
        g_free(signedinfo[1]->sigstatus_full);
300 56 hiro
        signedinfo[1]->sigstatus_full = NULL;
301 56 hiro
302 275 hiro
        g_free(signedinfo);
303 1 hiro
}
304 1 hiro
#endif /* USE_GPGME */
305 1 hiro
306 1 hiro
void mimeview_show_message(MimeView *mimeview, MimeInfo *mimeinfo,
307 1 hiro
                           const gchar *file)
308 1 hiro
{
309 275 hiro
        GtkTreeModel *model = GTK_TREE_MODEL(mimeview->store);
310 275 hiro
        GtkTreeIter iter;
311 275 hiro
        gboolean valid;
312 1 hiro
313 1 hiro
        mimeview_clear(mimeview);
314 1 hiro
        textview_clear(mimeview->messageview->textview);
315 1 hiro
316 1 hiro
        g_return_if_fail(file != NULL);
317 1 hiro
        g_return_if_fail(mimeinfo != NULL);
318 1 hiro
319 1 hiro
        mimeview->mimeinfo = mimeinfo;
320 1 hiro
321 1 hiro
        mimeview->file = g_strdup(file);
322 1 hiro
323 1 hiro
#if USE_GPGME
324 1 hiro
        if (prefs_common.auto_check_signatures) {
325 1 hiro
                FILE *fp;
326 1 hiro
327 1 hiro
                if ((fp = fopen(file, "rb")) == NULL) {
328 1 hiro
                        FILE_OP_ERROR(file, "fopen");
329 1 hiro
                        return;
330 1 hiro
                }
331 1 hiro
                rfc2015_check_signature(mimeinfo, fp);
332 1 hiro
                fclose(fp);
333 1 hiro
        } else
334 1 hiro
                set_unchecked_signature(mimeinfo);
335 1 hiro
#endif
336 1 hiro
337 1 hiro
        g_signal_handlers_block_by_func
338 275 hiro
                (G_OBJECT(mimeview->selection),
339 275 hiro
                 G_CALLBACK(mimeview_selection_changed), mimeview);
340 1 hiro
341 1 hiro
        mimeview_set_multipart_tree(mimeview, mimeinfo, NULL);
342 275 hiro
        gtk_tree_view_expand_all(GTK_TREE_VIEW(mimeview->treeview));
343 1 hiro
344 1 hiro
        g_signal_handlers_unblock_by_func
345 275 hiro
                (G_OBJECT(mimeview->selection),
346 275 hiro
                 G_CALLBACK(mimeview_selection_changed), mimeview);
347 1 hiro
348 1 hiro
        /* search first text part */
349 275 hiro
        for (valid = gtk_tree_model_get_iter_first(model, &iter); valid;
350 275 hiro
             valid = gtkut_tree_model_next(model, &iter)) {
351 1 hiro
                MimeInfo *partinfo;
352 1 hiro
353 275 hiro
                gtk_tree_model_get(model, &iter, COL_MIME_INFO, &partinfo, -1);
354 1 hiro
                if (partinfo &&
355 1 hiro
                    (partinfo->mime_type == MIME_TEXT ||
356 1 hiro
                     partinfo->mime_type == MIME_TEXT_HTML))
357 1 hiro
                        break;
358 1 hiro
        }
359 1 hiro
        textview_show_message(mimeview->messageview->textview, mimeinfo, file);
360 1 hiro
361 275 hiro
        if (!valid)
362 275 hiro
                valid = gtk_tree_model_get_iter_first(model, &iter);
363 1 hiro
364 275 hiro
        if (valid) {
365 275 hiro
                GtkTreePath *path;
366 275 hiro
367 275 hiro
                path = gtk_tree_model_get_path(model, &iter);
368 275 hiro
                gtk_tree_view_set_cursor(GTK_TREE_VIEW(mimeview->treeview),
369 275 hiro
                                         path, NULL, FALSE);
370 275 hiro
                gtk_tree_path_free(path);
371 154 hiro
                if (mimeview_get_selected_part(mimeview))
372 275 hiro
                        gtk_widget_grab_focus(mimeview->treeview);
373 1 hiro
        }
374 1 hiro
}
375 1 hiro
376 1 hiro
void mimeview_clear(MimeView *mimeview)
377 1 hiro
{
378 1 hiro
        procmime_mimeinfo_free_all(mimeview->mimeinfo);
379 1 hiro
        mimeview->mimeinfo = NULL;
380 1 hiro
381 275 hiro
        gtk_tree_store_clear(mimeview->store);
382 1 hiro
        textview_clear(mimeview->textview);
383 1 hiro
        imageview_clear(mimeview->imageview);
384 1 hiro
385 275 hiro
        gtk_tree_path_free(mimeview->opened);
386 1 hiro
        mimeview->opened = NULL;
387 1 hiro
388 1 hiro
        g_free(mimeview->file);
389 1 hiro
        mimeview->file = NULL;
390 291 hiro
391 291 hiro
        g_free(mimeview->drag_file);
392 291 hiro
        mimeview->drag_file = NULL;
393 1 hiro
}
394 1 hiro
395 1 hiro
void mimeview_destroy(MimeView *mimeview)
396 1 hiro
{
397 1 hiro
        textview_destroy(mimeview->textview);
398 1 hiro
        imageview_destroy(mimeview->imageview);
399 1 hiro
        procmime_mimeinfo_free_all(mimeview->mimeinfo);
400 1 hiro
        g_free(mimeview->file);
401 275 hiro
        g_free(mimeview->drag_file);
402 1 hiro
        g_free(mimeview);
403 1 hiro
}
404 1 hiro
405 1 hiro
MimeInfo *mimeview_get_selected_part(MimeView *mimeview)
406 1 hiro
{
407 275 hiro
        GtkTreeModel *model = GTK_TREE_MODEL(mimeview->store);
408 275 hiro
        GtkTreeIter iter;
409 275 hiro
        MimeInfo *partinfo = NULL;
410 275 hiro
411 275 hiro
        if (!mimeview->opened)
412 275 hiro
                return NULL;
413 1 hiro
        if (gtk_notebook_get_current_page
414 154 hiro
                (GTK_NOTEBOOK(mimeview->messageview->notebook)) == 0)
415 1 hiro
                return NULL;
416 1 hiro
417 275 hiro
        if (gtk_tree_model_get_iter(model, &iter, mimeview->opened))
418 275 hiro
                gtk_tree_model_get(model, &iter, COL_MIME_INFO, &partinfo, -1);
419 275 hiro
420 275 hiro
        return partinfo;
421 1 hiro
}
422 1 hiro
423 135 hiro
gboolean mimeview_step(MimeView *mimeview, GtkScrollType type)
424 135 hiro
{
425 275 hiro
        GtkTreeView *treeview = GTK_TREE_VIEW(mimeview->treeview);
426 275 hiro
        GtkTreeModel *model = GTK_TREE_MODEL(mimeview->store);
427 275 hiro
        GtkTreeIter iter;
428 275 hiro
        gboolean moved;
429 135 hiro
430 275 hiro
        if (!mimeview->opened)
431 275 hiro
                return FALSE;
432 275 hiro
        if (!gtk_tree_model_get_iter(model, &iter, mimeview->opened))
433 275 hiro
                return FALSE;
434 275 hiro
435 135 hiro
        if (type == GTK_SCROLL_STEP_FORWARD) {
436 275 hiro
                if (gtkut_tree_model_next(model, &iter))
437 275 hiro
                        gtkut_tree_view_expand_parent_all(treeview, &iter);
438 135 hiro
                else
439 135 hiro
                        return FALSE;
440 135 hiro
        } else {
441 275 hiro
                if (!gtkut_tree_model_prev(model, &iter))
442 135 hiro
                        return FALSE;
443 135 hiro
        }
444 135 hiro
445 275 hiro
        g_signal_emit_by_name(G_OBJECT(treeview), "move-cursor",
446 275 hiro
                              GTK_MOVEMENT_DISPLAY_LINES,
447 275 hiro
                              type == GTK_SCROLL_STEP_FORWARD ? 1 : -1, &moved);
448 135 hiro
449 135 hiro
        return TRUE;
450 135 hiro
}
451 135 hiro
452 1 hiro
static void mimeview_set_multipart_tree(MimeView *mimeview,
453 1 hiro
                                        MimeInfo *mimeinfo,
454 275 hiro
                                        GtkTreeIter *parent)
455 1 hiro
{
456 275 hiro
        GtkTreeIter iter;
457 1 hiro
458 1 hiro
        g_return_if_fail(mimeinfo != NULL);
459 1 hiro
460 1 hiro
        if (mimeinfo->children)
461 1 hiro
                mimeinfo = mimeinfo->children;
462 1 hiro
463 1 hiro
        while (mimeinfo != NULL) {
464 275 hiro
                mimeview_append_part(mimeview, mimeinfo, &iter, parent);
465 1 hiro
466 1 hiro
                if (mimeinfo->children)
467 275 hiro
                        mimeview_set_multipart_tree(mimeview, mimeinfo, &iter);
468 1 hiro
                else if (mimeinfo->sub &&
469 1 hiro
                         mimeinfo->sub->mime_type != MIME_TEXT &&
470 1 hiro
                         mimeinfo->sub->mime_type != MIME_TEXT_HTML)
471 1 hiro
                        mimeview_set_multipart_tree(mimeview, mimeinfo->sub,
472 275 hiro
                                                    &iter);
473 1 hiro
                mimeinfo = mimeinfo->next;
474 1 hiro
        }
475 1 hiro
}
476 1 hiro
477 1 hiro
static gchar *get_part_name(MimeInfo *partinfo)
478 1 hiro
{
479 1 hiro
#if USE_GPGME
480 1 hiro
        if (partinfo->sigstatus)
481 1 hiro
                return partinfo->sigstatus;
482 1 hiro
        else
483 1 hiro
#endif
484 1 hiro
        if (partinfo->name)
485 1 hiro
                return partinfo->name;
486 1 hiro
        else if (partinfo->filename)
487 1 hiro
                return partinfo->filename;
488 1 hiro
        else
489 1 hiro
                return "";
490 1 hiro
}
491 1 hiro
492 275 hiro
static gboolean mimeview_append_part(MimeView *mimeview, MimeInfo *partinfo,
493 275 hiro
                                     GtkTreeIter *iter, GtkTreeIter *parent)
494 1 hiro
{
495 275 hiro
        gchar *mime_type;
496 275 hiro
        gchar *size;
497 275 hiro
        gchar *name;
498 1 hiro
499 275 hiro
        mime_type = partinfo->content_type ? partinfo->content_type : "";
500 275 hiro
        size = to_human_readable(partinfo->size);
501 275 hiro
        name = get_part_name(partinfo);
502 1 hiro
503 275 hiro
        gtk_tree_store_append(mimeview->store, iter, parent);
504 275 hiro
        gtk_tree_store_set(mimeview->store, iter,
505 275 hiro
                           COL_MIMETYPE, mime_type,
506 275 hiro
                           COL_SIZE, size,
507 275 hiro
                           COL_NAME, name,
508 275 hiro
                           COL_MIME_INFO, partinfo,
509 275 hiro
                           -1);
510 1 hiro
511 275 hiro
        return TRUE;
512 1 hiro
}
513 1 hiro
514 1 hiro
static void mimeview_show_message_part(MimeView *mimeview, MimeInfo *partinfo)
515 1 hiro
{
516 1 hiro
        FILE *fp;
517 1 hiro
        const gchar *fname;
518 1 hiro
#if USE_GPGME
519 1 hiro
        MimeInfo *pi;
520 1 hiro
#endif
521 1 hiro
522 1 hiro
        if (!partinfo) return;
523 1 hiro
524 1 hiro
#if USE_GPGME
525 1 hiro
        for (pi = partinfo; pi && !pi->plaintextfile ; pi = pi->parent)
526 1 hiro
                ;
527 1 hiro
        fname = pi ? pi->plaintextfile : mimeview->file;
528 1 hiro
#else
529 1 hiro
        fname = mimeview->file;
530 1 hiro
#endif /* USE_GPGME */
531 1 hiro
        if (!fname) return;
532 1 hiro
533 1 hiro
        if ((fp = fopen(fname, "rb")) == NULL) {
534 1 hiro
                FILE_OP_ERROR(fname, "fopen");
535 1 hiro
                return;
536 1 hiro
        }
537 1 hiro
538 1 hiro
        if (fseek(fp, partinfo->fpos, SEEK_SET) < 0) {
539 1 hiro
                FILE_OP_ERROR(mimeview->file, "fseek");
540 1 hiro
                fclose(fp);
541 1 hiro
                return;
542 1 hiro
        }
543 1 hiro
544 1 hiro
        mimeview_change_view_type(mimeview, MIMEVIEW_TEXT);
545 1 hiro
        textview_show_part(mimeview->textview, partinfo, fp);
546 1 hiro
547 1 hiro
        fclose(fp);
548 1 hiro
}
549 1 hiro
550 1 hiro
static void mimeview_show_image_part(MimeView *mimeview, MimeInfo *partinfo)
551 1 hiro
{
552 1 hiro
        gchar *filename;
553 1 hiro
554 1 hiro
        if (!partinfo) return;
555 1 hiro
556 1 hiro
        filename = procmime_get_tmp_file_name(partinfo);
557 1 hiro
558 1 hiro
        if (procmime_get_part(filename, mimeview->file, partinfo) < 0)
559 1 hiro
                alertpanel_error
560 1 hiro
                        (_("Can't get the part of multipart message."));
561 1 hiro
        else {
562 1 hiro
                mimeview_change_view_type(mimeview, MIMEVIEW_IMAGE);
563 1 hiro
                imageview_show_image(mimeview->imageview, partinfo, filename,
564 1 hiro
                                     prefs_common.resize_image);
565 1 hiro
                unlink(filename);
566 1 hiro
        }
567 1 hiro
568 1 hiro
        g_free(filename);
569 1 hiro
}
570 1 hiro
571 135 hiro
static void save_as_button_clicked(GtkWidget *widget, gpointer data)
572 135 hiro
{
573 135 hiro
        MimeView *mimeview = (MimeView *)data;
574 135 hiro
575 135 hiro
        mimeview_save_as(mimeview);
576 135 hiro
}
577 135 hiro
578 135 hiro
static void display_as_text_button_clicked(GtkWidget *widget, gpointer data)
579 135 hiro
{
580 135 hiro
        MimeView *mimeview = (MimeView *)data;
581 135 hiro
582 135 hiro
        mimeview_display_as_text(mimeview);
583 135 hiro
}
584 135 hiro
585 135 hiro
static void open_button_clicked(GtkWidget *widget, gpointer data)
586 135 hiro
{
587 135 hiro
        MimeView *mimeview = (MimeView *)data;
588 135 hiro
589 135 hiro
        mimeview_launch(mimeview);
590 135 hiro
}
591 135 hiro
592 135 hiro
static void open_with_button_clicked(GtkWidget *widget, gpointer data)
593 135 hiro
{
594 135 hiro
        MimeView *mimeview = (MimeView *)data;
595 135 hiro
596 135 hiro
        mimeview_open_with(mimeview);
597 135 hiro
}
598 135 hiro
599 135 hiro
static void mimeview_show_mime_part(MimeView *mimeview, MimeInfo *partinfo)
600 135 hiro
{
601 135 hiro
        TextView *textview = mimeview->textview;
602 135 hiro
        GtkTextBuffer *buffer;
603 135 hiro
        GtkTextIter iter;
604 135 hiro
        GtkTextChildAnchor *anchor;
605 135 hiro
        GtkWidget *vbbox;
606 135 hiro
        GtkWidget *button;
607 135 hiro
        gchar buf[BUFFSIZE];
608 135 hiro
609 135 hiro
        if (!partinfo) return;
610 135 hiro
611 135 hiro
        textview_set_font(textview, NULL);
612 135 hiro
        textview_clear(textview);
613 135 hiro
614 135 hiro
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview->text));
615 135 hiro
        gtk_text_buffer_get_start_iter(buffer, &iter);
616 135 hiro
617 135 hiro
        gtk_text_buffer_insert(buffer, &iter,
618 135 hiro
                               _("Select an action for the attached file:\n"),
619 135 hiro
                               -1);
620 135 hiro
        if (partinfo->filename || partinfo->name)
621 135 hiro
                g_snprintf(buf, sizeof(buf), "[%s  %s (%d bytes)]\n\n",
622 135 hiro
                           partinfo->filename ? partinfo->filename :
623 135 hiro
                           partinfo->name,
624 135 hiro
                           partinfo->content_type, partinfo->size);
625 135 hiro
        else
626 135 hiro
                g_snprintf(buf, sizeof(buf), "[%s (%d bytes)]\n\n",
627 135 hiro
                           partinfo->content_type, partinfo->size);
628 135 hiro
        gtk_text_buffer_insert(buffer, &iter, buf, -1);
629 135 hiro
630 135 hiro
        vbbox = gtk_vbutton_box_new();
631 135 hiro
        gtk_box_set_spacing(GTK_BOX(vbbox), 5);
632 135 hiro
633 135 hiro
        button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
634 135 hiro
        gtk_container_add(GTK_CONTAINER(vbbox), button);
635 135 hiro
        g_signal_connect(button, "clicked", G_CALLBACK(open_button_clicked),
636 135 hiro
                         mimeview);
637 135 hiro
        button = gtk_button_new_with_mnemonic(_("Open _with..."));
638 135 hiro
        gtk_container_add(GTK_CONTAINER(vbbox), button);
639 135 hiro
        g_signal_connect(button, "clicked",
640 135 hiro
                         G_CALLBACK(open_with_button_clicked), mimeview);
641 135 hiro
        button = gtk_button_new_with_mnemonic(_("_Display as text"));
642 135 hiro
        gtk_container_add(GTK_CONTAINER(vbbox), button);
643 135 hiro
        g_signal_connect(button, "clicked",
644 135 hiro
                         G_CALLBACK(display_as_text_button_clicked), mimeview);
645 135 hiro
        button = gtk_button_new_with_mnemonic(_("_Save as..."));
646 135 hiro
        gtk_container_add(GTK_CONTAINER(vbbox), button);
647 135 hiro
        g_signal_connect(button, "clicked", G_CALLBACK(save_as_button_clicked),
648 135 hiro
                         mimeview);
649 135 hiro
650 135 hiro
        gtk_widget_show_all(vbbox);
651 135 hiro
652 135 hiro
        anchor = gtk_text_buffer_create_child_anchor(buffer, &iter);
653 135 hiro
        gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(textview->text),
654 135 hiro
                                          vbbox, anchor);
655 135 hiro
}
656 135 hiro
657 135 hiro
#if USE_GPGME
658 135 hiro
static void check_signature_button_clicked(GtkWidget *widget, gpointer data)
659 135 hiro
{
660 135 hiro
        MimeView *mimeview = (MimeView *)data;
661 135 hiro
662 135 hiro
        mimeview_check_signature(mimeview);
663 135 hiro
}
664 135 hiro
665 135 hiro
static void mimeview_show_signature_part(MimeView *mimeview,
666 135 hiro
                                         MimeInfo *partinfo)
667 135 hiro
{
668 135 hiro
        TextView *textview = mimeview->textview;
669 135 hiro
        GtkTextBuffer *buffer;
670 135 hiro
        GtkTextIter iter;
671 135 hiro
        GtkTextChildAnchor *anchor;
672 135 hiro
        GtkWidget *vbbox;
673 135 hiro
        GtkWidget *button;
674 135 hiro
675 135 hiro
        if (!partinfo) return;
676 135 hiro
677 135 hiro
        textview_set_font(textview, NULL);
678 135 hiro
        textview_clear(textview);
679 135 hiro
680 135 hiro
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview->text));
681 135 hiro
        gtk_text_buffer_get_start_iter(buffer, &iter);
682 135 hiro
683 135 hiro
        if (partinfo->sigstatus_full) {
684 135 hiro
                gtk_text_buffer_insert
685 135 hiro
                        (buffer, &iter, partinfo->sigstatus_full, -1);
686 135 hiro
                return;
687 135 hiro
        }
688 135 hiro
689 135 hiro
        gtk_text_buffer_insert
690 135 hiro
                (buffer, &iter,
691 135 hiro
                 _("This signature has not been checked yet.\n\n"), -1);
692 135 hiro
693 135 hiro
        vbbox = gtk_vbutton_box_new();
694 135 hiro
        gtk_box_set_spacing(GTK_BOX(vbbox), 5);
695 135 hiro
696 135 hiro
        button = gtk_button_new_with_mnemonic(_("_Check signature"));
697 135 hiro
        gtk_container_add(GTK_CONTAINER(vbbox), button);
698 135 hiro
        g_signal_connect(button, "clicked",
699 135 hiro
                         G_CALLBACK(check_signature_button_clicked), mimeview);
700 135 hiro
701 135 hiro
        gtk_widget_show_all(vbbox);
702 135 hiro
703 135 hiro
        anchor = gtk_text_buffer_create_child_anchor(buffer, &iter);
704 135 hiro
        gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(textview->text),
705 135 hiro
                                          vbbox, anchor);
706 135 hiro
}
707 135 hiro
#endif /* USE_GPGME */
708 135 hiro
709 1 hiro
static void mimeview_change_view_type(MimeView *mimeview, MimeViewType type)
710 1 hiro
{
711 1 hiro
        TextView  *textview  = mimeview->textview;
712 1 hiro
        ImageView *imageview = mimeview->imageview;
713 1 hiro
        GList *children;
714 1 hiro
715 1 hiro
        if (mimeview->type == type) return;
716 1 hiro
717 1 hiro
        children = gtk_container_get_children
718 1 hiro
                (GTK_CONTAINER(mimeview->mime_vbox));
719 1 hiro
        if (children) {
720 1 hiro
                gtkut_container_remove(GTK_CONTAINER(mimeview->mime_vbox),
721 1 hiro
                                       GTK_WIDGET(children->data));
722 1 hiro
                g_list_free(children);
723 1 hiro
        }
724 1 hiro
725 1 hiro
        switch (type) {
726 1 hiro
        case MIMEVIEW_IMAGE:
727 1 hiro
                gtk_container_add(GTK_CONTAINER(mimeview->mime_vbox),
728 1 hiro
                                  GTK_WIDGET_PTR(imageview));
729 1 hiro
                break;
730 1 hiro
        case MIMEVIEW_TEXT:
731 1 hiro
                gtk_container_add(GTK_CONTAINER(mimeview->mime_vbox),
732 1 hiro
                                  GTK_WIDGET_PTR(textview));
733 1 hiro
                break;
734 1 hiro
        default:
735 1 hiro
                return;
736 1 hiro
        }
737 1 hiro
738 1 hiro
        mimeview->type = type;
739 1 hiro
}
740 1 hiro
741 275 hiro
static void mimeview_selection_changed(GtkTreeSelection *selection,
742 275 hiro
                                       MimeView *mimeview)
743 1 hiro
{
744 275 hiro
        GtkTreeModel *model = GTK_TREE_MODEL(mimeview->store);
745 275 hiro
        GtkTreeIter iter;
746 275 hiro
        GtkTreePath *path;
747 1 hiro
        MimeInfo *partinfo;
748 1 hiro
749 275 hiro
        if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
750 275 hiro
                if (mimeview->opened) {
751 275 hiro
                        gtk_tree_path_free(mimeview->opened);
752 275 hiro
                        mimeview->opened = NULL;
753 275 hiro
                }
754 275 hiro
                return;
755 275 hiro
        }
756 1 hiro
757 275 hiro
        path = gtk_tree_model_get_path(model, &iter);
758 1 hiro
759 275 hiro
        if (mimeview->opened &&
760 275 hiro
            gtk_tree_path_compare(mimeview->opened, path) == 0) {
761 275 hiro
                gtk_tree_path_free(path);
762 275 hiro
                return;
763 1 hiro
        }
764 1 hiro
765 275 hiro
        gtk_tree_path_free(mimeview->opened);
766 275 hiro
        mimeview->opened = path;
767 275 hiro
        path = NULL;
768 275 hiro
769 275 hiro
        gtk_tree_model_get(model, &iter, COL_MIME_INFO, &partinfo, -1);
770 275 hiro
        if (!partinfo)
771 275 hiro
                return;
772 275 hiro
773 1 hiro
        switch (partinfo->mime_type) {
774 1 hiro
        case MIME_TEXT:
775 1 hiro
        case MIME_TEXT_HTML:
776 1 hiro
        case MIME_MESSAGE_RFC822:
777 1 hiro
        case MIME_MULTIPART:
778 1 hiro
                mimeview_show_message_part(mimeview, partinfo);
779 1 hiro
                break;
780 1 hiro
        case MIME_IMAGE:
781 1 hiro
                mimeview_show_image_part(mimeview, partinfo);
782 1 hiro
                break;
783 1 hiro
        default:
784 1 hiro
                mimeview_change_view_type(mimeview, MIMEVIEW_TEXT);
785 1 hiro
#if USE_GPGME
786 333 hiro
                if (g_ascii_strcasecmp(partinfo->content_type,
787 333 hiro
                                       "application/pgp-signature") == 0)
788 135 hiro
                        mimeview_show_signature_part(mimeview, partinfo);
789 1 hiro
                else
790 1 hiro
#endif
791 135 hiro
                        mimeview_show_mime_part(mimeview, partinfo);
792 1 hiro
                break;
793 1 hiro
        }
794 1 hiro
}
795 1 hiro
796 1 hiro
static gint mimeview_button_pressed(GtkWidget *widget, GdkEventButton *event,
797 1 hiro
                                    MimeView *mimeview)
798 1 hiro
{
799 275 hiro
        GtkTreeView *treeview = GTK_TREE_VIEW(widget);
800 1 hiro
        MimeInfo *partinfo;
801 1 hiro
802 1 hiro
        if (!event) return FALSE;
803 1 hiro
804 1 hiro
        if (event->button == 2 || event->button == 3) {
805 275 hiro
                GtkTreePath *path;
806 275 hiro
807 275 hiro
                if (!gtk_tree_view_get_path_at_pos(treeview, event->x, event->y,
808 275 hiro
                                                   &path, NULL, NULL, NULL))
809 1 hiro
                        return FALSE;
810 275 hiro
                gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
811 275 hiro
                gtk_tree_path_free(path);
812 1 hiro
        }
813 1 hiro
814 1 hiro
        if (event->button == 2 ||
815 1 hiro
            (event->button == 1 && event->type == GDK_2BUTTON_PRESS)) {
816 1 hiro
                /* call external program for image, audio or html */
817 1 hiro
                mimeview_launch(mimeview);
818 1 hiro
        } else if (event->button == 3) {
819 1 hiro
                partinfo = mimeview_get_selected_part(mimeview);
820 1 hiro
                if (partinfo && (partinfo->mime_type == MIME_TEXT ||
821 1 hiro
                                 partinfo->mime_type == MIME_TEXT_HTML ||
822 1 hiro
                                 partinfo->mime_type == MIME_MESSAGE_RFC822 ||
823 1 hiro
                                 partinfo->mime_type == MIME_IMAGE ||
824 1 hiro
                                 partinfo->mime_type == MIME_MULTIPART))
825 1 hiro
                        menu_set_sensitive(mimeview->popupfactory,
826 1 hiro
                                           "/Display as text", FALSE);
827 1 hiro
                else
828 1 hiro
                        menu_set_sensitive(mimeview->popupfactory,
829 1 hiro
                                           "/Display as text", TRUE);
830 1 hiro
                if (partinfo &&
831 1 hiro
                    partinfo->mime_type == MIME_APPLICATION_OCTET_STREAM)
832 1 hiro
                        menu_set_sensitive(mimeview->popupfactory,
833 1 hiro
                                           "/Open", FALSE);
834 1 hiro
                else
835 1 hiro
                        menu_set_sensitive(mimeview->popupfactory,
836 1 hiro
                                           "/Open", TRUE);
837 1 hiro
#if USE_GPGME
838 1 hiro
                menu_set_sensitive(mimeview->popupfactory,
839 1 hiro
                                   "/Check signature",
840 1 hiro
                                   mimeview_is_signed(mimeview));
841 1 hiro
#endif
842 1 hiro
843 1 hiro
                gtk_menu_popup(GTK_MENU(mimeview->popupmenu),
844 1 hiro
                               NULL, NULL, NULL, NULL,
845 1 hiro
                               event->button, event->time);
846 135 hiro
                return TRUE;
847 1 hiro
        }
848 1 hiro
849 1 hiro
        return FALSE;
850 1 hiro
}
851 1 hiro
852 1 hiro
void mimeview_pass_key_press_event(MimeView *mimeview, GdkEventKey *event)
853 1 hiro
{
854 275 hiro
        mimeview_key_pressed(mimeview->treeview, event, mimeview);
855 1 hiro
}
856 1 hiro
857 1 hiro
#define BREAK_ON_MODIFIER_KEY() \
858 1 hiro
        if ((event->state & (GDK_MOD1_MASK|GDK_CONTROL_MASK)) != 0) break
859 1 hiro
860 1 hiro
#define KEY_PRESS_EVENT_STOP() \
861 275 hiro
        g_signal_stop_emission_by_name(G_OBJECT(treeview), "key_press_event");
862 1 hiro
863 1 hiro
static gint mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event,
864 1 hiro
                                 MimeView *mimeview)
865 1 hiro
{
866 135 hiro
        SummaryView *summaryview = NULL;
867 275 hiro
        GtkTreeView *treeview = GTK_TREE_VIEW(widget);
868 275 hiro
        GtkTreeModel *model = GTK_TREE_MODEL(mimeview->store);
869 275 hiro
        GtkTreeIter iter;
870 135 hiro
        gboolean mod_pressed;
871 1 hiro
872 1 hiro
        if (!event) return FALSE;
873 1 hiro
        if (!mimeview->opened) return FALSE;
874 275 hiro
        if (!gtk_tree_model_get_iter(model, &iter, mimeview->opened))
875 275 hiro
                return FALSE;
876 1 hiro
877 135 hiro
        if (mimeview->messageview->mainwin)
878 135 hiro
                summaryview = mimeview->messageview->mainwin->summaryview;
879 135 hiro
        mod_pressed =
880 135 hiro
                ((event->state & (GDK_SHIFT_MASK|GDK_MOD1_MASK)) != 0);
881 135 hiro
882 1 hiro
        switch (event->keyval) {
883 1 hiro
        case GDK_space:
884 135 hiro
                if (textview_scroll_page(mimeview->textview, mod_pressed))
885 1 hiro
                        return TRUE;
886 1 hiro
887 275 hiro
                if (gtkut_tree_model_next(model, &iter)) {
888 275 hiro
                        GtkTreePath *path;
889 275 hiro
890 275 hiro
                        path = gtk_tree_model_get_path(model, &iter);
891 275 hiro
                        gtk_tree_view_set_cursor(treeview, path, NULL, FALSE);
892 275 hiro
                        gtk_tree_path_free(path);
893 1 hiro
                        return TRUE;
894 1 hiro
                }
895 135 hiro
                if (summaryview)
896 135 hiro
                        summary_pass_key_press_event(summaryview, event);
897 1 hiro
                break;
898 1 hiro
        case GDK_BackSpace:
899 1 hiro
                textview_scroll_page(mimeview->textview, TRUE);
900 1 hiro
                return TRUE;
901 1 hiro
        case GDK_Return:
902 135 hiro
                textview_scroll_one_line(mimeview->textview, mod_pressed);
903 1 hiro
                return TRUE;
904 1 hiro
        case GDK_t:
905 1 hiro
                BREAK_ON_MODIFIER_KEY();
906 1 hiro
                KEY_PRESS_EVENT_STOP();
907 1 hiro
                mimeview_display_as_text(mimeview);
908 1 hiro
                return TRUE;
909 165 hiro
        case GDK_Escape:
910 165 hiro
                if (summaryview)
911 237 hiro
                        gtk_widget_grab_focus(summaryview->treeview);
912 165 hiro
                break;
913 135 hiro
        case GDK_Left:
914 135 hiro
        case GDK_Delete:
915 135 hiro
                if (summaryview)
916 135 hiro
                        summary_pass_key_press_event(summaryview, event);
917 135 hiro
                break;
918 1 hiro
        default:
919 1 hiro
                break;
920 1 hiro
        }
921 1 hiro
922 135 hiro
        return FALSE;
923 1 hiro
}
924 1 hiro
925 275 hiro
static void mimeview_drag_begin(GtkWidget *widget, GdkDragContext *drag_context,
926 275 hiro
                                MimeView *mimeview)
927 1 hiro
{
928 275 hiro
        gchar *filename;
929 275 hiro
        gchar *bname = NULL;
930 1 hiro
        MimeInfo *partinfo;
931 1 hiro
932 1 hiro
        if (!mimeview->opened) return;
933 1 hiro
        if (!mimeview->file) return;
934 1 hiro
935 1 hiro
        partinfo = mimeview_get_selected_part(mimeview);
936 1 hiro
        if (!partinfo) return;
937 1 hiro
938 1 hiro
        filename = partinfo->filename ? partinfo->filename : partinfo->name;
939 275 hiro
        if (filename) {
940 275 hiro
                const gchar *bname_;
941 1 hiro
942 275 hiro
                bname_ = g_basename(filename);
943 275 hiro
                bname = conv_filename_from_utf8(bname_);
944 275 hiro
                subst_for_filename(bname);
945 275 hiro
        }
946 275 hiro
        if (!bname || *bname == '\0')
947 275 hiro
                filename = procmime_get_tmp_file_name(partinfo);
948 275 hiro
        else
949 275 hiro
                filename = g_strconcat(get_mime_tmp_dir(), G_DIR_SEPARATOR_S,
950 275 hiro
                                       bname, NULL);
951 1 hiro
952 275 hiro
        if (procmime_get_part(filename, mimeview->file, partinfo) < 0) {
953 275 hiro
                g_warning(_("Can't save the part of multipart message."));
954 275 hiro
        } else
955 291 hiro
                mimeview->drag_file = encode_uri(filename);
956 1 hiro
957 291 hiro
        g_free(filename);
958 291 hiro
959 275 hiro
        gtk_drag_set_icon_default(drag_context);
960 275 hiro
}
961 275 hiro
962 275 hiro
static void mimeview_drag_end(GtkWidget *widget, GdkDragContext *drag_context,
963 275 hiro
                              MimeView *mimeview)
964 275 hiro
{
965 275 hiro
        if (mimeview->drag_file) {
966 275 hiro
                g_free(mimeview->drag_file);
967 275 hiro
                mimeview->drag_file = NULL;
968 275 hiro
        }
969 275 hiro
}
970 275 hiro
971 275 hiro
static void mimeview_drag_data_get(GtkWidget            *widget,
972 275 hiro
                                   GdkDragContext   *drag_context,
973 275 hiro
                                   GtkSelectionData *selection_data,
974 275 hiro
                                   guint             info,
975 275 hiro
                                   guint             time,
976 275 hiro
                                   MimeView            *mimeview)
977 275 hiro
{
978 275 hiro
        if (!mimeview->drag_file) return;
979 275 hiro
980 1 hiro
        gtk_selection_data_set(selection_data, selection_data->target, 8,
981 291 hiro
                               mimeview->drag_file,
982 291 hiro
                               strlen(mimeview->drag_file));
983 1 hiro
}
984 1 hiro
985 1 hiro
static void mimeview_display_as_text(MimeView *mimeview)
986 1 hiro
{
987 1 hiro
        MimeInfo *partinfo;
988 1 hiro
989 1 hiro
        if (!mimeview->opened) return;
990 1 hiro
991 1 hiro
        partinfo = mimeview_get_selected_part(mimeview);
992 1 hiro
        g_return_if_fail(partinfo != NULL);
993 1 hiro
        mimeview_show_message_part(mimeview, partinfo);
994 1 hiro
}
995 1 hiro
996 152 hiro
void mimeview_save_as(MimeView *mimeview)
997 1 hiro
{
998 1 hiro
        gchar *filename;
999 1 hiro
        gchar *defname = NULL;
1000 1 hiro
        MimeInfo *partinfo;
1001 1 hiro
1002 1 hiro
        if (!mimeview->opened) return;
1003 1 hiro
        if (!mimeview->file) return;
1004 1 hiro
1005 1 hiro
        partinfo = mimeview_get_selected_part(mimeview);
1006 1 hiro
        g_return_if_fail(partinfo != NULL);
1007 1 hiro
1008 1 hiro
        if (partinfo->filename)
1009 1 hiro
                defname = partinfo->filename;
1010 1 hiro
        else if (partinfo->name) {
1011 1 hiro
                Xstrdup_a(defname, partinfo->name, return);
1012 1 hiro
                subst_for_filename(defname);
1013 1 hiro
        }
1014 1 hiro
1015 128 hiro
        filename = filesel_save_as(defname);
1016 1 hiro
        if (!filename) return;
1017 1 hiro
1018 1 hiro
        if (procmime_get_part(filename, mimeview->file, partinfo) < 0)
1019 1 hiro
                alertpanel_error
1020 1 hiro
                        (_("Can't save the part of multipart message."));
1021 128 hiro
1022 128 hiro
        g_free(filename);
1023 1 hiro
}
1024 1 hiro
1025 1 hiro
static void mimeview_launch(MimeView *mimeview)
1026 1 hiro
{
1027 1 hiro
        MimeInfo *partinfo;
1028 1 hiro
        gchar *filename;
1029 1 hiro
1030 1 hiro
        if (!mimeview->opened) return;
1031 1 hiro
        if (!mimeview->file) return;
1032 1 hiro
1033 1 hiro
        partinfo = mimeview_get_selected_part(mimeview);
1034 1 hiro
        g_return_if_fail(partinfo != NULL);
1035 1 hiro
1036 1 hiro
        filename = procmime_get_tmp_file_name(partinfo);
1037 1 hiro
1038 1 hiro
        if (procmime_get_part(filename, mimeview->file, partinfo) < 0)
1039 1 hiro
                alertpanel_error
1040 1 hiro
                        (_("Can't save the part of multipart message."));
1041 1 hiro
        else
1042 1 hiro
                mimeview_view_file(filename, partinfo, NULL);
1043 1 hiro
1044 1 hiro
        g_free(filename);
1045 1 hiro
}
1046 1 hiro
1047 1 hiro
static void mimeview_open_with(MimeView *mimeview)
1048 1 hiro
{
1049 1 hiro
        MimeInfo *partinfo;
1050 1 hiro
        gchar *filename;
1051 1 hiro
        gchar *cmd;
1052 1 hiro
1053 1 hiro
        if (!mimeview->opened) return;
1054 1 hiro
        if (!mimeview->file) return;
1055 1 hiro
1056 1 hiro
        partinfo = mimeview_get_selected_part(mimeview);
1057 1 hiro
        g_return_if_fail(partinfo != NULL);
1058 1 hiro
1059 1 hiro
        filename = procmime_get_tmp_file_name(partinfo);
1060 1 hiro
1061 1 hiro
        if (procmime_get_part(filename, mimeview->file, partinfo) < 0) {
1062 1 hiro
                alertpanel_error
1063 1 hiro
                        (_("Can't save the part of multipart message."));
1064 1 hiro
                g_free(filename);
1065 1 hiro
                return;
1066 1 hiro
        }
1067 1 hiro
1068 1 hiro
        if (!prefs_common.mime_open_cmd_history)
1069 1 hiro
                prefs_common.mime_open_cmd_history =
1070 1 hiro
                        add_history(NULL, prefs_common.mime_open_cmd);
1071 1 hiro
1072 1 hiro
        cmd = input_dialog_combo
1073 1 hiro
                (_("Open with"),
1074 1 hiro
                 _("Enter the command line to open file:\n"
1075 1 hiro
                   "(`%s' will be replaced with file name)"),
1076 1 hiro
                 prefs_common.mime_open_cmd,
1077 1 hiro
                 prefs_common.mime_open_cmd_history,
1078 1 hiro
                 TRUE);
1079 1 hiro
        if (cmd) {
1080 1 hiro
                mimeview_view_file(filename, partinfo, cmd);
1081 1 hiro
                g_free(prefs_common.mime_open_cmd);
1082 1 hiro
                prefs_common.mime_open_cmd = cmd;
1083 1 hiro
                prefs_common.mime_open_cmd_history =
1084 1 hiro
                        add_history(prefs_common.mime_open_cmd_history, cmd);
1085 1 hiro
        }
1086 1 hiro
1087 1 hiro
        g_free(filename);
1088 1 hiro
}
1089 1 hiro
1090 1 hiro
static void mimeview_view_file(const gchar *filename, MimeInfo *partinfo,
1091 1 hiro
                               const gchar *cmdline)
1092 1 hiro
{
1093 1 hiro
        static gchar *default_image_cmdline = "display '%s'";
1094 1 hiro
        static gchar *default_audio_cmdline = "play '%s'";
1095 1 hiro
        static gchar *default_html_cmdline = DEFAULT_BROWSER_CMD;
1096 1 hiro
        static gchar *mime_cmdline = "metamail -d -b -x -c %s '%s'";
1097 1 hiro
        gchar buf[1024];
1098 1 hiro
        gchar m_buf[1024];
1099 1 hiro
        const gchar *cmd;
1100 1 hiro
        const gchar *def_cmd;
1101 1 hiro
        const gchar *p;
1102 1 hiro
1103 1 hiro
        if (cmdline) {
1104 1 hiro
                cmd = cmdline;
1105 1 hiro
                def_cmd = NULL;
1106 1 hiro
        } else if (MIME_APPLICATION_OCTET_STREAM == partinfo->mime_type) {
1107 1 hiro
                return;
1108 1 hiro
        } else if (MIME_IMAGE == partinfo->mime_type) {
1109 1 hiro
                cmd = prefs_common.mime_image_viewer;
1110 1 hiro
                def_cmd = default_image_cmdline;
1111 1 hiro
        } else if (MIME_AUDIO == partinfo->mime_type) {
1112 1 hiro
                cmd = prefs_common.mime_audio_player;
1113 1 hiro
                def_cmd = default_audio_cmdline;
1114 1 hiro
        } else if (MIME_TEXT_HTML == partinfo->mime_type) {
1115 1 hiro
                cmd = prefs_common.uri_cmd;
1116 1 hiro
                def_cmd = default_html_cmdline;
1117 1 hiro
        } else {
1118 1 hiro
                g_snprintf(m_buf, sizeof(m_buf), mime_cmdline,
1119 1 hiro
                           partinfo->content_type, "%s");
1120 1 hiro
                cmd = m_buf;
1121 1 hiro
                def_cmd = NULL;
1122 1 hiro
        }
1123 1 hiro
1124 1 hiro
        if (cmd && (p = strchr(cmd, '%')) && *(p + 1) == 's' &&
1125 1 hiro
            !strchr(p + 2, '%'))
1126 1 hiro
                g_snprintf(buf, sizeof(buf), cmd, filename);
1127 1 hiro
        else {
1128 1 hiro
                if (cmd)
1129 1 hiro
                        g_warning(_("MIME viewer command line is invalid: `%s'"), cmd);
1130 1 hiro
                if (def_cmd)
1131 1 hiro
                        g_snprintf(buf, sizeof(buf), def_cmd, filename);
1132 1 hiro
                else
1133 1 hiro
                        return;
1134 1 hiro
        }
1135 1 hiro
1136 1 hiro
        execute_command_line(buf, TRUE);
1137 1 hiro
}
1138 1 hiro
1139 1 hiro
#if USE_GPGME
1140 275 hiro
static gboolean update_node_name_func(GtkTreeModel *model, GtkTreePath *path,
1141 275 hiro
                                      GtkTreeIter *iter, gpointer data)
1142 1 hiro
{
1143 1 hiro
        MimeInfo *partinfo;
1144 1 hiro
        gchar *part_name;
1145 1 hiro
1146 275 hiro
        gtk_tree_model_get(model, iter, COL_MIME_INFO, &partinfo, -1);
1147 275 hiro
        g_return_val_if_fail(partinfo != NULL, FALSE);
1148 1 hiro
1149 1 hiro
        part_name = get_part_name(partinfo);
1150 275 hiro
        gtk_tree_store_set(GTK_TREE_STORE(model), iter, COL_NAME, part_name,
1151 275 hiro
                           -1);
1152 275 hiro
1153 275 hiro
        return FALSE;
1154 1 hiro
}
1155 1 hiro
1156 1 hiro
static void mimeview_update_names(MimeView *mimeview)
1157 1 hiro
{
1158 275 hiro
        gtk_tree_model_foreach(GTK_TREE_MODEL(mimeview->store),
1159 275 hiro
                               update_node_name_func, NULL);
1160 1 hiro
}
1161 1 hiro
1162 1 hiro
static void mimeview_update_signature_info(MimeView *mimeview)
1163 1 hiro
{
1164 1 hiro
        MimeInfo *partinfo;
1165 1 hiro
1166 1 hiro
        if (!mimeview) return;
1167 1 hiro
        if (!mimeview->opened) return;
1168 1 hiro
1169 1 hiro
        partinfo = mimeview_get_selected_part(mimeview);
1170 1 hiro
        if (!partinfo) return;
1171 1 hiro
1172 333 hiro
        if (g_ascii_strcasecmp(partinfo->content_type,
1173 333 hiro
                               "application/pgp-signature") == 0) {
1174 1 hiro
                mimeview_change_view_type(mimeview, MIMEVIEW_TEXT);
1175 135 hiro
                mimeview_show_signature_part(mimeview, partinfo);
1176 1 hiro
        }
1177 1 hiro
}
1178 1 hiro
1179 1 hiro
static void mimeview_check_signature(MimeView *mimeview)
1180 1 hiro
{
1181 1 hiro
        MimeInfo *mimeinfo;
1182 1 hiro
        FILE *fp;
1183 1 hiro
1184 1 hiro
        g_return_if_fail (mimeview_is_signed(mimeview));
1185 1 hiro
1186 1 hiro
        mimeinfo = mimeview_get_selected_part(mimeview);
1187 1 hiro
        g_return_if_fail(mimeinfo != NULL);
1188 1 hiro
        g_return_if_fail(mimeview->file != NULL);
1189 1 hiro
1190 1 hiro
        while (mimeinfo->parent)
1191 1 hiro
                mimeinfo = mimeinfo->parent;
1192 1 hiro
1193 1 hiro
        if ((fp = fopen(mimeview->file, "rb")) == NULL) {
1194 1 hiro
                FILE_OP_ERROR(mimeview->file, "fopen");
1195 1 hiro
                return;
1196 1 hiro
        }
1197 1 hiro
1198 1 hiro
        rfc2015_check_signature(mimeinfo, fp);
1199 1 hiro
        fclose(fp);
1200 1 hiro
1201 1 hiro
        mimeview_update_names(mimeview);
1202 1 hiro
        mimeview_update_signature_info(mimeview);
1203 1 hiro
1204 1 hiro
        textview_show_message(mimeview->messageview->textview, mimeinfo,
1205 1 hiro
                              mimeview->file);
1206 1 hiro
}
1207 1 hiro
#endif /* USE_GPGME */