1 /* Ghostscript widget for GTK/GNOME
3 * Copyright (C) 1998 - 2005 the Free Software Foundation
5 * Authors: Jonathan Blandford, Jaka Mocnik
7 * Based on code by: Federico Mena (Quartic), Szekeres Istvan (Pista)
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 Ghostview interface to ghostscript
28 When the GHOSTVIEW environment variable is set, ghostscript draws on
29 an existing drawable rather than creating its own window. Ghostscript
30 can be directed to draw on either a window or a pixmap.
34 The GHOSTVIEW environment variable contains the window id of the target
35 window. The window id is an integer. Ghostscript will use the attributes
36 of the window to obtain the width, height, colormap, screen, and visual of
37 the window. The remainder of the information is gotten from the GHOSTVIEW
38 property on that window.
43 The GHOSTVIEW environment variable contains a window id and a pixmap id.
44 They are integers separated by white space. Ghostscript will use the
45 attributes of the window to obtain the colormap, screen, and visual to use.
46 The width and height will be obtained from the pixmap. The remainder of the
47 information, is gotten from the GHOSTVIEW property on the window. In this
48 case, the property is deleted when read.
50 The GHOSTVIEW environment variable
52 parameters: window-id [pixmap-id]
56 explanation of parameters:
58 window-id: tells ghostscript where to
59 - read the GHOSTVIEW property
61 If pixmap-id is not present,
62 ghostscript will draw on this window.
64 pixmap-id: If present, tells ghostscript that a pixmap will be used
65 as the final destination for drawing. The window will
66 not be touched for drawing purposes.
68 The GHOSTVIEW property
74 bpixmap orient llx lly urx ury xdpi ydpi [left bottom top right]
76 scanf format: "%d %d %d %d %d %d %f %f %d %d %d %d"
78 explanation of parameters:
80 bpixmap: pixmap id of the backing pixmap for the window. If no
81 pixmap is to be used, this parameter should be zero. This
82 parameter must be zero when drawing on a pixmap.
84 orient: orientation of the page. The number represents clockwise
85 rotation of the paper in degrees. Permitted values are
88 llx, lly, urx, ury: Bounding box of the drawable. The bounding box
89 is specified in PostScript points in default user coordinates.
91 xdpi, ydpi: Resolution of window. (This can be derived from the
92 other parameters, but not without roundoff error. These
93 values are included to avoid this error.)
95 left, bottom, top, right: (optional)
96 Margins around the window. The margins extend the imageable
97 area beyond the boundaries of the window. This is primarily
98 used for popup zoom windows. I have encountered several
99 instances of PostScript programs that position themselves
100 with respect to the imageable area. The margins are specified
101 in PostScript points. If omitted, the margins are assumed to
104 Events from ghostscript
106 If the final destination is a pixmap, the client will get a property notify
107 event when ghostscript reads the GHOSTVIEW property causing it to be deleted.
109 Ghostscript sends events to the window where it read the GHOSTVIEW property.
110 These events are of type ClientMessage. The message_type is set to
111 either PAGE or DONE. The first long data value gives the window to be used
112 to send replies to ghostscript. The second long data value gives the primary
113 drawable. If rendering to a pixmap, it is the primary drawable. If rendering
114 to a window, the backing pixmap is the primary drawable. If no backing pixmap
115 is employed, then the window is the primary drawable. This field is necessary
116 to distinguish multiple ghostscripts rendering to separate pixmaps where the
117 GHOSTVIEW property was placed on the same window.
119 The PAGE message indicates that a "page" has completed. Ghostscript will
120 wait until it receives a ClientMessage whose message_type is NEXT before
123 The DONE message indicates that ghostscript has finished processing.
132 #include <gtk/gtkobject.h>
133 #include <gdk/gdkprivate.h>
134 #include <gdk/gdkx.h>
137 # include <gdk/gdkx.h>
138 # include <X11/extensions/Xinerama.h>
139 #endif /* HAVE_XINERAMA */
140 #include <X11/Intrinsic.h>
145 #include <sys/stat.h>
146 #include <sys/types.h>
147 #include <sys/wait.h>
151 #include "ev-document.h"
153 #include "ggvutils.h"
155 #include "gsdefaults.h"
161 /* if POSIX O_NONBLOCK is not available, use O_NDELAY */
162 #if !defined(O_NONBLOCK) && defined(O_NDELAY)
163 # define O_NONBLOCK O_NDELAY
166 #define GTK_GS_WATCH_INTERVAL 1000
167 #define GTK_GS_WATCH_TIMEOUT 2
169 #define MAX_BUFSIZE 1024
171 enum { INTERPRETER_MESSAGE, INTERPRETER_ERROR, LAST_SIGNAL };
173 static gboolean broken_pipe = FALSE;
181 /* Forward declarations */
182 static void gtk_gs_init(GtkGS * gs);
183 static void gtk_gs_class_init(GtkGSClass * klass);
184 static void gtk_gs_interpreter_message(GtkGS * gs, gchar * msg,
186 static void gtk_gs_emit_error_msg(GtkGS * gs, const gchar * msg);
187 static void gtk_gs_finalize(GObject * object);
188 static void send_ps(GtkGS * gs, long begin, unsigned int len, gboolean close);
189 static void set_up_page(GtkGS * gs);
190 static void close_pipe(int p[2]);
191 static void interpreter_failed(GtkGS * gs);
192 static float compute_xdpi(void);
193 static float compute_ydpi(void);
194 static gboolean compute_size(GtkGS * gs);
195 static void output(gpointer data, gint source, GdkInputCondition condition);
196 static void input(gpointer data, gint source, GdkInputCondition condition);
197 static void stop_interpreter(GtkGS * gs);
198 static gint start_interpreter(GtkGS * gs);
199 gboolean computeSize(void);
200 static void ps_document_document_iface_init (EvDocumentIface *iface);
202 static GObjectClass *parent_class = NULL;
204 static GtkGSClass *gs_class = NULL;
206 static gint gtk_gs_signals[LAST_SIGNAL] = { 0 };
208 /* Static, private functions */
211 ggv_marshaller_VOID__POINTER(GClosure * closure,
212 GValue * return_value,
213 guint n_param_values,
214 const GValue * param_values,
215 gpointer invocation_hint, gpointer marshal_data)
217 typedef void (*GMarshalFunc_VOID__POINTER) (gpointer data1,
218 gpointer arg_1, gpointer data2);
219 register GMarshalFunc_VOID__POINTER callback;
220 register GCClosure *cc = (GCClosure *) closure;
221 register gpointer data1, data2;
223 g_return_if_fail(n_param_values == 2);
225 if(G_CCLOSURE_SWAP_DATA(closure)) {
226 data1 = closure->data;
227 data2 = g_value_peek_pointer(param_values + 0);
230 data1 = g_value_peek_pointer(param_values + 0);
231 data2 = closure->data;
234 (GMarshalFunc_VOID__POINTER) (marshal_data ? marshal_data : cc->callback);
236 callback(data1, g_value_get_pointer(param_values + 1), data2);
240 ggv_marshaller_VOID__INT(GClosure * closure,
241 GValue * return_value,
242 guint n_param_values,
243 const GValue * param_values,
244 gpointer invocation_hint, gpointer marshal_data)
246 typedef void (*GMarshalFunc_VOID__INT) (gpointer data1,
247 gint arg_1, gpointer data2);
248 register GMarshalFunc_VOID__INT callback;
249 register GCClosure *cc = (GCClosure *) closure;
250 register gpointer data1, data2;
252 g_return_if_fail(n_param_values == 2);
254 if(G_CCLOSURE_SWAP_DATA(closure)) {
255 data1 = closure->data;
256 data2 = g_value_peek_pointer(param_values + 0);
259 data1 = g_value_peek_pointer(param_values + 0);
260 data2 = closure->data;
263 (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback);
265 callback(data1, g_value_get_int(param_values + 1), data2);
269 gtk_gs_init(GtkGS * gs)
273 gs->current_page = -2;
274 gs->disable_start = FALSE;
275 gs->interpreter_pid = -1;
281 gs->gs_scanstyle = 0;
283 gs->gs_filename_dsc = 0;
284 gs->gs_filename_unc = 0;
288 gs->structured_doc = FALSE;
289 gs->reading_from_pipe = FALSE;
290 gs->send_filename_to_gs = FALSE;
295 gs->interpreter_input = -1;
296 gs->interpreter_output = -1;
297 gs->interpreter_err = -1;
298 gs->interpreter_input_id = 0;
299 gs->interpreter_output_id = 0;
300 gs->interpreter_error_id = 0;
303 gs->input_buffer = NULL;
304 gs->input_buffer_ptr = NULL;
306 gs->buffer_bytes_left = 0;
312 gs->xdpi = compute_xdpi();
313 gs->ydpi = compute_ydpi();
317 gs->right_margin = 0;
318 gs->bottom_margin = 0;
320 /* Set user defined defaults */
321 gs->override_orientation = gtk_gs_defaults_get_override_orientation();
322 gs->fallback_orientation = gtk_gs_defaults_get_orientation();
323 gs->zoom_factor = gtk_gs_defaults_get_zoom_factor();
324 gs->default_size = gtk_gs_defaults_get_size();
325 gs->antialiased = gtk_gs_defaults_get_antialiased();
326 gs->override_size = gtk_gs_defaults_get_override_size();
327 gs->respect_eof = gtk_gs_defaults_get_respect_eof();
328 gs->zoom_mode = gtk_gs_defaults_get_zoom_mode();
330 gs->gs_status = _("No document loaded.");
334 gtk_gs_class_init(GtkGSClass * klass)
336 GObjectClass *object_class;
338 object_class = (GObjectClass *) klass;
339 parent_class = gtk_type_class(gtk_widget_get_type());
342 gtk_gs_signals[INTERPRETER_MESSAGE] = g_signal_new("interpreter_message",
348 interpreter_message),
350 ggv_marshaller_VOID__POINTER,
353 gtk_gs_signals[INTERPRETER_ERROR] =
354 g_signal_new("interpreter_error", G_TYPE_FROM_CLASS(object_class),
355 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GtkGSClass,
357 NULL, NULL, ggv_marshaller_VOID__INT, G_TYPE_NONE, 1,
360 object_class->finalize = gtk_gs_finalize;
363 klass->gs_atom = gdk_atom_intern("GHOSTVIEW", FALSE);
364 klass->gs_colors_atom = gdk_atom_intern("GHOSTVIEW_COLORS", FALSE);
365 klass->next_atom = gdk_atom_intern("NEXT", FALSE);
366 klass->page_atom = gdk_atom_intern("PAGE", FALSE);
367 klass->done_atom = gdk_atom_intern("DONE", FALSE);
368 klass->string_atom = gdk_atom_intern("STRING", FALSE);
370 /* a default handler for "interpreter_message" signal */
371 klass->interpreter_message = gtk_gs_interpreter_message;
373 gtk_gs_defaults_load();
376 /* Clean all memory and temporal files */
378 gtk_gs_cleanup(GtkGS * gs)
380 g_return_if_fail(gs != NULL);
381 g_return_if_fail(GTK_IS_GS(gs));
383 stop_interpreter(gs);
386 fclose(gs->gs_psfile);
387 gs->gs_psfile = NULL;
389 if(gs->gs_filename) {
390 g_free(gs->gs_filename);
391 gs->gs_filename = NULL;
397 if(gs->gs_filename_dsc) {
398 unlink(gs->gs_filename_dsc);
399 g_free(gs->gs_filename_dsc);
400 gs->gs_filename_dsc = NULL;
402 if(gs->gs_filename_unc) {
403 unlink(gs->gs_filename_unc);
404 g_free(gs->gs_filename_unc);
405 gs->gs_filename_unc = NULL;
407 gs->current_page = -1;
416 /* free message as it was allocated in output() */
418 gtk_gs_interpreter_message(GtkGS * gs, gchar * msg, gpointer user_data)
420 gdk_pointer_ungrab(GDK_CURRENT_TIME);
421 if(strstr(msg, "Error:")) {
422 gs->gs_status = _("File is not a valid PostScript document.");
424 g_signal_emit_by_name(G_OBJECT(gs), "interpreter_error", 1, NULL);
430 gtk_gs_finalize(GObject * object)
434 g_return_if_fail(object != NULL);
435 g_return_if_fail(GTK_IS_GS(object));
441 if(gs->input_buffer) {
442 g_free(gs->input_buffer);
443 gs->input_buffer = NULL;
446 (*G_OBJECT_CLASS(parent_class)->finalize) (object);
450 gtk_gs_set_center(GtkGS * gs, gfloat hval, gfloat vval)
455 send_ps(GtkGS * gs, long begin, unsigned int len, gboolean close)
457 struct record_list *ps_new;
459 if(gs->interpreter_input < 0) {
460 g_critical("No pipe to gs: error in send_ps().");
464 ps_new = (struct record_list *) g_malloc(sizeof(struct record_list));
465 ps_new->fp = gs->gs_psfile;
466 ps_new->begin = begin;
468 ps_new->seek_needed = TRUE;
469 ps_new->close = close;
472 if(gs->input_buffer == NULL) {
473 gs->input_buffer = g_malloc(MAX_BUFSIZE);
476 if(gs->ps_input == NULL) {
477 gs->input_buffer_ptr = gs->input_buffer;
478 gs->bytes_left = len;
479 gs->buffer_bytes_left = 0;
480 gs->ps_input = ps_new;
481 gs->interpreter_input_id =
482 gdk_input_add(gs->interpreter_input, GDK_INPUT_WRITE, input, gs);
485 struct record_list *p = gs->ps_input;
486 while(p->next != NULL) {
494 set_up_page(GtkGS * gs)
498 //GdkColormap *colormap;
500 GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF }; /* pixel, r, g, b */
506 if (gs->pstarget == NULL)
509 /* Do we have to check if the actual geometry changed? */
511 stop_interpreter(gs);
513 orientation = gtk_gs_get_orientation(gs);
515 if(compute_size(gs)) {
518 /* clear new pixmap (set to white) */
519 fill = gdk_gc_new(gs->pstarget);
521 gdk_gc_set_foreground(fill, &white);
523 if(gs->width > 0 && gs->height > 0) {
525 gdk_drawable_unref(gs->bpixmap);
529 gs->bpixmap = gdk_pixmap_new(gs->pstarget, gs->width, gs->height, -1);
531 gdk_draw_rectangle(gs->bpixmap, fill, TRUE,
532 0, 0, gs->width, gs->height);
535 gdk_draw_rectangle(gs->pstarget, fill, TRUE,
536 0, 0, gs->width, gs->height);
545 /* gs needs floating point parameters with '.' as decimal point
546 * while some (european) locales use ',' instead, so we set the
547 * locale for this snprintf to "C".
549 savelocale = setlocale(LC_NUMERIC, "C");
552 g_snprintf(buf, 1024, "%ld %d %d %d %d %d %f %f %d %d %d %d",
559 gs->xdpi * gs->zoom_factor,
560 gs->ydpi * gs->zoom_factor,
562 gs->bottom_margin, gs->right_margin, gs->top_margin);
565 setlocale(LC_NUMERIC, savelocale);
567 gdk_property_change(gs->pstarget,
569 gs_class->string_atom,
570 8, GDK_PROP_MODE_REPLACE, buf, strlen(buf));
584 is_interpreter_ready(GtkGS * gs)
586 return (gs->interpreter_pid != -1 && !gs->busy && gs->ps_input == NULL);
590 interpreter_failed(GtkGS * gs)
592 stop_interpreter(gs);
596 output(gpointer data, gint source, GdkInputCondition condition)
598 char buf[MAX_BUFSIZE + 1], *msg;
600 GtkGS *gs = GTK_GS(data);
602 if(source == gs->interpreter_output) {
603 bytes = read(gs->interpreter_output, buf, MAX_BUFSIZE);
604 if(bytes == 0) { /* EOF occurred */
605 close(gs->interpreter_output);
606 gs->interpreter_output = -1;
607 gdk_input_remove(gs->interpreter_output_id);
610 else if(bytes == -1) {
612 interpreter_failed(gs);
615 if(gs->interpreter_err == -1) {
616 stop_interpreter(gs);
619 else if(source == gs->interpreter_err) {
620 bytes = read(gs->interpreter_err, buf, MAX_BUFSIZE);
621 if(bytes == 0) { /* EOF occurred */
622 close(gs->interpreter_err);
623 gs->interpreter_err = -1;
624 gdk_input_remove(gs->interpreter_error_id);
627 else if(bytes == -1) {
629 interpreter_failed(gs);
632 if(gs->interpreter_output == -1) {
633 stop_interpreter(gs);
639 g_signal_emit (G_OBJECT(gs), gtk_gs_signals[INTERPRETER_MESSAGE], 0, msg);
644 input(gpointer data, gint source, GdkInputCondition condition)
646 GtkGS *gs = GTK_GS(data);
648 void (*oldsig) (int);
649 oldsig = signal(SIGPIPE, catchPipe);
652 if(gs->buffer_bytes_left == 0) {
653 /* Get a new section if required */
654 if(gs->ps_input && gs->bytes_left == 0) {
655 struct record_list *ps_old = gs->ps_input;
656 gs->ps_input = ps_old->next;
657 if(ps_old->close && NULL != ps_old->fp)
659 g_free((char *) ps_old);
661 /* Have to seek at the beginning of each section */
662 if(gs->ps_input && gs->ps_input->seek_needed) {
663 fseek(gs->ps_input->fp, gs->ps_input->begin, SEEK_SET);
664 gs->ps_input->seek_needed = FALSE;
665 gs->bytes_left = gs->ps_input->len;
668 if(gs->bytes_left > MAX_BUFSIZE) {
669 gs->buffer_bytes_left =
670 fread(gs->input_buffer, sizeof(char), MAX_BUFSIZE, gs->ps_input->fp);
672 else if(gs->bytes_left > 0) {
673 gs->buffer_bytes_left =
674 fread(gs->input_buffer,
675 sizeof(char), gs->bytes_left, gs->ps_input->fp);
678 gs->buffer_bytes_left = 0;
680 if(gs->bytes_left > 0 && gs->buffer_bytes_left == 0) {
681 interpreter_failed(gs); /* Error occurred */
683 gs->input_buffer_ptr = gs->input_buffer;
684 gs->bytes_left -= gs->buffer_bytes_left;
687 if(gs->buffer_bytes_left > 0) {
688 /* g_print (" writing: %s\n",gs->input_buffer_ptr); */
690 bytes_written = write(gs->interpreter_input,
691 gs->input_buffer_ptr, gs->buffer_bytes_left);
694 gtk_gs_emit_error_msg(gs, g_strdup(_("Broken pipe.")));
696 interpreter_failed(gs);
698 else if(bytes_written == -1) {
699 if((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
700 interpreter_failed(gs); /* Something bad happened */
704 gs->buffer_bytes_left -= bytes_written;
705 gs->input_buffer_ptr += bytes_written;
709 while(gs->ps_input && gs->buffer_bytes_left == 0);
711 signal(SIGPIPE, oldsig);
713 if(gs->ps_input == NULL && gs->buffer_bytes_left == 0) {
714 if(gs->interpreter_input_id != 0) {
715 gdk_input_remove(gs->interpreter_input_id);
716 gs->interpreter_input_id = 0;
722 start_interpreter(GtkGS * gs)
724 int std_in[2] = { -1, -1 }; /* pipe to interp stdin */
725 int std_out[2]; /* pipe from interp stdout */
726 int std_err[2]; /* pipe from interp stderr */
729 #define NUM_GS_ARGS (NUM_ARGS - 20)
730 #define NUM_ALPHA_ARGS 10
732 char *argv[NUM_ARGS], *dir, *gv_env;
733 char **gs_args, **alpha_args = NULL;
739 stop_interpreter(gs);
741 if(gs->disable_start == TRUE)
744 /* set up the args... */
745 gs_args = g_strsplit(gtk_gs_defaults_get_interpreter_cmd(), " ", NUM_GS_ARGS);
746 for(i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++)
747 argv[argc] = gs_args[i];
749 if(gs->antialiased) {
750 if(strlen(gtk_gs_defaults_get_alpha_parameters()) == 0)
751 alpha_args = g_strsplit(ALPHA_PARAMS, " ", NUM_ALPHA_ARGS);
753 alpha_args = g_strsplit(gtk_gs_defaults_get_alpha_parameters(),
754 " ", NUM_ALPHA_ARGS);
755 for(i = 0; i < NUM_ALPHA_ARGS && alpha_args[i]; i++, argc++)
756 argv[argc] = alpha_args[i];
759 argv[argc++] = "-sDEVICE=x11";
760 argv[argc++] = "-dNOPAUSE";
761 argv[argc++] = "-dQUIET";
762 /* I assume we do _not_ want to change this... (: */
763 argv[argc++] = "-dSAFER";
765 /* set up the pipes */
766 if(gs->send_filename_to_gs) {
767 argv[argc++] = GTK_GS_GET_PS_FILE(gs);
769 argv[argc++] = "quit";
776 if(!gs->reading_from_pipe && !gs->send_filename_to_gs) {
777 if(pipe(std_in) == -1) {
778 g_critical("Unable to open pipe to Ghostscript.");
782 if(pipe(std_out) == -1) {
786 if(pipe(std_err) == -1) {
793 gs->interpreter_pid = fork();
794 switch (gs->interpreter_pid) {
810 if(!gs->reading_from_pipe) {
811 if(gs->send_filename_to_gs) {
813 /* just in case gs tries to read from stdin */
814 stdinfd = open("/dev/null", O_RDONLY);
827 gv_env = g_strdup_printf("GHOSTVIEW=%ld %ld",
828 gdk_x11_drawable_get_xid(gs->pstarget),
829 gdk_x11_drawable_get_xid(gs->bpixmap));
832 /* change to directory where the input file is. This helps
833 * with postscript-files which include other files using
835 dir = g_path_get_dirname(gs->gs_filename);
839 execvp(argv[0], argv);
842 g_print("Unable to execute [%s]\n", argv[0]);
846 g_strfreev(alpha_args);
849 default: /* parent */
850 if(!gs->send_filename_to_gs && !gs->reading_from_pipe) {
853 /* use non-blocking IO for pipe to ghostscript */
854 result = fcntl(std_in[1], F_GETFL, 0);
855 fcntl(std_in[1], F_SETFL, result | O_NONBLOCK);
856 gs->interpreter_input = std_in[1];
859 gs->interpreter_input = -1;
862 gs->interpreter_output = std_out[0];
864 gs->interpreter_err = std_err[0];
865 gs->interpreter_output_id =
866 gdk_input_add(std_out[0], GDK_INPUT_READ, output, gs);
867 gs->interpreter_error_id =
868 gdk_input_add(std_err[0], GDK_INPUT_READ, output, gs);
875 stop_interpreter(GtkGS * gs)
877 if(gs->interpreter_pid > 0) {
879 kill(gs->interpreter_pid, SIGTERM);
880 while((wait(&status) == -1) && (errno == EINTR)) ;
881 gs->interpreter_pid = -1;
884 gs->gs_status = _("Interpreter failed.");
885 g_signal_emit_by_name(G_OBJECT(gs), "interpreter_error", status);
889 if(gs->interpreter_input >= 0) {
890 close(gs->interpreter_input);
891 gs->interpreter_input = -1;
892 if(gs->interpreter_input_id != 0) {
893 gdk_input_remove(gs->interpreter_input_id);
894 gs->interpreter_input_id = 0;
896 while(gs->ps_input) {
897 struct record_list *ps_old = gs->ps_input;
898 gs->ps_input = gs->ps_input->next;
899 if(ps_old->close && NULL != ps_old->fp)
901 g_free((char *) ps_old);
905 if(gs->interpreter_output >= 0) {
906 close(gs->interpreter_output);
907 gs->interpreter_output = -1;
908 if(gs->interpreter_output_id) {
909 gdk_input_remove(gs->interpreter_output_id);
910 gs->interpreter_output_id = 0;
914 if(gs->interpreter_err >= 0) {
915 close(gs->interpreter_err);
916 gs->interpreter_err = -1;
917 if(gs->interpreter_error_id) {
918 gdk_input_remove(gs->interpreter_error_id);
919 gs->interpreter_error_id = 0;
928 * Decompress gs->gs_filename if necessary
929 * Set gs->filename_unc to the name of the uncompressed file or NULL.
930 * Error reporting via signal 'interpreter_message'
931 * Return name of input file to use or NULL on error..
934 check_filecompressed(GtkGS * gs)
938 gchar *filename, *filename_unc, *filename_err, *cmdline;
944 if((file = fopen(gs->gs_filename, "r"))
945 && (fread(buf, sizeof(gchar), 3, file) == 3)) {
946 if((buf[0] == '\037') && ((buf[1] == '\235') || (buf[1] == '\213'))) {
947 /* file is gzipped or compressed */
948 cmd = gtk_gs_defaults_get_ungzip_cmd();
950 else if(strncmp(buf, "BZh", 3) == 0) {
951 /* file is compressed with bzip2 */
952 cmd = gtk_gs_defaults_get_unbzip2_cmd();
959 return gs->gs_filename;
961 /* do the decompression */
962 filename = g_shell_quote(gs->gs_filename);
963 filename_unc = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
964 if((fd = mkstemp(filename_unc)) < 0) {
965 g_free(filename_unc);
970 filename_err = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
971 if((fd = mkstemp(filename_err)) < 0) {
972 g_free(filename_err);
973 g_free(filename_unc);
978 cmdline = g_strdup_printf("%s %s >%s 2>%s", cmd,
979 filename, filename_unc, filename_err);
980 if((system(cmdline) == 0)
981 && ggv_file_readable(filename_unc)
982 && (ggv_file_length(filename_err) == 0)) {
983 /* sucessfully uncompressed file */
984 gs->gs_filename_unc = filename_unc;
988 g_snprintf(buf, 1024, _("Error while decompressing file %s:\n"),
990 gtk_gs_emit_error_msg(gs, buf);
991 if(ggv_file_length(filename_err) > 0) {
993 if((err = fopen(filename_err, "r"))) {
994 /* print file to message window */
995 while(fgets(buf, 1024, err))
996 gtk_gs_emit_error_msg(gs, buf);
1000 unlink(filename_unc);
1001 g_free(filename_unc);
1002 filename_unc = NULL;
1004 unlink(filename_err);
1005 g_free(filename_err);
1008 return filename_unc;
1012 * Check if gs->gs_filename or gs->gs_filename_unc is a pdf file and scan
1013 * pdf file if necessary.
1014 * Set gs->filename_dsc to the name of the dsc file or NULL.
1015 * Error reporting via signal 'interpreter_message'.
1018 check_pdf(GtkGS * gs)
1021 gchar buf[1024], *filename;
1024 /* use uncompressed file as input if necessary */
1025 filename = (gs->gs_filename_unc ? gs->gs_filename_unc : gs->gs_filename);
1027 if((file = fopen(filename, "r"))
1028 && (fread(buf, sizeof(char), 5, file) == 5)
1029 && (strncmp(buf, "%PDF-", 5) == 0)) {
1030 /* we found a PDF file */
1031 gchar *fname, *filename_dsc, *filename_err, *cmd, *cmdline;
1032 filename_dsc = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
1033 if((fd = mkstemp(filename_dsc)) < 0) {
1037 filename_err = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
1038 if((fd = mkstemp(filename_err)) < 0) {
1039 g_free(filename_dsc);
1043 fname = g_shell_quote(filename);
1044 cmd = g_strdup_printf(gtk_gs_defaults_get_dsc_cmd(), filename_dsc, fname);
1046 /* this command (sometimes?) prints error messages to stdout! */
1047 cmdline = g_strdup_printf("%s >%s 2>&1", cmd, filename_err);
1050 if((system(cmdline) == 0) && ggv_file_readable(filename_dsc)) {
1053 filename = gs->gs_filename_dsc = filename_dsc;
1055 if(ggv_file_length(filename_err) > 0) {
1056 gchar *err_msg = " ";
1061 if((err = fopen(filename_err, "r"))) {
1063 /* print the content of the file to a message box */
1064 while(fgets(buf, 1024, err))
1065 err_msg = g_strconcat(err_msg, buf, NULL);
1067 /* FIXME The dialog is not yet set to modal, difficult to
1068 * get the parent of the dialog box here
1071 dialog = gtk_message_dialog_new(NULL,
1073 GTK_MESSAGE_WARNING,
1075 ("There was an error while scaning the file: %s \n%s"),
1076 gs->gs_filename, err_msg);
1078 gdk_color_parse("white", &color);
1079 gtk_widget_modify_bg(GTK_WIDGET(dialog), GTK_STATE_NORMAL, &color);
1081 g_signal_connect(G_OBJECT(dialog), "response",
1082 G_CALLBACK(gtk_widget_destroy), NULL);
1084 gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
1085 gtk_widget_show(dialog);
1093 g_snprintf(buf, 1024,
1094 _("Error while converting pdf file %s:\n"), filename);
1095 gtk_gs_emit_error_msg(gs, buf);
1097 if(ggv_file_length(filename_err) > 0) {
1099 if((err = fopen(filename_err, "r"))) {
1100 /* print file to message window */
1101 while(fgets(buf, 1024, err))
1102 gtk_gs_emit_error_msg(gs, buf);
1105 unlink(filename_dsc);
1106 g_free(filename_dsc);
1109 unlink(filename_err);
1110 g_free(filename_err);
1118 #ifdef BROKEN_XINERAMA_PATCH_THAT_SHOULD_NOT_BE_USED
1119 /* never mind this patch: a properly working X server should take care of
1120 calculating the proper values. */
1124 # ifndef HAVE_XINERAMA
1125 return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
1128 dpy = (Display *) GDK_DISPLAY();
1129 if(XineramaIsActive(dpy)) {
1131 XineramaScreenInfo *head_info;
1132 head_info = (XineramaScreenInfo *) XineramaQueryScreens(dpy, &num_heads);
1133 /* fake it with dimensions of the first head for now */
1134 return 25.4 * head_info[0].width / gdk_screen_width_mm();
1137 return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
1146 # ifndef HAVE_XINERAMA
1147 return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
1150 dpy = (Display *) GDK_DISPLAY();
1151 if(XineramaIsActive(dpy)) {
1153 XineramaScreenInfo *head_info;
1154 head_info = (XineramaScreenInfo *) XineramaQueryScreens(dpy, &num_heads);
1155 /* fake it with dimensions of the first head for now */
1156 return 25.4 * head_info[0].height / gdk_screen_height_mm();
1159 return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
1168 return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
1174 return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
1176 #endif /* BROKEN_XINERAMA_PATCH_THAT_SHOULD_NOT_BE_USED */
1178 /* Compute new size of window, sets xdpi and ydpi if necessary.
1179 * returns True if new window size is different */
1181 compute_size(GtkGS * gs)
1183 guint new_width = 1;
1184 guint new_height = 1;
1185 gboolean change = FALSE;
1188 /* width and height can be changed, calculate window size according */
1189 /* to xpdi and ydpi */
1190 orientation = gtk_gs_get_orientation(gs);
1192 switch (orientation) {
1193 case GTK_GS_ORIENTATION_PORTRAIT:
1194 case GTK_GS_ORIENTATION_UPSIDEDOWN:
1195 new_width = (gs->urx - gs->llx) / 72.0 * gs->xdpi + 0.5;
1196 new_height = (gs->ury - gs->lly) / 72.0 * gs->ydpi + 0.5;
1198 case GTK_GS_ORIENTATION_LANDSCAPE:
1199 case GTK_GS_ORIENTATION_SEASCAPE:
1200 new_width = (gs->ury - gs->lly) / 72.0 * gs->xdpi + 0.5;
1201 new_height = (gs->urx - gs->llx) / 72.0 * gs->ydpi + 0.5;
1205 change = (new_width != gs->width * gs->zoom_factor)
1206 || (new_height != gs->height * gs->zoom_factor);
1207 gs->width = (gint) (new_width * gs->zoom_factor);
1208 gs->height = (gint) (new_height * gs->zoom_factor);
1214 gtk_gs_enable_interpreter(GtkGS * gs)
1216 g_return_val_if_fail(gs != NULL, FALSE);
1217 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1219 if(!gs->gs_filename)
1222 gs->disable_start = FALSE;
1224 return start_interpreter(gs);
1227 /* publicly accessible functions */
1230 gtk_gs_get_type(void)
1232 static GType gs_type = 0;
1234 GTypeInfo gs_info = {
1236 (GBaseInitFunc) NULL,
1237 (GBaseFinalizeFunc) NULL,
1238 (GClassInitFunc) gtk_gs_class_init,
1239 (GClassFinalizeFunc) NULL,
1240 NULL, /* class_data */
1242 0, /* n_preallocs */
1243 (GInstanceInitFunc) gtk_gs_init
1246 static const GInterfaceInfo document_info =
1248 (GInterfaceInitFunc) ps_document_document_iface_init,
1253 gs_type = g_type_register_static(G_TYPE_OBJECT,
1254 "GtkGS", &gs_info, 0);
1256 g_type_add_interface_static (gs_type,
1266 gtk_gs_new(GtkAdjustment * hadj, GtkAdjustment * vadj)
1270 gs = g_object_new(GTK_GS_TYPE, NULL);
1277 gtk_gs_new_from_file(GtkAdjustment * hadj, GtkAdjustment * vadj, char *fname)
1279 GObject *gs = gtk_gs_new(hadj, vadj);
1280 gtk_gs_load(GTK_GS(gs), fname);
1285 gtk_gs_reload(GtkGS * gs)
1290 if(!gs->gs_filename)
1293 page = gtk_gs_get_current_page(gs);
1294 fname = g_strdup(gs->gs_filename);
1295 gtk_gs_load(gs, fname);
1296 gtk_gs_goto_page(gs, page);
1302 * Show error message -> send signal "interpreter_message"
1305 gtk_gs_emit_error_msg(GtkGS * gs, const gchar * msg)
1307 g_signal_emit (G_OBJECT(gs),
1308 gtk_gs_signals[INTERPRETER_MESSAGE], 0, g_strdup(msg));
1312 gtk_gs_disable_interpreter(GtkGS * gs)
1314 g_return_if_fail(gs != NULL);
1315 g_return_if_fail(GTK_IS_GS(gs));
1317 gs->disable_start = TRUE;
1319 stop_interpreter(gs);
1323 gtk_gs_load(GtkGS * gs, const gchar * fname)
1325 g_return_val_if_fail(gs != NULL, FALSE);
1326 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1328 /* clean up previous document */
1336 /* prepare this document */
1338 /* default values: no dsc information available */
1339 gs->structured_doc = FALSE;
1340 gs->send_filename_to_gs = TRUE;
1341 gs->current_page = -2;
1344 /* an absolute path */
1345 gs->gs_filename = g_strdup(fname);
1348 /* path relative to our cwd: make it absolute */
1349 gchar *cwd = g_get_current_dir();
1350 gs->gs_filename = g_strconcat(cwd, "/", fname, NULL);
1354 if((gs->reading_from_pipe = (strcmp(fname, "-") == 0))) {
1355 gs->send_filename_to_gs = FALSE;
1359 * We need to make sure that the file is loadable/exists!
1360 * otherwise we want to exit without loading new stuff...
1362 gchar *filename = NULL;
1364 if(!ggv_file_readable(fname)) {
1366 g_snprintf(buf, 1024, _("Cannot open file %s.\n"), fname);
1367 gtk_gs_emit_error_msg(gs, buf);
1368 gs->gs_status = _("File is not readable.");
1371 filename = check_filecompressed(gs);
1373 filename = check_pdf(gs);
1376 if(!filename || (gs->gs_psfile = fopen(filename, "r")) == NULL) {
1381 /* we grab the vital statistics!!! */
1382 gs->doc = psscan(gs->gs_psfile, gs->respect_eof, filename);
1384 if(gs->doc == NULL) {
1385 /* File does not seem to be a Postscript one */
1387 g_snprintf(buf, 1024, _("Error while scanning file %s\n"), fname);
1388 gtk_gs_emit_error_msg(gs, buf);
1390 gs->gs_status = _("The file is not a PostScript document.");
1394 if((!gs->doc->epsf && gs->doc->numpages > 0) ||
1395 (gs->doc->epsf && gs->doc->numpages > 1)) {
1396 gs->structured_doc = TRUE;
1397 gs->send_filename_to_gs = FALSE;
1400 /* We have to set up the orientation of the document */
1403 /* orientation can only be portrait, and landscape or none.
1404 This is the document default. A document can have
1405 pages in landscape and some in portrait */
1406 if(gs->override_orientation) {
1407 /* If the orientation should be override...
1408 then gs->orientation has already the correct
1409 value (it was set when the widget was created */
1414 /* Otherwise, set the proper orientation for the doc */
1415 gs->real_orientation = gs->doc->orientation;
1418 gtk_gs_set_page_size(gs, -1, gs->current_page);
1421 gs->gs_status = _("Document loaded.");
1428 gtk_gs_next_page(GtkGS * gs)
1432 g_return_val_if_fail(gs != NULL, FALSE);
1433 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1435 if(gs->interpreter_pid == 0) { /* no interpreter active */
1439 if(gs->busy) { /* interpreter is busy */
1445 event.xclient.type = ClientMessage;
1446 event.xclient.display = gdk_display;
1447 event.xclient.window = gs->message_window;
1448 event.xclient.message_type = gdk_x11_atom_to_xatom(gs_class->next_atom);
1449 event.xclient.format = 32;
1451 gdk_error_trap_push();
1452 XSendEvent(gdk_display, gs->message_window, FALSE, 0, &event);
1454 gdk_error_trap_pop();
1460 gtk_gs_get_current_page(GtkGS * gs)
1462 g_return_val_if_fail(gs != NULL, -1);
1463 g_return_val_if_fail(GTK_IS_GS(gs), -1);
1465 return gs->current_page;
1469 gtk_gs_get_page_count(GtkGS * gs)
1471 if(!gs->gs_filename)
1475 if(gs->structured_doc)
1476 return gs->doc->numpages;
1485 gtk_gs_goto_page(GtkGS * gs, gint page)
1487 g_return_val_if_fail(gs != NULL, FALSE);
1488 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1490 if(!gs->gs_filename) {
1494 /* range checking... */
1498 if(gs->structured_doc && gs->doc) {
1499 if(page >= gs->doc->numpages)
1500 page = gs->doc->numpages - 1;
1502 if(page == gs->current_page && !gs->changed)
1505 gs->current_page = page;
1507 if(gs->doc->pages[page].orientation != NONE &&
1508 !gs->override_orientation &&
1509 gs->doc->pages[page].orientation != gs->real_orientation) {
1510 gs->real_orientation = gs->doc->pages[page].orientation;
1514 gtk_gs_set_page_size(gs, -1, page);
1516 gs->changed = FALSE;
1518 if(is_interpreter_ready(gs)) {
1519 gtk_gs_next_page(gs);
1522 gtk_gs_enable_interpreter(gs);
1523 send_ps(gs, gs->doc->beginprolog, gs->doc->lenprolog, FALSE);
1524 send_ps(gs, gs->doc->beginsetup, gs->doc->lensetup, FALSE);
1527 send_ps(gs, gs->doc->pages[gs->current_page].begin,
1528 gs->doc->pages[gs->current_page].len, FALSE);
1531 /* Unstructured document */
1532 /* In the case of non structured documents,
1533 GS read the PS from the actual file (via command
1534 line. Hence, ggv only send a signal next page.
1535 If ghostview is not running it is usually because
1536 the last page of the file was displayed. In that
1537 case, ggv restarts GS again and the first page is displayed.
1539 if(page == gs->current_page && !gs->changed)
1542 if(!is_interpreter_ready(gs))
1543 gtk_gs_enable_interpreter(gs);
1545 gs->current_page = page;
1547 gtk_gs_next_page(gs);
1553 * set pagesize sets the size from
1554 * if new_pagesize is -1, then it is set to either
1555 * a) the default settings of pageid, if they exist, or if pageid != -1.
1556 * b) the default setting of the document, if it exists.
1557 * c) the default setting of the widget.
1558 * otherwise, the new_pagesize is used as the pagesize
1561 gtk_gs_set_page_size(GtkGS * gs, gint new_pagesize, gint pageid)
1567 GtkGSPaperSize *papersizes = gtk_gs_defaults_get_paper_sizes();
1569 g_return_val_if_fail(gs != NULL, FALSE);
1570 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1572 if(new_pagesize == -1) {
1573 if(gs->default_size > 0)
1574 new_pagesize = gs->default_size;
1575 if(!gs->override_size && gs->doc) {
1576 /* If we have a document:
1577 We use -- the page size (if specified)
1578 or the doc. size (if specified)
1579 or the page bbox (if specified)
1582 if((pageid >= 0) && (gs->doc->numpages > pageid) &&
1583 (gs->doc->pages) && (gs->doc->pages[pageid].size)) {
1584 new_pagesize = gs->doc->pages[pageid].size - gs->doc->size;
1586 else if(gs->doc->default_page_size != NULL) {
1587 new_pagesize = gs->doc->default_page_size - gs->doc->size;
1589 else if((pageid >= 0) &&
1590 (gs->doc->numpages > pageid) &&
1592 (gs->doc->pages[pageid].boundingbox[URX] >
1593 gs->doc->pages[pageid].boundingbox[LLX]) &&
1594 (gs->doc->pages[pageid].boundingbox[URY] >
1595 gs->doc->pages[pageid].boundingbox[LLY])) {
1598 else if((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
1599 (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
1605 /* Compute bounding box */
1606 if(gs->doc && ((gs->doc->epsf && !gs->override_size) || new_pagesize == -1)) { /* epsf or bbox */
1609 (gs->doc->pages[pageid].boundingbox[URX] >
1610 gs->doc->pages[pageid].boundingbox[LLX])
1611 && (gs->doc->pages[pageid].boundingbox[URY] >
1612 gs->doc->pages[pageid].boundingbox[LLY])) {
1614 new_llx = gs->doc->pages[pageid].boundingbox[LLX];
1615 new_lly = gs->doc->pages[pageid].boundingbox[LLY];
1616 new_urx = gs->doc->pages[pageid].boundingbox[URX];
1617 new_ury = gs->doc->pages[pageid].boundingbox[URY];
1619 else if((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
1620 (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
1622 new_llx = gs->doc->boundingbox[LLX];
1623 new_lly = gs->doc->boundingbox[LLY];
1624 new_urx = gs->doc->boundingbox[URX];
1625 new_ury = gs->doc->boundingbox[URY];
1629 if(new_pagesize < 0)
1630 new_pagesize = gs->default_size;
1631 new_llx = new_lly = 0;
1632 if(gs->doc && !gs->override_size && gs->doc->size &&
1633 (new_pagesize < gs->doc->numsizes)) {
1634 new_urx = gs->doc->size[new_pagesize].width;
1635 new_ury = gs->doc->size[new_pagesize].height;
1638 new_urx = papersizes[new_pagesize].width;
1639 new_ury = papersizes[new_pagesize].height;
1643 if(new_urx <= new_llx)
1644 new_urx = papersizes[12].width;
1645 if(new_ury <= new_lly)
1646 new_ury = papersizes[12].height;
1648 /* If bounding box changed, setup for new size. */
1649 /* gtk_gs_disable_interpreter (gs); */
1650 if((new_llx != gs->llx) || (new_lly != gs->lly) ||
1651 (new_urx != gs->urx) || (new_ury != gs->ury)) {
1668 gtk_gs_set_override_orientation(GtkGS * gs, gboolean bNewOverride)
1670 gint iOldOrientation;
1672 g_return_if_fail(gs != NULL);
1673 g_return_if_fail(GTK_IS_GS(gs));
1675 iOldOrientation = gtk_gs_get_orientation(gs);
1677 gs->override_orientation = bNewOverride;
1679 /* If the current orientation is different from the
1680 new orientation then redisplay */
1681 if(iOldOrientation != gtk_gs_get_orientation(gs)) {
1688 gtk_gs_get_override_orientation(GtkGS * gs)
1690 g_return_val_if_fail(gs != NULL, FALSE);
1691 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1693 return gs->override_orientation;
1697 gtk_gs_set_override_size(GtkGS * gs, gboolean f)
1699 g_return_if_fail(gs != NULL);
1700 g_return_if_fail(GTK_IS_GS(gs));
1702 if(f != gs->override_size) {
1703 gs->override_size = f;
1705 gtk_gs_set_page_size(gs, -1, gs->current_page);
1711 gtk_gs_get_override_size(GtkGS * gs)
1713 g_return_val_if_fail(gs != NULL, FALSE);
1714 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1716 return gs->override_size;
1720 gtk_gs_set_zoom(GtkGS * gs, gfloat zoom)
1722 g_return_if_fail(gs != NULL);
1723 g_return_if_fail(GTK_IS_GS(gs));
1725 switch (gs->zoom_mode) {
1726 case GTK_GS_ZOOM_FIT_WIDTH:
1727 zoom = gtk_gs_zoom_to_fit(gs, TRUE);
1729 case GTK_GS_ZOOM_FIT_PAGE:
1730 zoom = gtk_gs_zoom_to_fit(gs, FALSE);
1732 case GTK_GS_ZOOM_ABSOLUTE:
1736 if(zoom < ggv_zoom_levels[0])
1737 zoom = ggv_zoom_levels[0];
1738 else if(zoom > ggv_zoom_levels[ggv_max_zoom_levels])
1739 zoom = ggv_zoom_levels[ggv_max_zoom_levels];
1740 if(fabs(gs->zoom_factor - zoom) > 0.001) {
1741 gs->zoom_factor = zoom;
1748 gtk_gs_get_zoom(GtkGS * gs)
1750 g_return_val_if_fail(gs != NULL, 0.0);
1751 g_return_val_if_fail(GTK_IS_GS(gs), 0.0);
1753 return gs->zoom_factor;
1757 gtk_gs_zoom_to_fit(GtkGS * gs, gboolean fit_width)
1761 guint avail_w, avail_h;
1763 g_return_val_if_fail(gs != NULL, 0.0);
1764 g_return_val_if_fail(GTK_IS_GS(gs), 0.0);
1766 avail_w = (gs->avail_w > 0) ? gs->avail_w : gs->width;
1767 avail_h = (gs->avail_h > 0) ? gs->avail_h : gs->height;
1769 new_zoom = ((gfloat) avail_w) / ((gfloat) gs->width) * gs->zoom_factor;
1771 new_y = new_zoom * ((gfloat) gs->height) / gs->zoom_factor;
1773 new_zoom = ((gfloat) avail_h) / ((gfloat) gs->height) * gs->zoom_factor;
1780 gtk_gs_set_default_orientation(GtkGS * gs, gint orientation)
1782 gint iOldOrientation;
1784 g_return_val_if_fail(gs != NULL, FALSE);
1785 g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1786 g_return_val_if_fail((orientation == GTK_GS_ORIENTATION_PORTRAIT) ||
1787 (orientation == GTK_GS_ORIENTATION_LANDSCAPE) ||
1788 (orientation == GTK_GS_ORIENTATION_UPSIDEDOWN) ||
1789 (orientation == GTK_GS_ORIENTATION_SEASCAPE), FALSE);
1791 iOldOrientation = gtk_gs_get_orientation(gs);
1792 gs->fallback_orientation = orientation;
1794 /* We are setting the fallback orientation */
1795 if(iOldOrientation != gtk_gs_get_orientation(gs)) {
1805 gtk_gs_get_default_orientation(GtkGS * gs)
1807 g_return_val_if_fail(gs != NULL, -1);
1808 g_return_val_if_fail(GTK_IS_GS(gs), -1);
1810 return gs->fallback_orientation;
1814 gtk_gs_get_orientation(GtkGS * gs)
1816 g_return_val_if_fail(gs != NULL, -1);
1817 g_return_val_if_fail(GTK_IS_GS(gs), -1);
1820 if(gs->structured_doc) {
1821 if(gs->doc->pages[MAX(gs->current_page, 0)].orientation !=
1822 GTK_GS_ORIENTATION_NONE)
1823 gs->real_orientation =
1824 gs->doc->pages[MAX(gs->current_page, 0)].orientation;
1826 gs->real_orientation = gs->doc->default_page_orientation;
1829 if(gs->real_orientation == GTK_GS_ORIENTATION_NONE)
1830 gs->real_orientation = gs->doc->orientation;
1833 if(gs->override_orientation ||
1834 gs->real_orientation == GTK_GS_ORIENTATION_NONE)
1835 return gs->fallback_orientation;
1837 return gs->real_orientation;
1841 gtk_gs_set_default_size(GtkGS * gs, gint size)
1843 g_return_if_fail(gs != NULL);
1844 g_return_if_fail(GTK_IS_GS(gs));
1846 gs->default_size = size;
1847 gtk_gs_set_page_size(gs, -1, gs->current_page);
1851 gtk_gs_get_default_size(GtkGS * gs)
1853 g_return_val_if_fail(gs != NULL, -1);
1854 g_return_val_if_fail(GTK_IS_GS(gs), -1);
1856 return gs->default_size;
1860 gtk_gs_set_respect_eof(GtkGS * gs, gboolean f)
1862 g_return_if_fail(gs != NULL);
1863 g_return_if_fail(GTK_IS_GS(gs));
1865 if(gs->respect_eof == f)
1868 gs->respect_eof = f;
1869 gtk_gs_set_page_size(gs, -1, gs->current_page);
1873 gtk_gs_get_respect_eof(GtkGS * gs)
1875 g_return_val_if_fail(gs != NULL, -1);
1876 g_return_val_if_fail(GTK_IS_GS(gs), -1);
1878 return gs->respect_eof;
1882 gtk_gs_set_antialiasing(GtkGS * gs, gboolean f)
1884 g_return_if_fail(gs != NULL);
1885 g_return_if_fail(GTK_IS_GS(gs));
1887 if(gs->antialiased == f)
1890 gs->antialiased = f;
1892 start_interpreter(gs);
1893 gtk_gs_goto_page(gs, gs->current_page);
1897 gtk_gs_get_antialiasing(GtkGS * gs)
1899 g_return_val_if_fail(gs != NULL, -1);
1900 g_return_val_if_fail(GTK_IS_GS(gs), -1);
1902 return gs->antialiased;
1906 gtk_gs_get_document_title(GtkGS * gs)
1908 g_return_val_if_fail(gs != NULL, NULL);
1909 g_return_val_if_fail(GTK_IS_GS(gs), NULL);
1911 if(gs->doc && gs->doc->title)
1912 return gs->doc->title;
1918 gtk_gs_get_document_numpages(GtkGS * widget)
1920 g_return_val_if_fail(widget != NULL, 0);
1921 g_return_val_if_fail(GTK_IS_GS(widget), 0);
1924 return widget->doc->numpages;
1930 gtk_gs_get_document_page_label(GtkGS * widget, int page)
1932 g_return_val_if_fail(widget != NULL, NULL);
1933 g_return_val_if_fail(GTK_IS_GS(widget), NULL);
1935 if(widget->doc && widget->doc->pages && (widget->doc->numpages >= page))
1936 return widget->doc->pages[page - 1].label;
1942 gtk_gs_get_size_index(const gchar * string, GtkGSPaperSize * size)
1946 while(size[idx].name != NULL) {
1947 if(strcmp(size[idx].name, string) == 0)
1956 gtk_gs_get_postscript(GtkGS * gs, gint * pages)
1960 gboolean free_pages = FALSE;
1963 if(!gs->structured_doc) {
1967 if(stat(GTK_GS_GET_PS_FILE(gs), &sb))
1969 doc = g_new(gchar, sb.st_size);
1972 f = fopen(GTK_GS_GET_PS_FILE(gs), "r");
1973 if(NULL != f && fread(doc, sb.st_size, 1, f) != 1) {
1982 int i, n = gtk_gs_get_page_count(gs);
1983 pages = g_new0(gint, n);
1984 for(i = 0; i < n; i++)
1990 sink = gtk_gs_doc_sink_new();
1992 if(GTK_GS_IS_PDF(gs)) {
1993 gchar *tmpn = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
1997 if((tmpfd = mkstemp(tmpn)) < 0) {
2002 fname = g_shell_quote (gs->gs_filename_unc ?
2003 gs->gs_filename_unc : gs->gs_filename);
2004 cmd = g_strdup_printf(gtk_gs_defaults_get_convert_pdf_cmd(), tmpn, fname);
2006 if((system(cmd) == 0) && ggv_file_readable(tmpn)) {
2008 tmp_gs = gtk_gs_new_from_file(NULL, NULL, tmpn);
2009 if(NULL != tmp_gs) {
2010 if(GTK_GS(tmp_gs)->loaded)
2011 pscopydoc(sink, tmpn, GTK_GS(tmp_gs)->doc, pages);
2012 g_object_unref(tmp_gs);
2019 /* Use uncompressed file if necessary */
2020 pscopydoc(sink, GTK_GS_GET_PS_FILE(gs), gs->doc, pages);
2024 doc = gtk_gs_doc_sink_get_buffer(sink);
2025 gtk_gs_doc_sink_free(sink);
2030 gtk_gs_set_zoom_mode(GtkGS * gs, GtkGSZoomMode zoom_mode)
2032 if(zoom_mode != gs->zoom_mode) {
2033 gs->zoom_mode = zoom_mode;
2034 gtk_gs_set_zoom(gs, 1.0);
2039 gtk_gs_get_zoom_mode(GtkGS * gs)
2041 return gs->zoom_mode;
2045 gtk_gs_set_available_size(GtkGS * gs, guint avail_w, guint avail_h)
2047 gs->avail_w = avail_w;
2048 gs->avail_h = avail_h;
2049 if(gs->zoom_mode != GTK_GS_ZOOM_ABSOLUTE) {
2050 gtk_gs_set_zoom(gs, 0.0);
2055 ps_document_load (EvDocument *document,
2062 filename = g_filename_from_uri (uri, NULL, error);
2066 result = gtk_gs_load (GTK_GS (document), filename);
2074 ps_document_get_n_pages (EvDocument *document)
2076 return gtk_gs_get_page_count (GTK_GS (document));
2080 ps_document_set_page (EvDocument *document,
2083 gtk_gs_goto_page (GTK_GS (document), page);
2087 ps_document_get_page (EvDocument *document)
2089 return gtk_gs_get_current_page (GTK_GS (document));
2093 ps_document_set_target (EvDocument *document,
2094 GdkDrawable *target)
2096 GtkGS *gs = GTK_GS (document);
2098 gs->pstarget = target;
2099 gtk_gs_goto_page (gs, gs->current_page);
2103 ps_document_set_scale (EvDocument *document,
2106 gtk_gs_set_zoom (GTK_GS (document), scale);
2110 ps_document_set_page_offset (EvDocument *document,
2117 ps_document_get_page_size (EvDocument *document,
2121 GtkGS *gs = GTK_GS (document);
2128 *height = gs->height;
2133 ps_document_render (EvDocument *document,
2139 GtkGS *gs = GTK_GS (document);
2142 if (gs->pstarget == NULL ||
2143 gs->bpixmap == NULL) {
2147 gc = gdk_gc_new (gs->pstarget);
2149 gdk_draw_drawable (gs->pstarget, gc,
2153 clip_width, clip_height);
2155 g_object_unref (gc);
2159 ps_document_document_iface_init (EvDocumentIface *iface)
2161 iface->load = ps_document_load;
2162 iface->get_n_pages = ps_document_get_n_pages;
2163 iface->set_page = ps_document_set_page;
2164 iface->get_page = ps_document_get_page;
2165 iface->set_scale = ps_document_set_scale;
2166 iface->set_target = ps_document_set_target;
2167 iface->set_page_offset = ps_document_set_page_offset;
2168 iface->get_page_size = ps_document_get_page_size;
2169 iface->render = ps_document_render;