]> www.fi.muni.cz Git - evince.git/blob - backend/ps/ps-document.c
1e448e38f1c3dece75cd5ae6e80b59ca49d99de2
[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 static void
425 ps_interpreter_finished (GPid        pid,
426                          gint        status,
427                          PSDocument *gs)
428 {
429         g_spawn_close_pid (gs->interpreter_pid);
430         gs->interpreter_pid = -1;
431         ps_interpreter_failed (gs, NULL);
432 }
433
434 #define NUM_ARGS    100
435 #define NUM_GS_ARGS (NUM_ARGS - 20)
436 #define NUM_ALPHA_ARGS 10
437
438 static void
439 setup_interpreter_env (gchar **envp)
440 {
441         gint i;
442
443         for (i = 0; envp[i]; i++)
444                 putenv (envp[i]);
445 }
446
447 static void
448 ps_interpreter_start (PSDocument *gs)
449 {
450         gchar *argv[NUM_ARGS], *dir, *gv_env, *gs_path;
451         gchar **gs_args, **alpha_args = NULL;
452         gchar **envp;
453         gint pin, pout, perr;
454         gint argc = 0, i;
455         GError *error = NULL;
456         
457         if (!gs->gs_filename)
458                 return;
459
460         ps_interpreter_stop (gs);
461
462         dir = g_path_get_dirname (gs->gs_filename);
463
464         /* set up the args... */
465         gs_path = g_find_program_in_path ("gs");
466         gs_args = g_strsplit (gs_path, " ", NUM_GS_ARGS);
467         g_free (gs_path);
468         for (i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++) {
469                 argv[argc] = gs_args[i];
470         }
471
472         alpha_args = g_strsplit (ALPHA_PARAMS, " ", NUM_ALPHA_ARGS);
473         for (i = 0; i < NUM_ALPHA_ARGS && alpha_args[i]; i++, argc++) {
474                 argv[argc] = alpha_args[i];
475         }
476
477         argv[argc++] = "-dNOPAUSE";
478         argv[argc++] = "-dQUIET";
479         argv[argc++] = "-dSAFER";
480
481         if (gs->send_filename_to_gs) {
482                 argv[argc++] = PS_DOCUMENT_GET_PS_FILE (gs);
483                 argv[argc++] = "-c";
484                 argv[argc++] = "quit";
485         } else {
486                 argv[argc++] = "-";
487         }
488
489         argv[argc++] = NULL;
490
491         gv_env = g_strdup_printf ("GHOSTVIEW=%ld %ld;DISPLAY=%s",
492                                   gdk_x11_drawable_get_xid (gs->pstarget),
493                                   gdk_x11_drawable_get_xid (gs->bpixmap),
494                                   gdk_display_get_name (gdk_drawable_get_display (gs->pstarget)));
495         envp = g_strsplit (gv_env, ";", 2);
496         g_free (gv_env);
497
498         if (g_spawn_async_with_pipes (dir, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
499                                       (GSpawnChildSetupFunc)setup_interpreter_env, envp,
500                                       &(gs->interpreter_pid),
501                                       &pin, &pout, &perr,
502                                       &error)) {
503                 GIOFlags flags;
504
505                 g_child_watch_add (gs->interpreter_pid,
506                                    (GChildWatchFunc)ps_interpreter_finished, 
507                                    gs);
508
509                 gs->interpreter_input = g_io_channel_unix_new (pin);
510                 g_io_channel_set_encoding (gs->interpreter_input, NULL, NULL);
511                 flags = g_io_channel_get_flags (gs->interpreter_input);
512                 g_io_channel_set_flags (gs->interpreter_input,
513                                         flags | G_IO_FLAG_NONBLOCK, NULL);
514
515                 
516                 gs->interpreter_output = g_io_channel_unix_new (pout);
517                 flags = g_io_channel_get_flags (gs->interpreter_output);
518                 g_io_channel_set_flags (gs->interpreter_output,
519                                         flags | G_IO_FLAG_NONBLOCK, NULL);
520                 gs->interpreter_output_id =
521                         g_io_add_watch (gs->interpreter_output, G_IO_IN,
522                                         (GIOFunc)ps_interpreter_output,
523                                         gs);
524                 
525                 gs->interpreter_err = g_io_channel_unix_new (perr);
526                 flags = g_io_channel_get_flags (gs->interpreter_err);
527                 g_io_channel_set_flags (gs->interpreter_err,
528                                         flags | G_IO_FLAG_NONBLOCK, NULL);
529                 gs->interpreter_error_id =
530                         g_io_add_watch (gs->interpreter_err, G_IO_IN,
531                                         (GIOFunc)ps_interpreter_error,
532                                         gs);
533         } else {
534                 g_warning (error->message);
535                 g_error_free (error);
536         }
537
538         g_free (dir);
539         g_strfreev (envp);
540         g_strfreev (gs_args);
541         g_strfreev (alpha_args);
542 }
543
544 static void
545 ps_interpreter_stop (PSDocument *gs)
546 {
547         if (gs->interpreter_pid > 0) {
548                 gint status = 0;
549                 
550                 kill (gs->interpreter_pid, SIGTERM);
551                 while ((wait (&status) == -1) && (errno == EINTR));
552                 g_spawn_close_pid (gs->interpreter_pid);
553                 gs->interpreter_pid = -1;
554                 
555                 if (status == 1) {
556                         gs->gs_status = _("Interpreter failed.");
557                 }
558         }
559
560         if (gs->interpreter_input) {
561                 g_io_channel_unref (gs->interpreter_input);
562                 gs->interpreter_input = NULL;
563
564                 if (gs->interpreter_input_id > 0) {
565                         g_source_remove (gs->interpreter_input_id);
566                         gs->interpreter_input_id = 0;
567                 }
568                 
569                 if (gs->ps_input) {
570                         g_queue_foreach (gs->ps_input, (GFunc)ps_section_free, NULL);
571                         g_queue_free (gs->ps_input);
572                         gs->ps_input = g_queue_new ();
573                 }
574         }
575
576         if (gs->interpreter_output) {
577                 g_io_channel_unref (gs->interpreter_output);
578                 gs->interpreter_output = NULL;
579
580                 if (gs->interpreter_output_id > 0) {
581                         g_source_remove (gs->interpreter_output_id);
582                         gs->interpreter_output_id = 0;
583                 }
584         }
585
586         if (gs->interpreter_err) {
587                 g_io_channel_unref (gs->interpreter_err);
588                 gs->interpreter_err = NULL;
589                 
590                 if (gs->interpreter_error_id > 0) {
591                         g_source_remove (gs->interpreter_error_id);
592                         gs->interpreter_error_id = 0;
593                 }
594         }
595
596         gs->busy = FALSE;
597 }
598
599 static void
600 ps_interpreter_failed (PSDocument *gs, const char *msg)
601 {
602         g_warning (msg ? msg : _("Interpreter failed."));
603         
604         push_pixbuf (gs);
605         ps_interpreter_stop (gs);
606 }
607
608 static gboolean
609 ps_interpreter_is_ready (PSDocument *gs)
610 {
611         return (gs->interpreter_pid != -1 &&
612                 !gs->busy &&
613                 (g_queue_is_empty (gs->ps_input)));
614 }
615
616 /* EvDocumentIface */
617 /*
618  * Decompress gs->gs_filename if necessary
619  * Set gs->filename_unc to the name of the uncompressed file or NULL.
620  * Error reporting via signal 'interpreter_message'
621  * Return name of input file to use or NULL on error..
622  */
623 static const gchar *
624 check_filecompressed (PSDocument * gs)
625 {
626         FILE *file;
627         gchar buf[1024];
628         gchar *filename, *filename_unc, *filename_err, *cmdline;
629         const gchar *cmd;
630         int fd;
631
632         cmd = NULL;
633
634         if ((file = fopen(gs->gs_filename, "r")) &&
635             (fread (buf, sizeof(gchar), 3, file) == 3)) {
636                 if ((buf[0] == '\037') && ((buf[1] == '\235') || (buf[1] == '\213'))) {
637                         /* file is gzipped or compressed */
638                         cmd = gtk_gs_defaults_get_ungzip_cmd ();
639                 } else if (strncmp (buf, "BZh", 3) == 0) {
640                         /* file is compressed with bzip2 */
641                         cmd = gtk_gs_defaults_get_unbzip2_cmd ();
642                 }
643         }
644
645         if (NULL != file)
646                 fclose(file);
647
648         if (!cmd)
649                 return gs->gs_filename;
650
651         /* do the decompression */
652         filename = g_shell_quote (gs->gs_filename);
653         filename_unc = g_strconcat (g_get_tmp_dir (), "/evinceXXXXXX", NULL);
654         if ((fd = g_mkstemp (filename_unc)) < 0) {
655                 g_free (filename_unc);
656                 g_free (filename);
657                 return NULL;
658         }
659         close (fd);
660
661         filename_err = g_strconcat (g_get_tmp_dir (), "/evinceXXXXXX", NULL);
662         if ((fd = g_mkstemp (filename_err)) < 0) {
663                 g_free (filename_err);
664                 g_free (filename_unc);
665                 g_free (filename);
666                 return NULL;
667         }
668         close (fd);
669
670         cmdline = g_strdup_printf ("%s %s >%s 2>%s", cmd,
671                                    filename, filename_unc, filename_err);
672
673         if (system (cmdline) == 0 &&
674             g_file_test (filename_unc, G_FILE_TEST_IS_REGULAR)) {
675                         /* sucessfully uncompressed file */
676                         gs->gs_filename_unc = filename_unc;
677         } else {
678                 gchar *filename_dsp;
679                 gchar *msg;
680                 
681                 /* report error */
682                 filename_dsp = g_filename_display_name (gs->gs_filename);
683                 msg = g_strdup_printf (_("Error while decompressing file “%s”:\n"),
684                                        filename_dsp);
685                 g_free (filename_dsp);
686                 
687                 ps_interpreter_failed (gs, msg);
688                 g_free (msg);
689                 g_unlink (filename_unc);
690                 g_free (filename_unc);
691                 filename_unc = NULL;
692         }
693
694         g_unlink (filename_err);
695         g_free (filename_err);
696         g_free (cmdline);
697         g_free (filename);
698
699         return filename_unc;
700 }
701
702 static gboolean
703 document_load (PSDocument *gs, const gchar *fname)
704 {
705         const gchar *filename;
706         
707         if (fname == NULL) {
708                 gs->gs_status = "";
709                 return FALSE;
710         }
711
712         /* prepare this document */
713         gs->structured_doc = FALSE;
714         gs->send_filename_to_gs = TRUE;
715         gs->gs_filename = g_strdup (fname);
716
717         /*
718          * We need to make sure that the file is loadable/exists!
719          * otherwise we want to exit without loading new stuff...
720          */
721         if (!g_file_test (fname, G_FILE_TEST_IS_REGULAR)) {
722                 gchar *filename_dsp;
723                 gchar *msg;
724                 
725                 filename_dsp = g_filename_display_name (fname);
726                 msg = g_strdup_printf (_("Cannot open file “%s”.\n"), filename_dsp);
727                 g_free (filename_dsp);
728                 
729                 ps_interpreter_failed (gs, msg);
730                 g_free (msg);
731                 gs->gs_status = _("File is not readable.");
732                 
733                 return FALSE;
734         }
735
736         filename = check_filecompressed (gs);
737         
738         if (!filename || (gs->gs_psfile = fopen (filename, "r")) == NULL) {
739                 ps_interpreter_failed (gs, NULL);
740                 return FALSE;
741         }
742         
743         /* we grab the vital statistics!!! */
744         gs->doc = psscan (gs->gs_psfile, TRUE, filename);
745         
746         if ((!gs->doc->epsf && gs->doc->numpages > 0) ||
747             (gs->doc->epsf && gs->doc->numpages > 1)) {
748                 gs->structured_doc = TRUE;
749                 gs->send_filename_to_gs = FALSE;
750         }
751
752         gs->gs_status = _("Document loaded.");
753
754         return TRUE;
755 }
756
757 static gboolean
758 ps_document_load (EvDocument  *document,
759                   const char  *uri,
760                   GError     **error)
761 {
762         char *filename;
763         char *gs_path;
764         gboolean result;
765
766         filename = g_filename_from_uri (uri, NULL, error);
767         if (!filename)
768                 return FALSE;
769
770         gs_path = g_find_program_in_path ("gs");
771         if (!gs_path) {
772                     gchar *filename_dsp;
773                     
774                     filename_dsp = g_filename_display_name (filename);
775                     g_set_error (error,
776                                  G_FILE_ERROR,
777                                  G_FILE_ERROR_NOENT,
778                                  _("Failed to load document “%s”. Ghostscript interpreter was not found in path"),
779                                  filename);
780                     g_free (filename_dsp);
781                     g_free (filename);
782
783                     return FALSE;
784         }
785
786         result = document_load (PS_DOCUMENT (document), filename);
787         if (!result) {
788                 gchar *filename_dsp;
789                 
790                 filename_dsp = g_filename_display_name (filename);
791                 g_set_error (error, G_FILE_ERROR,
792                              G_FILE_ERROR_FAILED,
793                              _("Failed to load document “%s”"),
794                              filename_dsp);
795                 g_free (filename_dsp);
796         }
797         
798         g_free (gs_path);
799         g_free (filename);
800
801         return result;
802 }
803
804 static gboolean
805 save_document (PSDocument *document, const char *filename)
806 {
807         gboolean result = TRUE;
808         GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
809         FILE *f, *src_file;
810         gchar *buf;
811
812         src_file = fopen (PS_DOCUMENT_GET_PS_FILE(document), "r");
813         if (src_file) {
814                 struct stat stat_rec;
815
816                 if (stat (PS_DOCUMENT_GET_PS_FILE(document), &stat_rec) == 0) {
817                         pscopy (src_file, sink, 0, stat_rec.st_size - 1);
818                 }
819
820                 fclose (src_file);
821         }
822         
823         buf = gtk_gs_doc_sink_get_buffer (sink);
824         if (buf == NULL) {
825                 return FALSE;
826         }
827         
828         f = fopen (filename, "w");
829         if (f) {
830                 fputs (buf, f);
831                 fclose (f);
832         } else {
833                 result = FALSE;
834         }
835
836         g_free (buf);
837         gtk_gs_doc_sink_free (sink);
838         g_free (sink);
839
840         return result;
841 }
842
843 static gboolean
844 save_page_list (PSDocument *document, int *page_list, const char *filename)
845 {
846         gboolean result = TRUE;
847         GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
848         FILE *f;
849         gchar *buf;
850
851         pscopydoc (sink, PS_DOCUMENT_GET_PS_FILE(document), 
852                    document->doc, page_list);
853         
854         buf = gtk_gs_doc_sink_get_buffer (sink);
855         
856         f = fopen (filename, "w");
857         if (f) {
858                 fputs (buf, f);
859                 fclose (f);
860         } else {
861                 result = FALSE;
862         }
863
864         g_free (buf);
865         gtk_gs_doc_sink_free (sink);
866         g_free (sink);
867
868         return result;
869 }
870
871 static gboolean
872 ps_document_save (EvDocument  *document,
873                   const char  *uri,
874                   GError     **error)
875 {
876         PSDocument *ps = PS_DOCUMENT (document);
877         gboolean result;
878         char *filename;
879
880         filename = g_filename_from_uri (uri, NULL, error);
881         if (!filename)
882                 return FALSE;
883
884         result = save_document (ps, filename);
885
886         g_free (filename);
887
888         return result;
889 }
890
891 static int
892 ps_document_get_n_pages (EvDocument *document)
893 {
894         PSDocument *ps = PS_DOCUMENT (document);
895
896         if (!ps->gs_filename || !ps->doc) {
897                 return -1;
898         }
899
900         return ps->structured_doc ? ps->doc->numpages : 1;
901 }
902
903 #define DEFAULT_PAGE_SIZE 1
904
905 static void
906 get_page_box (PSDocument *gs, int page, int *urx, int *ury, int *llx, int *lly)
907 {
908         gint new_llx = 0;
909         gint new_lly = 0;
910         gint new_urx = 0;
911         gint new_ury = 0;
912         GtkGSPaperSize *papersizes = gtk_gs_defaults_get_paper_sizes ();
913         int new_pagesize = -1;
914
915         if (new_pagesize == -1) {
916                 new_pagesize = DEFAULT_PAGE_SIZE;
917                 if (gs->doc) {
918                         /* If we have a document:
919                          * We use -- the page size (if specified)       
920                          * or the doc. size (if specified)      
921                          * or the page bbox (if specified)      
922                          * or the bounding box  
923                          */
924                         if ((page >= 0) && (gs->doc->numpages > page) &&
925                             (gs->doc->pages) && (gs->doc->pages[page].size)) {
926                                 new_pagesize = gs->doc->pages[page].size - gs->doc->size;
927                         } else if (gs->doc->default_page_size != NULL) {
928                                 new_pagesize = gs->doc->default_page_size - gs->doc->size;
929                         } else if ((page >= 0) &&
930                                    (gs->doc->numpages > page) &&
931                                    (gs->doc->pages) &&
932                                    (gs->doc->pages[page].boundingbox[URX] >
933                                     gs->doc->pages[page].boundingbox[LLX]) &&
934                                    (gs->doc->pages[page].boundingbox[URY] >
935                                     gs->doc->pages[page].boundingbox[LLY])) {
936                                 new_pagesize = -1;
937                         } else if ((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
938                                    (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
939                                 new_pagesize = -1;
940                         }
941                 }
942         }
943
944         /* Compute bounding box */
945         if (gs->doc && (gs->doc->epsf || new_pagesize == -1)) {    /* epsf or bbox */
946                 if ((page >= 0) &&
947                     (gs->doc->pages) &&
948                     (gs->doc->pages[page].boundingbox[URX] >
949                      gs->doc->pages[page].boundingbox[LLX]) &&
950                     (gs->doc->pages[page].boundingbox[URY] >
951                      gs->doc->pages[page].boundingbox[LLY])) {
952                         /* use page bbox */
953                         new_llx = gs->doc->pages[page].boundingbox[LLX];
954                         new_lly = gs->doc->pages[page].boundingbox[LLY];
955                         new_urx = gs->doc->pages[page].boundingbox[URX];
956                         new_ury = gs->doc->pages[page].boundingbox[URY];
957                 } else if ((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
958                            (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
959                         /* use doc bbox */
960                         new_llx = gs->doc->boundingbox[LLX];
961                         new_lly = gs->doc->boundingbox[LLY];
962                         new_urx = gs->doc->boundingbox[URX];
963                         new_ury = gs->doc->boundingbox[URY];
964                 }
965         } else {
966                 if (new_pagesize < 0)
967                         new_pagesize = DEFAULT_PAGE_SIZE;
968                 new_llx = new_lly = 0;
969                 if (gs->doc && gs->doc->size &&
970                     (new_pagesize < gs->doc->numsizes)) {
971                         new_urx = gs->doc->size[new_pagesize].width;
972                         new_ury = gs->doc->size[new_pagesize].height;
973                 } else {
974                         new_urx = papersizes[new_pagesize].width;
975                         new_ury = papersizes[new_pagesize].height;
976                 }
977         }
978
979         if (new_urx <= new_llx)
980                 new_urx = papersizes[12].width;
981         if (new_ury <= new_lly)
982                 new_ury = papersizes[12].height;
983
984         *urx = new_urx;
985         *ury = new_ury;
986         *llx = new_llx;
987         *lly = new_lly;
988 }
989
990 static void
991 ps_document_get_page_size (EvDocument *document,
992                            int         page,
993                            double     *width,
994                            double     *height)
995 {
996         PSDocument *gs = PS_DOCUMENT (document);
997         int urx, ury, llx, lly;
998
999         get_page_box (gs, page, &urx, &ury, &llx, &lly);
1000
1001         if (width) {
1002                 *width = (urx - llx) + 0.5;
1003         }
1004
1005         if (height) {
1006                 *height = (ury - lly) + 0.5;
1007         }
1008 }
1009
1010 static gboolean
1011 ps_document_can_get_text (EvDocument *document)
1012 {
1013         return FALSE;
1014 }
1015
1016 static EvDocumentInfo *
1017 ps_document_get_info (EvDocument *document)
1018 {
1019         EvDocumentInfo *info;
1020         PSDocument *ps = PS_DOCUMENT (document);
1021         int urx, ury, llx, lly;
1022
1023         info = g_new0 (EvDocumentInfo, 1);
1024         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
1025                             EV_DOCUMENT_INFO_FORMAT |
1026                             EV_DOCUMENT_INFO_CREATOR |
1027                             EV_DOCUMENT_INFO_N_PAGES |
1028                             EV_DOCUMENT_INFO_PAPER_SIZE;
1029
1030         info->title = g_strdup (ps->doc->title);
1031         info->format = ps->doc->epsf ? g_strdup (_("Encapsulated PostScript"))
1032                                      : g_strdup (_("PostScript"));
1033         info->creator = g_strdup (ps->doc->creator);
1034         info->n_pages = ev_document_get_n_pages (document);
1035         
1036         get_page_box (PS_DOCUMENT (document), 0, &urx, &ury, &llx, &lly);
1037
1038         info->paper_width  = (urx - llx) / 72.0f * 25.4f;
1039         info->paper_height = (ury - lly) / 72.0f * 25.4f;
1040
1041         return info;
1042 }
1043
1044 static void
1045 ps_document_document_iface_init (EvDocumentIface *iface)
1046 {
1047         iface->load = ps_document_load;
1048         iface->save = ps_document_save;
1049         iface->can_get_text = ps_document_can_get_text;
1050         iface->get_n_pages = ps_document_get_n_pages;
1051         iface->get_page_size = ps_document_get_page_size;
1052         iface->get_info = ps_document_get_info;
1053 }
1054
1055 /* EvAsyncRendererIface */
1056 static void
1057 setup_page (PSDocument *gs, int page, double scale, int rotation)
1058 {
1059         gchar *buf;
1060         char scaled_dpi[G_ASCII_DTOSTR_BUF_SIZE];       
1061         int urx, ury, llx, lly;
1062         PSDocumentClass *gs_class;
1063
1064         gs_class = PS_DOCUMENT_GET_CLASS (gs);
1065
1066         get_page_box (gs, page, &urx, &ury, &llx, &lly);
1067         g_ascii_dtostr (scaled_dpi, G_ASCII_DTOSTR_BUF_SIZE, 72.0 * scale);
1068
1069         buf = g_strdup_printf ("%ld %d %d %d %d %d %s %s %d %d %d %d",
1070                                0L, rotation, llx, lly, urx, ury,
1071                                scaled_dpi, scaled_dpi,
1072                                0, 0, 0, 0);
1073         
1074         gdk_property_change (gs->pstarget, gs_class->gs_atom, gs_class->string_atom,
1075                              8, GDK_PROP_MODE_REPLACE, (guchar *)buf, strlen (buf));
1076         g_free (buf);
1077         
1078         gdk_flush ();
1079 }
1080
1081 static void
1082 setup_pixmap (PSDocument *gs, int page, double scale, int rotation)
1083 {
1084         GdkGC *fill;
1085         GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF };   /* pixel, r, g, b */
1086         GdkColormap *colormap;
1087         double width, height;
1088         int pixmap_width, pixmap_height;
1089         
1090         if (gs->pstarget == NULL)
1091                 return;
1092
1093         ev_document_get_page_size (EV_DOCUMENT (gs), page, &width, &height);
1094
1095         if (rotation == 90 || rotation == 270) {
1096                 pixmap_height = width * scale + 0.5;
1097                 pixmap_width = height * scale + 0.5;
1098         } else {
1099                 pixmap_width = width * scale + 0.5;
1100                 pixmap_height = height * scale + 0.5;
1101         }
1102
1103         if (gs->bpixmap) {
1104                 gint w, h;
1105
1106                 gdk_drawable_get_size (gs->bpixmap, &w, &h);
1107
1108                 if (pixmap_width != w || h != pixmap_height) {
1109                         g_object_unref (gs->bpixmap);
1110                         gs->bpixmap = NULL;
1111                         ps_interpreter_stop (gs);
1112                 }
1113         }
1114
1115         if (!gs->bpixmap) {
1116                 fill = gdk_gc_new (gs->pstarget);
1117                 colormap = gdk_drawable_get_colormap (gs->pstarget);
1118                 gdk_colormap_alloc_color (colormap, &white, FALSE, TRUE);
1119                 gdk_gc_set_foreground (fill, &white);
1120                 gs->bpixmap = gdk_pixmap_new (gs->pstarget, pixmap_width,
1121                                               pixmap_height, -1);
1122                 gdk_draw_rectangle (gs->bpixmap, fill, TRUE,
1123                                     0, 0, pixmap_width, pixmap_height);
1124         }
1125 }
1126
1127 static void
1128 push_pixbuf (PSDocument *gs)
1129 {
1130         GdkColormap *cmap;
1131         GdkPixbuf *pixbuf;
1132         gint width, height;
1133
1134         if (gs->pstarget == NULL)
1135                 return;
1136
1137         cmap = gdk_drawable_get_colormap (gs->pstarget);
1138         gdk_drawable_get_size (gs->bpixmap, &width, &height);
1139         pixbuf = gdk_pixbuf_get_from_drawable (NULL, gs->bpixmap, cmap,
1140                                                0, 0, 0, 0,
1141                                                width, height);
1142         g_signal_emit_by_name (gs, "render_finished", pixbuf);
1143         g_object_unref (pixbuf);
1144 }
1145
1146 static gboolean
1147 ps_document_widget_event (GtkWidget *widget, GdkEvent *event, gpointer data)
1148 {
1149         PSDocument *gs = (PSDocument *) data;
1150         PSDocumentClass *gs_class;
1151
1152         if (event->type != GDK_CLIENT_EVENT)
1153                 return FALSE;
1154
1155         gs_class = PS_DOCUMENT_GET_CLASS (gs);
1156         
1157         gs->message_window = event->client.data.l[0];
1158
1159         if (event->client.message_type == gs_class->page_atom) {
1160                 gs->busy = FALSE;
1161
1162                 push_pixbuf (gs);
1163         }
1164
1165         return TRUE;
1166 }
1167
1168 static void
1169 send_ps (PSDocument *gs, long begin, unsigned int len, gboolean close)
1170 {
1171         PSSection *ps_new;
1172
1173         if (!gs->interpreter_input) {
1174                 g_critical ("No pipe to gs: error in send_ps().");
1175                 return;
1176         }
1177
1178         ps_new = g_new0 (PSSection, 1);
1179         ps_new->fp = gs->gs_psfile;
1180         ps_new->begin = begin;
1181         ps_new->len = len;
1182         ps_new->seek_needed = TRUE;
1183         ps_new->close = close;
1184
1185         if (gs->input_buffer == NULL) {
1186                 gs->input_buffer = g_malloc (MAX_BUFSIZE);
1187         }
1188
1189         if (g_queue_is_empty (gs->ps_input)) {
1190                 gs->input_buffer_ptr = gs->input_buffer;
1191                 gs->bytes_left = len;
1192                 gs->buffer_bytes_left = 0;
1193                 g_queue_push_head (gs->ps_input, ps_new);
1194                 gs->interpreter_input_id =
1195                         g_io_add_watch (gs->interpreter_input,
1196                                         G_IO_OUT/* | G_IO_HUP | G_IO_ERR | G_IO_NVAL*/,
1197                                         (GIOFunc)ps_interpreter_input,
1198                                         gs);
1199         } else {
1200                 g_queue_push_head (gs->ps_input, ps_new);
1201         }
1202 }
1203
1204 static void
1205 ps_document_next_page (PSDocument *gs)
1206 {
1207         XEvent      event;
1208         GdkScreen  *screen;
1209         GdkDisplay *display;
1210         Display    *dpy;
1211         PSDocumentClass *gs_class;
1212
1213         g_assert (gs->interpreter_pid != 0);
1214         g_assert (gs->busy != TRUE);
1215
1216         gs_class = PS_DOCUMENT_GET_CLASS (gs);
1217         
1218         gs->busy = TRUE;
1219
1220         screen = gtk_window_get_screen (GTK_WINDOW (gs->target_window));
1221         display = gdk_screen_get_display (screen);
1222         dpy = gdk_x11_display_get_xdisplay (display);
1223
1224         event.xclient.type = ClientMessage;
1225         event.xclient.display = dpy;
1226         event.xclient.window = gs->message_window;
1227         event.xclient.message_type =
1228                 gdk_x11_atom_to_xatom_for_display (display,
1229                                                    gs_class->next_atom);
1230         event.xclient.format = 32;
1231
1232         gdk_error_trap_push ();
1233         XSendEvent (dpy, gs->message_window, FALSE, 0, &event);
1234         gdk_flush ();
1235         gdk_error_trap_pop ();
1236 }
1237
1238 static gboolean
1239 render_page (PSDocument *gs, int page)
1240 {
1241         g_assert (gs != NULL);
1242
1243         if (!gs->gs_filename) {
1244                 return FALSE;
1245         }
1246
1247         if (gs->structured_doc && gs->doc) {
1248                 if (ps_interpreter_is_ready (gs)) {
1249                         ps_document_next_page (gs);
1250                 } else {
1251                         ps_interpreter_start (gs);
1252                         send_ps (gs, gs->doc->beginprolog, gs->doc->lenprolog, FALSE);
1253                         send_ps (gs, gs->doc->beginsetup, gs->doc->lensetup, FALSE);
1254                 }
1255
1256                 send_ps (gs, gs->doc->pages[page].begin,
1257                          gs->doc->pages[page].len, FALSE);
1258         } else {
1259                 /* Unstructured document
1260                  *
1261                  * In the case of non structured documents,
1262                  * GS read the PS from the  actual file (via command
1263                  * line. Hence, ggv only send a signal next page.
1264                  * If ghostview is not running it is usually because
1265                  * the last page of the file was displayed. In that
1266                  * case, ggv restarts GS again and the first page is displayed.
1267                  */
1268
1269                 if (!ps_interpreter_is_ready (gs)) {
1270                         ps_interpreter_start (gs);
1271                 }
1272                 ps_document_next_page (gs);
1273         }
1274
1275         return TRUE;
1276 }
1277
1278 static void
1279 ps_async_renderer_render_pixbuf (EvAsyncRenderer *renderer,
1280                                  gint             page,
1281                                  gdouble          scale,
1282                                  gint             rotation)
1283 {
1284         PSDocument *gs = PS_DOCUMENT (renderer);
1285
1286         if (gs->pstarget == NULL) {
1287                 gs->target_window = gtk_window_new (GTK_WINDOW_POPUP);
1288                 gtk_widget_realize (gs->target_window);
1289                 gs->pstarget = gs->target_window->window;
1290
1291                 g_assert (gs->pstarget != NULL);
1292
1293                 g_signal_connect (gs->target_window, "event",
1294                                   G_CALLBACK (ps_document_widget_event),
1295                                   gs);
1296         }
1297
1298         setup_pixmap (gs, page, scale, rotation);
1299         setup_page (gs, page, scale, rotation);
1300
1301         render_page (gs, page);
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 /* EvFileExporterIface */
1311 static gboolean
1312 ps_document_file_exporter_format_supported (EvFileExporter      *exporter,
1313                                             EvFileExporterFormat format)
1314 {
1315         return (format == EV_FILE_FORMAT_PS);
1316 }
1317
1318 static void
1319 ps_document_file_exporter_begin (EvFileExporter      *exporter,
1320                                  EvFileExporterFormat format,
1321                                  const char          *filename,
1322                                  int                  first_page,
1323                                  int                  last_page,
1324                                  double               width,
1325                                  double               height,
1326                                  gboolean             duplex)
1327 {
1328         PSDocument *document = PS_DOCUMENT (exporter);
1329
1330         if (document->structured_doc) {
1331                 g_free (document->ps_export_pagelist);
1332         
1333                 document->ps_export_pagelist = g_new0 (int, document->doc->numpages);
1334         }
1335
1336         document->ps_export_filename = g_strdup (filename);
1337 }
1338
1339 static void
1340 ps_document_file_exporter_do_page (EvFileExporter *exporter, EvRenderContext *rc)
1341 {
1342         PSDocument *document = PS_DOCUMENT (exporter);
1343         
1344         if (document->structured_doc) {
1345                 document->ps_export_pagelist[rc->page] = 1;
1346         }
1347 }
1348
1349 static void
1350 ps_document_file_exporter_end (EvFileExporter *exporter)
1351 {
1352         PSDocument *document = PS_DOCUMENT (exporter);
1353
1354         if (!document->structured_doc) {
1355                 save_document (document, document->ps_export_filename);
1356         } else {
1357                 save_page_list (document, document->ps_export_pagelist,
1358                                 document->ps_export_filename);
1359                 g_free (document->ps_export_pagelist);
1360                 g_free (document->ps_export_filename);  
1361                 document->ps_export_pagelist = NULL;
1362                 document->ps_export_filename = NULL;
1363         }
1364 }
1365
1366 static void
1367 ps_document_file_exporter_iface_init (EvFileExporterIface *iface)
1368 {
1369         iface->format_supported = ps_document_file_exporter_format_supported;
1370         iface->begin = ps_document_file_exporter_begin;
1371         iface->do_page = ps_document_file_exporter_do_page;
1372         iface->end = ps_document_file_exporter_end;
1373 }