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