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