]> www.fi.muni.cz Git - evince.git/blob - ps/gtkgs.c
edb700d7f6957612592dfbd3c4d47fc229a4e760
[evince.git] / ps / gtkgs.c
1 /* Ghostscript widget for GTK/GNOME
2  * 
3  * Copyright (C) 1998 - 2005 the Free Software Foundation
4  * 
5  * Authors: Jonathan Blandford, Jaka Mocnik
6  * 
7  * Based on code by: Federico Mena (Quartic), Szekeres Istvan (Pista)
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24  
25 /*
26 Ghostview interface to ghostscript
27
28 When the GHOSTVIEW environment variable is set, ghostscript draws on
29 an existing drawable rather than creating its own window.  Ghostscript
30 can be directed to draw on either a window or a pixmap.
31
32 Drawing on a Window
33
34 The GHOSTVIEW environment variable contains the window id of the target
35 window.  The window id is an integer.  Ghostscript will use the attributes
36 of the window to obtain the width, height, colormap, screen, and visual of
37 the window. The remainder of the information is gotten from the GHOSTVIEW
38 property on that window.
39
40
41 Drawing on a Pixmap
42
43 The GHOSTVIEW environment variable contains a window id and a pixmap id.
44 They are integers separated by white space.  Ghostscript will use the
45 attributes of the window to obtain the colormap, screen, and visual to use.
46 The width and height will be obtained from the pixmap. The remainder of the
47 information, is gotten from the GHOSTVIEW property on the window.  In this
48 case, the property is deleted when read.
49
50 The GHOSTVIEW environment variable
51
52 parameters:     window-id [pixmap-id]
53
54 scanf format:   "%d %d"
55
56 explanation of parameters:
57
58         window-id: tells ghostscript where to
59                     - read the GHOSTVIEW property
60                     - send events
61                     If pixmap-id is not present,
62                     ghostscript will draw on this window.
63
64         pixmap-id: If present, tells ghostscript that a pixmap will be used
65                     as the final destination for drawing.  The window will
66                     not be touched for drawing purposes.
67
68 The GHOSTVIEW property
69
70 type:   STRING
71
72 parameters:
73
74     bpixmap orient llx lly urx ury xdpi ydpi [left bottom top right]
75
76 scanf format: "%d %d %d %d %d %d %f %f %d %d %d %d"
77
78 explanation of parameters:
79
80         bpixmap: pixmap id of the backing pixmap for the window.  If no
81                 pixmap is to be used, this parameter should be zero.  This
82                 parameter must be zero when drawing on a pixmap.
83
84         orient: orientation of the page.  The number represents clockwise
85                 rotation of the paper in degrees.  Permitted values are
86                 0, 90, 180, 270.
87
88         llx, lly, urx, ury: Bounding box of the drawable.  The bounding box
89                 is specified in PostScript points in default user coordinates.
90
91         xdpi, ydpi: Resolution of window.  (This can be derived from the
92                 other parameters, but not without roundoff error.  These
93                 values are included to avoid this error.)
94
95         left, bottom, top, right: (optional)
96                 Margins around the window.  The margins extend the imageable
97                 area beyond the boundaries of the window.  This is primarily
98                 used for popup zoom windows.  I have encountered several
99                 instances of PostScript programs that position themselves
100                 with respect to the imageable area.  The margins are specified
101                 in PostScript points.  If omitted, the margins are assumed to
102                 be 0.
103
104 Events from ghostscript
105
106 If the final destination is a pixmap, the client will get a property notify
107 event when ghostscript reads the GHOSTVIEW property causing it to be deleted.
108
109 Ghostscript sends events to the window where it read the GHOSTVIEW property.
110 These events are of type ClientMessage.  The message_type is set to
111 either PAGE or DONE.  The first long data value gives the window to be used
112 to send replies to ghostscript.  The second long data value gives the primary
113 drawable.  If rendering to a pixmap, it is the primary drawable.  If rendering
114 to a window, the backing pixmap is the primary drawable.  If no backing pixmap
115 is employed, then the window is the primary drawable.  This field is necessary
116 to distinguish multiple ghostscripts rendering to separate pixmaps where the
117 GHOSTVIEW property was placed on the same window.
118
119 The PAGE message indicates that a "page" has completed.  Ghostscript will
120 wait until it receives a ClientMessage whose message_type is NEXT before
121 continuing.
122
123 The DONE message indicates that ghostscript has finished processing.
124
125 */
126
127 #include "config.h"
128 #include <string.h>
129 #include <stdlib.h>
130 #include <signal.h>
131 #include <gtk/gtk.h>
132 #include <gtk/gtkobject.h>
133 #include <gdk/gdkprivate.h>
134 #include <gdk/gdkx.h>
135 #include <gdk/gdk.h>
136 #ifdef  HAVE_XINERAMA
137 #   include <gdk/gdkx.h>
138 #   include <X11/extensions/Xinerama.h>
139 #endif /* HAVE_XINERAMA */
140 #include <X11/Intrinsic.h>
141 #include <unistd.h>
142 #include <fcntl.h>
143 #include <stdlib.h>
144 #include <errno.h>
145 #include <sys/stat.h>
146 #include <sys/types.h>
147 #include <sys/wait.h>
148 #include <stdio.h>
149 #include <math.h>
150
151 #include "ev-document.h"
152 #include "gtkgs.h"
153 #include "ps.h"
154 #include "gsdefaults.h"
155
156 #ifdef HAVE_LOCALE_H
157 #   include <locale.h>
158 #endif
159
160 /* if POSIX O_NONBLOCK is not available, use O_NDELAY */
161 #if !defined(O_NONBLOCK) && defined(O_NDELAY)
162 #   define O_NONBLOCK O_NDELAY
163 #endif
164
165 #define GTK_GS_WATCH_INTERVAL 1000
166 #define GTK_GS_WATCH_TIMEOUT  2
167
168 #define MAX_BUFSIZE 1024
169
170 enum { INTERPRETER_MESSAGE, INTERPRETER_ERROR, LAST_SIGNAL };
171
172 static gboolean broken_pipe = FALSE;
173
174 static void
175 catchPipe(int i)
176 {
177   broken_pipe = True;
178 }
179
180 /* Forward declarations */
181 static void gtk_gs_init(GtkGS * gs);
182 static void gtk_gs_class_init(GtkGSClass * klass);
183 static void gtk_gs_interpreter_message(GtkGS * gs, gchar * msg,
184                                        gpointer user_data);
185 static void gtk_gs_emit_error_msg(GtkGS * gs, const gchar * msg);
186 static void gtk_gs_finalize(GObject * object);
187 static void send_ps(GtkGS * gs, long begin, unsigned int len, gboolean close);
188 static void set_up_page(GtkGS * gs);
189 static void close_pipe(int p[2]);
190 static void interpreter_failed(GtkGS * gs);
191 static float compute_xdpi(void);
192 static float compute_ydpi(void);
193 static gboolean compute_size(GtkGS * gs);
194 static void output(gpointer data, gint source, GdkInputCondition condition);
195 static void input(gpointer data, gint source, GdkInputCondition condition);
196 static void stop_interpreter(GtkGS * gs);
197 static gint start_interpreter(GtkGS * gs);
198 gboolean computeSize(void);
199 static void ps_document_document_iface_init (EvDocumentIface *iface);
200
201 static GObjectClass *parent_class = NULL;
202
203 static GtkGSClass *gs_class = NULL;
204
205 static gint gtk_gs_signals[LAST_SIGNAL] = { 0 };
206
207 /* Static, private functions */
208
209 static void
210 ggv_marshaller_VOID__POINTER(GClosure * closure,
211                              GValue * return_value,
212                              guint n_param_values,
213                              const GValue * param_values,
214                              gpointer invocation_hint, gpointer marshal_data)
215 {
216   typedef void (*GMarshalFunc_VOID__POINTER) (gpointer data1,
217                                               gpointer arg_1, gpointer data2);
218   register GMarshalFunc_VOID__POINTER callback;
219   register GCClosure *cc = (GCClosure *) closure;
220   register gpointer data1, data2;
221
222   g_return_if_fail(n_param_values == 2);
223
224   if(G_CCLOSURE_SWAP_DATA(closure)) {
225     data1 = closure->data;
226     data2 = g_value_peek_pointer(param_values + 0);
227   }
228   else {
229     data1 = g_value_peek_pointer(param_values + 0);
230     data2 = closure->data;
231   }
232   callback =
233     (GMarshalFunc_VOID__POINTER) (marshal_data ? marshal_data : cc->callback);
234
235   callback(data1, g_value_get_pointer(param_values + 1), data2);
236 }
237
238 static void
239 ggv_marshaller_VOID__INT(GClosure * closure,
240                          GValue * return_value,
241                          guint n_param_values,
242                          const GValue * param_values,
243                          gpointer invocation_hint, gpointer marshal_data)
244 {
245   typedef void (*GMarshalFunc_VOID__INT) (gpointer data1,
246                                           gint arg_1, gpointer data2);
247   register GMarshalFunc_VOID__INT callback;
248   register GCClosure *cc = (GCClosure *) closure;
249   register gpointer data1, data2;
250
251   g_return_if_fail(n_param_values == 2);
252
253   if(G_CCLOSURE_SWAP_DATA(closure)) {
254     data1 = closure->data;
255     data2 = g_value_peek_pointer(param_values + 0);
256   }
257   else {
258     data1 = g_value_peek_pointer(param_values + 0);
259     data2 = closure->data;
260   }
261   callback =
262     (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback);
263
264   callback(data1, g_value_get_int(param_values + 1), data2);
265 }
266
267 static void
268 gtk_gs_init(GtkGS * gs)
269 {
270   gs->bpixmap = NULL;
271
272   gs->current_page = -2;
273   gs->disable_start = FALSE;
274   gs->interpreter_pid = -1;
275
276   gs->width = -1;
277   gs->height = -1;
278   gs->busy = FALSE;
279   gs->changed = FALSE;
280   gs->gs_scanstyle = 0;
281   gs->gs_filename = 0;
282   gs->gs_filename_dsc = 0;
283   gs->gs_filename_unc = 0;
284
285   broken_pipe = FALSE;
286
287   gs->structured_doc = FALSE;
288   gs->reading_from_pipe = FALSE;
289   gs->send_filename_to_gs = FALSE;
290
291   gs->doc = NULL;
292   gs->loaded = FALSE;
293
294   gs->interpreter_input = -1;
295   gs->interpreter_output = -1;
296   gs->interpreter_err = -1;
297   gs->interpreter_input_id = 0;
298   gs->interpreter_output_id = 0;
299   gs->interpreter_error_id = 0;
300
301   gs->ps_input = NULL;
302   gs->input_buffer = NULL;
303   gs->input_buffer_ptr = NULL;
304   gs->bytes_left = 0;
305   gs->buffer_bytes_left = 0;
306
307   gs->llx = 0;
308   gs->lly = 0;
309   gs->urx = 0;
310   gs->ury = 0;
311   gs->xdpi = compute_xdpi();
312   gs->ydpi = compute_ydpi();
313
314   gs->left_margin = 0;
315   gs->top_margin = 0;
316   gs->right_margin = 0;
317   gs->bottom_margin = 0;
318
319   /* Set user defined defaults */
320   gs->override_orientation = gtk_gs_defaults_get_override_orientation();
321   gs->fallback_orientation = gtk_gs_defaults_get_orientation();
322   gs->zoom_factor = gtk_gs_defaults_get_zoom_factor();
323   gs->default_size = gtk_gs_defaults_get_size();
324   gs->antialiased = gtk_gs_defaults_get_antialiased();
325   gs->override_size = gtk_gs_defaults_get_override_size();
326   gs->respect_eof = gtk_gs_defaults_get_respect_eof();
327   gs->zoom_mode = gtk_gs_defaults_get_zoom_mode();
328
329   gs->gs_status = _("No document loaded.");
330 }
331
332 static void
333 gtk_gs_class_init(GtkGSClass * klass)
334 {
335   GObjectClass *object_class;
336
337   object_class = (GObjectClass *) klass;
338   parent_class = gtk_type_class(gtk_widget_get_type());
339   gs_class = klass;
340
341   gtk_gs_signals[INTERPRETER_MESSAGE] = g_signal_new("interpreter_message",
342                                                      G_TYPE_FROM_CLASS
343                                                      (object_class),
344                                                      G_SIGNAL_RUN_LAST,
345                                                      G_STRUCT_OFFSET
346                                                      (GtkGSClass,
347                                                       interpreter_message),
348                                                      NULL, NULL,
349                                                      ggv_marshaller_VOID__POINTER,
350                                                      G_TYPE_NONE, 1,
351                                                      G_TYPE_POINTER);
352   gtk_gs_signals[INTERPRETER_ERROR] =
353     g_signal_new("interpreter_error", G_TYPE_FROM_CLASS(object_class),
354                  G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GtkGSClass,
355                                                     interpreter_error),
356                  NULL, NULL, ggv_marshaller_VOID__INT, G_TYPE_NONE, 1,
357                  G_TYPE_INT);
358
359   object_class->finalize = gtk_gs_finalize;
360
361   /* Create atoms */
362   klass->gs_atom = gdk_atom_intern("GHOSTVIEW", FALSE);
363   klass->gs_colors_atom = gdk_atom_intern("GHOSTVIEW_COLORS", FALSE);
364   klass->next_atom = gdk_atom_intern("NEXT", FALSE);
365   klass->page_atom = gdk_atom_intern("PAGE", FALSE);
366   klass->done_atom = gdk_atom_intern("DONE", FALSE);
367   klass->string_atom = gdk_atom_intern("STRING", FALSE);
368
369   /* a default handler for "interpreter_message" signal */
370   klass->interpreter_message = gtk_gs_interpreter_message;
371
372   gtk_gs_defaults_load();
373 }
374
375 /* Clean all memory and temporal files */
376 static void
377 gtk_gs_cleanup(GtkGS * gs)
378 {
379   g_return_if_fail(gs != NULL);
380   g_return_if_fail(GTK_IS_GS(gs));
381
382   stop_interpreter(gs);
383
384   if(gs->gs_psfile) {
385     fclose(gs->gs_psfile);
386     gs->gs_psfile = NULL;
387   }
388   if(gs->gs_filename) {
389     g_free(gs->gs_filename);
390     gs->gs_filename = NULL;
391   }
392   if(gs->doc) {
393     psfree(gs->doc);
394     gs->doc = NULL;
395   }
396   if(gs->gs_filename_dsc) {
397     unlink(gs->gs_filename_dsc);
398     g_free(gs->gs_filename_dsc);
399     gs->gs_filename_dsc = NULL;
400   }
401   if(gs->gs_filename_unc) {
402     unlink(gs->gs_filename_unc);
403     g_free(gs->gs_filename_unc);
404     gs->gs_filename_unc = NULL;
405   }
406   gs->current_page = -1;
407   gs->loaded = FALSE;
408   gs->llx = 0;
409   gs->lly = 0;
410   gs->urx = 0;
411   gs->ury = 0;
412   set_up_page(gs);
413 }
414
415 /* free message as it was allocated in output() */
416 static void
417 gtk_gs_interpreter_message(GtkGS * gs, gchar * msg, gpointer user_data)
418 {
419   gdk_pointer_ungrab(GDK_CURRENT_TIME);
420   if(strstr(msg, "Error:")) {
421     gs->gs_status = _("File is not a valid PostScript document.");
422     gtk_gs_cleanup(gs);
423     g_signal_emit_by_name(G_OBJECT(gs), "interpreter_error", 1, NULL);
424   }
425   g_free(msg);
426 }
427
428 static void
429 gtk_gs_finalize(GObject * object)
430 {
431   GtkGS *gs;
432
433   g_return_if_fail(object != NULL);
434   g_return_if_fail(GTK_IS_GS(object));
435
436   gs = GTK_GS(object);
437
438   gtk_gs_cleanup(gs);
439
440   if(gs->input_buffer) {
441     g_free(gs->input_buffer);
442     gs->input_buffer = NULL;
443   }
444
445   (*G_OBJECT_CLASS(parent_class)->finalize) (object);
446 }
447
448 void
449 gtk_gs_set_center(GtkGS * gs, gfloat hval, gfloat vval)
450 {
451 }
452
453 static void
454 send_ps(GtkGS * gs, long begin, unsigned int len, gboolean close)
455 {
456   struct record_list *ps_new;
457
458   if(gs->interpreter_input < 0) {
459     g_critical("No pipe to gs: error in send_ps().");
460     return;
461   }
462
463   ps_new = (struct record_list *) g_malloc(sizeof(struct record_list));
464   ps_new->fp = gs->gs_psfile;
465   ps_new->begin = begin;
466   ps_new->len = len;
467   ps_new->seek_needed = TRUE;
468   ps_new->close = close;
469   ps_new->next = NULL;
470
471   if(gs->input_buffer == NULL) {
472     gs->input_buffer = g_malloc(MAX_BUFSIZE);
473   }
474
475   if(gs->ps_input == NULL) {
476     gs->input_buffer_ptr = gs->input_buffer;
477     gs->bytes_left = len;
478     gs->buffer_bytes_left = 0;
479     gs->ps_input = ps_new;
480     gs->interpreter_input_id =
481       gdk_input_add(gs->interpreter_input, GDK_INPUT_WRITE, input, gs);
482   }
483   else {
484     struct record_list *p = gs->ps_input;
485     while(p->next != NULL) {
486       p = p->next;
487     }
488     p->next = ps_new;
489   }
490 }
491
492 static void
493 set_up_page(GtkGS * gs)
494 {
495   guint orientation;
496   char buf[1024];
497   //GdkColormap *colormap;
498   GdkGC *fill;
499   GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF };   /* pixel, r, g, b */
500   GdkColormap *colormap;
501
502 #ifdef HAVE_LOCALE_H
503   char *savelocale;
504 #endif
505
506   if (gs->pstarget == NULL)
507     return;
508
509   /* Do we have to check if the actual geometry changed? */
510
511   stop_interpreter(gs);
512
513   orientation = gtk_gs_get_orientation(gs);
514
515   if(compute_size(gs)) {
516     gdk_flush();
517
518     /* clear new pixmap (set to white) */
519     fill = gdk_gc_new(gs->pstarget);
520     if(fill) {
521       colormap = gdk_drawable_get_colormap(gs->pstarget);
522       gdk_color_alloc (colormap, &white);
523       gdk_gc_set_foreground(fill, &white);
524
525       if(gs->width > 0 && gs->height > 0) {
526         if(gs->bpixmap) {
527           gdk_drawable_unref(gs->bpixmap);
528           gs->bpixmap = NULL;
529         }
530
531         gs->bpixmap = gdk_pixmap_new(gs->pstarget, gs->width, gs->height, -1);
532
533         gdk_draw_rectangle(gs->bpixmap, fill, TRUE,
534                            0, 0, gs->width, gs->height);
535       }
536       else {
537         gdk_draw_rectangle(gs->pstarget, fill, TRUE,
538                            0, 0, gs->width, gs->height);
539       }
540       gdk_gc_unref(fill);
541
542       gdk_flush();
543     }
544   }
545
546 #ifdef HAVE_LOCALE_H
547   /* gs needs floating point parameters with '.' as decimal point
548    * while some (european) locales use ',' instead, so we set the 
549    * locale for this snprintf to "C".
550    */
551   savelocale = setlocale(LC_NUMERIC, "C");
552 #endif
553
554   g_snprintf(buf, 1024, "%ld %d %d %d %d %d %f %f %d %d %d %d",
555              0L,
556              orientation * 90,
557              gs->llx,
558              gs->lly,
559              gs->urx,
560              gs->ury,
561              gs->xdpi * gs->zoom_factor,
562              gs->ydpi * gs->zoom_factor,
563              gs->left_margin,
564              gs->bottom_margin, gs->right_margin, gs->top_margin);
565
566 #ifdef HAVE_LOCALE_H
567   setlocale(LC_NUMERIC, savelocale);
568 #endif
569   gdk_property_change(gs->pstarget,
570                       gs_class->gs_atom,
571                       gs_class->string_atom,
572                       8, GDK_PROP_MODE_REPLACE, buf, strlen(buf));
573   gdk_flush();
574 }
575
576 static void
577 close_pipe(int p[2])
578 {
579   if(p[0] != -1)
580     close(p[0]);
581   if(p[1] != -1)
582     close(p[1]);
583 }
584
585 static gboolean
586 is_interpreter_ready(GtkGS * gs)
587 {
588   return (gs->interpreter_pid != -1 && !gs->busy && gs->ps_input == NULL);
589 }
590
591 static void
592 interpreter_failed(GtkGS * gs)
593 {
594   stop_interpreter(gs);
595 }
596
597 static void
598 output(gpointer data, gint source, GdkInputCondition condition)
599 {
600   char buf[MAX_BUFSIZE + 1], *msg;
601   guint bytes = 0;
602   GtkGS *gs = GTK_GS(data);
603
604   if(source == gs->interpreter_output) {
605     bytes = read(gs->interpreter_output, buf, MAX_BUFSIZE);
606     if(bytes == 0) {            /* EOF occurred */
607       close(gs->interpreter_output);
608       gs->interpreter_output = -1;
609       gdk_input_remove(gs->interpreter_output_id);
610       return;
611     }
612     else if(bytes == -1) {
613       /* trouble... */
614       interpreter_failed(gs);
615       return;
616     }
617     if(gs->interpreter_err == -1) {
618       stop_interpreter(gs);
619     }
620   }
621   else if(source == gs->interpreter_err) {
622     bytes = read(gs->interpreter_err, buf, MAX_BUFSIZE);
623     if(bytes == 0) {            /* EOF occurred */
624       close(gs->interpreter_err);
625       gs->interpreter_err = -1;
626       gdk_input_remove(gs->interpreter_error_id);
627       return;
628     }
629     else if(bytes == -1) {
630       /* trouble... */
631       interpreter_failed(gs);
632       return;
633     }
634     if(gs->interpreter_output == -1) {
635       stop_interpreter(gs);
636     }
637   }
638   if(bytes > 0) {
639     buf[bytes] = '\0';
640     msg = g_strdup(buf);
641     g_signal_emit (G_OBJECT(gs), gtk_gs_signals[INTERPRETER_MESSAGE], 0, msg);
642   }
643 }
644
645 static void
646 input(gpointer data, gint source, GdkInputCondition condition)
647 {
648   GtkGS *gs = GTK_GS(data);
649   int bytes_written;
650   void (*oldsig) (int);
651   oldsig = signal(SIGPIPE, catchPipe);
652
653   do {
654     if(gs->buffer_bytes_left == 0) {
655       /* Get a new section if required */
656       if(gs->ps_input && gs->bytes_left == 0) {
657         struct record_list *ps_old = gs->ps_input;
658         gs->ps_input = ps_old->next;
659         if(ps_old->close && NULL != ps_old->fp)
660           fclose(ps_old->fp);
661         g_free((char *) ps_old);
662       }
663       /* Have to seek at the beginning of each section */
664       if(gs->ps_input && gs->ps_input->seek_needed) {
665         fseek(gs->ps_input->fp, gs->ps_input->begin, SEEK_SET);
666         gs->ps_input->seek_needed = FALSE;
667         gs->bytes_left = gs->ps_input->len;
668       }
669
670       if(gs->bytes_left > MAX_BUFSIZE) {
671         gs->buffer_bytes_left =
672           fread(gs->input_buffer, sizeof(char), MAX_BUFSIZE, gs->ps_input->fp);
673       }
674       else if(gs->bytes_left > 0) {
675         gs->buffer_bytes_left =
676           fread(gs->input_buffer,
677                 sizeof(char), gs->bytes_left, gs->ps_input->fp);
678       }
679       else {
680         gs->buffer_bytes_left = 0;
681       }
682       if(gs->bytes_left > 0 && gs->buffer_bytes_left == 0) {
683         interpreter_failed(gs); /* Error occurred */
684       }
685       gs->input_buffer_ptr = gs->input_buffer;
686       gs->bytes_left -= gs->buffer_bytes_left;
687     }
688
689     if(gs->buffer_bytes_left > 0) {
690       /* g_print (" writing: %s\n",gs->input_buffer_ptr); */
691
692       bytes_written = write(gs->interpreter_input,
693                             gs->input_buffer_ptr, gs->buffer_bytes_left);
694
695       if(broken_pipe) {
696         gtk_gs_emit_error_msg(gs, g_strdup(_("Broken pipe.")));
697         broken_pipe = FALSE;
698         interpreter_failed(gs);
699       }
700       else if(bytes_written == -1) {
701         if((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
702           interpreter_failed(gs);   /* Something bad happened */
703         }
704       }
705       else {
706         gs->buffer_bytes_left -= bytes_written;
707         gs->input_buffer_ptr += bytes_written;
708       }
709     }
710   }
711   while(gs->ps_input && gs->buffer_bytes_left == 0);
712
713   signal(SIGPIPE, oldsig);
714
715   if(gs->ps_input == NULL && gs->buffer_bytes_left == 0) {
716     if(gs->interpreter_input_id != 0) {
717       gdk_input_remove(gs->interpreter_input_id);
718       gs->interpreter_input_id = 0;
719     }
720   }
721 }
722
723 static int
724 start_interpreter(GtkGS * gs)
725 {
726   int std_in[2] = { -1, -1 };   /* pipe to interp stdin */
727   int std_out[2];               /* pipe from interp stdout */
728   int std_err[2];               /* pipe from interp stderr */
729
730 #define NUM_ARGS    100
731 #define NUM_GS_ARGS (NUM_ARGS - 20)
732 #define NUM_ALPHA_ARGS 10
733
734   char *argv[NUM_ARGS], *dir, *gv_env;
735   char **gs_args, **alpha_args = NULL;
736   int argc = 0, i;
737
738   if(!gs->gs_filename)
739     return 0;
740
741   stop_interpreter(gs);
742
743   if(gs->disable_start == TRUE)
744     return 0;
745
746   /* set up the args... */
747   gs_args = g_strsplit(gtk_gs_defaults_get_interpreter_cmd(), " ", NUM_GS_ARGS);
748   for(i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++)
749     argv[argc] = gs_args[i];
750
751   if(gs->antialiased) {
752     if(strlen(gtk_gs_defaults_get_alpha_parameters()) == 0)
753       alpha_args = g_strsplit(ALPHA_PARAMS, " ", NUM_ALPHA_ARGS);
754     else
755       alpha_args = g_strsplit(gtk_gs_defaults_get_alpha_parameters(),
756                               " ", NUM_ALPHA_ARGS);
757     for(i = 0; i < NUM_ALPHA_ARGS && alpha_args[i]; i++, argc++)
758       argv[argc] = alpha_args[i];
759   }
760   else
761     argv[argc++] = "-sDEVICE=x11";
762   argv[argc++] = "-dNOPAUSE";
763   argv[argc++] = "-dQUIET";
764   /* I assume we do _not_ want to change this... (: */
765   argv[argc++] = "-dSAFER";
766
767   /* set up the pipes */
768   if(gs->send_filename_to_gs) {
769     argv[argc++] = GTK_GS_GET_PS_FILE(gs);
770     argv[argc++] = "-c";
771     argv[argc++] = "quit";
772   }
773   else
774     argv[argc++] = "-";
775
776   argv[argc++] = NULL;
777
778   if(!gs->reading_from_pipe && !gs->send_filename_to_gs) {
779     if(pipe(std_in) == -1) {
780       g_critical("Unable to open pipe to Ghostscript.");
781       return -1;
782     }
783   }
784   if(pipe(std_out) == -1) {
785     close_pipe(std_in);
786     return -1;
787   }
788   if(pipe(std_err) == -1) {
789     close_pipe(std_in);
790     close_pipe(std_out);
791     return -1;
792   }
793
794   gs->busy = TRUE;
795   gs->interpreter_pid = fork();
796   switch (gs->interpreter_pid) {
797   case -1:                     /* error */
798     close_pipe(std_in);
799     close_pipe(std_out);
800     close_pipe(std_err);
801     return -2;
802     break;
803   case 0:                      /* child */
804     close(std_out[0]);
805     dup2(std_out[1], 1);
806     close(std_out[1]);
807
808     close(std_err[0]);
809     dup2(std_err[1], 2);
810     close(std_err[1]);
811
812     if(!gs->reading_from_pipe) {
813       if(gs->send_filename_to_gs) {
814         int stdinfd;
815         /* just in case gs tries to read from stdin */
816         stdinfd = open("/dev/null", O_RDONLY);
817         if(stdinfd != 0) {
818           dup2(stdinfd, 0);
819           close(stdinfd);
820         }
821       }
822       else {
823         close(std_in[1]);
824         dup2(std_in[0], 0);
825         close(std_in[0]);
826       }
827     }
828
829     gv_env = g_strdup_printf("GHOSTVIEW=%ld %ld",
830                              gdk_x11_drawable_get_xid(gs->pstarget),
831                              gdk_x11_drawable_get_xid(gs->bpixmap));
832     putenv(gv_env);
833
834     /* change to directory where the input file is. This helps
835      * with postscript-files which include other files using
836      * a relative path */
837     dir = g_path_get_dirname(gs->gs_filename);
838     chdir(dir);
839     g_free(dir);
840
841     execvp(argv[0], argv);
842
843     /* Notify error */
844     g_print("Unable to execute [%s]\n", argv[0]);
845     g_strfreev(gs_args);
846     g_free(gv_env);
847     if(alpha_args)
848       g_strfreev(alpha_args);
849     _exit(1);
850     break;
851   default:                     /* parent */
852     if(!gs->send_filename_to_gs && !gs->reading_from_pipe) {
853       int result;
854       close(std_in[0]);
855       /* use non-blocking IO for pipe to ghostscript */
856       result = fcntl(std_in[1], F_GETFL, 0);
857       fcntl(std_in[1], F_SETFL, result | O_NONBLOCK);
858       gs->interpreter_input = std_in[1];
859     }
860     else {
861       gs->interpreter_input = -1;
862     }
863     close(std_out[1]);
864     gs->interpreter_output = std_out[0];
865     close(std_err[1]);
866     gs->interpreter_err = std_err[0];
867     gs->interpreter_output_id =
868       gdk_input_add(std_out[0], GDK_INPUT_READ, output, gs);
869     gs->interpreter_error_id =
870       gdk_input_add(std_err[0], GDK_INPUT_READ, output, gs);
871     break;
872   }
873   return TRUE;
874 }
875
876 static void
877 stop_interpreter(GtkGS * gs)
878 {
879   if(gs->interpreter_pid > 0) {
880     int status = 0;
881     kill(gs->interpreter_pid, SIGTERM);
882     while((wait(&status) == -1) && (errno == EINTR)) ;
883     gs->interpreter_pid = -1;
884     if(status == 1) {
885       gtk_gs_cleanup(gs);
886       gs->gs_status = _("Interpreter failed.");
887       g_signal_emit_by_name(G_OBJECT(gs), "interpreter_error", status);
888     }
889   }
890
891   if(gs->interpreter_input >= 0) {
892     close(gs->interpreter_input);
893     gs->interpreter_input = -1;
894     if(gs->interpreter_input_id != 0) {
895       gdk_input_remove(gs->interpreter_input_id);
896       gs->interpreter_input_id = 0;
897     }
898     while(gs->ps_input) {
899       struct record_list *ps_old = gs->ps_input;
900       gs->ps_input = gs->ps_input->next;
901       if(ps_old->close && NULL != ps_old->fp)
902         fclose(ps_old->fp);
903       g_free((char *) ps_old);
904     }
905   }
906
907   if(gs->interpreter_output >= 0) {
908     close(gs->interpreter_output);
909     gs->interpreter_output = -1;
910     if(gs->interpreter_output_id) {
911       gdk_input_remove(gs->interpreter_output_id);
912       gs->interpreter_output_id = 0;
913     }
914   }
915
916   if(gs->interpreter_err >= 0) {
917     close(gs->interpreter_err);
918     gs->interpreter_err = -1;
919     if(gs->interpreter_error_id) {
920       gdk_input_remove(gs->interpreter_error_id);
921       gs->interpreter_error_id = 0;
922     }
923   }
924
925   gs->busy = FALSE;
926 }
927
928 /* If file exists and is a regular file then return its length, else -1 */
929 static gint
930 file_length(const gchar * filename)
931 {
932   struct stat stat_rec;
933
934   if(filename && (stat(filename, &stat_rec) == 0)
935      && S_ISREG(stat_rec.st_mode))
936     return stat_rec.st_size;
937   else
938     return -1;
939 }
940
941 /* Test if file exists, is a regular file and its length is > 0 */
942 static gboolean
943 file_readable(const char *filename)
944 {
945   return (file_length(filename) > 0);
946 }
947
948 /*
949  * Decompress gs->gs_filename if necessary
950  * Set gs->filename_unc to the name of the uncompressed file or NULL.
951  * Error reporting via signal 'interpreter_message'
952  * Return name of input file to use or NULL on error..
953  */
954 static gchar *
955 check_filecompressed(GtkGS * gs)
956 {
957   FILE *file;
958   gchar buf[1024];
959   gchar *filename, *filename_unc, *filename_err, *cmdline;
960   const gchar *cmd;
961   int fd;
962
963   cmd = NULL;
964
965   if((file = fopen(gs->gs_filename, "r"))
966      && (fread(buf, sizeof(gchar), 3, file) == 3)) {
967     if((buf[0] == '\037') && ((buf[1] == '\235') || (buf[1] == '\213'))) {
968       /* file is gzipped or compressed */
969       cmd = gtk_gs_defaults_get_ungzip_cmd();
970     }
971     else if(strncmp(buf, "BZh", 3) == 0) {
972       /* file is compressed with bzip2 */
973       cmd = gtk_gs_defaults_get_unbzip2_cmd();
974     }
975   }
976   if(NULL != file)
977     fclose(file);
978
979   if(!cmd)
980     return gs->gs_filename;
981
982   /* do the decompression */
983   filename = g_shell_quote(gs->gs_filename);
984   filename_unc = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
985   if((fd = mkstemp(filename_unc)) < 0) {
986     g_free(filename_unc);
987     g_free(filename);
988     return NULL;
989   }
990   close(fd);
991   filename_err = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
992   if((fd = mkstemp(filename_err)) < 0) {
993     g_free(filename_err);
994     g_free(filename_unc);
995     g_free(filename);
996     return NULL;
997   }
998   close(fd);
999   cmdline = g_strdup_printf("%s %s >%s 2>%s", cmd,
1000                             filename, filename_unc, filename_err);
1001   if((system(cmdline) == 0)
1002      && file_readable(filename_unc)
1003      && (file_length(filename_err) == 0)) {
1004     /* sucessfully uncompressed file */
1005     gs->gs_filename_unc = filename_unc;
1006   }
1007   else {
1008     /* report error */
1009     g_snprintf(buf, 1024, _("Error while decompressing file %s:\n"),
1010                gs->gs_filename);
1011     gtk_gs_emit_error_msg(gs, buf);
1012     if(file_length(filename_err) > 0) {
1013       FILE *err;
1014       if((err = fopen(filename_err, "r"))) {
1015         /* print file to message window */
1016         while(fgets(buf, 1024, err))
1017           gtk_gs_emit_error_msg(gs, buf);
1018         fclose(err);
1019       }
1020     }
1021     unlink(filename_unc);
1022     g_free(filename_unc);
1023     filename_unc = NULL;
1024   }
1025   unlink(filename_err);
1026   g_free(filename_err);
1027   g_free(cmdline);
1028   g_free(filename);
1029   return filename_unc;
1030 }
1031
1032 /*
1033  * Check if gs->gs_filename or gs->gs_filename_unc is a pdf file and scan
1034  * pdf file if necessary.
1035  * Set gs->filename_dsc to the name of the dsc file or NULL.
1036  * Error reporting via signal 'interpreter_message'.
1037  */
1038 static gchar *
1039 check_pdf(GtkGS * gs)
1040 {
1041   FILE *file;
1042   gchar buf[1024], *filename;
1043   int fd;
1044
1045   /* use uncompressed file as input if necessary */
1046   filename = (gs->gs_filename_unc ? gs->gs_filename_unc : gs->gs_filename);
1047
1048   if((file = fopen(filename, "r"))
1049      && (fread(buf, sizeof(char), 5, file) == 5)
1050      && (strncmp(buf, "%PDF-", 5) == 0)) {
1051     /* we found a PDF file */
1052     gchar *fname, *filename_dsc, *filename_err, *cmd, *cmdline;
1053     filename_dsc = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
1054     if((fd = mkstemp(filename_dsc)) < 0) {
1055       return NULL;
1056     }
1057     close(fd);
1058     filename_err = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
1059     if((fd = mkstemp(filename_err)) < 0) {
1060       g_free(filename_dsc);
1061       return NULL;
1062     }
1063     close(fd);
1064     fname = g_shell_quote(filename);
1065     cmd = g_strdup_printf(gtk_gs_defaults_get_dsc_cmd(), filename_dsc, fname);
1066     g_free(fname);
1067     /* this command (sometimes?) prints error messages to stdout! */
1068     cmdline = g_strdup_printf("%s >%s 2>&1", cmd, filename_err);
1069     g_free(cmd);
1070
1071     if((system(cmdline) == 0) && file_readable(filename_dsc)) {
1072
1073       /* success */
1074       filename = gs->gs_filename_dsc = filename_dsc;
1075
1076       if(file_length(filename_err) > 0) {
1077         gchar *err_msg = " ";
1078         GtkWidget *dialog;
1079         FILE *err;
1080         GdkColor color;
1081
1082         if((err = fopen(filename_err, "r"))) {
1083
1084           /* print the content of the file to a message box */
1085           while(fgets(buf, 1024, err))
1086             err_msg = g_strconcat(err_msg, buf, NULL);
1087
1088           /* FIXME The dialog is not yet set to modal, difficult to 
1089            * get the parent of the dialog box here 
1090            */
1091
1092           dialog = gtk_message_dialog_new(NULL,
1093                                           GTK_DIALOG_MODAL,
1094                                           GTK_MESSAGE_WARNING,
1095                                           GTK_BUTTONS_OK,
1096                                           ("There was an error while scaning the file: %s \n%s"),
1097                                           gs->gs_filename, err_msg);
1098
1099           gdk_color_parse("white", &color);
1100           gtk_widget_modify_bg(GTK_WIDGET(dialog), GTK_STATE_NORMAL, &color);
1101
1102           g_signal_connect(G_OBJECT(dialog), "response",
1103                            G_CALLBACK(gtk_widget_destroy), NULL);
1104
1105           gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
1106           gtk_widget_show(dialog);
1107           g_free(err_msg);
1108         }
1109       }
1110
1111     }
1112     else {
1113       /* report error */
1114       g_snprintf(buf, 1024,
1115                  _("Error while converting pdf file %s:\n"), filename);
1116       gtk_gs_emit_error_msg(gs, buf);
1117
1118       if(file_length(filename_err) > 0) {
1119         FILE *err;
1120         if((err = fopen(filename_err, "r"))) {
1121           /* print file to message window */
1122           while(fgets(buf, 1024, err))
1123             gtk_gs_emit_error_msg(gs, buf);
1124         }
1125       }
1126       unlink(filename_dsc);
1127       g_free(filename_dsc);
1128       filename = NULL;
1129     }
1130     unlink(filename_err);
1131     g_free(filename_err);
1132     g_free(cmdline);
1133   }
1134   if(NULL != file)
1135     fclose(file);
1136   return filename;
1137 }
1138
1139 #ifdef BROKEN_XINERAMA_PATCH_THAT_SHOULD_NOT_BE_USED
1140 /* never mind this patch: a properly working X server should take care of
1141    calculating the proper values. */
1142 static float
1143 compute_xdpi(void)
1144 {
1145 #   ifndef HAVE_XINERAMA
1146   return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
1147 #   else
1148   Display *dpy;
1149   dpy = (Display *) GDK_DISPLAY();
1150   if(XineramaIsActive(dpy)) {
1151     int num_heads;
1152     XineramaScreenInfo *head_info;
1153     head_info = (XineramaScreenInfo *) XineramaQueryScreens(dpy, &num_heads);
1154     /* fake it with dimensions of the first head for now */
1155     return 25.4 * head_info[0].width / gdk_screen_width_mm();
1156   }
1157   else {
1158     return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
1159   }
1160 #   endif
1161   /* HAVE_XINERAMA */
1162 }
1163
1164 static float
1165 compute_ydpi(void)
1166 {
1167 #   ifndef HAVE_XINERAMA
1168   return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
1169 #   else
1170   Display *dpy;
1171   dpy = (Display *) GDK_DISPLAY();
1172   if(XineramaIsActive(dpy)) {
1173     int num_heads;
1174     XineramaScreenInfo *head_info;
1175     head_info = (XineramaScreenInfo *) XineramaQueryScreens(dpy, &num_heads);
1176     /* fake it with dimensions of the first head for now */
1177     return 25.4 * head_info[0].height / gdk_screen_height_mm();
1178   }
1179   else {
1180     return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
1181   }
1182 #   endif
1183   /* HAVE_XINERAMA */
1184 }
1185 #else
1186 static float
1187 compute_xdpi(void)
1188 {
1189   return 25.4 * gdk_screen_width() / gdk_screen_width_mm();
1190 }
1191
1192 static float
1193 compute_ydpi(void)
1194 {
1195   return 25.4 * gdk_screen_height() / gdk_screen_height_mm();
1196 }
1197 #endif /* BROKEN_XINERAMA_PATCH_THAT_SHOULD_NOT_BE_USED */
1198
1199 /* Compute new size of window, sets xdpi and ydpi if necessary.
1200  * returns True if new window size is different */
1201 static gboolean
1202 compute_size(GtkGS * gs)
1203 {
1204   guint new_width = 1;
1205   guint new_height = 1;
1206   gboolean change = FALSE;
1207   gint orientation;
1208
1209   /* width and height can be changed, calculate window size according */
1210   /* to xpdi and ydpi */
1211   orientation = gtk_gs_get_orientation(gs);
1212
1213   switch (orientation) {
1214   case GTK_GS_ORIENTATION_PORTRAIT:
1215   case GTK_GS_ORIENTATION_UPSIDEDOWN:
1216     new_width = (gs->urx - gs->llx) / 72.0 * gs->xdpi + 0.5;
1217     new_height = (gs->ury - gs->lly) / 72.0 * gs->ydpi + 0.5;
1218     break;
1219   case GTK_GS_ORIENTATION_LANDSCAPE:
1220   case GTK_GS_ORIENTATION_SEASCAPE:
1221     new_width = (gs->ury - gs->lly) / 72.0 * gs->xdpi + 0.5;
1222     new_height = (gs->urx - gs->llx) / 72.0 * gs->ydpi + 0.5;
1223     break;
1224   }
1225
1226   change = (new_width != gs->width * gs->zoom_factor)
1227     || (new_height != gs->height * gs->zoom_factor);
1228   gs->width = (gint) (new_width * gs->zoom_factor);
1229   gs->height = (gint) (new_height * gs->zoom_factor);
1230
1231   return (change);
1232 }
1233
1234 gint
1235 gtk_gs_enable_interpreter(GtkGS * gs)
1236 {
1237   g_return_val_if_fail(gs != NULL, FALSE);
1238   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1239
1240   if(!gs->gs_filename)
1241     return 0;
1242
1243   gs->disable_start = FALSE;
1244   
1245   return start_interpreter(gs);
1246 }
1247
1248 /* publicly accessible functions */
1249
1250 GType
1251 gtk_gs_get_type(void)
1252 {
1253   static GType gs_type = 0;
1254   if(!gs_type) {
1255     GTypeInfo gs_info = {
1256       sizeof(GtkGSClass),
1257       (GBaseInitFunc) NULL,
1258       (GBaseFinalizeFunc) NULL,
1259       (GClassInitFunc) gtk_gs_class_init,
1260       (GClassFinalizeFunc) NULL,
1261       NULL,                     /* class_data */
1262       sizeof(GtkGS),
1263       0,                        /* n_preallocs */
1264       (GInstanceInitFunc) gtk_gs_init
1265     };
1266
1267     static const GInterfaceInfo document_info =
1268     {
1269         (GInterfaceInitFunc) ps_document_document_iface_init,
1270         NULL,
1271         NULL
1272     };
1273
1274     gs_type = g_type_register_static(G_TYPE_OBJECT,
1275                                      "GtkGS", &gs_info, 0);
1276
1277     g_type_add_interface_static (gs_type,
1278                                  EV_TYPE_DOCUMENT,
1279                                  &document_info);
1280   }
1281   return gs_type;
1282
1283
1284 }
1285
1286 GObject *
1287 gtk_gs_new(GtkAdjustment * hadj, GtkAdjustment * vadj)
1288 {
1289   GObject *gs;
1290
1291   gs = g_object_new(GTK_GS_TYPE, NULL);
1292
1293   return gs;
1294 }
1295
1296
1297 GObject *
1298 gtk_gs_new_from_file(GtkAdjustment * hadj, GtkAdjustment * vadj, char *fname)
1299 {
1300   GObject *gs = gtk_gs_new(hadj, vadj);
1301   gtk_gs_load(GTK_GS(gs), fname);
1302   return gs;
1303 }
1304
1305 void
1306 gtk_gs_reload(GtkGS * gs)
1307 {
1308   gchar *fname;
1309   gint page;
1310
1311   if(!gs->gs_filename)
1312     return;
1313
1314   page = gtk_gs_get_current_page(gs);
1315   fname = g_strdup(gs->gs_filename);
1316   gtk_gs_load(gs, fname);
1317   gtk_gs_goto_page(gs, page);
1318   g_free(fname);
1319 }
1320
1321
1322 /*
1323  * Show error message -> send signal "interpreter_message"
1324  */
1325 static void
1326 gtk_gs_emit_error_msg(GtkGS * gs, const gchar * msg)
1327 {
1328   g_signal_emit (G_OBJECT(gs),
1329                  gtk_gs_signals[INTERPRETER_MESSAGE], 0, g_strdup(msg));
1330 }
1331
1332 void
1333 gtk_gs_disable_interpreter(GtkGS * gs)
1334 {
1335   g_return_if_fail(gs != NULL);
1336   g_return_if_fail(GTK_IS_GS(gs));
1337
1338   gs->disable_start = TRUE;
1339
1340   stop_interpreter(gs);
1341 }
1342
1343 gboolean
1344 gtk_gs_load(GtkGS * gs, const gchar * fname)
1345 {
1346   g_return_val_if_fail(gs != NULL, FALSE);
1347   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1348
1349   /* clean up previous document */
1350   gtk_gs_cleanup(gs);
1351
1352   if(fname == NULL) {
1353     gs->gs_status = "";
1354     return FALSE;
1355   }
1356
1357   /* prepare this document */
1358
1359   /* default values: no dsc information available  */
1360   gs->structured_doc = FALSE;
1361   gs->send_filename_to_gs = TRUE;
1362   gs->current_page = -2;
1363   gs->loaded = FALSE;
1364   if(*fname == '/') {
1365     /* an absolute path */
1366     gs->gs_filename = g_strdup(fname);
1367   }
1368   else {
1369     /* path relative to our cwd: make it absolute */
1370     gchar *cwd = g_get_current_dir();
1371     gs->gs_filename = g_strconcat(cwd, "/", fname, NULL);
1372     g_free(cwd);
1373   }
1374
1375   if((gs->reading_from_pipe = (strcmp(fname, "-") == 0))) {
1376     gs->send_filename_to_gs = FALSE;
1377   }
1378   else {
1379     /*
1380      * We need to make sure that the file is loadable/exists!
1381      * otherwise we want to exit without loading new stuff...
1382      */
1383     gchar *filename = NULL;
1384
1385     if(!file_readable(fname)) {
1386       gchar buf[1024];
1387       g_snprintf(buf, 1024, _("Cannot open file %s.\n"), fname);
1388       gtk_gs_emit_error_msg(gs, buf);
1389       gs->gs_status = _("File is not readable.");
1390     }
1391     else {
1392       filename = check_filecompressed(gs);
1393       if(filename)
1394         filename = check_pdf(gs);
1395     }
1396
1397     if(!filename || (gs->gs_psfile = fopen(filename, "r")) == NULL) {
1398       gtk_gs_cleanup(gs);
1399       return FALSE;
1400     }
1401
1402     /* we grab the vital statistics!!! */
1403     gs->doc = psscan(gs->gs_psfile, gs->respect_eof, filename);
1404
1405     if(gs->doc == NULL) {
1406       /* File does not seem to be a Postscript one */
1407       gchar buf[1024];
1408       g_snprintf(buf, 1024, _("Error while scanning file %s\n"), fname);
1409       gtk_gs_emit_error_msg(gs, buf);
1410       gtk_gs_cleanup(gs);
1411       gs->gs_status = _("The file is not a PostScript document.");
1412       return FALSE;
1413     }
1414
1415     if((!gs->doc->epsf && gs->doc->numpages > 0) ||
1416        (gs->doc->epsf && gs->doc->numpages > 1)) {
1417       gs->structured_doc = TRUE;
1418       gs->send_filename_to_gs = FALSE;
1419     }
1420
1421     /* We have to set up the orientation of the document */
1422
1423
1424     /* orientation can only be portrait, and landscape or none.
1425        This is the document default. A document can have
1426        pages in landscape and some in portrait */
1427     if(gs->override_orientation) {
1428       /* If the orientation should be override... 
1429          then gs->orientation has already the correct
1430          value (it was set when the widget was created */
1431       /* So do nothing */
1432
1433     }
1434     else {
1435       /* Otherwise, set the proper orientation for the doc */
1436       gs->real_orientation = gs->doc->orientation;
1437     }
1438   }
1439   gtk_gs_set_page_size(gs, -1, gs->current_page);
1440   gs->loaded = TRUE;
1441
1442   gs->gs_status = _("Document loaded.");
1443
1444   return gs->loaded;
1445 }
1446
1447
1448 gboolean
1449 gtk_gs_next_page(GtkGS * gs)
1450 {
1451   XEvent event;
1452
1453   g_return_val_if_fail(gs != NULL, FALSE);
1454   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1455
1456   if(gs->interpreter_pid == 0) {    /* no interpreter active */
1457     return FALSE;
1458   }
1459
1460   if(gs->busy) {                /* interpreter is busy */
1461     return FALSE;
1462   }
1463
1464   gs->busy = TRUE;
1465
1466   event.xclient.type = ClientMessage;
1467   event.xclient.display = gdk_display;
1468   event.xclient.window = gs->message_window;
1469   event.xclient.message_type = gdk_x11_atom_to_xatom(gs_class->next_atom);
1470   event.xclient.format = 32;
1471
1472   gdk_error_trap_push();
1473   XSendEvent(gdk_display, gs->message_window, FALSE, 0, &event);
1474   gdk_flush();
1475   gdk_error_trap_pop();
1476
1477   return TRUE;
1478 }
1479
1480 gint
1481 gtk_gs_get_current_page(GtkGS * gs)
1482 {
1483   g_return_val_if_fail(gs != NULL, -1);
1484   g_return_val_if_fail(GTK_IS_GS(gs), -1);
1485
1486   return gs->current_page;
1487 }
1488
1489 gint
1490 gtk_gs_get_page_count(GtkGS * gs)
1491 {
1492   if(!gs->gs_filename)
1493     return 0;
1494
1495   if(gs->doc) {
1496     if(gs->structured_doc)
1497       return gs->doc->numpages;
1498     else
1499       return G_MAXINT;
1500   }
1501   else
1502     return 0;
1503 }
1504
1505 gboolean
1506 gtk_gs_goto_page(GtkGS * gs, gint page)
1507 {
1508   g_return_val_if_fail(gs != NULL, FALSE);
1509   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1510
1511   if(!gs->gs_filename) {
1512     return FALSE;
1513   }
1514
1515   /* range checking... */
1516   if(page < 0)
1517     page = 0;
1518
1519   if(gs->structured_doc && gs->doc) {
1520     if(page >= gs->doc->numpages)
1521       page = gs->doc->numpages - 1;
1522
1523     if(page == gs->current_page && !gs->changed)
1524       return TRUE;
1525
1526     gs->current_page = page;
1527
1528     if(gs->doc->pages[page].orientation != NONE &&
1529        !gs->override_orientation &&
1530        gs->doc->pages[page].orientation != gs->real_orientation) {
1531       gs->real_orientation = gs->doc->pages[page].orientation;
1532       gs->changed = TRUE;
1533     }
1534
1535     gtk_gs_set_page_size(gs, -1, page);
1536
1537     gs->changed = FALSE;
1538
1539     if(is_interpreter_ready(gs)) {
1540       gtk_gs_next_page(gs);
1541     }
1542     else {
1543       gtk_gs_enable_interpreter(gs);
1544       send_ps(gs, gs->doc->beginprolog, gs->doc->lenprolog, FALSE);
1545       send_ps(gs, gs->doc->beginsetup, gs->doc->lensetup, FALSE);
1546     }
1547
1548     send_ps(gs, gs->doc->pages[gs->current_page].begin,
1549             gs->doc->pages[gs->current_page].len, FALSE);
1550   }
1551   else {
1552     /* Unstructured document */
1553     /* In the case of non structured documents,
1554        GS read the PS from the  actual file (via command
1555        line. Hence, ggv only send a signal next page.
1556        If ghostview is not running it is usually because
1557        the last page of the file was displayed. In that
1558        case, ggv restarts GS again and the first page is displayed.
1559      */
1560     if(page == gs->current_page && !gs->changed)
1561       return TRUE;
1562
1563     if(!is_interpreter_ready(gs))
1564       gtk_gs_enable_interpreter(gs);
1565
1566     gs->current_page = page;
1567
1568     gtk_gs_next_page(gs);
1569   }
1570   return TRUE;
1571 }
1572
1573 /*
1574  * set pagesize sets the size from
1575  * if new_pagesize is -1, then it is set to either
1576  *  a) the default settings of pageid, if they exist, or if pageid != -1.
1577  *  b) the default setting of the document, if it exists.
1578  *  c) the default setting of the widget.
1579  * otherwise, the new_pagesize is used as the pagesize
1580  */
1581 gboolean
1582 gtk_gs_set_page_size(GtkGS * gs, gint new_pagesize, gint pageid)
1583 {
1584   gint new_llx = 0;
1585   gint new_lly = 0;
1586   gint new_urx = 0;
1587   gint new_ury = 0;
1588   GtkGSPaperSize *papersizes = gtk_gs_defaults_get_paper_sizes();
1589
1590   g_return_val_if_fail(gs != NULL, FALSE);
1591   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1592
1593   if(new_pagesize == -1) {
1594     if(gs->default_size > 0)
1595       new_pagesize = gs->default_size;
1596     if(!gs->override_size && gs->doc) {
1597       /* If we have a document:
1598          We use -- the page size (if specified)
1599          or the doc. size (if specified)
1600          or the page bbox (if specified)
1601          or the bounding box
1602        */
1603       if((pageid >= 0) && (gs->doc->numpages > pageid) &&
1604          (gs->doc->pages) && (gs->doc->pages[pageid].size)) {
1605         new_pagesize = gs->doc->pages[pageid].size - gs->doc->size;
1606       }
1607       else if(gs->doc->default_page_size != NULL) {
1608         new_pagesize = gs->doc->default_page_size - gs->doc->size;
1609       }
1610       else if((pageid >= 0) &&
1611               (gs->doc->numpages > pageid) &&
1612               (gs->doc->pages) &&
1613               (gs->doc->pages[pageid].boundingbox[URX] >
1614                gs->doc->pages[pageid].boundingbox[LLX]) &&
1615               (gs->doc->pages[pageid].boundingbox[URY] >
1616                gs->doc->pages[pageid].boundingbox[LLY])) {
1617         new_pagesize = -1;
1618       }
1619       else if((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
1620               (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
1621         new_pagesize = -1;
1622       }
1623     }
1624   }
1625
1626   /* Compute bounding box */
1627   if(gs->doc && ((gs->doc->epsf && !gs->override_size) || new_pagesize == -1)) {    /* epsf or bbox */
1628     if((pageid >= 0) &&
1629        (gs->doc->pages) &&
1630        (gs->doc->pages[pageid].boundingbox[URX] >
1631         gs->doc->pages[pageid].boundingbox[LLX])
1632        && (gs->doc->pages[pageid].boundingbox[URY] >
1633            gs->doc->pages[pageid].boundingbox[LLY])) {
1634       /* use page bbox */
1635       new_llx = gs->doc->pages[pageid].boundingbox[LLX];
1636       new_lly = gs->doc->pages[pageid].boundingbox[LLY];
1637       new_urx = gs->doc->pages[pageid].boundingbox[URX];
1638       new_ury = gs->doc->pages[pageid].boundingbox[URY];
1639     }
1640     else if((gs->doc->boundingbox[URX] > gs->doc->boundingbox[LLX]) &&
1641             (gs->doc->boundingbox[URY] > gs->doc->boundingbox[LLY])) {
1642       /* use doc bbox */
1643       new_llx = gs->doc->boundingbox[LLX];
1644       new_lly = gs->doc->boundingbox[LLY];
1645       new_urx = gs->doc->boundingbox[URX];
1646       new_ury = gs->doc->boundingbox[URY];
1647     }
1648   }
1649   else {
1650     if(new_pagesize < 0)
1651       new_pagesize = gs->default_size;
1652     new_llx = new_lly = 0;
1653     if(gs->doc && !gs->override_size && gs->doc->size &&
1654        (new_pagesize < gs->doc->numsizes)) {
1655       new_urx = gs->doc->size[new_pagesize].width;
1656       new_ury = gs->doc->size[new_pagesize].height;
1657     }
1658     else {
1659       new_urx = papersizes[new_pagesize].width;
1660       new_ury = papersizes[new_pagesize].height;
1661     }
1662   }
1663
1664   if(new_urx <= new_llx)
1665     new_urx = papersizes[12].width;
1666   if(new_ury <= new_lly)
1667     new_ury = papersizes[12].height;
1668
1669   /* If bounding box changed, setup for new size. */
1670   /* gtk_gs_disable_interpreter (gs); */
1671   if((new_llx != gs->llx) || (new_lly != gs->lly) ||
1672      (new_urx != gs->urx) || (new_ury != gs->ury)) {
1673     gs->llx = new_llx;
1674     gs->lly = new_lly;
1675     gs->urx = new_urx;
1676     gs->ury = new_ury;
1677     gs->changed = TRUE;
1678   }
1679
1680   if(gs->changed) {
1681     set_up_page(gs);
1682     return TRUE;
1683   }
1684
1685   return FALSE;
1686 }
1687
1688 void
1689 gtk_gs_set_override_orientation(GtkGS * gs, gboolean bNewOverride)
1690 {
1691   gint iOldOrientation;
1692
1693   g_return_if_fail(gs != NULL);
1694   g_return_if_fail(GTK_IS_GS(gs));
1695
1696   iOldOrientation = gtk_gs_get_orientation(gs);
1697
1698   gs->override_orientation = bNewOverride;
1699
1700   /* If the current orientation is different from the 
1701      new orientation  then redisplay */
1702   if(iOldOrientation != gtk_gs_get_orientation(gs)) {
1703     gs->changed = TRUE;
1704     set_up_page(gs);
1705   }
1706 }
1707
1708 gboolean
1709 gtk_gs_get_override_orientation(GtkGS * gs)
1710 {
1711   g_return_val_if_fail(gs != NULL, FALSE);
1712   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1713
1714   return gs->override_orientation;
1715 }
1716
1717 void
1718 gtk_gs_set_override_size(GtkGS * gs, gboolean f)
1719 {
1720   g_return_if_fail(gs != NULL);
1721   g_return_if_fail(GTK_IS_GS(gs));
1722
1723   if(f != gs->override_size) {
1724     gs->override_size = f;
1725     gs->changed = TRUE;
1726     gtk_gs_set_page_size(gs, -1, gs->current_page);
1727     set_up_page(gs);
1728   }
1729 }
1730
1731 gboolean
1732 gtk_gs_get_override_size(GtkGS * gs)
1733 {
1734   g_return_val_if_fail(gs != NULL, FALSE);
1735   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1736
1737   return gs->override_size;
1738 }
1739
1740 void
1741 gtk_gs_set_zoom(GtkGS * gs, gfloat zoom)
1742 {
1743   g_return_if_fail(gs != NULL);
1744   g_return_if_fail(GTK_IS_GS(gs));
1745
1746   switch (gs->zoom_mode) {
1747   case GTK_GS_ZOOM_FIT_WIDTH:
1748     zoom = gtk_gs_zoom_to_fit(gs, TRUE);
1749     break;
1750   case GTK_GS_ZOOM_FIT_PAGE:
1751     zoom = gtk_gs_zoom_to_fit(gs, FALSE);
1752     break;
1753   case GTK_GS_ZOOM_ABSOLUTE:
1754   default:
1755     break;
1756   }
1757
1758   if(fabs(gs->zoom_factor - zoom) > 0.001) {
1759     gs->zoom_factor = zoom;
1760     set_up_page(gs);
1761     gs->changed = TRUE;
1762   }
1763
1764   gtk_gs_goto_page(gs, gs->current_page);
1765 }
1766
1767 gfloat
1768 gtk_gs_get_zoom(GtkGS * gs)
1769 {
1770   g_return_val_if_fail(gs != NULL, 0.0);
1771   g_return_val_if_fail(GTK_IS_GS(gs), 0.0);
1772
1773   return gs->zoom_factor;
1774 }
1775
1776 gfloat
1777 gtk_gs_zoom_to_fit(GtkGS * gs, gboolean fit_width)
1778 {
1779   gint new_y;
1780   gfloat new_zoom;
1781   guint avail_w, avail_h;
1782
1783   g_return_val_if_fail(gs != NULL, 0.0);
1784   g_return_val_if_fail(GTK_IS_GS(gs), 0.0);
1785
1786   avail_w = (gs->avail_w > 0) ? gs->avail_w : gs->width;
1787   avail_h = (gs->avail_h > 0) ? gs->avail_h : gs->height;
1788
1789   new_zoom = ((gfloat) avail_w) / ((gfloat) gs->width) * gs->zoom_factor;
1790   if(!fit_width) {
1791     new_y = new_zoom * ((gfloat) gs->height) / gs->zoom_factor;
1792     if(new_y > avail_h)
1793       new_zoom = ((gfloat) avail_h) / ((gfloat) gs->height) * gs->zoom_factor;
1794   }
1795
1796   return new_zoom;
1797 }
1798
1799 gboolean
1800 gtk_gs_set_default_orientation(GtkGS * gs, gint orientation)
1801 {
1802   gint iOldOrientation;
1803
1804   g_return_val_if_fail(gs != NULL, FALSE);
1805   g_return_val_if_fail(GTK_IS_GS(gs), FALSE);
1806   g_return_val_if_fail((orientation == GTK_GS_ORIENTATION_PORTRAIT) ||
1807                        (orientation == GTK_GS_ORIENTATION_LANDSCAPE) ||
1808                        (orientation == GTK_GS_ORIENTATION_UPSIDEDOWN) ||
1809                        (orientation == GTK_GS_ORIENTATION_SEASCAPE), FALSE);
1810
1811   iOldOrientation = gtk_gs_get_orientation(gs);
1812   gs->fallback_orientation = orientation;
1813
1814   /* We are setting the fallback orientation */
1815   if(iOldOrientation != gtk_gs_get_orientation(gs)) {
1816     gs->changed = TRUE;
1817     set_up_page(gs);
1818     return TRUE;
1819   }
1820
1821   return FALSE;
1822 }
1823
1824 gint
1825 gtk_gs_get_default_orientation(GtkGS * gs)
1826 {
1827   g_return_val_if_fail(gs != NULL, -1);
1828   g_return_val_if_fail(GTK_IS_GS(gs), -1);
1829
1830   return gs->fallback_orientation;
1831 }
1832
1833 gint
1834 gtk_gs_get_orientation(GtkGS * gs)
1835 {
1836   g_return_val_if_fail(gs != NULL, -1);
1837   g_return_val_if_fail(GTK_IS_GS(gs), -1);
1838
1839   if(gs->doc) {
1840     if(gs->structured_doc) {
1841       if(gs->doc->pages[MAX(gs->current_page, 0)].orientation !=
1842          GTK_GS_ORIENTATION_NONE)
1843         gs->real_orientation =
1844           gs->doc->pages[MAX(gs->current_page, 0)].orientation;
1845       else
1846         gs->real_orientation = gs->doc->default_page_orientation;
1847     }
1848
1849     if(gs->real_orientation == GTK_GS_ORIENTATION_NONE)
1850       gs->real_orientation = gs->doc->orientation;
1851   }
1852
1853   if(gs->override_orientation ||
1854      gs->real_orientation == GTK_GS_ORIENTATION_NONE)
1855     return gs->fallback_orientation;
1856   else
1857     return gs->real_orientation;
1858 }
1859
1860 void
1861 gtk_gs_set_default_size(GtkGS * gs, gint size)
1862 {
1863   g_return_if_fail(gs != NULL);
1864   g_return_if_fail(GTK_IS_GS(gs));
1865
1866   gs->default_size = size;
1867   gtk_gs_set_page_size(gs, -1, gs->current_page);
1868 }
1869
1870 gint
1871 gtk_gs_get_default_size(GtkGS * gs)
1872 {
1873   g_return_val_if_fail(gs != NULL, -1);
1874   g_return_val_if_fail(GTK_IS_GS(gs), -1);
1875
1876   return gs->default_size;
1877 }
1878
1879 void
1880 gtk_gs_set_respect_eof(GtkGS * gs, gboolean f)
1881 {
1882   g_return_if_fail(gs != NULL);
1883   g_return_if_fail(GTK_IS_GS(gs));
1884
1885   if(gs->respect_eof == f)
1886     return;
1887
1888   gs->respect_eof = f;
1889   gtk_gs_set_page_size(gs, -1, gs->current_page);
1890 }
1891
1892 gint
1893 gtk_gs_get_respect_eof(GtkGS * gs)
1894 {
1895   g_return_val_if_fail(gs != NULL, -1);
1896   g_return_val_if_fail(GTK_IS_GS(gs), -1);
1897
1898   return gs->respect_eof;
1899 }
1900
1901 void
1902 gtk_gs_set_antialiasing(GtkGS * gs, gboolean f)
1903 {
1904   g_return_if_fail(gs != NULL);
1905   g_return_if_fail(GTK_IS_GS(gs));
1906
1907   if(gs->antialiased == f)
1908     return;
1909
1910   gs->antialiased = f;
1911   gs->changed = TRUE;
1912   start_interpreter(gs);
1913   gtk_gs_goto_page(gs, gs->current_page);
1914 }
1915
1916 gint
1917 gtk_gs_get_antialiasing(GtkGS * gs)
1918 {
1919   g_return_val_if_fail(gs != NULL, -1);
1920   g_return_val_if_fail(GTK_IS_GS(gs), -1);
1921
1922   return gs->antialiased;
1923 }
1924
1925 const gchar *
1926 gtk_gs_get_document_title(GtkGS * gs)
1927 {
1928   g_return_val_if_fail(gs != NULL, NULL);
1929   g_return_val_if_fail(GTK_IS_GS(gs), NULL);
1930
1931   if(gs->doc && gs->doc->title)
1932     return gs->doc->title;
1933
1934   return NULL;
1935 }
1936
1937 guint
1938 gtk_gs_get_document_numpages(GtkGS * widget)
1939 {
1940   g_return_val_if_fail(widget != NULL, 0);
1941   g_return_val_if_fail(GTK_IS_GS(widget), 0);
1942
1943   if(widget->doc)
1944     return widget->doc->numpages;
1945
1946   return 0;
1947 }
1948
1949 const gchar *
1950 gtk_gs_get_document_page_label(GtkGS * widget, int page)
1951 {
1952   g_return_val_if_fail(widget != NULL, NULL);
1953   g_return_val_if_fail(GTK_IS_GS(widget), NULL);
1954
1955   if(widget->doc && widget->doc->pages && (widget->doc->numpages >= page))
1956     return widget->doc->pages[page - 1].label;
1957
1958   return NULL;
1959 }
1960
1961 gint
1962 gtk_gs_get_size_index(const gchar * string, GtkGSPaperSize * size)
1963 {
1964   guint idx = 0;
1965
1966   while(size[idx].name != NULL) {
1967     if(strcmp(size[idx].name, string) == 0)
1968       return idx;
1969     idx++;
1970   }
1971
1972   return -1;
1973 }
1974
1975 gchar *
1976 gtk_gs_get_postscript(GtkGS * gs, gint * pages)
1977 {
1978   GtkGSDocSink *sink;
1979   gchar *doc;
1980   gboolean free_pages = FALSE;
1981
1982   if(pages == NULL) {
1983     if(!gs->structured_doc) {
1984       FILE *f;
1985       struct stat sb;
1986
1987       if(stat(GTK_GS_GET_PS_FILE(gs), &sb))
1988         return NULL;
1989       doc = g_new(gchar, sb.st_size);
1990       if(!doc)
1991         return NULL;
1992       f = fopen(GTK_GS_GET_PS_FILE(gs), "r");
1993       if(NULL != f && fread(doc, sb.st_size, 1, f) != 1) {
1994         g_free(doc);
1995         doc = NULL;
1996       }
1997       if(NULL != f)
1998         fclose(f);
1999       return doc;
2000     }
2001     else {
2002       int i, n = gtk_gs_get_page_count(gs);
2003       pages = g_new0(gint, n);
2004       for(i = 0; i < n; i++)
2005         pages[i] = TRUE;
2006       free_pages = TRUE;
2007     }
2008   }
2009
2010   sink = gtk_gs_doc_sink_new();
2011
2012   if(GTK_GS_IS_PDF(gs)) {
2013     gchar *tmpn = g_strconcat(g_get_tmp_dir(), "/ggvXXXXXX", NULL);
2014     gchar *cmd, *fname;
2015     int tmpfd;
2016
2017     if((tmpfd = mkstemp(tmpn)) < 0) {
2018       g_free(tmpn);
2019       return NULL;
2020     }
2021     close(tmpfd);
2022     fname = g_shell_quote (gs->gs_filename_unc ?
2023                            gs->gs_filename_unc : gs->gs_filename);
2024     cmd = g_strdup_printf(gtk_gs_defaults_get_convert_pdf_cmd(), tmpn, fname);
2025     g_free(fname);
2026     if((system(cmd) == 0) && file_readable(tmpn)) {
2027       GObject *tmp_gs;
2028       tmp_gs = gtk_gs_new_from_file(NULL, NULL, tmpn);
2029       if(NULL != tmp_gs) {
2030         if(GTK_GS(tmp_gs)->loaded)
2031           pscopydoc(sink, tmpn, GTK_GS(tmp_gs)->doc, pages);
2032         g_object_unref(tmp_gs);
2033       }
2034     }
2035     g_free(cmd);
2036     g_free(tmpn);
2037   }
2038   else {
2039     /* Use uncompressed file if necessary */
2040     pscopydoc(sink, GTK_GS_GET_PS_FILE(gs), gs->doc, pages);
2041   }
2042   if(free_pages)
2043     g_free(pages);
2044   doc = gtk_gs_doc_sink_get_buffer(sink);
2045   gtk_gs_doc_sink_free(sink);
2046   return doc;
2047 }
2048
2049 void
2050 gtk_gs_set_zoom_mode(GtkGS * gs, GtkGSZoomMode zoom_mode)
2051 {
2052   if(zoom_mode != gs->zoom_mode) {
2053     gs->zoom_mode = zoom_mode;
2054     gtk_gs_set_zoom(gs, 1.0);
2055   }
2056   gtk_gs_goto_page(gs, gs->current_page);
2057 }
2058
2059 GtkGSZoomMode
2060 gtk_gs_get_zoom_mode(GtkGS * gs)
2061 {
2062   return gs->zoom_mode;
2063 }
2064
2065 void
2066 gtk_gs_set_available_size(GtkGS * gs, guint avail_w, guint avail_h)
2067 {
2068   gs->avail_w = avail_w;
2069   gs->avail_h = avail_h;
2070   if(gs->zoom_mode != GTK_GS_ZOOM_ABSOLUTE) {
2071     gtk_gs_set_zoom(gs, 0.0);
2072   }
2073 }
2074
2075 static gboolean
2076 ps_document_load (EvDocument  *document,
2077                    const char  *uri,
2078                    GError     **error)
2079 {
2080         gboolean result;
2081         char *filename;
2082
2083         filename = g_filename_from_uri (uri, NULL, error);
2084         if (!filename)
2085                 return FALSE;
2086
2087         result = gtk_gs_load (GTK_GS (document), filename);
2088
2089         g_free (filename);
2090
2091         return result;
2092 }
2093
2094 static int
2095 ps_document_get_n_pages (EvDocument  *document)
2096 {
2097         return gtk_gs_get_page_count (GTK_GS (document));
2098 }
2099
2100 static void
2101 ps_document_set_page (EvDocument  *document,
2102                        int          page)
2103 {
2104         gtk_gs_goto_page (GTK_GS (document), page);
2105 }
2106
2107 static int
2108 ps_document_get_page (EvDocument  *document)
2109 {
2110         return gtk_gs_get_current_page (GTK_GS (document));
2111 }
2112
2113 static gboolean
2114 gtk_gs_widget_event (GtkWidget *widget, GdkEvent *event, gpointer data)
2115 {
2116         GtkGS *gs = (GtkGS *) data;
2117
2118         if(event->type != GDK_CLIENT_EVENT)
2119                 return FALSE;
2120
2121         if (event->client.message_type == gs_class->page_atom) {
2122                 gs->busy = FALSE;
2123                 ev_document_changed (EV_DOCUMENT (gs));
2124         }
2125
2126         return TRUE;
2127 }
2128
2129 static void
2130 ps_document_set_target (EvDocument  *document,
2131                         GdkDrawable *target)
2132 {
2133         GtkGS *gs = GTK_GS (document);
2134         GtkWidget *widget;
2135         gpointer data;
2136
2137         gs->pstarget = target;
2138
2139         if (gs->pstarget) {
2140                 gdk_window_get_user_data (gs->pstarget, &data);
2141                 g_return_if_fail (GTK_IS_WIDGET (data));
2142
2143                 widget = GTK_WIDGET (data);
2144                 g_signal_connect (widget, "event",
2145                                   G_CALLBACK (gtk_gs_widget_event),
2146                                   document);
2147         }
2148
2149         gtk_gs_goto_page (gs, gs->current_page);
2150 }
2151
2152 static void
2153 ps_document_set_scale (EvDocument  *document,
2154                         double       scale)
2155 {
2156         gtk_gs_set_zoom (GTK_GS (document), scale);
2157 }
2158
2159 static void
2160 ps_document_set_page_offset (EvDocument  *document,
2161                               int          x,
2162                               int          y)
2163 {
2164 }
2165
2166 static void
2167 ps_document_get_page_size (EvDocument   *document,
2168                             int          *width,
2169                             int          *height)
2170 {
2171         GtkGS *gs = GTK_GS (document);
2172
2173         if (width) {
2174                 *width = gs->width;
2175         }
2176
2177         if (height) {
2178                 *height = gs->height;
2179         }
2180 }
2181
2182 static void
2183 ps_document_render (EvDocument  *document,
2184                     int          clip_x,
2185                     int          clip_y,
2186                     int          clip_width,
2187                     int          clip_height)
2188 {
2189         GtkGS *gs = GTK_GS (document);
2190         GdkGC *gc;
2191
2192         if (gs->pstarget == NULL ||
2193             gs->bpixmap == NULL) {
2194                 return;
2195         }
2196
2197         gc = gdk_gc_new (gs->pstarget);
2198
2199         gdk_draw_drawable (gs->pstarget, gc,
2200                            gs->bpixmap,
2201                            clip_x, clip_y,
2202                            clip_x, clip_y,
2203                            clip_width, clip_height);
2204
2205         g_object_unref (gc);
2206 }
2207
2208 static void
2209 ps_document_document_iface_init (EvDocumentIface *iface)
2210 {
2211         iface->load = ps_document_load;
2212         iface->get_n_pages = ps_document_get_n_pages;
2213         iface->set_page = ps_document_set_page;
2214         iface->get_page = ps_document_get_page;
2215         iface->set_scale = ps_document_set_scale;
2216         iface->set_target = ps_document_set_target;
2217         iface->set_page_offset = ps_document_set_page_offset;
2218         iface->get_page_size = ps_document_get_page_size;
2219         iface->render = ps_document_render;
2220 }