]> www.fi.muni.cz Git - evince.git/blob - ps/ps-document.c
Really make use of the orientation bit of the render context. Use the
[evince.git] / ps / ps-document.c
1 /* Ghostscript widget for GTK/GNOME
2  * 
3  * Copyright (C) 1998 - 2005 the Free Software Foundation
4  * 
5  * Authors: Jonathan Blandford, Jaka Mocnik
6  * 
7  * Based on code by: Federico Mena (Quartic), Szekeres Istvan (Pista)
8  *
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.
13  *
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.
18  *
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.
23  */
24  
25 #include "config.h"
26 #include <string.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <gtk/gtk.h>
30 #include <gtk/gtkobject.h>
31 #include <gdk/gdkprivate.h>
32 #include <gdk/gdkx.h>
33 #include <gdk/gdk.h>
34 #include <glib/gi18n.h>
35 #include <X11/Intrinsic.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <errno.h>
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #include <sys/wait.h>
43 #include <stdio.h>
44 #include <math.h>
45
46 #include "ps-document.h"
47 #include "ev-debug.h"
48 #include "gsdefaults.h"
49 #include "ev-ps-exporter.h"
50 #include "ev-async-renderer.h"
51
52 #define MAX_BUFSIZE 1024
53
54 #define PS_DOCUMENT_IS_COMPRESSED(gs) (PS_DOCUMENT(gs)->gs_filename_unc != NULL)
55 #define PS_DOCUMENT_GET_PS_FILE(gs)   (PS_DOCUMENT_IS_COMPRESSED(gs) ? \
56                                        PS_DOCUMENT(gs)->gs_filename_unc : \
57                                        PS_DOCUMENT(gs)->gs_filename)
58
59 /* structure to describe section of file to send to ghostscript */
60 struct record_list
61 {
62         FILE *fp;
63         long begin;
64         guint len;
65         gboolean seek_needed;
66         gboolean close;
67         struct record_list *next;
68 };
69
70 static gboolean broken_pipe = FALSE;
71
72 /* Forward declarations */
73 static void     ps_document_init                        (PSDocument           *gs);
74 static void     ps_document_class_init                  (PSDocumentClass      *klass);
75 static void     send_ps                                 (PSDocument           *gs,
76                                                          long                  begin,
77                                                          unsigned int          len,
78                                                          gboolean              close);
79 static void     output                                  (gpointer              data,
80                                                          gint                  source,
81                                                          GdkInputCondition     condition);
82 static void     input                                   (gpointer              data,
83                                                          gint                  source,
84                                                          GdkInputCondition     condition);
85 static void     stop_interpreter                        (PSDocument           *gs);
86 static gint     start_interpreter                       (PSDocument           *gs);
87 static void     ps_document_document_iface_init         (EvDocumentIface      *iface);
88 static void     ps_document_ps_exporter_iface_init      (EvPSExporterIface    *iface);
89 static void     ps_async_renderer_iface_init            (EvAsyncRendererIface *iface);
90
91 G_DEFINE_TYPE_WITH_CODE (PSDocument, ps_document, G_TYPE_OBJECT,
92                          {
93                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
94                                                         ps_document_document_iface_init);
95                                  G_IMPLEMENT_INTERFACE (EV_TYPE_PS_EXPORTER,
96                                                         ps_document_ps_exporter_iface_init);
97                                  G_IMPLEMENT_INTERFACE (EV_TYPE_ASYNC_RENDERER,
98                                                         ps_async_renderer_iface_init);
99                          });
100
101 static GObjectClass *parent_class = NULL;
102 static PSDocumentClass *gs_class = NULL;
103
104 static void
105 ps_document_init (PSDocument *gs)
106 {
107         gs->bpixmap = NULL;
108
109         gs->interpreter_pid = -1;
110
111         gs->busy = FALSE;
112         gs->gs_filename = 0;
113         gs->gs_filename_unc = 0;
114
115         broken_pipe = FALSE;
116
117         gs->structured_doc = FALSE;
118         gs->reading_from_pipe = FALSE;
119         gs->send_filename_to_gs = FALSE;
120
121         gs->doc = NULL;
122
123         gs->interpreter_input = -1;
124         gs->interpreter_output = -1;
125         gs->interpreter_err = -1;
126         gs->interpreter_input_id = 0;
127         gs->interpreter_output_id = 0;
128         gs->interpreter_error_id = 0;
129
130         gs->ps_input = NULL;
131         gs->input_buffer = NULL;
132         gs->input_buffer_ptr = NULL;
133         gs->bytes_left = 0;
134         gs->buffer_bytes_left = 0;
135
136         gs->gs_status = _("No document loaded.");
137
138         gs->ps_export_pagelist = NULL;
139         gs->ps_export_filename = NULL;
140
141         gs->orientation = GTK_GS_ORIENTATION_NONE;
142 }
143
144 static void
145 ps_document_dispose (GObject *object)
146 {
147         PSDocument *gs = PS_DOCUMENT (object);
148
149         g_return_if_fail (gs != NULL);
150
151         if (gs->gs_psfile) {
152                 fclose (gs->gs_psfile);
153                 gs->gs_psfile = NULL;
154         }
155
156         if (gs->gs_filename) {
157                 g_free (gs->gs_filename);
158                 gs->gs_filename = NULL;
159         }
160
161         if (gs->doc) {
162                 psfree (gs->doc);
163                 gs->doc = NULL;
164         }
165
166         if (gs->gs_filename_unc) {
167                 unlink(gs->gs_filename_unc);
168                 g_free(gs->gs_filename_unc);
169                 gs->gs_filename_unc = NULL;
170         }
171
172         if (gs->bpixmap) {
173                 gdk_drawable_unref (gs->bpixmap);
174         }
175
176         if(gs->input_buffer) {
177                 g_free(gs->input_buffer);
178                 gs->input_buffer = NULL;
179         }
180
181         if (gs->target_window) {
182                 gtk_widget_destroy (gs->target_window);
183                 gs->target_window = NULL;
184                 gs->pstarget = NULL;
185         }
186
187         stop_interpreter (gs);
188
189         G_OBJECT_CLASS (parent_class)->dispose (object);
190 }
191
192 static void
193 ps_document_class_init(PSDocumentClass *klass)
194 {
195         GObjectClass *object_class;
196
197         object_class = (GObjectClass *) klass;
198         parent_class = g_type_class_peek_parent (klass);
199         gs_class = klass;
200
201         object_class->dispose = ps_document_dispose;    
202
203         klass->gs_atom = gdk_atom_intern ("GHOSTVIEW", FALSE);
204         klass->next_atom = gdk_atom_intern ("NEXT", FALSE);
205         klass->page_atom = gdk_atom_intern ("PAGE", FALSE);
206         klass->string_atom = gdk_atom_intern ("STRING", FALSE);
207 }
208
209 static void
210 push_pixbuf (PSDocument *gs)
211 {
212         GdkColormap *cmap;
213         GdkPixbuf *pixbuf;
214         int width, height;
215
216         cmap = gdk_window_get_colormap (gs->pstarget);
217         gdk_drawable_get_size (gs->bpixmap, &width, &height);
218         pixbuf =  gdk_pixbuf_get_from_drawable (NULL, gs->bpixmap, cmap,
219                                                 0, 0, 0, 0,
220                                                 width, height);
221         g_signal_emit_by_name (gs, "render_finished", pixbuf);
222         g_object_unref (pixbuf);
223 }
224
225 static void
226 interpreter_failed (PSDocument *gs, char *msg)
227 {
228         LOG ("Interpreter failed %s", msg);
229
230         push_pixbuf (gs);
231
232         stop_interpreter (gs);
233 }
234
235 static gboolean
236 ps_document_widget_event (GtkWidget *widget, GdkEvent *event, gpointer data)
237 {
238         PSDocument *gs = (PSDocument *) data;
239
240         if(event->type != GDK_CLIENT_EVENT)
241                 return FALSE;
242
243         gs->message_window = event->client.data.l[0];
244
245         if (event->client.message_type == gs_class->page_atom) {
246                 LOG ("GS rendered the document");
247                 gs->busy = FALSE;
248
249                 push_pixbuf (gs);
250         }
251
252         return TRUE;
253 }
254
255 static void
256 send_ps (PSDocument *gs, long begin, unsigned int len, gboolean close)
257 {
258         struct record_list *ps_new;
259
260         if (gs->interpreter_input < 0) {
261                 g_critical("No pipe to gs: error in send_ps().");
262                 return;
263         }
264
265         ps_new = g_new0 (struct record_list, 1);
266         ps_new->fp = gs->gs_psfile;
267         ps_new->begin = begin;
268         ps_new->len = len;
269         ps_new->seek_needed = TRUE;
270         ps_new->close = close;
271         ps_new->next = NULL;
272
273         if (gs->input_buffer == NULL) {
274                 gs->input_buffer = g_malloc(MAX_BUFSIZE);
275         }
276
277         if (gs->ps_input == NULL) {
278                 gs->input_buffer_ptr = gs->input_buffer;
279                 gs->bytes_left = len;
280                 gs->buffer_bytes_left = 0;
281                 gs->ps_input = ps_new;
282                 gs->interpreter_input_id = gdk_input_add
283                         (gs->interpreter_input, GDK_INPUT_WRITE, input, gs);
284         } else {
285                 struct record_list *p = gs->ps_input;
286                 while (p->next != NULL) {
287                         p = p->next;
288                 }
289                 p->next = ps_new;
290         }
291 }
292
293 static float
294 get_xdpi (PSDocument *gs)
295 {
296         return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
297 }
298
299 static float
300 get_ydpi (PSDocument *gs)
301 {
302         return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
303 }
304
305 static void
306 setup_pixmap (PSDocument *gs, int page, double scale)
307 {
308         GdkGC *fill;
309         GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF };   /* pixel, r, g, b */
310         GdkColormap *colormap;
311         double width, height;
312         int pixmap_width, pixmap_height;
313
314         ev_document_get_page_size (EV_DOCUMENT (gs), page, &width, &height);
315         pixmap_width = width * scale + 0.5;
316         pixmap_height = height * scale + 0.5;
317
318         if(gs->bpixmap) {
319                 int w, h;
320
321                 gdk_drawable_get_size (gs->bpixmap, &w, &h);
322
323                 if (pixmap_width != w || h != pixmap_height) {
324                         gdk_drawable_unref (gs->bpixmap);
325                         gs->bpixmap = NULL;
326                         stop_interpreter (gs);
327                 }
328         }
329
330         if (!gs->bpixmap) {
331                 LOG ("Create pixmap");
332
333                 fill = gdk_gc_new (gs->pstarget);
334                 colormap = gdk_drawable_get_colormap (gs->pstarget);
335                 gdk_color_alloc (colormap, &white);
336                 gdk_gc_set_foreground (fill, &white);
337                 gs->bpixmap = gdk_pixmap_new (gs->pstarget, pixmap_width,
338                                               pixmap_height, -1);
339                 gdk_draw_rectangle (gs->bpixmap, fill, TRUE,
340                                     0, 0, pixmap_width, pixmap_height);
341         }
342 }
343
344 #define DEFAULT_PAGE_SIZE 1
345
346 static void
347 get_page_box (PSDocument *gs, int page, int *urx, int *ury, int *llx, int *lly)
348 {
349         gint new_llx = 0;
350         gint new_lly = 0;
351         gint new_urx = 0;
352         gint new_ury = 0;
353         GtkGSPaperSize *papersizes = gtk_gs_defaults_get_paper_sizes ();
354         int new_pagesize = -1;
355
356         g_return_if_fail (PS_IS_DOCUMENT (gs));
357
358         if (new_pagesize == -1) {
359                 new_pagesize = DEFAULT_PAGE_SIZE;
360                 if (gs->doc) {
361                 /* If we have a document:
362                  * We use -- the page size (if specified)
363                  * or the doc. size (if specified)
364                  * or the page bbox (if specified)
365                  * or the bounding box
366                  */
367                         if ((page >= 0) && (gs->doc->numpages > page) &&
368                             (gs->doc->pages) && (gs->doc->pages[page].size)) {
369                                 new_pagesize = gs->doc->pages[page].size - gs->doc->size;
370                         } else if (gs->doc->default_page_size != NULL) {
371                                 new_pagesize = gs->doc->default_page_size - gs->doc->size;
372                         } else if ((page >= 0) &&
373                                    (gs->doc->numpages > page) &&
374                                    (gs->doc->pages) &&
375                                    (gs->doc->pages[page].boundingbox[URX] >
376                                     gs->doc->pages[page].boundingbox[LLX]) &&
377                                    (gs->doc->pages[page].boundingbox[URY] >
378                                     gs->doc->pages[page].boundingbox[LLY])) {
379                                 new_pagesize = -1;
380                         } else if ((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
381                                    (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
382                                 new_pagesize = -1;
383                         }
384                 }
385         }
386
387         /* Compute bounding box */
388         if (gs->doc && (gs->doc->epsf || new_pagesize == -1)) {    /* epsf or bbox */
389                 if ((page >= 0) &&
390                     (gs->doc->pages) &&
391                     (gs->doc->pages[page].boundingbox[URX] >
392                      gs->doc->pages[page].boundingbox[LLX]) &&
393                     (gs->doc->pages[page].boundingbox[URY] >
394                      gs->doc->pages[page].boundingbox[LLY])) {
395                         /* use page bbox */
396                         new_llx = gs->doc->pages[page].boundingbox[LLX];
397                         new_lly = gs->doc->pages[page].boundingbox[LLY];
398                         new_urx = gs->doc->pages[page].boundingbox[URX];
399                         new_ury = gs->doc->pages[page].boundingbox[URY];
400                 } else if ((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
401                            (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
402                         /* use doc bbox */
403                         new_llx = gs->doc->boundingbox[LLX];
404                         new_lly = gs->doc->boundingbox[LLY];
405                         new_urx = gs->doc->boundingbox[URX];
406                         new_ury = gs->doc->boundingbox[URY];
407                 }
408         } else {
409                 if (new_pagesize < 0)
410                         new_pagesize = DEFAULT_PAGE_SIZE;
411                 new_llx = new_lly = 0;
412                 if (gs->doc && gs->doc->size &&
413                     (new_pagesize < gs->doc->numsizes)) {
414                         new_urx = gs->doc->size[new_pagesize].width;
415                         new_ury = gs->doc->size[new_pagesize].height;
416                 } else {
417                         new_urx = papersizes[new_pagesize].width;
418                         new_ury = papersizes[new_pagesize].height;
419                 }
420         }
421
422         if (new_urx <= new_llx)
423                 new_urx = papersizes[12].width;
424         if (new_ury <= new_lly)
425                 new_ury = papersizes[12].height;
426
427         *urx = new_urx;
428         *ury = new_ury;
429         *llx = new_llx;
430         *lly = new_lly;
431 }
432
433 static int
434 get_page_orientation (PSDocument *gs, int page)
435 {
436         int orientation;
437
438         orientation = GTK_GS_ORIENTATION_NONE;
439
440         if (gs->structured_doc) {
441                 orientation = gs->doc->pages[page].orientation;
442         }
443         if (orientation == GTK_GS_ORIENTATION_NONE) {
444                 orientation = gs->doc->default_page_orientation;
445         }
446         if (orientation == GTK_GS_ORIENTATION_NONE) {
447                 orientation = gs->doc->orientation;
448         }
449         if (orientation == GTK_GS_ORIENTATION_NONE) {
450                 orientation = GTK_GS_ORIENTATION_PORTRAIT;
451         }
452         if (gs->orientation != GTK_GS_ORIENTATION_NONE) {
453                 orientation = gs->orientation;
454         }
455
456         return orientation;
457 }
458
459 static void
460 setup_page (PSDocument *gs, int page, double scale)
461 {
462         char buf[1024];
463         int urx, ury, llx, lly, orientation;
464         char scaled_xdpi[G_ASCII_DTOSTR_BUF_SIZE];      
465         char scaled_ydpi[G_ASCII_DTOSTR_BUF_SIZE];
466
467         LOG ("Setup the page");
468
469         get_page_box (gs, page, &urx, &ury, &llx, &lly);
470         orientation = get_page_orientation (gs, page);
471         g_ascii_dtostr (scaled_xdpi, G_ASCII_DTOSTR_BUF_SIZE, get_xdpi (gs) * scale);
472         g_ascii_dtostr (scaled_ydpi, G_ASCII_DTOSTR_BUF_SIZE, get_ydpi (gs) * scale);
473
474         g_snprintf (buf, 1024, "%ld %d %d %d %d %d %s %s %d %d %d %d",
475                     0L, orientation * 90, llx, lly, urx, ury,
476                     scaled_xdpi, scaled_ydpi,               
477                     0, 0, 0, 0);
478         LOG ("GS property %s", buf);
479
480         gdk_property_change (gs->pstarget, gs_class->gs_atom, gs_class->string_atom,
481                              8, GDK_PROP_MODE_REPLACE, (guchar *)buf, strlen(buf));
482         gdk_flush ();
483 }
484
485 static void
486 close_pipe (int p[2])
487 {
488         if (p[0] != -1) {
489                 close (p[0]);
490         }
491         if (p[1] != -1) {
492                 close (p[1]);
493         }
494 }
495
496 static gboolean
497 is_interpreter_ready (PSDocument *gs)
498 {
499         return (gs->interpreter_pid != -1 && !gs->busy && gs->ps_input == NULL);
500 }
501
502 static void
503 output (gpointer data, gint source, GdkInputCondition condition)
504 {
505         char buf[MAX_BUFSIZE + 1];
506         guint bytes = 0;
507         PSDocument *gs = PS_DOCUMENT(data);
508
509         if (source == gs->interpreter_output) {
510                 bytes = read(gs->interpreter_output, buf, MAX_BUFSIZE);
511                 if (bytes == 0) {            /* EOF occurred */
512                         close (gs->interpreter_output);
513                         gs->interpreter_output = -1;
514                         gdk_input_remove (gs->interpreter_output_id);
515                         return;
516                 } else if (bytes == -1) {
517                         /* trouble... */
518                         interpreter_failed (gs, NULL);
519                         return;
520                 }
521                 if (gs->interpreter_err == -1) {
522                         interpreter_failed (gs, NULL);
523                 }
524         } else if (source == gs->interpreter_err) {
525                 bytes = read (gs->interpreter_err, buf, MAX_BUFSIZE);
526                 if (bytes == 0) {            /* EOF occurred */
527                         close (gs->interpreter_err);
528                         gs->interpreter_err = -1;
529                         gdk_input_remove (gs->interpreter_error_id);
530                         return;
531                 } else if (bytes == -1) {
532                         /* trouble... */
533                         interpreter_failed (gs, NULL);
534                         return;
535                 }
536                 if (gs->interpreter_output == -1) {
537                         interpreter_failed(gs, NULL);
538                 }
539         }
540
541         if (bytes > 0) {
542                 buf[bytes] = '\0';
543                 printf ("%s", buf);
544         }
545 }
546
547 static void
548 catchPipe (int i)
549 {
550         broken_pipe = True;
551 }
552
553 static void
554 input(gpointer data, gint source, GdkInputCondition condition)
555 {
556         PSDocument *gs = PS_DOCUMENT(data);
557         int bytes_written;
558         void (*oldsig) (int);
559         oldsig = signal(SIGPIPE, catchPipe);
560
561         LOG ("Input");
562
563         do {
564                 if (gs->buffer_bytes_left == 0) {
565                         /* Get a new section if required */
566                         if (gs->ps_input && gs->bytes_left == 0) {
567                                 struct record_list *ps_old = gs->ps_input;
568                                 gs->ps_input = ps_old->next;
569                                 if (ps_old->close && NULL != ps_old->fp)
570                                         fclose (ps_old->fp);
571                                 g_free (ps_old);
572                         }
573
574                         /* Have to seek at the beginning of each section */
575                         if (gs->ps_input && gs->ps_input->seek_needed) {
576                                 fseek (gs->ps_input->fp, gs->ps_input->begin, SEEK_SET);
577                                 gs->ps_input->seek_needed = FALSE;
578                                 gs->bytes_left = gs->ps_input->len;
579                         }
580
581                         if (gs->bytes_left > MAX_BUFSIZE) {
582                                 gs->buffer_bytes_left = fread (gs->input_buffer, sizeof(char),
583                                                                MAX_BUFSIZE, gs->ps_input->fp);
584                         } else if (gs->bytes_left > 0) {
585                                 gs->buffer_bytes_left = fread (gs->input_buffer, sizeof(char),
586                                                                gs->bytes_left, gs->ps_input->fp);
587                         } else {
588                                 gs->buffer_bytes_left = 0;
589                         }
590                         if (gs->bytes_left > 0 && gs->buffer_bytes_left == 0) {
591                                 interpreter_failed (gs, NULL); /* Error occurred */
592                         }
593                         gs->input_buffer_ptr = gs->input_buffer;
594                         gs->bytes_left -= gs->buffer_bytes_left;
595                 }
596
597                 if (gs->buffer_bytes_left > 0) {
598                         bytes_written = write (gs->interpreter_input,
599                                                gs->input_buffer_ptr, gs->buffer_bytes_left);
600
601                         if (broken_pipe) {
602                                 interpreter_failed (gs, g_strdup(_("Broken pipe.")));
603                                 broken_pipe = FALSE;
604                                 interpreter_failed (gs, NULL);
605                         } else if (bytes_written == -1) {
606                                 if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
607                                         interpreter_failed (gs, NULL);   /* Something bad happened */
608                                 }
609                                 } else {
610                                 gs->buffer_bytes_left -= bytes_written;
611                                 gs->input_buffer_ptr += bytes_written;
612                         }
613                 }
614         } while (gs->ps_input && gs->buffer_bytes_left == 0);
615
616         signal (SIGPIPE, oldsig);
617
618         if (gs->ps_input == NULL && gs->buffer_bytes_left == 0) {
619                 if (gs->interpreter_input_id != 0) {
620                         gdk_input_remove (gs->interpreter_input_id);
621                         gs->interpreter_input_id = 0;
622                 }
623         }
624 }
625
626 static int
627 start_interpreter (PSDocument *gs)
628 {
629         int std_in[2] = { -1, -1 };   /* pipe to interp stdin */
630         int std_out[2];               /* pipe from interp stdout */
631         int std_err[2];               /* pipe from interp stderr */
632
633 #define NUM_ARGS    100
634 #define NUM_GS_ARGS (NUM_ARGS - 20)
635 #define NUM_ALPHA_ARGS 10
636
637         char *argv[NUM_ARGS], *dir, *gv_env;
638         char **gs_args, **alpha_args = NULL;
639         int argc = 0, i;
640
641         LOG ("Start the interpreter");
642
643         if(!gs->gs_filename)
644                 return 0;
645
646         stop_interpreter(gs);
647
648         /* set up the args... */
649         gs_args = g_strsplit (gtk_gs_defaults_get_interpreter_cmd (), " ", NUM_GS_ARGS);
650         for(i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++) {
651                 argv[argc] = gs_args[i];
652         }
653
654         alpha_args = g_strsplit (ALPHA_PARAMS, " ", NUM_ALPHA_ARGS);
655         for(i = 0; i < NUM_ALPHA_ARGS && alpha_args[i]; i++, argc++) {
656                 argv[argc] = alpha_args[i];
657         }
658
659         argv[argc++] = "-dNOPAUSE";
660         argv[argc++] = "-dQUIET";
661         argv[argc++] = "-dSAFER";
662
663         /* set up the pipes */
664         if (gs->send_filename_to_gs) {
665                 argv[argc++] = PS_DOCUMENT_GET_PS_FILE (gs);
666                 argv[argc++] = "-c";
667                 argv[argc++] = "quit";
668         } else {
669                 argv[argc++] = "-";
670         }
671
672         argv[argc++] = NULL;
673
674         if (!gs->reading_from_pipe && !gs->send_filename_to_gs) {
675                 if (pipe (std_in) == -1) {
676                         g_critical ("Unable to open pipe to Ghostscript.");
677                         return -1;
678                 }
679         }
680
681         if (pipe (std_out) == -1) {
682                 close_pipe (std_in);
683                 return -1;
684         }
685
686         if (pipe(std_err) == -1) {
687                 close_pipe (std_in);
688                 close_pipe (std_out);
689                 return -1;
690         }
691
692         gv_env = g_strdup_printf ("GHOSTVIEW=%ld %ld",
693                                   gdk_x11_drawable_get_xid (gs->pstarget),
694                                   gdk_x11_drawable_get_xid (gs->bpixmap));
695         LOG ("Launching ghostview with env %s", gv_env);
696
697         gs->interpreter_pid = fork ();
698         switch (gs->interpreter_pid) {
699                 case -1:                     /* error */
700                         close_pipe (std_in);
701                         close_pipe (std_out);
702                         close_pipe (std_err);
703                         return -2;
704                         break;
705                 case 0:                      /* child */
706                         close (std_out[0]);
707                         dup2 (std_out[1], 1);
708                         close (std_out[1]);
709
710                         close (std_err[0]);
711                         dup2 (std_err[1], 2);
712                         close (std_err[1]);
713
714                         if (!gs->reading_from_pipe) {
715                                 if (gs->send_filename_to_gs) {
716                                         int stdinfd;
717                                         /* just in case gs tries to read from stdin */
718                                         stdinfd = open("/dev/null", O_RDONLY);
719                                         if (stdinfd != 0) {
720                                                 dup2(stdinfd, 0);
721                                                 close(stdinfd);
722                                         }
723                                 } else {
724                                         close (std_in[1]);
725                                         dup2 (std_in[0], 0);
726                                         close (std_in[0]);
727                                 }
728                         }
729
730                         putenv(gv_env);
731
732                         /* change to directory where the input file is. This helps
733                          * with postscript-files which include other files using
734                          * a relative path */
735                         dir = g_path_get_dirname (gs->gs_filename);
736                         chdir (dir);
737                         g_free (dir);
738
739                         execvp (argv[0], argv);
740
741                         /* Notify error */
742                         g_critical ("Unable to execute [%s]\n", argv[0]);
743                         g_strfreev (gs_args);
744                         g_free (gv_env);
745                         g_strfreev (alpha_args);
746                         _exit (1);
747                         break;
748                 default:                     /* parent */
749                         if (!gs->send_filename_to_gs && !gs->reading_from_pipe) {
750                                 int result;
751                                 close (std_in[0]);
752                                 /* use non-blocking IO for pipe to ghostscript */
753                                 result = fcntl (std_in[1], F_GETFL, 0);
754                                 fcntl (std_in[1], F_SETFL, result | O_NONBLOCK);
755                                 gs->interpreter_input = std_in[1];
756                         } else {
757                                 gs->interpreter_input = -1;
758                         }
759                         close (std_out[1]);
760
761                         gs->interpreter_output = std_out[0];
762                         close (std_err[1]);
763                         gs->interpreter_err = std_err[0];
764                         gs->interpreter_output_id =
765                                 gdk_input_add (std_out[0], GDK_INPUT_READ, output, gs);
766                         gs->interpreter_error_id =
767                                 gdk_input_add (std_err[0], GDK_INPUT_READ, output, gs);
768                         break;
769         }
770
771         return TRUE;
772 }
773
774 static void
775 stop_interpreter(PSDocument * gs)
776 {
777         if (gs->interpreter_pid > 0) {
778                 int status = 0;
779                 LOG ("Stop the interpreter");
780                 kill (gs->interpreter_pid, SIGTERM);
781                 while ((wait(&status) == -1) && (errno == EINTR));
782                 gs->interpreter_pid = -1;
783                 if (status == 1) {
784                         gs->gs_status = _("Interpreter failed.");
785                 }
786         }
787
788         if (gs->interpreter_input >= 0) {
789                 close (gs->interpreter_input);
790                 gs->interpreter_input = -1;
791                 if (gs->interpreter_input_id != 0) {
792                         gdk_input_remove(gs->interpreter_input_id);
793                         gs->interpreter_input_id = 0;
794                 }
795                 while (gs->ps_input) {
796                         struct record_list *ps_old = gs->ps_input;
797                         gs->ps_input = gs->ps_input->next;
798                         if (ps_old->close && NULL != ps_old->fp)
799                                 fclose (ps_old->fp);
800                         g_free (ps_old);
801                 }
802         }
803
804         if (gs->interpreter_output >= 0) {
805                 close (gs->interpreter_output);
806                 gs->interpreter_output = -1;
807                 if (gs->interpreter_output_id) {
808                         gdk_input_remove (gs->interpreter_output_id);
809                         gs->interpreter_output_id = 0;
810                 }
811         }
812
813         if (gs->interpreter_err >= 0) {
814                 close (gs->interpreter_err);
815                 gs->interpreter_err = -1;
816                 if (gs->interpreter_error_id) {
817                         gdk_input_remove (gs->interpreter_error_id);
818                         gs->interpreter_error_id = 0;
819                 }
820         }
821
822         gs->busy = FALSE;
823 }
824
825 /* If file exists and is a regular file then return its length, else -1 */
826 static gint
827 file_length (const gchar * filename)
828 {
829         struct stat stat_rec;
830
831         if (filename && (stat (filename, &stat_rec) == 0) && S_ISREG (stat_rec.st_mode))
832                 return stat_rec.st_size;
833         else
834                 return -1;
835 }
836
837 /* Test if file exists, is a regular file and its length is > 0 */
838 static gboolean
839 file_readable(const char *filename)
840 {
841         return (file_length (filename) > 0);
842 }
843
844 /*
845  * Decompress gs->gs_filename if necessary
846  * Set gs->filename_unc to the name of the uncompressed file or NULL.
847  * Error reporting via signal 'interpreter_message'
848  * Return name of input file to use or NULL on error..
849  */
850 static gchar *
851 check_filecompressed (PSDocument * gs)
852 {
853         FILE *file;
854         gchar buf[1024];
855         gchar *filename, *filename_unc, *filename_err, *cmdline;
856         const gchar *cmd;
857         int fd;
858
859         cmd = NULL;
860
861         if ((file = fopen(gs->gs_filename, "r")) &&
862             (fread (buf, sizeof(gchar), 3, file) == 3)) {
863                 if ((buf[0] == '\037') && ((buf[1] == '\235') || (buf[1] == '\213'))) {
864                         /* file is gzipped or compressed */
865                         cmd = gtk_gs_defaults_get_ungzip_cmd ();
866                 } else if (strncmp (buf, "BZh", 3) == 0) {
867                         /* file is compressed with bzip2 */
868                         cmd = gtk_gs_defaults_get_unbzip2_cmd ();
869                 }
870         }
871
872         if (NULL != file)
873                 fclose(file);
874
875         if (!cmd)
876                 return gs->gs_filename;
877
878         /* do the decompression */
879         filename = g_shell_quote (gs->gs_filename);
880         filename_unc = g_strconcat (g_get_tmp_dir (), "/evinceXXXXXX", NULL);
881         if ((fd = mkstemp (filename_unc)) < 0) {
882                 g_free (filename_unc);
883                 g_free (filename);
884                 return NULL;
885         }
886         close (fd);
887
888         filename_err = g_strconcat (g_get_tmp_dir (), "/evinceXXXXXX", NULL);
889         if ((fd = mkstemp(filename_err)) < 0) {
890                 g_free (filename_err);
891                 g_free (filename_unc);
892                 g_free (filename);
893                 return NULL;
894         }
895         close (fd);
896
897         cmdline = g_strdup_printf ("%s %s >%s 2>%s", cmd,
898                                    filename, filename_unc, filename_err);
899         if (system (cmdline) == 0 &&
900             file_readable (filename_unc) &&
901             file_length (filename_err) == 0) {
902                 /* sucessfully uncompressed file */
903                 gs->gs_filename_unc = filename_unc;
904         } else {
905                 /* report error */
906                 g_snprintf (buf, 1024, _("Error while decompressing file %s:\n"),
907                             gs->gs_filename);
908                 interpreter_failed (gs, buf);
909                 unlink (filename_unc);
910                 g_free (filename_unc);
911                 filename_unc = NULL;
912         }
913
914         unlink (filename_err);
915         g_free (filename_err);
916         g_free (cmdline);
917         g_free (filename);
918
919         return filename_unc;
920 }
921
922 static gint
923 ps_document_enable_interpreter(PSDocument *gs)
924 {
925         g_return_val_if_fail (PS_IS_DOCUMENT (gs), FALSE);
926
927         if (!gs->gs_filename)
928                 return 0;
929
930         return start_interpreter (gs);
931 }
932
933 static gboolean
934 document_load (PSDocument *gs, const gchar *fname)
935 {
936         g_return_val_if_fail (PS_IS_DOCUMENT(gs), FALSE);
937
938         LOG ("Load the document");
939
940         if (fname == NULL) {
941                 gs->gs_status = "";
942                 return FALSE;
943         }
944
945         /* prepare this document */
946         gs->structured_doc = FALSE;
947         gs->send_filename_to_gs = TRUE;
948         gs->gs_filename = g_strdup (fname);
949
950         if ((gs->reading_from_pipe = (strcmp (fname, "-") == 0))) {
951                 gs->send_filename_to_gs = FALSE;
952         } else {
953                 /*
954                  * We need to make sure that the file is loadable/exists!
955                  * otherwise we want to exit without loading new stuff...
956                  */
957                 gchar *filename = NULL;
958
959                 if (!file_readable(fname)) {
960                         gchar buf[1024];
961
962                         g_snprintf (buf, 1024, _("Cannot open file %s.\n"), fname);
963                         interpreter_failed (gs, buf);
964                         gs->gs_status = _("File is not readable.");
965                 } else {
966                         filename = check_filecompressed(gs);
967                 }
968
969                 if (!filename || (gs->gs_psfile = fopen(filename, "r")) == NULL) {
970                         interpreter_failed (gs, NULL);
971                         return FALSE;
972                 }
973
974                 /* we grab the vital statistics!!! */
975                 gs->doc = psscan(gs->gs_psfile, TRUE, filename);
976
977                 if ((!gs->doc->epsf && gs->doc->numpages > 0) ||
978                     (gs->doc->epsf && gs->doc->numpages > 1)) {
979                         gs->structured_doc = TRUE;
980                         gs->send_filename_to_gs = FALSE;
981                 }
982         }
983
984         gs->gs_status = _("Document loaded.");
985
986         return TRUE;
987 }
988
989 static gboolean
990 ps_document_next_page (PSDocument *gs)
991 {
992         XEvent event;
993
994         LOG ("Make ghostscript render next page");
995
996         g_return_val_if_fail (PS_IS_DOCUMENT(gs), FALSE);
997         g_return_val_if_fail (gs->interpreter_pid != 0, FALSE);
998         g_return_val_if_fail (gs->busy != TRUE, FALSE);
999
1000         gs->busy = TRUE;
1001
1002         event.xclient.type = ClientMessage;
1003         event.xclient.display = gdk_display;
1004         event.xclient.window = gs->message_window;
1005         event.xclient.message_type = gdk_x11_atom_to_xatom(gs_class->next_atom);
1006         event.xclient.format = 32;
1007
1008         gdk_error_trap_push ();
1009         XSendEvent (gdk_display, gs->message_window, FALSE, 0, &event);
1010         gdk_flush ();
1011         gdk_error_trap_pop ();
1012
1013         return TRUE;
1014 }
1015
1016 static gboolean
1017 render_page (PSDocument *gs, int page)
1018 {
1019         g_return_val_if_fail(gs != NULL, FALSE);
1020         g_return_val_if_fail(PS_IS_DOCUMENT(gs), FALSE);
1021
1022         if(!gs->gs_filename) {
1023                 return FALSE;
1024         }
1025
1026         if (gs->structured_doc && gs->doc) {
1027                 LOG ("It's a structured document, let's send one page to gs");
1028
1029                 if (is_interpreter_ready (gs)) {
1030                         ps_document_next_page (gs);
1031                 } else {
1032                         ps_document_enable_interpreter (gs);
1033                         send_ps (gs, gs->doc->beginprolog, gs->doc->lenprolog, FALSE);
1034                         send_ps (gs, gs->doc->beginsetup, gs->doc->lensetup, FALSE);
1035                 }
1036
1037                 send_ps (gs, gs->doc->pages[page].begin,
1038                          gs->doc->pages[page].len, FALSE);
1039         } else {
1040                 /* Unstructured document
1041                  *
1042                  * In the case of non structured documents,
1043                  * GS read the PS from the  actual file (via command
1044                  * line. Hence, ggv only send a signal next page.
1045                  * If ghostview is not running it is usually because
1046                  * the last page of the file was displayed. In that
1047                  * case, ggv restarts GS again and the first page is displayed.
1048                  */
1049
1050                 LOG ("It's an unstructured document, gs will just read the file");
1051
1052                 if (!is_interpreter_ready (gs)) {
1053                         ps_document_enable_interpreter(gs);
1054                 }
1055                 ps_document_next_page(gs);
1056         }
1057
1058         return TRUE;
1059 }
1060
1061 static gboolean
1062 ps_document_load (EvDocument  *document,
1063                   const char  *uri,
1064                   GError     **error)
1065 {
1066         gboolean result;
1067         char *filename;
1068
1069         filename = g_filename_from_uri (uri, NULL, error);
1070         if (!filename)
1071                 return FALSE;
1072
1073         result = document_load (PS_DOCUMENT (document), filename);
1074         if (!result) {
1075                 g_set_error (error, G_FILE_ERROR,
1076                              G_FILE_ERROR_FAILED,
1077                              "Failed to load document '%s'\n",
1078                              uri);
1079         }
1080
1081         g_free (filename);
1082
1083         return result;
1084 }
1085
1086 static gboolean
1087 save_page_list (PSDocument *document, int *page_list, const char *filename)
1088 {
1089         gboolean result = TRUE;
1090         GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
1091         FILE *f;
1092         gchar *buf;
1093
1094         pscopydoc (sink, document->gs_filename, document->doc, page_list);
1095         
1096         buf = gtk_gs_doc_sink_get_buffer (sink);
1097         
1098         f = fopen (filename, "w");
1099         if (f) {
1100                 fputs (buf, f);
1101                 fclose (f);
1102         } else {
1103                 result = FALSE;
1104         }
1105
1106         g_free (buf);
1107         gtk_gs_doc_sink_free (sink);
1108         g_free (sink);
1109
1110         return result;
1111 }
1112
1113 static gboolean
1114 ps_document_save (EvDocument  *document,
1115                   const char  *uri,
1116                   GError     **error)
1117 {
1118         PSDocument *ps = PS_DOCUMENT (document);
1119         int *page_list;
1120         gboolean result;
1121         int i;
1122         char *filename;
1123
1124         filename = g_filename_from_uri (uri, NULL, error);
1125         if (!filename)
1126                 return FALSE;
1127
1128         page_list = g_new0 (int, ps->doc->numpages);
1129         for (i = 0; i < ps->doc->numpages; i++) {
1130                 page_list[i] = 1;
1131         }
1132
1133         result = save_page_list (ps, page_list, filename);
1134
1135         g_free (page_list);
1136         g_free (filename);
1137
1138         return result;
1139 }
1140
1141 static int
1142 ps_document_get_n_pages (EvDocument  *document)
1143 {
1144         PSDocument *ps = PS_DOCUMENT (document);
1145
1146         g_return_val_if_fail (ps != NULL, -1);
1147
1148         if (!ps->gs_filename || !ps->doc) {
1149                 return -1;
1150         }
1151
1152         return ps->structured_doc ? ps->doc->numpages : 1;
1153 }
1154
1155 static void
1156 ps_document_get_page_size (EvDocument   *document,
1157                            int           page,
1158                            double       *width,
1159                            double       *height)
1160 {
1161         PSDocument *gs = PS_DOCUMENT (document);
1162         int w, h;
1163         int urx, ury, llx, lly, orientation;
1164
1165         get_page_box (PS_DOCUMENT (document), page, &urx, &ury, &llx, &lly);
1166         orientation = get_page_orientation (PS_DOCUMENT (document), page);
1167
1168         switch (orientation) {
1169                 case GTK_GS_ORIENTATION_PORTRAIT:
1170                 case GTK_GS_ORIENTATION_UPSIDEDOWN:
1171                         w = (urx - llx) / 72.0 * get_xdpi (gs) + 0.5;
1172                         h = (ury - lly) / 72.0 * get_ydpi (gs) + 0.5;
1173                         break;
1174                 case GTK_GS_ORIENTATION_LANDSCAPE:
1175                 case GTK_GS_ORIENTATION_SEASCAPE:
1176                         w = (ury - lly) / 72.0 * get_xdpi (gs) + 0.5;
1177                         h = (urx - llx) / 72.0 * get_ydpi (gs) + 0.5;
1178                         break;
1179                 default:
1180                         w = h = 0;
1181                         g_assert_not_reached ();
1182                         break;
1183         }
1184
1185         if (width) {
1186                 *width = w;
1187         }
1188
1189         if (height) {
1190                 *height = h;
1191         }
1192 }
1193
1194 static gboolean
1195 ps_document_can_get_text (EvDocument *document)
1196 {
1197         return FALSE;
1198 }
1199
1200 static void
1201 ps_async_renderer_render_pixbuf (EvAsyncRenderer *renderer, int page, double scale)
1202 {
1203         PSDocument *gs = PS_DOCUMENT (renderer);
1204
1205         if (gs->pstarget == NULL) {
1206                 gs->target_window = gtk_window_new (GTK_WINDOW_POPUP);
1207                 gtk_widget_realize (gs->target_window);
1208                 gs->pstarget = gs->target_window->window;
1209
1210                 g_assert (gs->pstarget != NULL);
1211
1212                 g_signal_connect (gs->target_window, "event",
1213                                   G_CALLBACK (ps_document_widget_event),
1214                                   gs);
1215         }
1216
1217         setup_pixmap (gs, page, scale);
1218         setup_page (gs, page, scale);
1219
1220         render_page (gs, page);
1221 }
1222
1223 static EvDocumentInfo *
1224 ps_document_get_info (EvDocument *document)
1225 {
1226         EvDocumentInfo *info;
1227         PSDocument *ps = PS_DOCUMENT (document);
1228
1229         info = g_new0 (EvDocumentInfo, 1);
1230         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
1231                             EV_DOCUMENT_INFO_FORMAT |
1232                             EV_DOCUMENT_INFO_CREATOR |
1233                             EV_DOCUMENT_INFO_N_PAGES;
1234         info->title = g_strdup (ps->doc->title);
1235         info->format = ps->doc->epsf ? g_strdup (_("Encapsulated PostScript"))
1236                                      : g_strdup (_("PostScript"));
1237         info->creator = g_strdup (ps->doc->creator);
1238         info->n_pages = ev_document_get_n_pages (document);
1239
1240         return info;
1241 }
1242
1243 static EvOrientation
1244 ps_document_get_orientation (EvDocument *document)
1245 {
1246         EvOrientation orientation;
1247         PSDocument *ps = PS_DOCUMENT (document);
1248
1249         g_return_val_if_fail (ps != NULL, EV_ORIENTATION_PORTRAIT);
1250
1251         switch (ps->orientation) {
1252                 case GTK_GS_ORIENTATION_PORTRAIT:
1253                         orientation = EV_ORIENTATION_PORTRAIT;
1254                         break;
1255                 case GTK_GS_ORIENTATION_LANDSCAPE:
1256                         orientation = EV_ORIENTATION_LANDSCAPE;
1257                         break;
1258                 case GTK_GS_ORIENTATION_UPSIDEDOWN:
1259                         orientation = EV_ORIENTATION_UPSIDEDOWN;
1260                         break;
1261                 case GTK_GS_ORIENTATION_SEASCAPE:
1262                         orientation = EV_ORIENTATION_SEASCAPE;
1263                         break;
1264                 default:
1265                         orientation = EV_ORIENTATION_PORTRAIT;
1266                         break;
1267         }
1268
1269         return orientation;
1270 }
1271
1272 static void
1273 ps_document_document_iface_init (EvDocumentIface *iface)
1274 {
1275         iface->load = ps_document_load;
1276         iface->save = ps_document_save;
1277         iface->can_get_text = ps_document_can_get_text;
1278         iface->get_n_pages = ps_document_get_n_pages;
1279         iface->get_page_size = ps_document_get_page_size;
1280         iface->get_info = ps_document_get_info;
1281         iface->get_orientation = ps_document_get_orientation;
1282 }
1283
1284 static void
1285 ps_async_renderer_iface_init (EvAsyncRendererIface *iface)
1286 {
1287         iface->render_pixbuf = ps_async_renderer_render_pixbuf;
1288 }
1289
1290 static void
1291 ps_document_ps_export_begin (EvPSExporter *exporter, const char *filename,
1292                              int first_page, int last_page,
1293                              double width, double height, gboolean duplex)
1294 {
1295         PSDocument *document = PS_DOCUMENT (exporter);
1296
1297         g_free (document->ps_export_pagelist);
1298         
1299         document->ps_export_pagelist = g_new0 (int, document->doc->numpages);
1300         document->ps_export_filename = g_strdup (filename);
1301 }
1302
1303 static void
1304 ps_document_ps_export_do_page (EvPSExporter *exporter, EvRenderContext *rc)
1305 {
1306         PSDocument *document = PS_DOCUMENT (exporter);
1307         
1308         document->ps_export_pagelist[rc->page] = 1;
1309 }
1310
1311 static void
1312 ps_document_ps_export_end (EvPSExporter *exporter)
1313 {
1314         PSDocument *document = PS_DOCUMENT (exporter);
1315
1316         save_page_list (document, document->ps_export_pagelist,
1317                         document->ps_export_filename);
1318
1319         g_free (document->ps_export_pagelist);
1320         g_free (document->ps_export_filename);  
1321         document->ps_export_pagelist = NULL;
1322         document->ps_export_filename = NULL;
1323 }
1324
1325 static void
1326 ps_document_ps_exporter_iface_init (EvPSExporterIface *iface)
1327 {
1328         iface->begin = ps_document_ps_export_begin;
1329         iface->do_page = ps_document_ps_export_do_page;
1330         iface->end = ps_document_ps_export_end;
1331 }