~ubuntu-branches/ubuntu/trusty/evince/trusty-proposed

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