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