2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2016 Salvatore De Paolis & the Claws Mail Team
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 3 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, see <http://www.gnu.org/licenses/>.
21 #include "claws-features.h"
25 #include <glib/gi18n.h>
27 #include "poppler_viewer.h"
29 #include "prefs_common.h"
30 #include "gtk/gtkutils.h"
31 #include "gtk/inputdialog.h"
33 #include "summaryview.h"
34 #ifndef POPPLER_WITH_GDK
38 static FileType pdf_viewer_mimepart_get_type(MimeInfo *partinfo);
39 static MimeViewerFactory pdf_viewer_factory;
41 static void pdf_viewer_show_mimepart(MimeViewer *_viewer, const gchar *infile,
44 static MimeViewer *pdf_viewer_create(void);
45 static void pdf_viewer_clear(MimeViewer *_viewer);
46 static void pdf_viewer_destroy(MimeViewer *_viewer);
47 static void pdf_viewer_update(MimeViewer *_viewer, gboolean reload_file, int page_num);
49 static GtkWidget *pdf_viewer_get_widget(MimeViewer *_viewer);
51 static void pdf_viewer_hide_index_pane(PdfViewer *viewer);
52 static void pdf_viewer_set_index_button_sensitive(PdfViewer *viewer);
53 static void pdf_viewer_scroll_to(PdfViewer *viewer, gfloat x, gfloat y);
55 static void search_matches_free(PdfViewer *viewer);
56 static gboolean pdf_viewer_text_search(MimeViewer *_viewer, gboolean backward,
57 const gchar *str, gboolean case_sens);
58 static void pdf_viewer_render_selection(PdfViewer *viewer, PopplerRectangle *rect, PageResult *page_results);
59 static void pdf_viewer_render_page(PopplerPage *page, GtkWidget *view, double width, double height, double zoom, gint rotate);
61 static char * pdf_viewer_get_document_format_data(GTime utime);
62 static void pdf_viewer_get_document_index(PdfViewer *viewer, PopplerIndexIter *index_iter, GtkTreeIter *parentiter);
63 static void pdf_viewer_index_row_activated(GtkTreeView *tree_view,
65 GtkTreeViewColumn *column,
68 static GtkTable * pdf_viewer_fill_info_table(PdfViewer *viewer);
71 static void pdf_viewer_move_events_cb(GtkWidget *widget, GdkEventMotion *event, PdfViewer *viewer);
72 static void pdf_viewer_button_press_events_cb(GtkWidget *widget, GdkEventButton *event, PdfViewer *viewer);
73 static void pdf_viewer_mouse_scroll_destroy_cb(GtkWidget *widget, GdkEventButton *event, PdfViewer *viewer);
74 static void pdf_viewer_button_first_page_cb(GtkButton *button, PdfViewer *viewer);
75 static void pdf_viewer_button_last_page_cb(GtkButton *button, PdfViewer *viewer);
76 static void pdf_viewer_button_zoom_in_cb(GtkButton *button, PdfViewer *viewer);
77 static void pdf_viewer_button_zoom_out_cb(GtkButton *button, PdfViewer *viewer);
78 static void pdf_viewer_button_zoom_fit_cb(GtkButton *button, PdfViewer *viewer);
79 static void pdf_viewer_button_zoom_width_cb(GtkButton *button, PdfViewer *viewer);
80 static void pdf_viewer_button_rotate_right_cb(GtkButton *button, PdfViewer *viewer);
81 static void pdf_viewer_button_rotate_left_cb(GtkButton *button, PdfViewer *viewer);
82 static void pdf_viewer_spin_change_page_cb(GtkSpinButton *button, PdfViewer *viewer);
83 static void pdf_viewer_spin_zoom_scroll_cb(GtkSpinButton *button, PdfViewer *viewer);
84 /* Show/Hide the index pane */
85 static void pdf_viewer_show_document_index_cb(GtkButton *button, PdfViewer *viewer);
86 static void pdf_viewer_button_print_cb(GtkButton *button, PdfViewer *viewer);
87 static void pdf_viewer_button_document_info_cb(GtkButton *button, PdfViewer *viewer);
89 static void pdf_viewer_show_controls(PdfViewer *viewer, gboolean show);
90 static gboolean pdf_viewer_scroll_page(MimeViewer *_viewer, gboolean up);
91 static void pdf_viewer_scroll_one_line(MimeViewer *_viewer, gboolean up);
93 /** Claws-Mail Plugin functions*/
94 gint plugin_init(gchar **error);
95 const gchar *plugin_name(void);
96 const gchar *plugin_desc(void);
97 const gchar *plugin_type(void);
98 const gchar *plugin_licence(void);
99 const gchar *plugin_version(void);
100 struct PluginFeature *plugin_provides(void);
102 #ifndef POPPLER_WITH_GDK
104 copy_cairo_surface_to_pixbuf (cairo_surface_t *surface,
107 int cairo_width, cairo_height, cairo_rowstride;
108 unsigned char *pixbuf_data, *dst, *cairo_data;
109 int pixbuf_rowstride, pixbuf_n_channels;
113 cairo_width = cairo_image_surface_get_width (surface);
114 cairo_height = cairo_image_surface_get_height (surface);
115 cairo_rowstride = cairo_image_surface_get_stride (surface);
116 cairo_data = cairo_image_surface_get_data (surface);
118 pixbuf_data = gdk_pixbuf_get_pixels (pixbuf);
119 pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
120 pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
122 if (cairo_width > gdk_pixbuf_get_width (pixbuf))
123 cairo_width = gdk_pixbuf_get_width (pixbuf);
124 if (cairo_height > gdk_pixbuf_get_height (pixbuf))
125 cairo_height = gdk_pixbuf_get_height (pixbuf);
126 for (y = 0; y < cairo_height; y++) {
127 src = (unsigned int *) (cairo_data + y * cairo_rowstride);
128 dst = pixbuf_data + y * pixbuf_rowstride;
129 for (x = 0; x < cairo_width; x++) {
130 dst[0] = (*src >> 16) & 0xff;
131 dst[1] = (*src >> 8) & 0xff;
132 dst[2] = (*src >> 0) & 0xff;
133 if (pixbuf_n_channels == 4)
134 dst[3] = (*src >> 24) & 0xff;
135 dst += pixbuf_n_channels;
141 _poppler_page_render_to_pixbuf (PopplerPage *page,
142 int src_x, int src_y,
143 int src_width, int src_height,
150 cairo_surface_t *surface;
152 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
153 src_width, src_height);
154 cr = cairo_create (surface);
158 cairo_translate (cr, src_x + src_width, -src_y);
161 cairo_translate (cr, src_x + src_width, src_y + src_height);
164 cairo_translate (cr, -src_x, src_y + src_height);
167 cairo_translate (cr, -src_x, -src_y);
171 cairo_scale (cr, scale, scale);
174 cairo_rotate (cr, rotation * G_PI / 180.0);
177 poppler_page_render_for_printing (page, cr);
179 poppler_page_render (page, cr);
182 cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
183 cairo_set_source_rgb (cr, 1., 1., 1.);
188 copy_cairo_surface_to_pixbuf (surface, pixbuf);
189 cairo_surface_destroy (surface);
193 * poppler_page_render_to_pixbuf:
194 * @page: the page to render from
195 * @src_x: x coordinate of upper left corner
196 * @src_y: y coordinate of upper left corner
197 * @src_width: width of rectangle to render
198 * @src_height: height of rectangle to render
199 * @scale: scale specified as pixels per point
200 * @rotation: rotate the document by the specified degree
201 * @pixbuf: pixbuf to render into
203 * First scale the document to match the specified pixels per point,
204 * then render the rectangle given by the upper left corner at
205 * (src_x, src_y) and src_width and src_height.
206 * This function is for rendering a page that will be displayed.
207 * If you want to render a page that will be printed use
208 * poppler_page_render_to_pixbuf_for_printing() instead
213 poppler_page_render_to_pixbuf (PopplerPage *page,
214 int src_x, int src_y,
215 int src_width, int src_height,
220 g_return_if_fail (POPPLER_IS_PAGE (page));
221 g_return_if_fail (scale > 0.0);
222 g_return_if_fail (pixbuf != NULL);
224 _poppler_page_render_to_pixbuf (page, src_x, src_y,
225 src_width, src_height,
231 static GtkWidget *pdf_viewer_get_widget(MimeViewer *_viewer)
233 PdfViewer *viewer = (PdfViewer *) _viewer;
234 debug_print("pdf_viewer_get_widget: %p\n", viewer->vbox);
236 return GTK_WIDGET(viewer->vbox);
238 /** Hide the index panel */
239 static void pdf_viewer_hide_index_pane(PdfViewer *viewer)
241 if (viewer->pdf_index) {
242 poppler_index_iter_free(viewer->pdf_index);
243 viewer->pdf_index = NULL;
244 gtk_widget_hide(GTK_WIDGET(viewer->frame_index));
248 static void search_matches_free(PdfViewer *viewer)
251 for(cur = viewer->text_found; cur; cur = cur->next) {
252 PageResult *res = (PageResult *)cur->data;
253 g_list_free(res->results);
256 g_list_free(viewer->text_found);
257 viewer->text_found = NULL;
258 g_free(viewer->last_search);
259 viewer->last_search = NULL;
260 if (viewer->last_rect && viewer->last_page_result) {
261 viewer->last_rect = NULL;
262 viewer->last_page_result = NULL;
263 pdf_viewer_update((MimeViewer *)viewer,
265 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page)));
269 static void pdf_viewer_scroll_to(PdfViewer *viewer, gfloat x, gfloat y)
273 vadj = gtk_scrolled_window_get_vadjustment(
274 GTK_SCROLLED_WINDOW(viewer->scrollwin));
276 if (y < gtk_adjustment_get_value(vadj)) {
277 gtk_adjustment_set_value(vadj, y);
280 while(y > gtk_adjustment_get_value(vadj) + gtk_adjustment_get_page_size(vadj)) {
281 gtk_adjustment_set_value(vadj,
282 gtk_adjustment_get_value(vadj) + gtk_adjustment_get_page_size(vadj));
286 hadj = gtk_scrolled_window_get_hadjustment(
287 GTK_SCROLLED_WINDOW(viewer->scrollwin));
289 if (x < gtk_adjustment_get_value(hadj)) {
290 gtk_adjustment_set_value(hadj, x);
293 while(x > gtk_adjustment_get_value(hadj) + gtk_adjustment_get_page_size(hadj)) {
294 gtk_adjustment_set_value(hadj,
295 gtk_adjustment_get_value(hadj) + gtk_adjustment_get_page_size(hadj));
299 g_signal_emit_by_name(G_OBJECT(hadj), "value-changed", 0);
300 g_signal_emit_by_name(G_OBJECT(vadj), "value-changed", 0);
302 static void pdf_viewer_render_page(PopplerPage *page, GtkWidget *view, double width,
303 double height, double zoom, gint rotate)
307 debug_print("width: %f\n", width);
308 pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
311 (int)(height * zoom));
313 poppler_page_render_to_pixbuf(page, 0, 0,
315 (int)(height * zoom),
318 gtk_image_set_from_pixbuf(GTK_IMAGE(view), pb);
319 g_object_unref(G_OBJECT(pb));
321 static void pdf_viewer_render_selection(PdfViewer *viewer, PopplerRectangle *rect, PageResult *page_results)
324 double width_points, height_points;
326 GdkPixbuf *sel_pb, *page_pb;
327 gfloat x1, x2, y1, y2;
331 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page));
333 viewer->last_match = viewer->res_cnt;
335 viewer->last_rect = NULL;
336 viewer->last_page_result = NULL;
337 if (cur_page_num != page_results->page_num) {
338 /* we changed page. update the view */
339 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->cur_page),
340 (gdouble) page_results->page_num);
343 viewer->last_rect = rect;
344 viewer->last_page_result = page_results;
348 poppler_page_get_size(POPPLER_PAGE(viewer->pdf_page), &width_points, &height_points);
349 width = (int)((width_points * viewer->zoom) + 0.5);
350 height = (int)((height_points * viewer->zoom) + 0.5);
352 if (viewer->rotate == 90) {
353 x1 = MIN(rect->y1,rect->y2) * viewer->zoom;
354 x2 = MAX(rect->y1,rect->y2) * viewer->zoom;
355 y1 = MAX(rect->x1,rect->x2) * viewer->zoom;
356 y2 = MIN(rect->x1,rect->x2) * viewer->zoom;
360 } else if (viewer->rotate == 180) {
361 x1 = width - rect->x2 * viewer->zoom;
362 x2 = width - rect->x1 * viewer->zoom;
363 y1 = height - rect->y2 * viewer->zoom;
364 y2 = height - rect->y1 * viewer->zoom;
370 } else if (viewer->rotate == 270) {
371 x1 = height - MAX(rect->y1,rect->y2) * viewer->zoom;
372 x2 = height - MIN(rect->y1,rect->y2) * viewer->zoom;
373 y1 = width - MIN(rect->x1,rect->x2) * viewer->zoom;
374 y2 = width - MAX(rect->x1,rect->x2) * viewer->zoom;
378 x1 = rect->x1 * viewer->zoom;
379 x2 = rect->x2 * viewer->zoom;
380 y1 = rect->y1 * viewer->zoom;
381 y2 = rect->y2 * viewer->zoom;
388 sel_pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
391 gdk_pixbuf_fill(sel_pb, SELECTION_COLOR);
393 page_pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
395 (int)(viewer->width * viewer->zoom),
396 (int)(viewer->height * viewer->zoom));
398 poppler_page_render_to_pixbuf(viewer->pdf_page,
401 (int)(viewer->width * viewer->zoom),
402 (int)(viewer->height * viewer->zoom),
407 gdk_pixbuf_composite(sel_pb, page_pb,
408 x1, y2, selw, selh, 0, 0,
409 viewer->zoom, viewer->zoom,
410 GDK_INTERP_BILINEAR, ALPHA_CHANNEL);
412 gtk_image_set_from_pixbuf(GTK_IMAGE(viewer->pdf_view), page_pb);
414 pdf_viewer_scroll_to(viewer, MIN(x1,x2), MIN(y1,y2));
416 g_object_unref(G_OBJECT(sel_pb));
417 g_object_unref(G_OBJECT(page_pb));
421 static gboolean pdf_viewer_text_search(MimeViewer *_viewer, gboolean backward,
422 const gchar *str, gboolean case_sens)
424 PdfViewer *viewer = (PdfViewer *)_viewer;
425 GList *all_pages_results, *cur_page_results;
428 debug_print("pdf_viewer_text_search: %s\n", str);
429 main_window_cursor_wait(mainwindow_get_mainwindow());
431 if (viewer->last_search && strcmp(str, viewer->last_search)) {
432 search_matches_free(viewer);
433 viewer->last_match = -1;
434 viewer->num_matches = 0;
435 } else if (!viewer->last_search) {
436 viewer->last_match = -1;
437 viewer->num_matches = 0;
439 /* It's a new search, build list of matches
440 * across all pages */
441 if (viewer->last_match == -1) {
444 for(i = 1; i <= viewer->num_pages; i++) {
446 PopplerPage *pdf_page = poppler_document_get_page(viewer->pdf_doc, i - 1);
447 viewer->page_results = poppler_page_find_text(pdf_page, str);
449 if (viewer->page_results != NULL) {
450 debug_print("page_results %p\n", viewer->page_results);
451 /* store results for this page */
453 PageResult *res = g_new0(PageResult, 1);
454 res->results = viewer->page_results;
456 /* found text, prepend this page(faster than append) */
457 viewer->text_found = g_list_prepend(viewer->text_found, res);
458 num_res = g_list_length(viewer->page_results);
459 debug_print("%d results on page %d\n", num_res, i);
460 viewer->num_matches += num_res;
462 g_object_unref(G_OBJECT(pdf_page));
465 if (viewer->text_found == NULL) {
466 main_window_cursor_normal(mainwindow_get_mainwindow());
469 /* put back the list in the correct order */
470 viewer->text_found = g_list_reverse(viewer->text_found);
473 if (!viewer->text_found) {
474 main_window_cursor_normal(mainwindow_get_mainwindow());
477 viewer->last_search = g_strdup(str);
481 /* if backward, we have to initialize stuff to search
483 viewer->res_cnt = viewer->num_matches-1;
484 if (viewer->last_match == -1) {
485 viewer->last_match = viewer->num_matches+1;
487 all_pages_results = g_list_last(viewer->text_found);
490 all_pages_results = viewer->text_found;
493 for(; all_pages_results; all_pages_results = (backward?all_pages_results->prev:all_pages_results->next)) {
495 PageResult * page_results = (PageResult *)all_pages_results->data;
498 cur_page_results = g_list_last(page_results->results);
501 cur_page_results = page_results->results;
504 for(; cur_page_results; cur_page_results = (backward?cur_page_results->prev:cur_page_results->next)) {
506 gboolean valid = FALSE;
507 /* first valid result is the last+1 if searching
508 * forward, last-1 if searching backward */
510 valid = (viewer->res_cnt < viewer->last_match);
513 valid = (viewer->res_cnt > viewer->last_match);
516 pdf_viewer_render_selection(viewer,
517 (PopplerRectangle *)cur_page_results->data,
519 main_window_cursor_normal(mainwindow_get_mainwindow());
531 main_window_cursor_normal(mainwindow_get_mainwindow());
532 search_matches_free(viewer);
536 static void pdf_viewer_get_document_index(PdfViewer *viewer, PopplerIndexIter *index_iter, GtkTreeIter *parentiter)
538 PopplerAction *action;
539 PopplerIndexIter *child;
540 GtkTreeIter childiter;
542 debug_print("get document index\n");
546 action = poppler_index_iter_get_action(index_iter);
548 if (action->type != POPPLER_ACTION_GOTO_DEST) {
549 poppler_action_free(action);
553 if (action->goto_dest.dest->type == POPPLER_DEST_XYZ || action->goto_dest.dest->type == POPPLER_DEST_FITH) {
554 page_num = action->goto_dest.dest->page_num;
556 #ifdef HAVE_POPPLER_DEST_NAMED
557 else if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
558 PopplerDest *dest = poppler_document_find_dest(
559 viewer->pdf_doc, action->goto_dest.dest->named_dest);
560 if (dest->type != POPPLER_DEST_XYZ) {
561 g_warning("couldn't figure out link");
562 poppler_dest_free(dest);
565 page_num = dest->page_num;
566 poppler_dest_free(dest);
570 #ifdef HAVE_POPPLER_DEST_NAMED
571 g_warning("unhandled link type %d. please contact developers", action->goto_dest.dest->type);
573 g_warning("unhandled link type %d. please upgrade libpoppler-glib to 0.5.4", action->goto_dest.dest->type);
577 gtk_tree_store_append(GTK_TREE_STORE(viewer->index_model), &childiter, parentiter);
578 gtk_tree_store_set(GTK_TREE_STORE(viewer->index_model), &childiter,
579 INDEX_NAME, action->named.title,
580 INDEX_PAGE, page_num,
581 INDEX_TOP, action->goto_dest.dest->top,
583 poppler_action_free(action);
584 child = poppler_index_iter_get_child(index_iter);
586 pdf_viewer_get_document_index(viewer, child, &childiter);
587 poppler_index_iter_free(child);
590 while(poppler_index_iter_next(index_iter));
593 static void pdf_viewer_index_row_activated(GtkTreeView *tree_view,
595 GtkTreeViewColumn *column,
599 GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
600 PdfViewer *viewer = (PdfViewer *)data;
603 debug_print("index_row_activated\n");
604 if (!gtk_tree_model_get_iter(model, &iter, path)) return;
606 gtk_tree_model_get(model, &iter,
607 INDEX_PAGE, &page_num,
611 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->cur_page),(gdouble)page_num);
612 debug_print("Page num: %d\n", page_num);
617 /** Disable the index button if the document doesn't have an index */
618 static void pdf_viewer_set_index_button_sensitive(PdfViewer *viewer)
620 viewer->pdf_index = poppler_index_iter_new(viewer->pdf_doc);
621 if (viewer->pdf_index) {
622 if (!gtk_widget_is_sensitive(viewer->doc_index)) {
623 gtk_widget_set_sensitive(viewer->doc_index, TRUE);
627 gtk_widget_set_sensitive(viewer->doc_index, FALSE);
630 poppler_index_iter_free(viewer->pdf_index);
631 viewer->pdf_index = NULL;
634 static char * pdf_viewer_get_document_format_data(GTime utime)
636 time_t time = (time_t) utime;
639 const char *fmt_hack = "%c";
642 if (time == 0 || !localtime_r(&time, &t)) return NULL;
644 len = strftime(s, sizeof(s), fmt_hack, &t);
646 if (len == 0 || s[0] == '\0') return NULL;
648 return g_locale_to_utf8(s, -1, NULL, NULL, NULL);
651 #define ADD_TO_TABLE(LABEL, VALUE) \
652 label = gtk_label_new(LABEL); \
653 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); \
654 gtk_misc_set_padding(GTK_MISC(label), 4, 0); \
655 gtk_table_attach(viewer->table_doc_info, label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); \
657 label = gtk_label_new(VALUE); \
658 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); \
659 gtk_misc_set_padding(GTK_MISC(label), 4, 0); \
660 gtk_table_attach(viewer->table_doc_info, label, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); \
664 static GtkTable * pdf_viewer_fill_info_table(PdfViewer *viewer)
667 const gchar *title, *format, *author, *subject, *keywords, *creator, *producer;
672 GTime creation_date, mod_date;
674 PopplerPageLayout layout;
675 PopplerPageMode mode;
676 PopplerPermissions permissions;
677 PopplerViewerPreferences view_prefs;
679 title = format = author = subject = keywords = creator = producer = tmp = 0;
681 g_object_get(viewer->pdf_doc,
686 "keywords", &keywords,
687 "creation-date", &creation_date,
688 "permissions", &permissions,
689 "mod-date", &mod_date,
691 "producer", &producer,
692 "linearized", &linearized,
694 "page-layout", &layout,
695 "viewer-preferences", &view_prefs,
698 viewer->table_doc_info = GTK_TABLE(gtk_table_new(13, 2, FALSE));
700 ADD_TO_TABLE(_("Filename:"), viewer->target_filename)
701 ADD_TO_TABLE(_("Size:"), to_human_readable(viewer->to_load->length))
702 ADD_TO_TABLE(NULL, NULL)
703 ADD_TO_TABLE(_("Title:"), title)
704 ADD_TO_TABLE(_("Subject:"), subject)
705 ADD_TO_TABLE(_("Author:"), author)
706 ADD_TO_TABLE(_("Keywords:"), keywords)
707 ADD_TO_TABLE(_("Creator:"), creator)
708 ADD_TO_TABLE(_("Producer:"), producer)
710 tmp = pdf_viewer_get_document_format_data(creation_date);
711 ADD_TO_TABLE(_("Created:"), tmp)
714 tmp = pdf_viewer_get_document_format_data(mod_date);
715 ADD_TO_TABLE(_("Modified:"), tmp)
718 ADD_TO_TABLE(_("Format:"), format)
720 ADD_TO_TABLE(_("Optimized:"), _("Yes"))
723 ADD_TO_TABLE(_("Optimized:"), _("No"))
725 //ADD_TO_TABLE(_("Page Mode:"), pdf_viewer_get_document_info_mode(mode))
726 //ADD_TO_TABLE(_("Page Layout:"), pdf_viewer_get_document_info_layout(layout))
728 return(GtkTable *) viewer->table_doc_info;
732 static FileType pdf_viewer_mimepart_get_type(MimeInfo *partinfo)
734 gchar *content_type = NULL;
735 FileType type = TYPE_UNKNOWN;
736 debug_print("mimepart_get_type\n");
737 if ((partinfo->type == MIMETYPE_APPLICATION) &&
738 (!g_ascii_strcasecmp(partinfo->subtype, "octet-stream"))) {
740 const gchar *filename;
742 filename = procmime_mimeinfo_get_parameter(partinfo, "filename");
744 if (filename == NULL)
745 filename = procmime_mimeinfo_get_parameter(partinfo, "name");
746 if (filename != NULL)
747 content_type = procmime_get_mime_type(filename);
750 content_type = procmime_get_content_type_str(partinfo->type, partinfo->subtype);
753 if (content_type == NULL) type = TYPE_UNKNOWN;
754 else if (!strcmp(content_type, "application/pdf")) type = TYPE_PDF;
755 else if (!strcmp(content_type, "application/postscript")) type = TYPE_PS;
756 else type = TYPE_UNKNOWN;
758 g_free(content_type);
763 static void pdf_viewer_button_first_page_cb(GtkButton *button, PdfViewer *viewer)
766 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_HOME, 1);
769 static void pdf_viewer_button_prev_page_cb(GtkButton *button, PdfViewer *viewer)
772 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_STEP_BACKWARD, 1);
775 static void pdf_viewer_button_next_page_cb(GtkButton *button, PdfViewer *viewer)
778 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_STEP_FORWARD, 1);
781 static void pdf_viewer_button_last_page_cb(GtkButton *button, PdfViewer *viewer)
784 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_END, 1);
787 static void pdf_viewer_spin_change_page_cb(GtkSpinButton *button, PdfViewer *viewer)
789 pdf_viewer_update((MimeViewer *)viewer,
791 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page)));
794 static void pdf_viewer_button_zoom_in_cb(GtkButton *button, PdfViewer *viewer)
797 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->zoom_scroll), GTK_SPIN_STEP_FORWARD, ZOOM_FACTOR);
800 static void pdf_viewer_spin_zoom_scroll_cb(GtkSpinButton *button, PdfViewer *viewer)
802 viewer->zoom = gtk_spin_button_get_value(GTK_SPIN_BUTTON(viewer->zoom_scroll));
803 pdf_viewer_update((MimeViewer *)viewer,
805 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page)));
808 static void pdf_viewer_button_zoom_out_cb(GtkButton *button, PdfViewer *viewer)
811 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->zoom_scroll), GTK_SPIN_STEP_BACKWARD, ZOOM_FACTOR);
815 static void pdf_viewer_button_press_events_cb(GtkWidget *widget, GdkEventButton *event, PdfViewer *viewer)
819 #ifdef HAVE_POPPLER_DEST_NAMED
822 static GdkCursor *hand_cur = NULL;
824 if (!hand_cur) hand_cur = gdk_cursor_new(GDK_FLEUR);
826 /* Execute Poppler Links */
827 if (event->button == 1 && viewer->in_link) {
828 switch (viewer->link_action->type) {
829 case POPPLER_ACTION_UNKNOWN:
830 debug_print("action unknown\n");
832 case POPPLER_ACTION_GOTO_DEST:
833 if (viewer->link_action->goto_dest.dest->type == POPPLER_DEST_XYZ ||
834 viewer->link_action->goto_dest.dest->type == POPPLER_DEST_FITH) {
835 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->cur_page),
836 (gdouble)viewer->link_action->goto_dest.dest->page_num);
838 #ifdef HAVE_POPPLER_DEST_NAMED
839 else if (viewer->link_action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
840 dest = poppler_document_find_dest(
841 viewer->pdf_doc, viewer->link_action->goto_dest.dest->named_dest);
842 if (dest->type != POPPLER_DEST_XYZ) {
843 g_warning("couldn't figure out link");
844 poppler_dest_free(dest);
847 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->cur_page),
848 (gdouble)dest->page_num);
849 poppler_dest_free(dest);
853 case POPPLER_ACTION_GOTO_REMOTE:
854 #ifdef HAVE_POPPLER_DEST_NAMED
855 dest = poppler_document_find_dest(
856 viewer->pdf_doc, viewer->link_action->goto_remote.dest->named_dest);
857 if (dest->type != POPPLER_DEST_XYZ) {
858 g_warning ("couldn't figure out link");
859 poppler_dest_free(dest);
862 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->cur_page),
863 (gdouble)dest->page_num);
864 poppler_dest_free(dest);
867 case POPPLER_ACTION_LAUNCH:
868 debug_print("action launch not yet implemented\n");
870 case POPPLER_ACTION_URI:
871 uri = g_strdup(viewer->link_action->uri.uri);
872 if (!g_ascii_strncasecmp(uri, "mailto:", 7))
873 compose_new(NULL, uri + 7, NULL);
875 open_uri(uri, prefs_common_get_uri_cmd());
878 case POPPLER_ACTION_NAMED:
879 debug_print("action named not yet implemented\n");
881 case POPPLER_ACTION_NONE:
882 debug_print("action none does nothing, surprise!\n");
884 case POPPLER_ACTION_MOVIE:
885 debug_print("yoyoyo ;-) a movie?\n");
887 #if POPPLER_CHECK_VERSION(0,14,0)
888 case POPPLER_ACTION_RENDITION:
889 debug_print("yoyoyo ;-) multimedia?\n");
891 case POPPLER_ACTION_OCG_STATE:
892 debug_print("yoyoyo ;-) layer state?\n");
894 #if POPPLER_CHECK_VERSION(0,18,0)
895 case POPPLER_ACTION_JAVASCRIPT:
896 debug_print("yoyoyo ;-) javascript?\n");
901 if (((MimeViewer *)viewer)->mimeview &&
902 ((MimeViewer *)viewer)->mimeview->messageview &&
903 ((MimeViewer *)viewer)->mimeview->messageview->window &&
904 (gdkwin = gtk_widget_get_window(((MimeViewer *)viewer)->mimeview->messageview->window)) != NULL)
905 gdk_window_set_cursor (gdkwin, NULL);
907 gdk_window_set_cursor (gtk_widget_get_window(mainwindow_get_mainwindow()->window), NULL);
910 /* Init document to be scrolled with left mouse click */
911 if (event->button == 1 && !viewer->in_link) {
912 viewer->pdf_view_scroll = TRUE;
913 if (((MimeViewer *)viewer)->mimeview &&
914 ((MimeViewer *)viewer)->mimeview->messageview &&
915 ((MimeViewer *)viewer)->mimeview->messageview->window &&
916 (gdkwin = gtk_widget_get_window(((MimeViewer *)viewer)->mimeview->messageview->window)) != NULL)
917 gdk_window_set_cursor (gdkwin, hand_cur);
919 gdk_window_set_cursor (gtk_widget_get_window(mainwindow_get_mainwindow()->window), hand_cur);
921 viewer->last_x = event->x;
922 viewer->last_y = event->y;
923 viewer->last_dir_x = 0;
924 viewer->last_dir_y = 0;
927 /* Set the normal cursor*/
928 static void pdf_viewer_mouse_scroll_destroy_cb(GtkWidget *widget, GdkEventButton *event, PdfViewer *viewer)
932 if (event->button == 1) {
933 viewer->pdf_view_scroll = FALSE;
934 if (((MimeViewer *)viewer)->mimeview &&
935 ((MimeViewer *)viewer)->mimeview->messageview &&
936 ((MimeViewer *)viewer)->mimeview->messageview->window &&
937 (gdkwin = gtk_widget_get_window(((MimeViewer *)viewer)->mimeview->messageview->window)) != NULL)
938 gdk_window_set_cursor (gdkwin, NULL);
940 gdk_window_set_cursor (gtk_widget_get_window(mainwindow_get_mainwindow()->window), NULL);
944 static void pdf_viewer_move_events_cb(GtkWidget *widget, GdkEventMotion *event, PdfViewer *viewer)
948 /* Grab the document and scroll it with mouse */
949 if (viewer->pdf_view_scroll) {
951 viewer->pdf_view_vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin));
952 viewer->pdf_view_hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin));
954 if (event->x < viewer->last_x
955 && gtk_adjustment_get_value(viewer->pdf_view_hadj) < (gtk_adjustment_get_upper(viewer->pdf_view_hadj) - gtk_adjustment_get_page_size(viewer->pdf_view_hadj))) {
956 if (viewer->last_dir_x == -1) {
957 gtk_adjustment_set_value(viewer->pdf_view_hadj,
958 gtk_adjustment_get_value(viewer->pdf_view_hadj)
961 g_signal_emit_by_name(G_OBJECT(viewer->pdf_view_hadj),
964 viewer->last_dir_x = -1;
966 else if (event->x > viewer->last_x
967 && gtk_adjustment_get_value(viewer->pdf_view_hadj) > 0.0) {
968 if (viewer->last_dir_x == +1) {
969 gtk_adjustment_set_value(viewer->pdf_view_hadj,
970 gtk_adjustment_get_value(viewer->pdf_view_hadj)
973 g_signal_emit_by_name(G_OBJECT(viewer->pdf_view_hadj),
976 viewer->last_dir_x = +1;
979 if (event->y < viewer->last_y
980 && gtk_adjustment_get_value(viewer->pdf_view_vadj) < (gtk_adjustment_get_upper(viewer->pdf_view_vadj) - gtk_adjustment_get_page_size(viewer->pdf_view_vadj))) {
981 if (viewer->last_dir_y == -1) {
982 gtk_adjustment_set_value(viewer->pdf_view_vadj,
983 gtk_adjustment_get_value(viewer->pdf_view_vadj)
986 g_signal_emit_by_name(G_OBJECT(viewer->pdf_view_vadj),
989 viewer->last_dir_y = -1;
991 else if (event->y > viewer->last_y
992 && gtk_adjustment_get_value(viewer->pdf_view_vadj) > 0.0) {
993 if (viewer->last_dir_y == +1) {
994 gtk_adjustment_set_value(viewer->pdf_view_vadj,
995 gtk_adjustment_get_value(viewer->pdf_view_vadj)
998 g_signal_emit_by_name(G_OBJECT(viewer->pdf_view_vadj),
1001 viewer->last_dir_y = +1;
1003 viewer->last_x = event->x;
1004 viewer->last_y = event->y;
1010 static GdkCursor *link_cur = NULL;
1011 static GtkRequisition size;
1012 static gdouble x,y, x1, y1, x2, y2;
1015 viewer->pdf_view_vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin));
1016 viewer->pdf_view_hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin));
1018 if (!link_cur) link_cur = gdk_cursor_new(GDK_HAND2);
1021 viewer->in_link = FALSE;
1022 for (l = viewer->link_map; l; l = g_list_next (l)) {
1024 PopplerLinkMapping *lmapping;
1025 lmapping = (PopplerLinkMapping *)l->data;
1027 x1 = lmapping->area.x1;
1028 y1 = lmapping->area.y1;
1029 x2 = lmapping->area.x2;
1030 y2 = lmapping->area.y2;
1031 gtk_widget_size_request(viewer->pdf_view, &size);
1033 upper = gtk_adjustment_get_upper(viewer->pdf_view_hadj);
1034 switch (viewer->rotate) {
1037 if (size.width != upper)
1038 x = (event->x - (upper - size.width) / 2) / viewer->zoom;
1040 x = event->x / viewer->zoom;
1042 y = (upper - event->y) / viewer->zoom;
1045 if (size.width != upper)
1046 y = (event->x - (upper - size.width) / 2) / viewer->zoom;
1048 y = event->x / viewer->zoom;
1050 x = (event->y) / viewer->zoom;
1053 if (size.width != upper)
1054 x = ((upper - event->x) - ((upper - size.width) / 2)) / viewer->zoom;
1056 x = ((upper - event->x) - (upper - size.width)) / viewer->zoom;
1058 y = (event->y) / viewer->zoom;
1061 if (size.width != upper)
1062 y = ((upper - event->x) - ((upper - size.width) / 2)) / viewer->zoom;
1064 y = ((upper - event->x) - (upper - size.width)) / viewer->zoom;
1066 x = (upper - event->y) / viewer->zoom;
1070 if ( (x > x1 && x < x2) && (y > y1 && y < y2) ) {
1071 viewer->in_link = TRUE;
1072 if (((MimeViewer *)viewer)->mimeview &&
1073 ((MimeViewer *)viewer)->mimeview->messageview &&
1074 ((MimeViewer *)viewer)->mimeview->messageview->window &&
1075 (gdkwin = gtk_widget_get_window(((MimeViewer *)viewer)->mimeview->messageview->window)) != NULL)
1076 gdk_window_set_cursor (gdkwin, link_cur);
1078 gdk_window_set_cursor (gtk_widget_get_window(mainwindow_get_mainwindow()->window), link_cur);
1080 viewer->link_action = lmapping->action;
1084 if (((MimeViewer *)viewer)->mimeview &&
1085 ((MimeViewer *)viewer)->mimeview->messageview &&
1086 ((MimeViewer *)viewer)->mimeview->messageview->window &&
1087 (gdkwin = gtk_widget_get_window(((MimeViewer *)viewer)->mimeview->messageview->window)) != NULL)
1088 gdk_window_set_cursor (gdkwin, NULL);
1090 gdk_window_set_cursor (gtk_widget_get_window(mainwindow_get_mainwindow()->window), NULL);
1096 static gboolean pdf_viewer_scroll_cb(GtkWidget *widget, GdkEventScroll *event,
1099 GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin));
1100 static gboolean in_scroll_cb = FALSE;
1101 gboolean handled = FALSE;
1102 gint cur_p = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page));
1107 in_scroll_cb = TRUE;
1109 if (event->direction == GDK_SCROLL_UP &&
1110 gtk_adjustment_get_value(adj) == gtk_adjustment_get_lower(adj) &&
1112 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_STEP_BACKWARD, 1);
1113 gtk_adjustment_set_value(adj,
1114 gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj));
1116 } else if (event->direction == GDK_SCROLL_DOWN &&
1117 gtk_adjustment_get_value(adj) + gtk_adjustment_get_page_size(adj) == gtk_adjustment_get_upper(adj) &&
1118 cur_p < viewer->num_pages) {
1119 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_STEP_FORWARD, 1);
1120 gtk_adjustment_set_value(adj, 0.0);
1123 in_scroll_cb = FALSE;
1127 static void pdf_viewer_button_zoom_fit_cb(GtkButton *button, PdfViewer *viewer)
1129 GtkAllocation allocation;
1130 double xratio, yratio;
1131 gtk_widget_get_allocation(viewer->scrollwin, &allocation);
1132 debug_print("width: %d\n", allocation.width);
1133 debug_print("height: %d\n", allocation.height);
1134 xratio = allocation.width / viewer->width;
1135 yratio = allocation.height / viewer->height;
1137 if (xratio >= yratio) {
1138 viewer->zoom = yratio;
1139 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->zoom_scroll),viewer->zoom);
1142 viewer->zoom = xratio;
1143 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->zoom_scroll),viewer->zoom);
1147 static void pdf_viewer_button_zoom_width_cb(GtkButton *button, PdfViewer *viewer)
1149 GtkAllocation allocation;
1151 gtk_widget_get_allocation(viewer->scrollwin, &allocation);
1152 debug_print("width: %d\n", allocation.width);
1153 xratio = allocation.width / viewer->width;
1154 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->zoom_scroll), xratio);
1157 static void pdf_viewer_button_rotate_right_cb(GtkButton *button, PdfViewer *viewer)
1159 if (viewer->rotate == 360) {
1163 viewer->rotate += (gint) ROTATION;
1164 pdf_viewer_update((MimeViewer *)viewer, FALSE,
1165 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page)));
1168 static void pdf_viewer_button_rotate_left_cb(GtkButton *button, PdfViewer *viewer)
1170 if (viewer->rotate == 0) {
1171 viewer->rotate = 360;
1174 viewer->rotate = abs(viewer->rotate -(gint) ROTATION);
1175 pdf_viewer_update((MimeViewer *)viewer, FALSE,
1176 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page)));
1179 /* Show/Hide the index pane */
1180 static void pdf_viewer_show_document_index_cb(GtkButton *button, PdfViewer *viewer)
1182 if (!viewer->pdf_index) {
1183 viewer->pdf_index = poppler_index_iter_new(viewer->pdf_doc);
1186 gtk_tree_store_clear(GTK_TREE_STORE(viewer->index_model));
1188 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(viewer->doc_index))) {
1189 pdf_viewer_get_document_index(viewer,(PopplerIndexIter *) viewer->pdf_index, NULL);
1190 gtk_widget_show(GTK_WIDGET(viewer->frame_index));
1193 pdf_viewer_hide_index_pane(viewer);
1198 static void pdf_viewer_button_print_cb(GtkButton *button, PdfViewer *viewer)
1200 MainWindow *mainwin = mainwindow_get_mainwindow();
1201 summary_print(mainwin->summaryview);
1204 static void pdf_viewer_button_document_info_cb(GtkButton *button, PdfViewer *viewer)
1206 alertpanel_full(_("PDF properties"), NULL, GTK_STOCK_CLOSE, NULL, NULL,
1207 FALSE, (GtkWidget *) pdf_viewer_fill_info_table(viewer),
1208 ALERT_NOTICE, G_ALERTDEFAULT);
1212 static const char * poppler_get_document_info_mode(PopplerPageMode mode)
1214 GEnumValue *enum_value;
1216 enum_value = g_enum_get_value((GEnumClass *) g_type_class_peek(POPPLER_TYPE_PAGE_MODE), mode);
1217 return(gchar *) enum_value->value_name;
1219 static const char * poppler_get_document_info_layout(PopplerPageLayout layout)
1222 GEnumValue *enum_value;
1224 enum_value = g_enum_get_value((GEnumClass *) g_type_class_peek(POPPLER_TYPE_PAGE_LAYOUT), layout);
1225 return(gchar *) enum_value->value_name;
1228 static void pdf_viewer_show_controls(PdfViewer *viewer, gboolean show)
1231 gtk_widget_show(viewer->first_page);
1232 gtk_widget_show(viewer->cur_page);
1233 gtk_widget_show(viewer->prev_page);
1234 gtk_widget_show(viewer->next_page);
1235 gtk_widget_show(viewer->last_page);
1236 gtk_widget_show(viewer->zoom_in);
1237 gtk_widget_show(viewer->zoom_out);
1238 gtk_widget_show(viewer->zoom_fit);
1239 gtk_widget_show(viewer->zoom_width);
1240 gtk_widget_show(viewer->zoom_scroll);
1241 gtk_widget_show(viewer->widgets_table);
1242 gtk_widget_show(viewer->rotate_right);
1243 gtk_widget_show(viewer->rotate_left);
1244 gtk_widget_show(viewer->print);
1245 gtk_widget_show(viewer->doc_info);
1246 gtk_widget_show(viewer->doc_index);
1248 gtk_widget_hide(viewer->first_page);
1249 gtk_widget_hide(viewer->cur_page);
1250 gtk_widget_hide(viewer->prev_page);
1251 gtk_widget_hide(viewer->next_page);
1252 gtk_widget_hide(viewer->last_page);
1253 gtk_widget_hide(viewer->zoom_in);
1254 gtk_widget_hide(viewer->zoom_out);
1255 gtk_widget_hide(viewer->zoom_fit);
1256 gtk_widget_hide(viewer->zoom_width);
1257 gtk_widget_hide(viewer->zoom_scroll);
1258 gtk_widget_hide(viewer->widgets_table);
1259 gtk_widget_hide(viewer->rotate_right);
1260 gtk_widget_hide(viewer->rotate_left);
1261 gtk_widget_hide(viewer->print);
1262 gtk_widget_hide(viewer->doc_info);
1263 gtk_widget_hide(viewer->doc_index);
1266 /** Render the current page, page_num on the viewer */
1267 static void pdf_viewer_update(MimeViewer *_viewer, gboolean reload_file, int page_num)
1270 PdfViewer *viewer = (PdfViewer *) _viewer;
1271 GError *error = NULL;
1272 gchar *tmpfile = NULL;
1274 gchar *password = NULL;
1276 debug_print("pdf_viewer_update\n");
1279 if (viewer->pdf_doc) {
1280 g_object_unref(G_OBJECT(viewer->pdf_doc));
1281 viewer->pdf_doc = NULL;
1284 if (pdf_viewer_mimepart_get_type(viewer->to_load) == TYPE_PS) {
1285 stock_pixbuf_gdk(STOCK_PIXMAP_MIME_PS,
1286 &viewer->icon_pixbuf);
1287 gtk_image_set_from_pixbuf(GTK_IMAGE(viewer->icon_type),
1288 viewer->icon_pixbuf);
1290 else if (pdf_viewer_mimepart_get_type(viewer->to_load) == TYPE_PDF) {
1291 stock_pixbuf_gdk(STOCK_PIXMAP_MIME_PDF,
1292 &viewer->icon_pixbuf);
1293 gtk_image_set_from_pixbuf(GTK_IMAGE(viewer->icon_type),
1294 viewer->icon_pixbuf);
1297 stock_pixbuf_gdk(STOCK_PIXMAP_MIME_APPLICATION,
1298 &viewer->icon_pixbuf);
1299 gtk_image_set_from_pixbuf(GTK_IMAGE(viewer->icon_type),
1300 viewer->icon_pixbuf);
1303 gtk_label_set_text(GTK_LABEL(viewer->doc_label), _("Loading..."));
1304 pdf_viewer_show_controls(viewer, FALSE);
1305 main_window_cursor_wait(mainwindow_get_mainwindow());
1309 if (pdf_viewer_mimepart_get_type(viewer->to_load) == TYPE_PS) {
1310 gchar *cmdline = NULL, *tmp = NULL, *gspath = NULL;
1313 if ((gspath = g_find_program_in_path("gs")) != NULL) {
1315 /* convert postscript to pdf */
1316 tmpfile = get_tmp_file();
1317 cmdline = g_strdup_printf(
1318 "gs -dSAFER -dCompatibilityLevel=1.2 -q -dNOPAUSE -dBATCH "
1319 "-sDEVICE=pdfwrite -sOutputFile=%s -c .setpdfwrite -f \"%s\"",
1320 tmpfile, viewer->filename);
1321 result = execute_command_line(cmdline, FALSE, NULL);
1323 tmp = g_filename_to_uri(tmpfile, NULL, NULL);
1324 viewer->pdf_doc = poppler_document_new_from_file( tmp, NULL, &error);
1328 g_warning("gs conversion failed: %s returned %d", cmdline, result);
1329 tmp = g_strdup_printf("gs: err %d", result);
1330 alertpanel_warning("%s", tmp);
1335 claws_unlink(tmpfile);
1339 g_warning("gs conversion disabled: gs binary was not found");
1340 alertpanel_warning("PostScript view disabled: required gs program not found");
1345 main_window_cursor_normal(mainwindow_get_mainwindow());
1350 viewer->pdf_doc = poppler_document_new_from_file( viewer->fsname, NULL, &error);
1352 if (error && g_error_matches(error, POPPLER_ERROR, POPPLER_ERROR_ENCRYPTED)) {
1353 g_clear_error(&error);
1354 password = input_dialog_with_invisible(_("Enter password"),
1355 _("This document is locked and requires a password before it can be opened."),
1357 viewer->pdf_doc = poppler_document_new_from_file(viewer->fsname, password, &error);
1361 viewer->num_pages = poppler_document_get_n_pages(viewer->pdf_doc);
1363 g_signal_handlers_block_by_func(G_OBJECT(viewer->cur_page), pdf_viewer_spin_change_page_cb,(gpointer *)viewer);
1364 gtk_spin_button_set_range(GTK_SPIN_BUTTON(viewer->cur_page),
1366 (gdouble)viewer->num_pages );
1368 g_signal_handlers_unblock_by_func(G_OBJECT(viewer->cur_page), pdf_viewer_spin_change_page_cb,(gpointer *)viewer);
1369 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_HOME, 1);
1370 tmp = g_strdup_printf(_("%s Document"),pdf_viewer_mimepart_get_type(viewer->to_load) == TYPE_PDF ? "PDF":"Postscript");
1372 GTK_WIDGET(viewer->icon_type_ebox),
1376 tmp = g_strdup_printf(_("of %d"), viewer->num_pages);
1377 gtk_label_set_text(GTK_LABEL(viewer->doc_label), tmp);
1380 pdf_viewer_show_controls(viewer, TRUE);
1381 main_window_cursor_normal(mainwindow_get_mainwindow());
1383 if (viewer->pdf_doc == NULL) {
1384 stock_pixbuf_gdk(STOCK_PIXMAP_MIME_APPLICATION,
1385 &viewer->icon_pixbuf);
1387 gtk_image_set_from_pixbuf(GTK_IMAGE(viewer->icon_type), viewer->icon_pixbuf);
1389 strretchomp(error->message);
1390 alertpanel_error("%s", error->message);
1392 alertpanel_error(_("PDF rendering failed for an unknown reason."));
1394 pdf_viewer_show_controls(viewer, FALSE);
1395 g_error_free(error);
1399 if (page_num == 1) {
1400 gtk_widget_set_sensitive(viewer->first_page, FALSE);
1401 gtk_widget_set_sensitive(viewer->prev_page, FALSE);
1404 gtk_widget_set_sensitive(viewer->first_page, TRUE);
1405 gtk_widget_set_sensitive(viewer->prev_page, TRUE);
1408 if (page_num == viewer->num_pages) {
1409 gtk_widget_set_sensitive(viewer->last_page, FALSE);
1410 gtk_widget_set_sensitive(viewer->next_page, FALSE);
1413 gtk_widget_set_sensitive(viewer->last_page, TRUE);
1414 gtk_widget_set_sensitive(viewer->next_page, TRUE);
1417 /* check for the index if exists */
1418 pdf_viewer_set_index_button_sensitive((PdfViewer *) viewer);
1420 if (page_num > 0 && page_num <= viewer->num_pages) {
1424 if (viewer->pdf_page) {
1425 g_object_unref(G_OBJECT(viewer->pdf_page));
1428 viewer->pdf_page = poppler_document_get_page(viewer->pdf_doc, page_num - 1);
1430 if (viewer->pdf_page == NULL) {
1431 g_warning("Page not found");
1435 if (viewer->rotate == 90 || viewer->rotate == 270) {
1436 poppler_page_get_size(viewer->pdf_page, &viewer->height, &viewer->width);
1439 poppler_page_get_size(viewer->pdf_page, &viewer->width, &viewer->height);
1442 if (viewer->last_rect && viewer->last_page_result &&
1443 viewer->last_page_result->page_num == page_num) {
1444 pdf_viewer_render_selection(viewer, viewer->last_rect, viewer->last_page_result);
1447 pdf_viewer_render_page(viewer->pdf_page, viewer->pdf_view, viewer->width,
1448 viewer->height, viewer->zoom, viewer->rotate);
1452 /* Get Links Mapping */
1453 if (viewer->link_map) {
1454 poppler_page_free_link_mapping(viewer->link_map);
1456 viewer->link_map = poppler_page_get_link_mapping(viewer->pdf_page);
1462 static void pdf_viewer_show_mimepart(MimeViewer *_viewer, const gchar *infile,
1465 PdfViewer *viewer = (PdfViewer *) _viewer;
1467 const gchar *charset = NULL;
1468 MessageView *messageview = ((MimeViewer *)viewer)->mimeview
1469 ?((MimeViewer *)viewer)->mimeview->messageview
1473 viewer->to_load = partinfo;
1476 messageview->updating = TRUE;
1478 memset(buf, 0, sizeof(buf));
1479 debug_print("pdf_viewer_show_mimepart\n");
1481 if (viewer->filename != NULL) {
1482 claws_unlink(viewer->filename);
1483 g_free(viewer->filename);
1484 viewer->filename = NULL;
1487 viewer->mimeinfo = NULL;
1490 viewer->target_filename = procmime_get_part_file_name(partinfo);
1491 viewer->filename = procmime_get_tmp_file_name(partinfo);
1492 viewer->fsname = g_filename_to_uri(viewer->filename, NULL, NULL);
1495 if (partinfo && !(procmime_get_part(viewer->filename, partinfo) < 0)) {
1497 if (messageview && messageview->forced_charset)
1498 charset = _viewer->mimeview->messageview->forced_charset;
1500 charset = procmime_mimeinfo_get_parameter(partinfo, "charset");
1502 if (charset == NULL) {
1503 charset = conv_get_locale_charset_str();
1506 debug_print("using charset %s\n", charset);
1508 viewer->mimeinfo = partinfo;
1511 pdf_viewer_update((MimeViewer *)viewer, TRUE, 1);
1514 messageview->updating = FALSE;
1517 static void pdf_viewer_clear(MimeViewer *_viewer)
1519 PdfViewer *viewer = (PdfViewer *) _viewer;
1520 GtkAdjustment *vadj;
1522 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(viewer->doc_index), FALSE);
1523 gtk_widget_hide(viewer->frame_index);
1525 debug_print("pdf_viewer_clear\n");
1526 viewer->to_load = NULL;
1528 if (viewer->pdf_doc) {
1529 g_object_unref(G_OBJECT(viewer->pdf_doc));
1530 viewer->pdf_doc = NULL;
1533 vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin));
1534 gtk_adjustment_set_value(vadj, 0.0);
1535 g_signal_emit_by_name(G_OBJECT(vadj), "value-changed", 0);
1536 vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewer->scrollwin_index));
1537 gtk_adjustment_set_value(vadj, 0.0);
1538 g_signal_emit_by_name(G_OBJECT(vadj), "value-changed", 0);
1539 gtk_tree_store_clear(GTK_TREE_STORE(viewer->index_model));
1540 gtk_image_set_from_pixbuf(GTK_IMAGE(viewer->pdf_view), NULL);
1543 static void pdf_viewer_destroy(MimeViewer *_viewer)
1545 PdfViewer *viewer = (PdfViewer *) _viewer;
1547 debug_print("pdf_viewer_destroy\n");
1549 if (viewer->pdf_index) poppler_index_iter_free(viewer->pdf_index);
1551 poppler_page_free_link_mapping (viewer->link_map);
1552 g_object_unref(GTK_WIDGET(viewer->vbox));
1553 g_object_unref(GTK_WIDGET(viewer->pdf_view));
1554 g_object_unref(GTK_WIDGET(viewer->doc_index_pane));
1555 g_object_unref(GTK_WIDGET(viewer->scrollwin));
1556 g_object_unref(GTK_WIDGET(viewer->scrollwin_index));
1557 claws_unlink(viewer->filename);
1558 g_free(viewer->filename);
1562 static gboolean pdf_viewer_scroll_page(MimeViewer *_viewer, gboolean up)
1564 PdfViewer *viewer = (PdfViewer *)_viewer;
1565 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1566 GTK_SCROLLED_WINDOW(viewer->scrollwin));
1568 gint cur_p = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page));
1570 if (viewer->pdf_view == NULL) return FALSE;
1572 if (!gtkutils_scroll_page(GTK_WIDGET(viewer->pdf_view), vadj, up)) {
1573 if (!up && cur_p != viewer->num_pages) {
1574 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_STEP_FORWARD, 1);
1575 vadj = gtk_scrolled_window_get_vadjustment(
1576 GTK_SCROLLED_WINDOW(viewer->scrollwin));
1577 gtk_adjustment_set_value(vadj, 0.0);
1578 g_signal_emit_by_name(G_OBJECT(vadj), "value-changed", 0);
1581 else if (up && cur_p != 1) {
1582 gtk_spin_button_spin(GTK_SPIN_BUTTON(viewer->cur_page), GTK_SPIN_STEP_BACKWARD, 1);
1583 vadj = gtk_scrolled_window_get_vadjustment(
1584 GTK_SCROLLED_WINDOW(viewer->scrollwin));
1585 gtk_adjustment_set_value(vadj,
1586 gtk_adjustment_get_upper(vadj) - gtk_adjustment_get_page_size(vadj));
1587 g_signal_emit_by_name(G_OBJECT(vadj), "value-changed", 0);
1595 static void pdf_viewer_scroll_one_line(MimeViewer *_viewer, gboolean up)
1597 PdfViewer *viewer = (PdfViewer *)_viewer;
1598 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1599 GTK_SCROLLED_WINDOW(viewer->scrollwin));
1601 cur_p = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(viewer->cur_page));
1603 if (viewer->pdf_view == NULL) return;
1604 debug_print("up: %d\n", up);
1605 if (gtk_adjustment_get_value(vadj) < (gtk_adjustment_get_upper(vadj) - gtk_adjustment_get_page_size(vadj))) {
1606 gtkutils_scroll_one_line(GTK_WIDGET(viewer->pdf_view), vadj, up);
1609 if (cur_p != viewer->num_pages) {
1610 pdf_viewer_scroll_page((MimeViewer *)viewer, up);
1616 #define BUTTON_H_PADDING 3
1617 #define ADD_BUTTON_TO_TABLE(widget, stock_image) \
1618 widget = gtk_button_new(); \
1619 img = stock_pixmap_widget(stock_image); \
1620 gtk_button_set_image(GTK_BUTTON(widget), img); \
1621 gtk_table_attach(GTK_TABLE(viewer->widgets_table), GTK_WIDGET(widget), \
1622 col, col+1, 0, 1, 0, 0, BUTTON_H_PADDING, 0); \
1625 #define ADD_SEP_TO_TABLE \
1626 sep = gtk_label_new(""); \
1627 gtk_table_attach(GTK_TABLE(viewer->widgets_table), GTK_WIDGET(sep), \
1628 col, col+1, 0, 1, 0, 0, 0, 0); \
1629 gtk_table_set_col_spacing(GTK_TABLE(viewer->widgets_table), col, 3*BUTTON_H_PADDING); \
1632 #if POPPLER_HAS_CAIRO
1633 static PangoContext *pdf_viewer_get_pango_context(gpointer data)
1638 static gpointer pdf_viewer_get_data_to_print(gpointer data, gint sel_start, gint sel_end)
1640 return NULL; /* we don't need it */
1643 static void pdf_viewer_cb_begin_print(GtkPrintOperation *op, GtkPrintContext *context,
1646 PrintData *print_data;
1647 PopplerDocument *pdf_doc;
1649 print_data = (PrintData*) user_data;
1650 pdf_doc = (PopplerDocument *)printing_get_renderer_data(print_data);
1652 debug_print("Preparing print job...\n");
1654 n_pages = poppler_document_get_n_pages(pdf_doc);
1655 printing_set_n_pages(print_data, n_pages);
1656 gtk_print_operation_set_n_pages(op, n_pages);
1658 debug_print("Starting print job...\n");
1661 static void pdf_viewer_cb_draw_page(GtkPrintOperation *op, GtkPrintContext *context,
1662 int page_nr, gpointer user_data)
1665 PrintData *print_data;
1666 PopplerDocument *pdf_doc;
1667 PopplerPage *pdf_page;
1669 print_data = (PrintData*) user_data;
1670 pdf_doc = (PopplerDocument *)printing_get_renderer_data(print_data);
1671 pdf_page = poppler_document_get_page(pdf_doc, page_nr);
1673 cr = gtk_print_context_get_cairo_context(context);
1674 cairo_scale(cr, printing_get_zoom(print_data), printing_get_zoom(print_data));
1675 cairo_set_source_rgb(cr, 0., 0., 0.);
1677 poppler_page_render_for_printing(pdf_page, cr);
1679 g_object_unref(G_OBJECT(pdf_page));
1681 debug_print("Sent page %d to printer\n", page_nr+1);
1684 static void pdf_viewer_print(MimeViewer *mviewer)
1686 PdfViewer *viewer = (PdfViewer *)mviewer;
1687 PrintRenderer *pdf_renderer = g_new0(PrintRenderer, 1);
1688 MainWindow *mainwin = mainwindow_get_mainwindow();
1690 pdf_renderer->get_pango_context = pdf_viewer_get_pango_context;
1691 pdf_renderer->get_data_to_print = pdf_viewer_get_data_to_print;
1692 pdf_renderer->cb_begin_print = pdf_viewer_cb_begin_print;
1693 pdf_renderer->cb_draw_page = pdf_viewer_cb_draw_page;
1695 printing_print_full(mainwin ? GTK_WINDOW(mainwin->window):NULL,
1696 pdf_renderer, viewer->pdf_doc, -1, -1, NULL);
1698 g_free(pdf_renderer);
1702 static MimeViewer *pdf_viewer_create(void)
1705 GtkTreeViewColumn *column;
1706 GtkCellRenderer *renderer;
1707 GtkTreeStore *tree_store;
1712 viewer = g_new0(PdfViewer, 1);
1713 debug_print("pdf_viewer_create\n");
1717 viewer->mimeviewer.factory = &pdf_viewer_factory;
1718 viewer->mimeviewer.get_widget = pdf_viewer_get_widget;
1719 viewer->mimeviewer.show_mimepart = pdf_viewer_show_mimepart;
1720 viewer->mimeviewer.clear_viewer = pdf_viewer_clear;
1721 viewer->mimeviewer.destroy_viewer = pdf_viewer_destroy;
1722 viewer->mimeviewer.text_search = pdf_viewer_text_search;
1723 viewer->mimeviewer.scroll_page = pdf_viewer_scroll_page;
1724 viewer->mimeviewer.scroll_one_line = pdf_viewer_scroll_one_line;
1725 #if POPPLER_HAS_CAIRO
1726 viewer->mimeviewer.print = pdf_viewer_print;
1728 viewer->scrollwin = gtk_scrolled_window_new(NULL, NULL);
1729 viewer->scrollwin_index = gtk_scrolled_window_new(NULL, NULL);
1730 viewer->pdf_view_ebox = gtk_event_box_new();
1731 gtk_event_box_set_visible_window(GTK_EVENT_BOX(viewer->pdf_view_ebox), FALSE);
1733 viewer->mimeinfo = NULL;
1735 viewer->pdf_view = gtk_image_new();
1736 gtk_widget_set_events(viewer->pdf_view_ebox,
1737 GDK_BUTTON_RELEASE_MASK
1738 | GDK_POINTER_MOTION_MASK
1739 | GDK_BUTTON_PRESS_MASK
1740 | GDK_BUTTON_MOTION_MASK
1742 gtk_container_add (GTK_CONTAINER(viewer->pdf_view_ebox), viewer->pdf_view);
1743 viewer->icon_type = gtk_image_new();
1744 viewer->icon_type_ebox = gtk_event_box_new();
1746 gtk_container_add(GTK_CONTAINER(viewer->icon_type_ebox), viewer->icon_type);
1748 viewer->doc_label = gtk_label_new("");
1750 viewer->widgets_table = gtk_table_new(1, 1, FALSE);
1752 viewer->doc_index_pane = gtk_hpaned_new();
1754 viewer->frame_index = gtk_frame_new(NULL);
1755 gtk_frame_set_shadow_type(GTK_FRAME(viewer->frame_index), GTK_SHADOW_IN);
1756 gtk_widget_set_size_request(viewer->frame_index, 18, -1);
1757 gtk_frame_set_label(GTK_FRAME(viewer->frame_index), _("Document Index"));
1760 ADD_BUTTON_TO_TABLE(viewer->first_page, STOCK_PIXMAP_FIRST_ARROW)
1761 ADD_BUTTON_TO_TABLE(viewer->prev_page, STOCK_PIXMAP_LEFT_ARROW)
1762 viewer->cur_page = gtk_spin_button_new_with_range(0.0, 0.0, 1.0);
1763 viewer->zoom_scroll = gtk_spin_button_new_with_range(0.20, 8.0, 0.20);
1764 gtk_spin_button_set_value(GTK_SPIN_BUTTON(viewer->zoom_scroll), 1.0);
1766 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(viewer->cur_page), TRUE);
1767 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(viewer->zoom_scroll), TRUE);
1768 gtk_table_attach(GTK_TABLE(viewer->widgets_table), GTK_WIDGET(viewer->cur_page),
1774 gtk_table_attach(GTK_TABLE(viewer->widgets_table), GTK_WIDGET(viewer->doc_label),
1781 ADD_BUTTON_TO_TABLE(viewer->next_page, STOCK_PIXMAP_RIGHT_ARROW)
1782 ADD_BUTTON_TO_TABLE(viewer->last_page, STOCK_PIXMAP_LAST_ARROW)
1784 ADD_BUTTON_TO_TABLE(viewer->zoom_fit, STOCK_PIXMAP_ZOOM_FIT)
1785 ADD_BUTTON_TO_TABLE(viewer->zoom_in, STOCK_PIXMAP_ZOOM_IN)
1786 gtk_table_attach(GTK_TABLE(viewer->widgets_table), GTK_WIDGET(viewer->zoom_scroll),
1792 ADD_BUTTON_TO_TABLE(viewer->zoom_out, STOCK_PIXMAP_ZOOM_OUT)
1793 ADD_BUTTON_TO_TABLE(viewer->zoom_width, STOCK_PIXMAP_ZOOM_WIDTH)
1795 ADD_BUTTON_TO_TABLE(viewer->rotate_left, STOCK_PIXMAP_ROTATE_LEFT)
1796 ADD_BUTTON_TO_TABLE(viewer->rotate_right, STOCK_PIXMAP_ROTATE_RIGHT)
1798 ADD_BUTTON_TO_TABLE(viewer->print, STOCK_PIXMAP_PRINTER)
1799 ADD_BUTTON_TO_TABLE(viewer->doc_info, STOCK_PIXMAP_DOC_INFO)
1800 ADD_BUTTON_TO_TABLE(viewer->doc_index, STOCK_PIXMAP_DOC_INDEX)
1802 gtk_scrolled_window_set_policy(
1803 GTK_SCROLLED_WINDOW(viewer->scrollwin),
1804 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1806 gtk_scrolled_window_set_shadow_type(
1807 GTK_SCROLLED_WINDOW(viewer->scrollwin),
1810 gtk_scrolled_window_add_with_viewport(
1811 GTK_SCROLLED_WINDOW(viewer->scrollwin),
1812 viewer->pdf_view_ebox);
1814 viewer->vbox = gtk_vbox_new(FALSE, 4);
1815 viewer->hbox = gtk_hbox_new(FALSE, 4);
1818 tree_store = gtk_tree_store_new(N_INDEX_COLUMNS,
1823 viewer->index_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tree_store));
1824 renderer = gtk_cell_renderer_text_new();
1825 column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", 0, NULL);
1826 gtk_tree_view_append_column(GTK_TREE_VIEW(viewer->index_list), column);
1827 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(viewer->index_list), FALSE);
1829 viewer->index_model = GTK_TREE_MODEL(tree_store);
1831 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(viewer->index_list)),
1832 GTK_SELECTION_SINGLE);
1834 g_signal_connect(G_OBJECT(viewer->index_list), "row_activated",
1835 G_CALLBACK(pdf_viewer_index_row_activated),
1838 gtk_scrolled_window_set_policy(
1839 GTK_SCROLLED_WINDOW(viewer->scrollwin_index),
1840 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1842 gtk_scrolled_window_set_shadow_type(
1843 GTK_SCROLLED_WINDOW(viewer->scrollwin_index),
1846 gtk_scrolled_window_add_with_viewport(
1847 GTK_SCROLLED_WINDOW(viewer->scrollwin_index),
1848 viewer->index_list);
1852 stock_pixbuf_gdk(STOCK_PIXMAP_MIME_TEXT_PLAIN,
1853 &viewer->icon_pixbuf);
1855 gtk_image_set_from_pixbuf(GTK_IMAGE(viewer->icon_type),
1856 viewer->icon_pixbuf);
1859 gtk_box_pack_start(GTK_BOX(viewer->hbox), viewer->icon_type_ebox, FALSE, FALSE, 0);
1860 gtk_box_pack_start(GTK_BOX(viewer->hbox), viewer->widgets_table, FALSE, FALSE, 0);
1862 gtk_container_add(GTK_CONTAINER(viewer->frame_index), viewer->scrollwin_index);
1864 gtk_paned_pack1(GTK_PANED(viewer->doc_index_pane), viewer->frame_index, FALSE, FALSE);
1865 gtk_paned_pack2(GTK_PANED(viewer->doc_index_pane), viewer->scrollwin, FALSE, FALSE);
1867 gtk_box_pack_start(GTK_BOX(viewer->vbox), viewer->hbox, FALSE, FALSE, 0);
1868 gtk_box_pack_start(GTK_BOX(viewer->vbox), viewer->doc_index_pane, TRUE, TRUE, 0);
1870 gtk_widget_show(GTK_WIDGET(viewer->doc_index_pane));
1871 g_object_ref(GTK_WIDGET(viewer->doc_index_pane));
1872 gtk_widget_show(GTK_WIDGET(viewer->scrollwin));
1873 g_object_ref(GTK_WIDGET(viewer->scrollwin));
1874 gtk_widget_show(GTK_WIDGET(viewer->icon_type_ebox));
1875 g_object_ref(GTK_WIDGET(viewer->icon_type_ebox));
1876 gtk_widget_show(GTK_WIDGET(viewer->pdf_view_ebox));
1877 g_object_ref(GTK_WIDGET(viewer->pdf_view_ebox));
1878 gtk_widget_show(GTK_WIDGET(viewer->scrollwin_index));
1879 g_object_ref(GTK_WIDGET(viewer->scrollwin_index));
1880 gtk_widget_show(GTK_WIDGET(viewer->hbox));
1881 g_object_ref(GTK_WIDGET(viewer->hbox));
1882 gtk_widget_show(GTK_WIDGET(viewer->vbox));
1883 g_object_ref(GTK_WIDGET(viewer->vbox));
1885 gtk_widget_show(GTK_WIDGET(viewer->widgets_table));
1886 g_object_ref(GTK_WIDGET(viewer->widgets_table));
1888 gtk_widget_show(GTK_WIDGET(viewer->cur_page));
1889 g_object_ref(GTK_WIDGET(viewer->cur_page));
1891 gtk_widget_show(GTK_WIDGET(viewer->first_page));
1892 g_object_ref(GTK_WIDGET(viewer->first_page));
1894 gtk_widget_show(GTK_WIDGET(viewer->last_page));
1895 g_object_ref(GTK_WIDGET(viewer->last_page));
1897 gtk_widget_show(GTK_WIDGET(viewer->prev_page));
1898 g_object_ref(GTK_WIDGET(viewer->prev_page));
1900 gtk_widget_show(GTK_WIDGET(viewer->next_page));
1901 g_object_ref(GTK_WIDGET(viewer->next_page));
1903 gtk_widget_show(GTK_WIDGET(viewer->zoom_in));
1904 g_object_ref(GTK_WIDGET(viewer->zoom_in));
1905 gtk_widget_show(GTK_WIDGET(viewer->zoom_out));
1906 g_object_ref(GTK_WIDGET(viewer->zoom_out));
1907 gtk_widget_show(GTK_WIDGET(viewer->zoom_fit));
1908 g_object_ref(GTK_WIDGET(viewer->zoom_fit));
1909 gtk_widget_show(GTK_WIDGET(viewer->zoom_width));
1910 g_object_ref(GTK_WIDGET(viewer->zoom_width));
1912 gtk_widget_show(GTK_WIDGET(viewer->rotate_right));
1913 g_object_ref(GTK_WIDGET(viewer->rotate_right));
1914 gtk_widget_show(GTK_WIDGET(viewer->rotate_left));
1915 g_object_ref(GTK_WIDGET(viewer->rotate_left));
1916 gtk_widget_show(GTK_WIDGET(viewer->print));
1917 g_object_ref(GTK_WIDGET(viewer->print));
1918 gtk_widget_show(GTK_WIDGET(viewer->doc_info));
1919 g_object_ref(GTK_WIDGET(viewer->doc_info));
1920 gtk_widget_show(GTK_WIDGET(viewer->doc_index));
1921 g_object_ref(GTK_WIDGET(viewer->doc_index));
1923 gtk_widget_show(GTK_WIDGET(viewer->doc_label));
1924 g_object_ref(GTK_WIDGET(viewer->doc_label));
1925 gtk_widget_show(GTK_WIDGET(viewer->icon_type));
1926 g_object_ref(GTK_WIDGET(viewer->icon_type));
1927 gtk_widget_show(GTK_WIDGET(viewer->pdf_view));
1928 g_object_ref(GTK_WIDGET(viewer->pdf_view));
1929 gtk_widget_show(GTK_WIDGET(viewer->zoom_scroll));
1930 g_object_ref(GTK_WIDGET(viewer->zoom_scroll));
1932 gtk_widget_show(GTK_WIDGET(viewer->index_list));
1933 g_object_ref(GTK_WIDGET(viewer->index_list));
1936 CLAWS_SET_TIP(viewer->first_page,
1939 CLAWS_SET_TIP(viewer->prev_page,
1940 _("Previous Page"));
1942 CLAWS_SET_TIP(viewer->next_page,
1945 CLAWS_SET_TIP(viewer->last_page,
1948 CLAWS_SET_TIP(viewer->zoom_in,
1950 CLAWS_SET_TIP(viewer->zoom_out,
1953 CLAWS_SET_TIP(viewer->zoom_fit,
1956 CLAWS_SET_TIP(viewer->zoom_width,
1957 _("Fit Page Width"));
1959 CLAWS_SET_TIP(viewer->rotate_left,
1962 CLAWS_SET_TIP(viewer->rotate_right,
1965 CLAWS_SET_TIP(viewer->print,
1966 _("Print Document"));
1968 CLAWS_SET_TIP(viewer->doc_info,
1969 _("Document Info"));
1971 CLAWS_SET_TIP(viewer->doc_index,
1972 _("Document Index"));
1973 CLAWS_SET_TIP(viewer->cur_page,
1975 CLAWS_SET_TIP(viewer->zoom_scroll,
1977 /* Connect Signals */
1978 g_signal_connect(G_OBJECT(viewer->cur_page),
1980 G_CALLBACK(pdf_viewer_spin_change_page_cb),
1983 g_signal_connect(G_OBJECT(viewer->first_page),
1985 G_CALLBACK(pdf_viewer_button_first_page_cb),
1987 g_signal_connect(G_OBJECT(viewer->prev_page),
1989 G_CALLBACK(pdf_viewer_button_prev_page_cb),
1991 g_signal_connect(G_OBJECT(viewer->next_page),
1993 G_CALLBACK(pdf_viewer_button_next_page_cb),
1995 g_signal_connect(G_OBJECT(viewer->last_page),
1997 G_CALLBACK(pdf_viewer_button_last_page_cb),
1999 g_signal_connect(G_OBJECT(viewer->zoom_in),
2001 G_CALLBACK(pdf_viewer_button_zoom_in_cb),
2003 g_signal_connect(G_OBJECT(viewer->zoom_out),
2005 G_CALLBACK(pdf_viewer_button_zoom_out_cb),
2007 g_signal_connect(G_OBJECT(viewer->zoom_scroll),
2009 G_CALLBACK(pdf_viewer_spin_zoom_scroll_cb),
2012 g_signal_connect(G_OBJECT(viewer->zoom_fit),
2014 G_CALLBACK(pdf_viewer_button_zoom_fit_cb),
2017 g_signal_connect(G_OBJECT(viewer->zoom_width),
2019 G_CALLBACK(pdf_viewer_button_zoom_width_cb),
2022 g_signal_connect(G_OBJECT(viewer->rotate_right),
2024 G_CALLBACK(pdf_viewer_button_rotate_right_cb),
2027 g_signal_connect(G_OBJECT(viewer->rotate_left),
2029 G_CALLBACK(pdf_viewer_button_rotate_left_cb),
2032 g_signal_connect(G_OBJECT(viewer->print),
2034 G_CALLBACK(pdf_viewer_button_print_cb),
2037 g_signal_connect(G_OBJECT(viewer->doc_info),
2039 G_CALLBACK(pdf_viewer_button_document_info_cb),
2042 g_signal_connect(G_OBJECT(viewer->doc_index),
2044 G_CALLBACK(pdf_viewer_show_document_index_cb),
2046 g_signal_connect(G_OBJECT(viewer->scrollwin),
2048 G_CALLBACK(pdf_viewer_scroll_cb),
2050 g_signal_connect(G_OBJECT(viewer->pdf_view_ebox),
2051 "button_press_event",
2052 G_CALLBACK(pdf_viewer_button_press_events_cb),
2054 g_signal_connect(G_OBJECT(viewer->pdf_view_ebox),
2055 "button_release_event",
2056 G_CALLBACK(pdf_viewer_mouse_scroll_destroy_cb),
2058 g_signal_connect(G_OBJECT(viewer->pdf_view_ebox),
2059 "motion_notify_event",
2060 G_CALLBACK(pdf_viewer_move_events_cb),
2063 viewer->target_filename = NULL;
2064 viewer->filename = NULL;
2065 viewer->fsname = NULL;
2067 return(MimeViewer *) viewer;
2070 #undef ADD_BUTTON_TO_TABLE
2071 #undef ADD_SEP_TO_TABLE
2072 #undef BUTTON_H_PADDING
2073 #undef SEP_H_PADDING
2075 static MimeViewerFactory pdf_viewer_factory =
2082 gint plugin_init(gchar **error)
2084 gchar *gspath = NULL;
2086 msg = g_strdup_printf(_("This plugin enables the viewing of PDF and PostScript "
2087 "attachments using the Poppler %s Lib and the gs tool.\n\n"
2088 "Any feedback is welcome: iwkse@claws-mail.org"
2089 ), poppler_get_version());
2091 if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
2092 VERSION_NUMERIC, _("PDF Viewer"), error)) return -1;
2094 if ((gspath = g_find_program_in_path("gs")) == NULL) {
2096 msg = g_strdup_printf(_("Warning: could not find ghostscript binary (gs) required "
2097 "for %s plugin to process PostScript attachments, only PDF "
2098 "attachments will be displayed. To enable PostScript "
2099 "support please install gs program.\n\n%s"
2100 ), _("PDF Viewer"), pmsg);
2107 mimeview_register_viewer_factory(&pdf_viewer_factory);
2111 gboolean plugin_done(void)
2114 mimeview_unregister_viewer_factory(&pdf_viewer_factory);
2118 const gchar *plugin_name(void)
2120 return _("PDF Viewer");
2123 const gchar *plugin_desc(void)
2128 const gchar *plugin_type(void)
2133 const gchar *plugin_licence(void)
2138 const gchar *plugin_version(void)
2143 struct PluginFeature *plugin_provides(void)
2145 static struct PluginFeature features[] =
2146 { {PLUGIN_MIMEVIEWER, "application/pdf"},
2147 {PLUGIN_MIMEVIEWER, "application/postscript"},
2148 {PLUGIN_NOTHING, NULL} };