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