+++ /dev/null
-/* Ghostscript widget for GTK/GNOME
- *
- * Copyright (C) 1998 - 2005 the Free Software Foundation
- *
- * Authors: Jonathan Blandford, Jaka Mocnik, Carlos Garcia Campos
- *
- * Based on code by: Federico Mena (Quartic), Szekeres Istvan (Pista)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <glib/gstdio.h>
-#include <glib/gi18n.h>
-#include <gdk/gdkpixbuf.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "ps-document.h"
-#include "ps-interpreter.h"
-#include "ps.h"
-#include "gstypes.h"
-#include "gsdefaults.h"
-#include "ev-file-exporter.h"
-#include "ev-async-renderer.h"
-#include "ev-document-thumbnails.h"
-#include "ev-document-misc.h"
-
-struct _PSDocument {
- GObject object;
-
- gchar *filename;
- struct document *doc;
- gboolean structured_doc;
-
- PSInterpreter *gs;
-
- /* Document Thumbnails */
- PSInterpreter *thumbs_gs;
- GdkPixbuf *thumbnail;
- EvRenderContext *thumbs_rc;
- GMutex *thumbs_mutex;
- GCond *thumbs_cond;
-
- /* File exporter */
- gint *ps_export_pagelist;
- gchar *ps_export_filename;
-};
-
-struct _PSDocumentClass {
- GObjectClass parent_class;
-};
-
-static void ps_document_document_iface_init (EvDocumentIface *iface);
-static void ps_document_file_exporter_iface_init (EvFileExporterIface *iface);
-static void ps_async_renderer_iface_init (EvAsyncRendererIface *iface);
-static void ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
-
-static void ps_interpreter_page_rendered (PSInterpreter *gs,
- GdkPixbuf *pixbuf,
- PSDocument *ps_document);
-
-EV_BACKEND_REGISTER_WITH_CODE (PSDocument, ps_document,
- {
- EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
- ps_document_document_thumbnails_iface_init);
- EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
- ps_document_file_exporter_iface_init);
- EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_ASYNC_RENDERER,
- ps_async_renderer_iface_init);
- });
-
-/* PSDocument */
-static void
-ps_document_init (PSDocument *ps_document)
-{
-}
-
-static void
-ps_document_dispose (GObject *object)
-{
- PSDocument *ps_document = PS_DOCUMENT (object);
-
- if (ps_document->gs) {
- g_object_unref (ps_document->gs);
- ps_document->gs = NULL;
- }
-
- if (ps_document->thumbs_gs) {
- g_object_unref (ps_document->thumbs_gs);
- ps_document->thumbs_gs = NULL;
- }
-
- if (ps_document->filename) {
- g_free (ps_document->filename);
- ps_document->filename = NULL;
- }
-
- if (ps_document->doc) {
- psfree (ps_document->doc);
- ps_document->doc = NULL;
- }
-
- if (ps_document->thumbnail) {
- g_object_unref (ps_document->thumbnail);
- ps_document->thumbnail = NULL;
- }
-
- if (ps_document->thumbs_mutex) {
- g_mutex_free (ps_document->thumbs_mutex);
- ps_document->thumbs_mutex = NULL;
- }
-
- if (ps_document->thumbs_cond) {
- g_cond_free (ps_document->thumbs_cond);
- ps_document->thumbs_cond = NULL;
- }
-
- if (ps_document->thumbs_rc) {
- g_object_unref (ps_document->thumbs_rc);
- ps_document->thumbs_rc = NULL;
- }
-
- G_OBJECT_CLASS (ps_document_parent_class)->dispose (object);
-}
-
-static void
-ps_document_class_init (PSDocumentClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = ps_document_dispose;
-}
-
-/* EvDocumentIface */
-static gboolean
-document_load (PSDocument *ps_document, const gchar *fname, GError **error)
-{
- FILE *fd;
-
- ps_document->filename = g_strdup (fname);
-
- /*
- * We need to make sure that the file is loadable/exists!
- * otherwise we want to exit without loading new stuff...
- */
- if (!g_file_test (fname, G_FILE_TEST_IS_REGULAR)) {
- gchar *filename_dsp;
-
- filename_dsp = g_filename_display_name (fname);
- g_set_error (error,
- G_FILE_ERROR,
- G_FILE_ERROR_NOENT,
- _("Cannot open file “%s”."),
- filename_dsp);
- g_free (filename_dsp);
-
- return FALSE;
- }
-
- if ((fd = fopen (ps_document->filename, "r")) == NULL) {
- gchar *filename_dsp;
-
- filename_dsp = g_filename_display_name (fname);
- g_set_error (error,
- G_FILE_ERROR,
- G_FILE_ERROR_NOENT,
- _("Cannot open file “%s”."),
- filename_dsp);
- g_free (filename_dsp);
-
- return FALSE;
- }
-
- /* we grab the vital statistics!!! */
- ps_document->doc = psscan (fd, TRUE, ps_document->filename);
- fclose (fd);
- if (!ps_document->doc)
- return FALSE;
-
- ps_document->structured_doc =
- ((!ps_document->doc->epsf && ps_document->doc->numpages > 0) ||
- (ps_document->doc->epsf && ps_document->doc->numpages > 1));
-
- ps_document->gs = ps_interpreter_new (ps_document->filename,
- ps_document->doc);
- g_signal_connect (G_OBJECT (ps_document->gs), "page_rendered",
- G_CALLBACK (ps_interpreter_page_rendered),
- (gpointer) ps_document);
-
- return TRUE;
-}
-
-static gboolean
-ps_document_load (EvDocument *document,
- const char *uri,
- GError **error)
-{
- char *filename;
- char *gs_path;
- gboolean result;
-
- filename = g_filename_from_uri (uri, NULL, error);
- if (!filename)
- return FALSE;
-
- gs_path = g_find_program_in_path ("gs");
- if (!gs_path) {
- gchar *filename_dsp;
-
- filename_dsp = g_filename_display_name (filename);
- g_set_error (error,
- G_FILE_ERROR,
- G_FILE_ERROR_NOENT,
- _("Failed to load document “%s”. Ghostscript interpreter was not found in path"),
- filename);
- g_free (filename_dsp);
- g_free (filename);
-
- return FALSE;
- }
- g_free (gs_path);
-
- result = document_load (PS_DOCUMENT (document), filename, error);
- if (!result && !(*error)) {
- gchar *filename_dsp;
-
- filename_dsp = g_filename_display_name (filename);
- g_set_error (error,
- G_FILE_ERROR,
- G_FILE_ERROR_FAILED,
- _("Failed to load document “%s”"),
- filename_dsp);
- g_free (filename_dsp);
- }
-
- g_free (filename);
-
- return result;
-}
-
-static gboolean
-save_document (PSDocument *document, const char *filename)
-{
- gboolean result = TRUE;
- GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
- FILE *f, *src_file;
- gchar *buf;
-
- src_file = fopen (document->filename, "r");
- if (src_file) {
- struct stat stat_rec;
-
- if (stat (document->filename, &stat_rec) == 0) {
- pscopy (src_file, sink, 0, stat_rec.st_size - 1);
- }
-
- fclose (src_file);
- }
-
- buf = gtk_gs_doc_sink_get_buffer (sink);
- if (buf == NULL) {
- return FALSE;
- }
-
- f = fopen (filename, "w");
- if (f) {
- fputs (buf, f);
- fclose (f);
- } else {
- result = FALSE;
- }
-
- g_free (buf);
- gtk_gs_doc_sink_free (sink);
- g_free (sink);
-
- return result;
-}
-
-static gboolean
-save_page_list (PSDocument *document, int *page_list, const char *filename)
-{
- gboolean result = TRUE;
- GtkGSDocSink *sink = gtk_gs_doc_sink_new ();
- FILE *f;
- gchar *buf;
-
- pscopydoc (sink, document->filename,
- document->doc, page_list);
-
- buf = gtk_gs_doc_sink_get_buffer (sink);
-
- f = fopen (filename, "w");
- if (f) {
- fputs (buf, f);
- fclose (f);
- } else {
- result = FALSE;
- }
-
- g_free (buf);
- gtk_gs_doc_sink_free (sink);
- g_free (sink);
-
- return result;
-}
-
-static gboolean
-ps_document_save (EvDocument *document,
- const char *uri,
- GError **error)
-{
- PSDocument *ps = PS_DOCUMENT (document);
- gboolean result;
- char *filename;
-
- filename = g_filename_from_uri (uri, NULL, error);
- if (!filename)
- return FALSE;
-
- result = save_document (ps, filename);
-
- g_free (filename);
-
- return result;
-}
-
-static int
-ps_document_get_n_pages (EvDocument *document)
-{
- PSDocument *ps = PS_DOCUMENT (document);
-
- if (!ps->filename || !ps->doc) {
- return -1;
- }
-
- return ps->structured_doc ? ps->doc->numpages : 1;
-}
-
-static gint
-ps_document_get_page_rotation (PSDocument *ps_document,
- int page)
-{
- gint rotation = GTK_GS_ORIENTATION_NONE;
-
- g_assert (ps_document->doc != NULL);
-
- if (ps_document->structured_doc) {
- if (ps_document->doc->pages[page].orientation != GTK_GS_ORIENTATION_NONE)
- rotation = ps_document->doc->pages[page].orientation;
- else
- rotation = ps_document->doc->default_page_orientation;
- }
-
- if (rotation == GTK_GS_ORIENTATION_NONE)
- rotation = ps_document->doc->orientation;
-
- if (rotation == GTK_GS_ORIENTATION_NONE)
- rotation = GTK_GS_ORIENTATION_PORTRAIT;
-
- return rotation;
-}
-
-static void
-ps_document_get_page_size (EvDocument *document,
- int page,
- double *width,
- double *height)
-{
- PSDocument *ps_document = PS_DOCUMENT (document);
- int urx, ury, llx, lly;
- gdouble pwidth, pheight;
- gdouble page_width, page_height;
- gint rotate;
-
- psgetpagebox (ps_document->doc, page, &urx, &ury, &llx, &lly);
-
- pwidth = (urx - llx) + 0.5;
- pheight = (ury - lly) + 0.5;
-
- rotate = ps_document_get_page_rotation (ps_document, page);
- if (rotate == 90 || rotate == 270) {
- page_height = pwidth;
- page_width = pheight;
- } else {
- page_width = pwidth;
- page_height = pheight;
- }
-
- if (width) {
- *width = page_width;
- }
-
- if (height) {
- *height = page_height;
- }
-}
-
-static EvDocumentInfo *
-ps_document_get_info (EvDocument *document)
-{
- EvDocumentInfo *info;
- PSDocument *ps = PS_DOCUMENT (document);
- int urx, ury, llx, lly;
-
- info = g_new0 (EvDocumentInfo, 1);
- info->fields_mask = EV_DOCUMENT_INFO_TITLE |
- EV_DOCUMENT_INFO_FORMAT |
- EV_DOCUMENT_INFO_CREATOR |
- EV_DOCUMENT_INFO_N_PAGES |
- EV_DOCUMENT_INFO_PAPER_SIZE;
-
- info->title = g_strdup (ps->doc->title);
- info->format = ps->doc->epsf ? g_strdup (_("Encapsulated PostScript"))
- : g_strdup (_("PostScript"));
- info->creator = g_strdup (ps->doc->creator);
- info->n_pages = ev_document_get_n_pages (document);
-
- psgetpagebox (PS_DOCUMENT (document)->doc, 0, &urx, &ury, &llx, &lly);
-
- info->paper_width = (urx - llx) / 72.0f * 25.4f;
- info->paper_height = (ury - lly) / 72.0f * 25.4f;
-
- return info;
-}
-
-static void
-ps_document_document_iface_init (EvDocumentIface *iface)
-{
- iface->load = ps_document_load;
- iface->save = ps_document_save;
- iface->get_n_pages = ps_document_get_n_pages;
- iface->get_page_size = ps_document_get_page_size;
- iface->get_info = ps_document_get_info;
-}
-
-/* EvAsyncRendererIface */
-static void
-ps_interpreter_page_rendered (PSInterpreter *gs,
- GdkPixbuf *pixbuf,
- PSDocument *ps_document)
-{
- g_signal_emit_by_name (ps_document, "render_finished", pixbuf);
-}
-
-static void
-ps_async_renderer_render_pixbuf (EvAsyncRenderer *renderer,
- gint page,
- gdouble scale,
- gint rotation)
-{
- PSDocument *ps_document = PS_DOCUMENT (renderer);
-
- g_return_if_fail (PS_IS_INTERPRETER (ps_document->gs));
-
- rotation = (rotation + ps_document_get_page_rotation (ps_document, page)) % 360;
-
- ps_interpreter_render_page (ps_document->gs, page, scale, rotation);
-}
-
-static void
-ps_async_renderer_iface_init (EvAsyncRendererIface *iface)
-{
- iface->render_pixbuf = ps_async_renderer_render_pixbuf;
-}
-
-/* EvDocumentThumbnailsIface */
-static void
-ps_interpreter_thumbnail_rendered (PSInterpreter *gs,
- GdkPixbuf *pixbuf,
- PSDocument *ps_document)
-{
- if (ps_document->thumbnail)
- g_object_unref (ps_document->thumbnail);
- ps_document->thumbnail = g_object_ref (pixbuf);
-
- g_cond_broadcast (ps_document->thumbs_cond);
-}
-
-static gboolean
-ps_document_render_thumbnail (PSDocument *ps_document)
-{
- ps_interpreter_render_page (ps_document->thumbs_gs,
- ps_document->thumbs_rc->page,
- ps_document->thumbs_rc->scale,
- ps_document->thumbs_rc->rotation);
-
- return FALSE;
-}
-
-static GdkPixbuf *
-ps_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
- EvRenderContext *rc,
- gboolean border)
-{
- PSDocument *ps_document;
- GdkPixbuf *pixbuf = NULL;
-
- ps_document = PS_DOCUMENT (document_thumbnails);
-
- g_return_val_if_fail (ps_document->filename != NULL, NULL);
- g_return_val_if_fail (ps_document->doc != NULL, NULL);
-
- if (!ps_document->thumbs_gs) {
- ps_document->thumbs_gs = ps_interpreter_new (ps_document->filename,
- ps_document->doc);
- g_signal_connect (G_OBJECT (ps_document->thumbs_gs), "page_rendered",
- G_CALLBACK (ps_interpreter_thumbnail_rendered),
- (gpointer) ps_document);
- }
-
- if (!ps_document->thumbs_mutex)
- ps_document->thumbs_mutex = g_mutex_new ();
- ps_document->thumbs_cond = g_cond_new ();
-
- if (ps_document->thumbs_rc)
- g_object_unref (ps_document->thumbs_rc);
- ps_document->thumbs_rc = g_object_ref (rc);
-
- ev_document_doc_mutex_unlock ();
- g_mutex_lock (ps_document->thumbs_mutex);
- g_idle_add ((GSourceFunc)ps_document_render_thumbnail, ps_document);
- g_cond_wait (ps_document->thumbs_cond, ps_document->thumbs_mutex);
- g_cond_free (ps_document->thumbs_cond);
- ps_document->thumbs_cond = NULL;
- g_mutex_unlock (ps_document->thumbs_mutex);
- ev_document_doc_mutex_lock ();
-
- pixbuf = ps_document->thumbnail;
- ps_document->thumbnail = NULL;
-
- if (border) {
- GdkPixbuf *border_pixbuf;
-
- border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
- g_object_unref (pixbuf);
- pixbuf = border_pixbuf;
- }
-
- return pixbuf;
-}
-
-static void
-ps_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
- EvRenderContext *rc,
- gint *width,
- gint *height)
-{
- PSDocument *ps_document;
- gdouble page_width, page_height;
-
- ps_document = PS_DOCUMENT (document_thumbnails);
-
- ps_document_get_page_size (EV_DOCUMENT (ps_document),
- rc->page,
- &page_width, &page_height);
-
- if (rc->rotation == 90 || rc->rotation == 270) {
- *width = (gint) (page_height * rc->scale);
- *height = (gint) (page_width * rc->scale);
- } else {
- *width = (gint) (page_width * rc->scale);
- *height = (gint) (page_height * rc->scale);
- }
-}
-
-static void
-ps_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
-{
- iface->get_thumbnail = ps_document_thumbnails_get_thumbnail;
- iface->get_dimensions = ps_document_thumbnails_get_dimensions;
-}
-
-/* EvFileExporterIface */
-static void
-ps_document_file_exporter_begin (EvFileExporter *exporter,
- EvFileExporterContext *fc)
-{
- PSDocument *document = PS_DOCUMENT (exporter);
-
- if (document->structured_doc) {
- g_free (document->ps_export_pagelist);
-
- document->ps_export_pagelist = g_new0 (int, document->doc->numpages);
- }
-
- document->ps_export_filename = g_strdup (fc->filename);
-}
-
-static void
-ps_document_file_exporter_do_page (EvFileExporter *exporter,
- EvRenderContext *rc)
-{
- PSDocument *document = PS_DOCUMENT (exporter);
-
- if (document->structured_doc) {
- document->ps_export_pagelist[rc->page] = 1;
- }
-}
-
-static void
-ps_document_file_exporter_end (EvFileExporter *exporter)
-{
- PSDocument *document = PS_DOCUMENT (exporter);
-
- if (!document->structured_doc) {
- save_document (document, document->ps_export_filename);
- } else {
- save_page_list (document, document->ps_export_pagelist,
- document->ps_export_filename);
- g_free (document->ps_export_pagelist);
- g_free (document->ps_export_filename);
- document->ps_export_pagelist = NULL;
- document->ps_export_filename = NULL;
- }
-}
-
-static EvFileExporterCapabilities
-ps_document_file_exporter_get_capabilities (EvFileExporter *exporter)
-{
- return EV_FILE_EXPORTER_CAN_PAGE_SET |
- EV_FILE_EXPORTER_CAN_GENERATE_PS;
-}
-
-static void
-ps_document_file_exporter_iface_init (EvFileExporterIface *iface)
-{
- iface->begin = ps_document_file_exporter_begin;
- iface->do_page = ps_document_file_exporter_do_page;
- iface->end = ps_document_file_exporter_end;
- iface->get_capabilities = ps_document_file_exporter_get_capabilities;
-}
+++ /dev/null
-/* this file is part of evince, a gnome document viewer
- *
- * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
- * Copyright 1998 - 2005 The Free Software Foundation
- *
- * Evince is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Evince is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <glib/gstdio.h>
-#include <glib/gi18n.h>
-#include <gtk/gtkwidget.h>
-#include <gtk/gtkwindow.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <errno.h>
-
-#include "ps-interpreter.h"
-#include "ps.h"
-
-#define MAX_BUFSIZE 1024
-
-enum {
- PAGE_RENDERED,
- LAST_SIGNAL
-};
-
-/* structure to describe section of file to send to ghostscript */
-typedef struct {
- FILE *fp;
- glong begin;
- guint len;
- gboolean seek_needed;
- gboolean close;
-} PSSection;
-
-struct _PSInterpreter {
- GObject object;
-
- GtkWidget *target_window;
- GdkWindow *pstarget;
- GdkPixmap *bpixmap;
- glong message_window; /* Used by ghostview to receive messages from app */
-
- GPid pid; /* PID of interpreter, -1 if none */
- GIOChannel *input; /* stdin of interpreter */
- GIOChannel *output; /* stdout of interpreter */
- GIOChannel *error; /* stderr of interpreter */
- guint input_id;
- guint output_id;
- guint error_id;
-
- gboolean busy; /* Is gs busy drawing? */
- gboolean structured_doc;
-
- GQueue *ps_input;
- gchar *input_buffer_ptr;
- guint bytes_left;
- guint buffer_bytes_left;
-
- FILE *psfile; /* the currently loaded FILE */
- gchar *psfilename; /* the currently loaded filename */
- gchar *input_buffer;
- gboolean send_filename_to_gs; /* True if gs should read from file directly */
- const struct document *doc;
-};
-
-struct _PSInterpreterClass {
- GObjectClass parent_class;
-
- void (* page_rendered) (PSInterpreter *gs,
- GdkPixbuf *pixbuf);
-
- GdkAtom gs_atom;
- GdkAtom next_atom;
- GdkAtom page_atom;
- GdkAtom string_atom;
-};
-
-static void ps_interpreter_start (PSInterpreter *gs);
-static void ps_interpreter_stop (PSInterpreter *gs);
-static void ps_interpreter_failed (PSInterpreter *gs,
- const gchar *msg);
-static gboolean ps_interpreter_is_ready (PSInterpreter *gs);
-
-static void push_pixbuf (PSInterpreter *gs);
-
-G_DEFINE_TYPE (PSInterpreter, ps_interpreter, G_TYPE_OBJECT)
-
-static guint gs_signals[LAST_SIGNAL];
-
-static void
-ps_section_free (PSSection *section)
-{
- if (!section)
- return;
-
- if (section->close && section->fp)
- fclose (section->fp);
-
- g_free (section);
-}
-
-static void
-ps_interpreter_init (PSInterpreter *gs)
-{
- gs->pid = -1;
- gs->ps_input = g_queue_new ();
-}
-
-static void
-ps_interpreter_dispose (GObject *object)
-{
- PSInterpreter *gs = PS_INTERPRETER (object);
-
- gs->doc = NULL;
-
- if (gs->psfile) {
- fclose (gs->psfile);
- gs->psfile = NULL;
- }
-
- if (gs->psfilename) {
- g_free (gs->psfilename);
- gs->psfilename = NULL;
- }
-
- if (gs->bpixmap) {
- g_object_unref (gs->bpixmap);
- gs->bpixmap = NULL;
- }
-
- if (gs->input_buffer) {
- g_free (gs->input_buffer);
- gs->input_buffer = NULL;
- }
-
- if (gs->target_window) {
- gtk_widget_destroy (gs->target_window);
- gs->target_window = NULL;
- gs->pstarget = NULL;
- }
-
- if (gs->ps_input) {
- g_queue_foreach (gs->ps_input, (GFunc)ps_section_free, NULL);
- g_queue_free (gs->ps_input);
- gs->ps_input = NULL;
- }
-
- ps_interpreter_stop (gs);
-
- G_OBJECT_CLASS (ps_interpreter_parent_class)->dispose (object);
-}
-
-static void
-ps_interpreter_class_init (PSInterpreterClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (klass);
-
- gs_signals[PAGE_RENDERED] =
- g_signal_new ("page_rendered",
- PS_TYPE_INTERPRETER,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (PSInterpreterClass, page_rendered),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
- GDK_TYPE_PIXBUF);
-
- klass->gs_atom = gdk_atom_intern ("GHOSTVIEW", FALSE);
- klass->next_atom = gdk_atom_intern ("NEXT", FALSE);
- klass->page_atom = gdk_atom_intern ("PAGE", FALSE);
- klass->string_atom = gdk_atom_intern ("STRING", FALSE);
-
- object_class->dispose = ps_interpreter_dispose;
-}
-
-static gboolean
-ps_interpreter_input (GIOChannel *io,
- GIOCondition condition,
- PSInterpreter *gs)
-{
- PSSection *section = NULL;
-
- do {
- if (gs->buffer_bytes_left == 0) {
- /* Get a new section if required */
- if (gs->bytes_left == 0) {
- ps_section_free (section);
- section = NULL;
- g_queue_pop_tail (gs->ps_input);
- }
-
- if (section == NULL) {
- section = g_queue_peek_tail (gs->ps_input);
- }
-
- /* Have to seek at the beginning of each section */
- if (section && section->seek_needed) {
- fseek (section->fp, section->begin, SEEK_SET);
- section->seek_needed = FALSE;
- gs->bytes_left = section->len;
- }
-
- if (gs->bytes_left > MAX_BUFSIZE) {
- gs->buffer_bytes_left = fread (gs->input_buffer, sizeof (char),
- MAX_BUFSIZE, section->fp);
- } else if (gs->bytes_left > 0) {
- gs->buffer_bytes_left = fread (gs->input_buffer, sizeof (char),
- gs->bytes_left, section->fp);
- } else {
- gs->buffer_bytes_left = 0;
- }
-
- if (gs->bytes_left > 0 && gs->buffer_bytes_left == 0) {
- ps_interpreter_failed (gs, NULL); /* Error occurred */
- }
-
- gs->input_buffer_ptr = gs->input_buffer;
- gs->bytes_left -= gs->buffer_bytes_left;
- }
-
- if (gs->buffer_bytes_left > 0) {
- GIOStatus status;
- gsize bytes_written;
- GError *error = NULL;
-
- status = g_io_channel_write_chars (gs->input,
- gs->input_buffer_ptr,
- gs->buffer_bytes_left,
- &bytes_written,
- &error);
- switch (status) {
- case G_IO_STATUS_NORMAL:
- gs->buffer_bytes_left -= bytes_written;
- gs->input_buffer_ptr += bytes_written;
-
- break;
- case G_IO_STATUS_ERROR:
- ps_interpreter_failed (gs, error->message);
- g_error_free (error);
-
- break;
- case G_IO_STATUS_AGAIN:
- default:
- break;
- }
- }
- } while (!g_queue_is_empty (gs->ps_input) && gs->buffer_bytes_left == 0);
-
- if (g_queue_is_empty (gs->ps_input) && gs->buffer_bytes_left == 0) {
- GIOFlags flags;
-
- flags = g_io_channel_get_flags (gs->input);
-
- g_io_channel_set_flags (gs->input,
- flags & ~G_IO_FLAG_NONBLOCK, NULL);
- g_io_channel_flush (gs->input, NULL);
- g_io_channel_set_flags (gs->input,
- flags | G_IO_FLAG_NONBLOCK, NULL);
-
- gs->input_id = 0;
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-ps_interpreter_output (GIOChannel *io,
- GIOCondition condition,
- PSInterpreter *gs)
-{
- gchar buf[MAX_BUFSIZE + 1];
- gsize bytes = 0;
- GIOStatus status;
- GError *error = NULL;
-
- status = g_io_channel_read_chars (io, buf, MAX_BUFSIZE,
- &bytes, &error);
- switch (status) {
- case G_IO_STATUS_NORMAL:
- if (bytes > 0) {
- buf[bytes] = '\0';
- g_print ("%s", buf);
- }
- break;
- case G_IO_STATUS_EOF:
- g_io_channel_unref (gs->output);
- gs->output = NULL;
- gs->output_id = 0;
-
- return FALSE;
- case G_IO_STATUS_ERROR:
- ps_interpreter_failed (gs, error->message);
- g_error_free (error);
- gs->output_id = 0;
-
- return FALSE;
- default:
- break;
- }
-
- if (!gs->error) {
- ps_interpreter_failed (gs, NULL);
- }
-
- return TRUE;
-}
-
-static gboolean
-ps_interpreter_error (GIOChannel *io,
- GIOCondition condition,
- PSInterpreter *gs)
-{
- gchar buf[MAX_BUFSIZE + 1];
- gsize bytes = 0;
- GIOStatus status;
- GError *error = NULL;
-
- status = g_io_channel_read_chars (io, buf, MAX_BUFSIZE,
- &bytes, &error);
- switch (status) {
- case G_IO_STATUS_NORMAL:
- if (bytes > 0) {
- buf[bytes] = '\0';
- g_print ("%s", buf);
- }
-
- break;
- case G_IO_STATUS_EOF:
- g_io_channel_unref (gs->error);
- gs->error = NULL;
- gs->error_id = 0;
-
- return FALSE;
- case G_IO_STATUS_ERROR:
- ps_interpreter_failed (gs, error->message);
- g_error_free (error);
- gs->error_id = 0;
-
- break;
- default:
- break;
- }
-
- if (!gs->output) {
- ps_interpreter_failed (gs, NULL);
- }
-
- return TRUE;
-}
-
-static void
-ps_interpreter_finished (GPid pid,
- gint status,
- PSInterpreter *gs)
-{
- g_spawn_close_pid (gs->pid);
- gs->pid = -1;
- ps_interpreter_failed (gs, NULL);
-}
-
-#define NUM_ARGS 100
-#define NUM_GS_ARGS (NUM_ARGS - 20)
-#define NUM_ALPHA_ARGS 10
-
-static void
-setup_interpreter_env (gchar **envp)
-{
- gint i;
-
- for (i = 0; envp[i]; i++)
- putenv (envp[i]);
-}
-
-static void
-ps_interpreter_start (PSInterpreter *gs)
-{
- gchar *argv[NUM_ARGS], *dir, *gv_env, *gs_path;
- gchar **gs_args, **alpha_args = NULL;
- gchar **envp;
- gint pin, pout, perr;
- gint argc = 0, i;
- GError *error = NULL;
-
- g_assert (gs->psfilename != NULL);
-
- ps_interpreter_stop (gs);
-
- dir = g_path_get_dirname (gs->psfilename);
-
- /* set up the args... */
- gs_path = g_find_program_in_path ("gs");
- gs_args = g_strsplit (gs_path, " ", NUM_GS_ARGS);
- g_free (gs_path);
- for (i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++) {
- argv[argc] = gs_args[i];
- }
-
- alpha_args = g_strsplit (ALPHA_PARAMS, " ", NUM_ALPHA_ARGS);
- for (i = 0; i < NUM_ALPHA_ARGS && alpha_args[i]; i++, argc++) {
- argv[argc] = alpha_args[i];
- }
-
- argv[argc++] = "-dNOPAUSE";
- argv[argc++] = "-dQUIET";
- argv[argc++] = "-dSAFER";
-
- if (gs->send_filename_to_gs) {
- argv[argc++] = gs->psfilename;
- argv[argc++] = "-c";
- argv[argc++] = "quit";
- } else {
- argv[argc++] = "-";
- }
-
- argv[argc++] = NULL;
-
- gv_env = g_strdup_printf ("GHOSTVIEW=%ld %ld;DISPLAY=%s",
- gdk_x11_drawable_get_xid (gs->pstarget),
- gdk_x11_drawable_get_xid (gs->bpixmap),
- gdk_display_get_name (gdk_drawable_get_display (gs->pstarget)));
- envp = g_strsplit (gv_env, ";", 2);
- g_free (gv_env);
-
- if (g_spawn_async_with_pipes (dir, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
- (GSpawnChildSetupFunc)setup_interpreter_env, envp,
- &(gs->pid), &pin, &pout, &perr,
- &error)) {
- GIOFlags flags;
-
- g_child_watch_add (gs->pid,
- (GChildWatchFunc)ps_interpreter_finished,
- gs);
-
- gs->input = g_io_channel_unix_new (pin);
- g_io_channel_set_encoding (gs->input, NULL, NULL);
- flags = g_io_channel_get_flags (gs->input);
- g_io_channel_set_flags (gs->input, flags | G_IO_FLAG_NONBLOCK, NULL);
-
-
- gs->output = g_io_channel_unix_new (pout);
- flags = g_io_channel_get_flags (gs->output);
- g_io_channel_set_flags (gs->output, flags | G_IO_FLAG_NONBLOCK, NULL);
- gs->output_id = g_io_add_watch (gs->output, G_IO_IN,
- (GIOFunc)ps_interpreter_output,
- gs);
-
- gs->error = g_io_channel_unix_new (perr);
- flags = g_io_channel_get_flags (gs->error);
- g_io_channel_set_flags (gs->error, flags | G_IO_FLAG_NONBLOCK, NULL);
- gs->error_id = g_io_add_watch (gs->error, G_IO_IN,
- (GIOFunc)ps_interpreter_error,
- gs);
- } else {
- g_warning (error->message);
- g_error_free (error);
- }
-
- g_free (dir);
- g_strfreev (envp);
- g_strfreev (gs_args);
- g_strfreev (alpha_args);
-}
-
-static void
-ps_interpreter_stop (PSInterpreter *gs)
-{
- if (gs->pid > 0) {
- gint status = 0;
-
- kill (gs->pid, SIGTERM);
- while ((wait (&status) == -1) && (errno == EINTR));
- g_spawn_close_pid (gs->pid);
- gs->pid = -1;
- }
-
- if (gs->input) {
- g_io_channel_unref (gs->input);
- gs->input = NULL;
-
- if (gs->input_id > 0) {
- g_source_remove (gs->input_id);
- gs->input_id = 0;
- }
-
- if (gs->ps_input) {
- g_queue_foreach (gs->ps_input, (GFunc)ps_section_free, NULL);
- g_queue_free (gs->ps_input);
- gs->ps_input = g_queue_new ();
- }
- }
-
- if (gs->output) {
- g_io_channel_unref (gs->output);
- gs->output = NULL;
-
- if (gs->output_id > 0) {
- g_source_remove (gs->output_id);
- gs->output_id = 0;
- }
- }
-
- if (gs->error) {
- g_io_channel_unref (gs->error);
- gs->error = NULL;
-
- if (gs->error_id > 0) {
- g_source_remove (gs->error_id);
- gs->error_id = 0;
- }
- }
-
- gs->busy = FALSE;
-}
-
-static void
-ps_interpreter_failed (PSInterpreter *gs, const char *msg)
-{
- g_warning (msg ? msg : _("Interpreter failed."));
-
- push_pixbuf (gs);
- ps_interpreter_stop (gs);
-}
-
-static gboolean
-ps_interpreter_is_ready (PSInterpreter *gs)
-{
- return (gs->pid != -1 && !gs->busy &&
- (g_queue_is_empty (gs->ps_input)));
-}
-
-static void
-setup_page (PSInterpreter *gs, int page, double scale, int rotation)
-{
- gchar *buf;
- char scaled_dpi[G_ASCII_DTOSTR_BUF_SIZE];
- int urx, ury, llx, lly;
- PSInterpreterClass *gs_class = PS_INTERPRETER_GET_CLASS (gs);
-
- psgetpagebox (gs->doc, page, &urx, &ury, &llx, &lly);
- g_ascii_dtostr (scaled_dpi, G_ASCII_DTOSTR_BUF_SIZE, 72.0 * scale);
-
- buf = g_strdup_printf ("%ld %d %d %d %d %d %s %s %d %d %d %d",
- 0L, rotation, llx, lly, urx, ury,
- scaled_dpi, scaled_dpi,
- 0, 0, 0, 0);
-
- gdk_property_change (gs->pstarget, gs_class->gs_atom, gs_class->string_atom,
- 8, GDK_PROP_MODE_REPLACE, (guchar *)buf, strlen (buf));
- g_free (buf);
-
- gdk_flush ();
-}
-
-static void
-setup_pixmap (PSInterpreter *gs, int page, double scale, int rotation)
-{
- GdkGC *fill;
- GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF }; /* pixel, r, g, b */
- GdkColormap *colormap;
- double width, height;
- int pixmap_width, pixmap_height;
- int urx, ury, llx, lly;
-
- psgetpagebox (gs->doc, page, &urx, &ury, &llx, &lly);
- width = (urx - llx) + 0.5;
- height = (ury - lly) + 0.5;
-
- if (rotation == 90 || rotation == 270) {
- pixmap_height = width * scale + 0.5;
- pixmap_width = height * scale + 0.5;
- } else {
- pixmap_width = width * scale + 0.5;
- pixmap_height = height * scale + 0.5;
- }
-
- if (gs->bpixmap) {
- gint w, h;
-
- gdk_drawable_get_size (gs->bpixmap, &w, &h);
-
- if (pixmap_width != w || h != pixmap_height) {
- g_object_unref (gs->bpixmap);
- gs->bpixmap = NULL;
- ps_interpreter_stop (gs);
- }
- }
-
- if (!gs->bpixmap) {
- fill = gdk_gc_new (gs->pstarget);
- colormap = gdk_drawable_get_colormap (gs->pstarget);
- gdk_colormap_alloc_color (colormap, &white, FALSE, TRUE);
- gdk_gc_set_foreground (fill, &white);
- gs->bpixmap = gdk_pixmap_new (gs->pstarget, pixmap_width,
- pixmap_height, -1);
- gdk_draw_rectangle (gs->bpixmap, fill, TRUE,
- 0, 0, pixmap_width, pixmap_height);
- }
-}
-
-static void
-push_pixbuf (PSInterpreter *gs)
-{
- GdkColormap *cmap;
- GdkPixbuf *pixbuf;
- gint width, height;
-
- if (gs->pstarget == NULL)
- return;
-
- cmap = gdk_drawable_get_colormap (gs->pstarget);
- gdk_drawable_get_size (gs->bpixmap, &width, &height);
- pixbuf = gdk_pixbuf_get_from_drawable (NULL, gs->bpixmap, cmap,
- 0, 0, 0, 0,
- width, height);
- g_signal_emit (gs, gs_signals[PAGE_RENDERED], 0, pixbuf);
- g_object_unref (pixbuf);
-}
-
-static gboolean
-ps_interpreter_widget_event (GtkWidget *widget,
- GdkEvent *event,
- PSInterpreter *gs)
-{
- PSInterpreterClass *gs_class = PS_INTERPRETER_GET_CLASS (gs);
-
- if (event->type != GDK_CLIENT_EVENT)
- return FALSE;
-
- gs->message_window = event->client.data.l[0];
-
- if (event->client.message_type == gs_class->page_atom) {
- gs->busy = FALSE;
-
- push_pixbuf (gs);
- }
-
- return TRUE;
-}
-
-static void
-send_ps (PSInterpreter *gs, glong begin, guint len, gboolean close)
-{
- PSSection *ps_new;
-
- g_assert (gs->psfile != NULL);
-
- if (!gs->input) {
- g_critical ("No pipe to gs: error in send_ps().");
- return;
- }
-
- ps_new = g_new0 (PSSection, 1);
- ps_new->fp = gs->psfile;
- ps_new->begin = begin;
- ps_new->len = len;
- ps_new->seek_needed = TRUE;
- ps_new->close = close;
-
- if (gs->input_buffer == NULL) {
- gs->input_buffer = g_malloc (MAX_BUFSIZE);
- }
-
- if (g_queue_is_empty (gs->ps_input)) {
- gs->input_buffer_ptr = gs->input_buffer;
- gs->bytes_left = len;
- gs->buffer_bytes_left = 0;
- g_queue_push_head (gs->ps_input, ps_new);
- gs->input_id = g_io_add_watch (gs->input, G_IO_OUT,
- (GIOFunc)ps_interpreter_input,
- gs);
- } else {
- g_queue_push_head (gs->ps_input, ps_new);
- }
-}
-
-static void
-ps_interpreter_next_page (PSInterpreter *gs)
-{
- XEvent event;
- GdkScreen *screen;
- GdkDisplay *display;
- Display *dpy;
- PSInterpreterClass *gs_class = PS_INTERPRETER_GET_CLASS (gs);
-
- g_assert (gs->pid != 0);
- g_assert (gs->busy != TRUE);
-
- gs->busy = TRUE;
-
- screen = gtk_window_get_screen (GTK_WINDOW (gs->target_window));
- display = gdk_screen_get_display (screen);
- dpy = gdk_x11_display_get_xdisplay (display);
-
- event.xclient.type = ClientMessage;
- event.xclient.display = dpy;
- event.xclient.window = gs->message_window;
- event.xclient.message_type =
- gdk_x11_atom_to_xatom_for_display (display,
- gs_class->next_atom);
- event.xclient.format = 32;
-
- gdk_error_trap_push ();
- XSendEvent (dpy, gs->message_window, FALSE, 0, &event);
- gdk_flush ();
- gdk_error_trap_pop ();
-}
-
-static void
-render_page (PSInterpreter *gs, gint page)
-{
- if (gs->structured_doc && gs->doc) {
- if (ps_interpreter_is_ready (gs)) {
- ps_interpreter_next_page (gs);
- } else {
- ps_interpreter_start (gs);
- send_ps (gs, gs->doc->beginprolog, gs->doc->lenprolog, FALSE);
- send_ps (gs, gs->doc->beginsetup, gs->doc->lensetup, FALSE);
- }
-
- send_ps (gs, gs->doc->pages[page].begin,
- gs->doc->pages[page].len, FALSE);
- } else {
- /* Unstructured document
- *
- * In the case of non structured documents,
- * GS read the PS from the actual file (via command
- * line. Hence, ggv only send a signal next page.
- * If ghostview is not running it is usually because
- * the last page of the file was displayed. In that
- * case, ggv restarts GS again and the first page is displayed.
- */
-
- if (!ps_interpreter_is_ready (gs)) {
- ps_interpreter_start (gs);
- }
- ps_interpreter_next_page (gs);
- }
-}
-
-/* Public methods */
-PSInterpreter *
-ps_interpreter_new (const gchar *filename,
- const struct document *doc)
-{
- PSInterpreter *gs;
-
- g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (doc != NULL, NULL);
-
- gs = PS_INTERPRETER (g_object_new (PS_TYPE_INTERPRETER, NULL));
-
- gs->psfilename = g_strdup (filename);
- gs->doc = doc;
- gs->structured_doc = FALSE;
- gs->send_filename_to_gs = TRUE;
- gs->psfile = fopen (gs->psfilename, "r");
-
- if ((!gs->doc->epsf && gs->doc->numpages > 0) ||
- (gs->doc->epsf && gs->doc->numpages > 1)) {
- gs->structured_doc = TRUE;
- gs->send_filename_to_gs = FALSE;
- }
-
- return gs;
-}
-
-void
-ps_interpreter_render_page (PSInterpreter *gs,
- gint page,
- gdouble scale,
- gint rotation)
-{
- g_return_if_fail (PS_IS_INTERPRETER (gs));
-
- if (gs->pstarget == NULL) {
- gs->target_window = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_widget_realize (gs->target_window);
- gs->pstarget = gs->target_window->window;
-
- g_assert (gs->pstarget != NULL);
-
- g_signal_connect (gs->target_window, "event",
- G_CALLBACK (ps_interpreter_widget_event),
- gs);
- }
-
- setup_pixmap (gs, page, scale, rotation);
- setup_page (gs, page, scale, rotation);
-
- render_page (gs, page);
-}
+++ /dev/null
-/*
- * ps.c -- Postscript scanning and copying routines.
- * Copyright (C) 1992, 1998 Timothy O. Theisen
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Tim Theisen Systems Programmer
- * Internet: tim@cs.wisc.edu Department of Computer Sciences
- * UUCP: uwvax!tim University of Wisconsin-Madison
- * Phone: (608)262-0438 1210 West Dayton Street
- * FAX: (608)262-9777 Madison, WI 53706
- */
-
-/* 18/3/98 Jake Hamby patch */
-
-/*
- * 98/03/17: Jake Hamby (jehamby@lightside.com):
- * Added support for compressed/gzipped Postscript and PDF files.
- * Compressed files are gunzipped to a temporary file, and PDF files are
- * scanned by calling Ghostscript to generate a fake DSC file.
- * This is based on code from GV 3.5.8, which is available at:
- * http://wwwthep.physik.uni-mainz.de/~plass/gv/
- */
-
-/* GV by Johannes Plass
- * Department of Physics
- * Johannes Gutenberg University
- * Mainz, Germany
- *
- * <plass@thep.physik.uni-mainz.de>
- */
-
-/* end of patch */
-
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#ifndef SEEK_SET
-# define SEEK_SET 0
-#endif
-#ifndef BUFSIZ
-# define BUFSIZ 1024
-#endif
-#include <ctype.h>
-#include <X11/Xos.h> /* #includes the appropriate <string.h> */
-#include "gstypes.h"
-#include "gsdefaults.h"
-#include "ps.h"
-#include "gsio.h"
-
-#include <glib.h>
-
-/* length calculates string length at compile time */
-/* can only be used with character constants */
-#define length(a) (sizeof(a)-1)
-#define iscomment(a, b) (strncmp(a, b, length(b)) == 0)
-#define DSCcomment(a) (a[0] == '%' && a[1] == '%')
-
- /* list of standard paper sizes from Adobe's PPD. */
-
-/*--------------------------------------------------*/
-/* Declarations for ps_io_*() routines. */
-
-typedef struct FileDataStruct_ *FileData;
-
-typedef struct FileDataStruct_ {
- FILE *file; /* file */
- int file_desc; /* file descriptor corresponding to file */
- int filepos; /* file position corresponding to the start of the line */
- char *buf; /* buffer */
- int buf_size; /* size of buffer */
- int buf_end; /* last char in buffer given as offset to buf */
- int line_begin; /* start of the line given as offset to buf */
- int line_end; /* end of the line given as offset to buf */
- int line_len; /* length of line, i.e. (line_end-line_begin) */
- char line_termchar; /* char exchanged for a '\0' at end of line */
- int status; /* 0 = okay, 1 = failed */
-} FileDataStruct;
-
-static FileData ps_io_init (FILE *file);
-static void ps_io_exit (FileData data);
-static char *ps_io_fgetchars (FileData data, int offset);
-
-static char *skipped_line = "% ps_io_fgetchars: skipped line";
-static char *empty_string = "";
-
-static char *readline (FileData fd, char **lineP, long *positionP, unsigned int *line_lenP);
-static char *gettextline(char *line);
-static char *get_next_text(char *line, char **next_char);
-static int blank(char *line);
-
-static struct page *
-pages_new(struct page *pages, int current, int maxpages)
-{
- struct page *oldpages = pages;
- if(!oldpages)
- pages = g_new0(struct page, maxpages);
- else
- pages = g_renew(struct page, oldpages, maxpages);
- for(; current < maxpages; current++) {
- memset(&(pages[current]), 0x00, sizeof(struct page));
- pages[current].orientation = GTK_GS_ORIENTATION_NONE;
- }
- return pages;
-}
-
-/*
- * psscan -- scan the PostScript file for document structuring comments.
- *
- * This scanner is designed to retrieve the information necessary for
- * the ghostview previewer. It will scan files that conform to any
- * version (1.0, 2.0, 2.1, or 3.0) of the document structuring conventions.
- * It does not really care which version of comments the file contains.
- * (The comments are largely upward compatible.) It will scan a number
- * of non-conforming documents. (You could have part of the document
- * conform to V2.0 and the rest conform to V3.0. It would be similar
- * to the DC-2 1/2+, it would look funny but it can still fly.)
- *
- * This routine returns a pointer to the document structure.
- * The structure contains the information relevant to previewing.
- * These include EPSF flag (to tell if the file is a encapsulated figure),
- * Page Size (for the Page Size), Bounding Box (to minimize backing
- * pixmap size or determine window size for encapsulated PostScript),
- * Orientation of Paper (for default transformation matrix), and
- * Page Order. The Title, Creator, and CreationDate are also retrieved to
- * help identify the document.
- *
- * The following comments are examined:
- *
- * Header section:
- * Must start with %!PS-Adobe-. Version numbers ignored.
- * Also allowed to be just %!PS, many files seem to have that.
- *
- * %!PS-Adobe-* [EPSF-*]
- * %%BoundingBox: <int> <int> <int> <int>|(atend)
- * %%Creator: <textline>
- * %%CreationDate: <textline>
- * %%Orientation: Portrait|Landscape|(atend)
- * %%Pages: <uint> [<int>]|(atend)
- * %%PageOrder: Ascend|Descend|Special|(atend)
- * %%Title: <textline>
- * %%DocumentMedia: <text> <real> <real> <real> <text> <text>
- * %%DocumentPaperSizes: <text>
- * %%EndComments
- *
- * Note: Either the 3.0 or 2.0 syntax for %%Pages is accepted.
- * Also either the 2.0 %%DocumentPaperSizes or the 3.0
- * %%DocumentMedia comments are accepted as well.
- *
- * The header section ends either explicitly with %%EndComments or
- * implicitly with any line that does not begin with %X where X is
- * a not whitespace character.
- *
- * If the file is encapsulated PostScript the optional Preview section
- * is next:
- *
- * %%BeginPreview
- * %%EndPreview
- *
- * This section explicitly begins and ends with the above comments.
- *
- * Next the Defaults section for version 3 page defaults:
- *
- * %%BeginDefaults
- * %%PageBoundingBox: <int> <int> <int> <int>
- * %%PageOrientation: Portrait|Landscape
- * %%PageMedia: <text>
- * %%EndDefaults
- *
- * This section explicitly begins and ends with the above comments.
- *
- * The prolog section either explicitly starts with %%BeginProlog or
- * implicitly with any nonblank line.
- *
- * %%BeginProlog
- * %%EndProlog
- *
- * The Prolog should end with %%EndProlog, however the proglog implicitly
- * ends when %%BeginSetup, %%Page, %%Trailer or %%EOF are encountered.
- *
- * The Setup section is where the version 2 page defaults are found.
- * This section either explicitly begins with %%BeginSetup or implicitly
- * with any nonblank line after the Prolog.
- *
- * %%BeginSetup
- * %%PageBoundingBox: <int> <int> <int> <int>
- * %%PageOrientation: Portrait|Landscape
- * %%PaperSize: <text>
- * %%EndSetup
- *
- * The Setup should end with %%EndSetup, however the setup implicitly
- * ends when %%Page, %%Trailer or %%EOF are encountered.
- *
- * Next each page starts explicitly with %%Page and ends implicitly with
- * %%Page or %%Trailer or %%EOF. The following comments are recognized:
- *
- * %%Page: <text> <uint>
- * %%PageBoundingBox: <int> <int> <int> <int>|(atend)
- * %%PageOrientation: Portrait|Landscape
- * %%PageMedia: <text>
- * %%PaperSize: <text>
- *
- * The tralier section start explicitly with %%Trailer and end with %%EOF.
- * The following comment are examined with the proper (atend) notation
- * was used in the header:
- *
- * %%Trailer
- * %%BoundingBox: <int> <int> <int> <int>|(atend)
- * %%Orientation: Portrait|Landscape|(atend)
- * %%Pages: <uint> [<int>]|(atend)
- * %%PageOrder: Ascend|Descend|Special|(atend)
- * %%EOF
- *
- *
- * + A DC-3 received severe damage to one of its wings. The wing was a total
- * loss. There was no replacement readily available, so the mechanic
- * installed a wing from a DC-2.
- */
-
-#include <glib.h>
-
-struct document *
-psscan(FILE * file, int respect_eof, const gchar * fname)
-{
- struct document *doc;
- int bb_set = NONE;
- int pages_set = NONE;
- int page_order_set = NONE;
- int orientation_set = NONE;
- int page_bb_set = NONE;
- int page_size_set = NONE;
- int preread; /* flag which tells the readline isn't needed */
- int i;
- unsigned int maxpages = 0;
- unsigned int nextpage = 1; /* Next expected page */
- unsigned int thispage;
- int ignore = 0; /* whether to ignore page ordinals */
- char *label;
- char *line;
- char text[PSLINELENGTH]; /* Temporary storage for text */
- long position; /* Position of the current line */
- long beginsection; /* Position of the beginning of the section */
- unsigned int line_len; /* Length of the current line */
- unsigned int section_len; /* Place to accumulate the section length */
- char *next_char; /* 1st char after text returned by get_next_text() */
- char *cp;
- GtkGSPaperSize *dmp;
- GtkGSPaperSize *papersizes = gtk_gs_defaults_get_paper_sizes();
- FileData fd;
-
- if(!file)
- return NULL;
-
- rewind(file);
-
- fd = ps_io_init(file);
- if (!readline(fd, &line, &position, &line_len)) {
- fprintf(stderr, "Warning: empty file.\n");
- ps_io_exit(fd);
- return(NULL);
- }
-
- /* HP printer job language data follows. Some printer drivers add pjl
- * commands to switch a pjl printer to postscript mode. If no PS header
- * follows, this seems to be a real pjl file. */
- if(iscomment(line, "\033%-12345X@PJL")) {
- /* read until first DSC comment */
- while(readline(fd, &line, &position, &line_len)
- && (line[0] != '%')) ;
- if(line[0] != '%') {
- g_print("psscan error: input files seems to be a PJL file.\n");
- ps_io_exit(fd);
- return (NULL);
- }
- }
-
- /* Header comments */
-
- /* Header should start with "%!PS-Adobe-", but some programms omit
- * parts of this or add a ^D at the beginning. */
- if(iscomment(line, "%!PS") || iscomment(line, "\004%!PS")) {
- doc = g_new0(struct document, 1);
- doc->default_page_orientation = GTK_GS_ORIENTATION_NONE;
- doc->orientation = GTK_GS_ORIENTATION_NONE;
-
- /* ignore possible leading ^D */
- if(*line == '\004') {
- position++;
- line_len--;
- }
-
-/* Jake Hamby patch 18/3/98 */
-
- text[0] = '\0';
- sscanf(line, "%*s %256s", text);
- /*doc->epsf = iscomment(text, "EPSF-"); */
- doc->epsf = iscomment(text, "EPSF"); /* Hamby - This line changed */
- doc->beginheader = position;
- section_len = line_len;
- }
- else {
- /* There are postscript documents that do not have
- %PS at the beginning, usually unstructured. We should GS decide
- For instance, the tech reports at this university:
-
- http://svrc.it.uq.edu.au/Bibliography/svrc-tr.html?94-45
-
- add ugly PostScript before the actual document.
-
- GS and gv is
- able to display them correctly as unstructured PS.
-
- In a way, this makes sense, a program PostScript does not need
- the !PS at the beginning.
- */
- doc = g_new0(struct document, 1);
- doc->default_page_orientation = GTK_GS_ORIENTATION_NONE;
- doc->orientation = GTK_GS_ORIENTATION_NONE;
- ps_io_exit(fd);
- return (doc);
- }
-
- preread = 0;
- while(preread || readline(fd, &line, &position, &line_len)) {
- if(!preread)
- section_len += line_len;
- preread = 0;
- if(line[0] != '%' ||
- iscomment(line + 1, "%EndComments") ||
- line[1] == ' ' || line[1] == '\t' || line[1] == '\n' ||
- !isprint(line[1])) {
- break;
- }
- else if(line[1] != '%') {
- /* Do nothing */
- }
- else if(doc->title == NULL && iscomment(line + 2, "Title:")) {
- doc->title = gettextline(line + length("%%Title:"));
- }
- else if(doc->date == NULL && iscomment(line + 2, "CreationDate:")) {
- doc->date = gettextline(line + length("%%CreationDate:"));
- }
- else if(doc->creator == NULL && iscomment(line + 2, "Creator:")) {
- doc->creator = gettextline(line + length("%%Creator:"));
- }
- else if(bb_set == NONE && iscomment(line + 2, "BoundingBox:")) {
- sscanf(line + length("%%BoundingBox:"), "%256s", text);
- if(strcmp(text, "(atend)") == 0) {
- bb_set = ATEND;
- }
- else {
- if(sscanf(line + length("%%BoundingBox:"), "%d %d %d %d",
- &(doc->boundingbox[LLX]),
- &(doc->boundingbox[LLY]),
- &(doc->boundingbox[URX]), &(doc->boundingbox[URY])) == 4)
- bb_set = 1;
- else {
- float fllx, flly, furx, fury;
- if(sscanf(line + length("%%BoundingBox:"), "%f %f %f %f",
- &fllx, &flly, &furx, &fury) == 4) {
- bb_set = 1;
- doc->boundingbox[LLX] = fllx;
- doc->boundingbox[LLY] = flly;
- doc->boundingbox[URX] = furx;
- doc->boundingbox[URY] = fury;
- if(fllx < doc->boundingbox[LLX])
- doc->boundingbox[LLX]--;
- if(flly < doc->boundingbox[LLY])
- doc->boundingbox[LLY]--;
- if(furx > doc->boundingbox[URX])
- doc->boundingbox[URX]++;
- if(fury > doc->boundingbox[URY])
- doc->boundingbox[URY]++;
- }
- }
- }
- }
- else if(orientation_set == NONE && iscomment(line + 2, "Orientation:")) {
- sscanf(line + length("%%Orientation:"), "%256s", text);
- if(strcmp(text, "(atend)") == 0) {
- orientation_set = ATEND;
- }
- else if(strcmp(text, "Portrait") == 0) {
- doc->orientation = GTK_GS_ORIENTATION_PORTRAIT;
- orientation_set = 1;
- }
- else if(strcmp(text, "Landscape") == 0) {
- doc->orientation = GTK_GS_ORIENTATION_LANDSCAPE;
- orientation_set = 1;
- }
- else if(strcmp(text, "Seascape") == 0) {
- doc->orientation = GTK_GS_ORIENTATION_SEASCAPE;
- orientation_set = 1;
- }
- }
- else if(page_order_set == NONE && iscomment(line + 2, "PageOrder:")) {
- sscanf(line + length("%%PageOrder:"), "%256s", text);
- if(strcmp(text, "(atend)") == 0) {
- page_order_set = ATEND;
- }
- else if(strcmp(text, "Ascend") == 0) {
- doc->pageorder = ASCEND;
- page_order_set = 1;
- }
- else if(strcmp(text, "Descend") == 0) {
- doc->pageorder = DESCEND;
- page_order_set = 1;
- }
- else if(strcmp(text, "Special") == 0) {
- doc->pageorder = SPECIAL;
- page_order_set = 1;
- }
- }
- else if(pages_set == NONE && iscomment(line + 2, "Pages:")) {
- sscanf(line + length("%%Pages:"), "%256s", text);
- if(strcmp(text, "(atend)") == 0) {
- pages_set = ATEND;
- }
- else {
- switch (sscanf(line + length("%%Pages:"), "%d %d", &maxpages, &i)) {
- case 2:
- if(page_order_set == NONE) {
- if(i == -1) {
- doc->pageorder = DESCEND;
- page_order_set = 1;
- }
- else if(i == 0) {
- doc->pageorder = SPECIAL;
- page_order_set = 1;
- }
- else if(i == 1) {
- doc->pageorder = ASCEND;
- page_order_set = 1;
- }
- }
- case 1:
- if(maxpages > 0)
- doc->pages = pages_new(NULL, 0, maxpages);
- }
- }
- }
- else if(doc->numsizes == NONE && iscomment(line + 2, "DocumentMedia:")) {
- float w, h;
- doc->size = g_new0(GtkGSPaperSize, 1);
- doc->size[0].name =
- get_next_text(line + length("%%DocumentMedia:"), &next_char);
- if(doc->size[0].name != NULL) {
- if(sscanf(next_char, "%f %f", &w, &h) == 2) {
- doc->size[0].width = w + 0.5;
- doc->size[0].height = h + 0.5;
- }
- if(doc->size[0].width != 0 && doc->size[0].height != 0)
- doc->numsizes = 1;
- else
- g_free(doc->size[0].name);
- }
- preread = 1;
- while(readline(fd, &line, &position, &line_len) &&
- DSCcomment(line) && iscomment(line + 2, "+")) {
- section_len += line_len;
- doc->size = g_renew(GtkGSPaperSize, doc->size, doc->numsizes + 1);
- doc->size[doc->numsizes].name =
- get_next_text(line + length("%%+"), &next_char);
- if(doc->size[doc->numsizes].name != NULL) {
- if(sscanf(next_char, "%f %f", &w, &h) == 2) {
- doc->size[doc->numsizes].width = w + 0.5;
- doc->size[doc->numsizes].height = h + 0.5;
- }
- if(doc->size[doc->numsizes].width != 0 &&
- doc->size[doc->numsizes].height != 0)
- doc->numsizes++;
- else
- g_free(doc->size[doc->numsizes].name);
- }
- }
- section_len += line_len;
- if(doc->numsizes != 0)
- doc->default_page_size = doc->size;
- }
- else if(doc->numsizes == NONE && iscomment(line + 2, "DocumentPaperSizes:")) {
-
- doc->size = g_new0(GtkGSPaperSize, 1);
- doc->size[0].name =
- get_next_text(line + length("%%DocumentPaperSizes:"), &next_char);
- if(doc->size[0].name != NULL) {
- doc->size[0].width = 0;
- doc->size[0].height = 0;
- for(dmp = papersizes; dmp->name != NULL; dmp++) {
- /* Note: Paper size comment uses down cased paper size
- * name. Case insensitive compares are only used for
- * PaperSize comments.
- */
- if(strcasecmp(doc->size[0].name, dmp->name) == 0) {
- g_free(doc->size[0].name);
- doc->size[0].name = g_strdup(dmp->name);
- doc->size[0].width = dmp->width;
- doc->size[0].height = dmp->height;
- break;
- }
- }
- if(doc->size[0].width != 0 && doc->size[0].height != 0)
- doc->numsizes = 1;
- else
- g_free(doc->size[0].name);
- }
- while((cp = get_next_text(next_char, &next_char))) {
- doc->size = g_renew(GtkGSPaperSize, doc->size, doc->numsizes + 1);
- doc->size[doc->numsizes].name = cp;
- doc->size[doc->numsizes].width = 0;
- doc->size[doc->numsizes].height = 0;
- for(dmp = papersizes; dmp->name != NULL; dmp++) {
- /* Note: Paper size comment uses down cased paper size
- * name. Case insensitive compares are only used for
- * PaperSize comments.
- */
- if(strcasecmp(doc->size[doc->numsizes].name, dmp->name) == 0) {
- g_free(doc->size[doc->numsizes].name);
- doc->size[doc->numsizes].name = g_strdup(dmp->name);
- doc->size[doc->numsizes].name = dmp->name;
- doc->size[doc->numsizes].width = dmp->width;
- doc->size[doc->numsizes].height = dmp->height;
- break;
- }
- }
- if(doc->size[doc->numsizes].width != 0 &&
- doc->size[doc->numsizes].height != 0)
- doc->numsizes++;
- else
- g_free(doc->size[doc->numsizes].name);
- }
- preread = 1;
- while(readline(fd, &line, &position, &line_len) &&
- DSCcomment(line) && iscomment(line + 2, "+")) {
- section_len += line_len;
- next_char = line + length("%%+");
- while((cp = get_next_text(next_char, &next_char))) {
- doc->size = g_renew(GtkGSPaperSize, doc->size, doc->numsizes + 1);
- doc->size[doc->numsizes].name = cp;
- doc->size[doc->numsizes].width = 0;
- doc->size[doc->numsizes].height = 0;
- for(dmp = papersizes; dmp->name != NULL; dmp++) {
- /* Note: Paper size comment uses down cased paper size
- * name. Case insensitive compares are only used for
- * PaperSize comments.
- */
- if(strcasecmp(doc->size[doc->numsizes].name, dmp->name) == 0) {
- doc->size[doc->numsizes].width = dmp->width;
- doc->size[doc->numsizes].height = dmp->height;
- break;
- }
- }
- if(doc->size[doc->numsizes].width != 0 &&
- doc->size[doc->numsizes].height != 0)
- doc->numsizes++;
- else
- g_free(doc->size[doc->numsizes].name);
- }
- }
- section_len += line_len;
- if(doc->numsizes != 0)
- doc->default_page_size = doc->size;
- }
- }
-
- if(DSCcomment(line) && iscomment(line + 2, "EndComments")) {
- readline(fd, &line, &position, &line_len);
- section_len += line_len;
- }
- doc->endheader = position;
- doc->lenheader = section_len - line_len;
-
- /* Optional Preview comments for encapsulated PostScript files */
-
- beginsection = position;
- section_len = line_len;
- while(blank(line) && readline(fd, &line, &position, &line_len)) {
- section_len += line_len;
- }
-
- if(doc->epsf && DSCcomment(line) && iscomment(line + 2, "BeginPreview")) {
- doc->beginpreview = beginsection;
- beginsection = 0;
- while(readline(fd, &line, &position, &line_len) &&
- !(DSCcomment(line) && iscomment(line + 2, "EndPreview"))) {
- section_len += line_len;
- }
- section_len += line_len;
- readline(fd, &line, &position, &line_len);
- section_len += line_len;
- doc->endpreview = position;
- doc->lenpreview = section_len - line_len;
- }
-
- /* Page Defaults for Version 3.0 files */
-
- if(beginsection == 0) {
- beginsection = position;
- section_len = line_len;
- }
- while(blank(line) && readline(fd, &line, &position, &line_len)) {
- section_len += line_len;
- }
-
- if(DSCcomment(line) && iscomment(line + 2, "BeginDefaults")) {
- doc->begindefaults = beginsection;
- beginsection = 0;
- while(readline(fd, &line, &position, &line_len) &&
- !(DSCcomment(line) && iscomment(line + 2, "EndDefaults"))) {
- section_len += line_len;
- if(!DSCcomment(line)) {
- /* Do nothing */
- }
- else if(doc->default_page_orientation == GTK_GS_ORIENTATION_NONE &&
- iscomment(line + 2, "PageOrientation:")) {
- sscanf(line + length("%%PageOrientation:"), "%256s", text);
- if(strcmp(text, "Portrait") == 0) {
- doc->default_page_orientation = GTK_GS_ORIENTATION_PORTRAIT;
- }
- else if(strcmp(text, "Landscape") == 0) {
- doc->default_page_orientation = GTK_GS_ORIENTATION_LANDSCAPE;
- }
- else if(strcmp(text, "Seascape") == 0) {
- doc->default_page_orientation = GTK_GS_ORIENTATION_SEASCAPE;
- }
- }
- else if(page_size_set == NONE && iscomment(line + 2, "PageMedia:")) {
- cp = get_next_text(line + length("%%PageMedia:"), NULL);
- for(dmp = doc->size, i = 0; i < doc->numsizes; i++, dmp++) {
- if(strcmp(cp, dmp->name) == 0) {
- doc->default_page_size = dmp;
- page_size_set = 1;
- break;
- }
- }
- g_free(cp);
- }
- else if(page_bb_set == NONE && iscomment(line + 2, "PageBoundingBox:")) {
- if(sscanf(line + length("%%PageBoundingBox:"), "%d %d %d %d",
- &(doc->default_page_boundingbox[LLX]),
- &(doc->default_page_boundingbox[LLY]),
- &(doc->default_page_boundingbox[URX]),
- &(doc->default_page_boundingbox[URY])) == 4)
- page_bb_set = 1;
- else {
- float fllx, flly, furx, fury;
- if(sscanf
- (line + length("%%PageBoundingBox:"), "%f %f %f %f",
- &fllx, &flly, &furx, &fury) == 4) {
- page_bb_set = 1;
- doc->default_page_boundingbox[LLX] = fllx;
- doc->default_page_boundingbox[LLY] = flly;
- doc->default_page_boundingbox[URX] = furx;
- doc->default_page_boundingbox[URY] = fury;
- if(fllx < doc->default_page_boundingbox[LLX])
- doc->default_page_boundingbox[LLX]--;
- if(flly < doc->default_page_boundingbox[LLY])
- doc->default_page_boundingbox[LLY]--;
- if(furx > doc->default_page_boundingbox[URX])
- doc->default_page_boundingbox[URX]++;
- if(fury > doc->default_page_boundingbox[URY])
- doc->default_page_boundingbox[URY]++;
- }
- }
- }
- }
- section_len += line_len;
- readline(fd, &line, &position, &line_len);
- section_len += line_len;
- doc->enddefaults = position;
- doc->lendefaults = section_len - line_len;
- }
-
- /* Document Prolog */
-
- if(beginsection == 0) {
- beginsection = position;
- section_len = line_len;
- }
- while(blank(line) && readline(fd, &line, &position, &line_len)) {
- section_len += line_len;
- }
-
- if(!(DSCcomment(line) &&
- (iscomment(line + 2, "BeginSetup") ||
- iscomment(line + 2, "Page:") ||
- iscomment(line + 2, "Trailer") || iscomment(line + 2, "EOF")))) {
- doc->beginprolog = beginsection;
- beginsection = 0;
- preread = 1;
-
- while((preread ||
- readline(fd, &line, &position, &line_len)) &&
- !(DSCcomment(line) &&
- (iscomment(line + 2, "EndProlog") ||
- iscomment(line + 2, "BeginSetup") ||
- iscomment(line + 2, "Page:") ||
- iscomment(line + 2, "Trailer") || iscomment(line + 2, "EOF")))) {
- if(!preread)
- section_len += line_len;
- preread = 0;
- }
- section_len += line_len;
- if(DSCcomment(line) && iscomment(line + 2, "EndProlog")) {
- readline(fd, &line, &position, &line_len);
- section_len += line_len;
- }
- doc->endprolog = position;
- doc->lenprolog = section_len - line_len;
- }
-
- /* Document Setup, Page Defaults found here for Version 2 files */
-
- if(beginsection == 0) {
- beginsection = position;
- section_len = line_len;
- }
- while(blank(line) && readline(fd, &line, &position, &line_len)) {
- section_len += line_len;
- }
-
- if(!(DSCcomment(line) &&
- (iscomment(line + 2, "Page:") ||
- iscomment(line + 2, "Trailer") ||
- (respect_eof && iscomment(line + 2, "EOF"))))) {
- doc->beginsetup = beginsection;
- beginsection = 0;
- preread = 1;
- while((preread ||
- readline(fd, &line, &position, &line_len)) &&
- !(DSCcomment(line) &&
- (iscomment(line + 2, "EndSetup") ||
- iscomment(line + 2, "Page:") ||
- iscomment(line + 2, "Trailer") ||
- (respect_eof && iscomment(line + 2, "EOF"))))) {
- if(!preread)
- section_len += line_len;
- preread = 0;
- if(!DSCcomment(line)) {
- /* Do nothing */
- }
- else if(doc->default_page_orientation == GTK_GS_ORIENTATION_NONE &&
- iscomment(line + 2, "PageOrientation:")) {
- sscanf(line + length("%%PageOrientation:"), "%256s", text);
- if(strcmp(text, "Portrait") == 0) {
- doc->default_page_orientation = GTK_GS_ORIENTATION_PORTRAIT;
- }
- else if(strcmp(text, "Landscape") == 0) {
- doc->default_page_orientation = GTK_GS_ORIENTATION_LANDSCAPE;
- }
- else if(strcmp(text, "Seascape") == 0) {
- doc->default_page_orientation = GTK_GS_ORIENTATION_SEASCAPE;
- }
- }
- else if(page_size_set == NONE && iscomment(line + 2, "PaperSize:")) {
- cp = get_next_text(line + length("%%PaperSize:"), NULL);
- for(dmp = doc->size, i = 0; i < doc->numsizes; i++, dmp++) {
- /* Note: Paper size comment uses down cased paper size
- * name. Case insensitive compares are only used for
- * PaperSize comments.
- */
- if(strcasecmp(cp, dmp->name) == 0) {
- doc->default_page_size = dmp;
- page_size_set = 1;
- break;
- }
- }
- g_free(cp);
- }
- else if(page_bb_set == NONE && iscomment(line + 2, "PageBoundingBox:")) {
- if(sscanf(line + length("%%PageBoundingBox:"), "%d %d %d %d",
- &(doc->default_page_boundingbox[LLX]),
- &(doc->default_page_boundingbox[LLY]),
- &(doc->default_page_boundingbox[URX]),
- &(doc->default_page_boundingbox[URY])) == 4)
- page_bb_set = 1;
- else {
- float fllx, flly, furx, fury;
- if(sscanf
- (line + length("%%PageBoundingBox:"), "%f %f %f %f",
- &fllx, &flly, &furx, &fury) == 4) {
- page_bb_set = 1;
- doc->default_page_boundingbox[LLX] = fllx;
- doc->default_page_boundingbox[LLY] = flly;
- doc->default_page_boundingbox[URX] = furx;
- doc->default_page_boundingbox[URY] = fury;
- if(fllx < doc->default_page_boundingbox[LLX])
- doc->default_page_boundingbox[LLX]--;
- if(flly < doc->default_page_boundingbox[LLY])
- doc->default_page_boundingbox[LLY]--;
- if(furx > doc->default_page_boundingbox[URX])
- doc->default_page_boundingbox[URX]++;
- if(fury > doc->default_page_boundingbox[URY])
- doc->default_page_boundingbox[URY]++;
- }
- }
- }
- }
- section_len += line_len;
- if(DSCcomment(line) && iscomment(line + 2, "EndSetup")) {
- readline(fd, &line, &position, &line_len);
- section_len += line_len;
- }
- doc->endsetup = position;
- doc->lensetup = section_len - line_len;
- }
-
- /* HACK: Mozilla 1.8 Workaround.
-
- It seems that Mozilla 1.8 generates important postscript code
- after the '%%EndProlog' and before the first page comment '%%Page: x y'.
- See comment below also.
- */
-
- if(doc->beginprolog && !doc->beginsetup) {
- doc->lenprolog += section_len - line_len;
- doc->endprolog = position;
- }
-
- /* HACK: Windows NT Workaround
-
- Mark Pfeifer (pfeiferm%ppddev@comet.cmis.abbott.com) noticed
- about problems when viewing Windows NT 3.51 generated postscript
- files with gv. He found that the relevant postscript files
- show important postscript code after the '%%EndSetup' and before
- the first page comment '%%Page: x y'.
- */
- if(doc->beginsetup) {
- while(!(DSCcomment(line) &&
- (iscomment(line + 2, "EndSetup") ||
- (iscomment(line + 2, "Page:") ||
- iscomment(line + 2, "Trailer") ||
- (respect_eof && iscomment(line + 2, "EOF"))))) &&
- (readline(fd, &line, &position, &line_len))) {
- section_len += line_len;
- doc->lensetup = section_len - line_len;
- doc->endsetup = position;
- }
- }
-
- /* Individual Pages */
-
- if(beginsection == 0) {
- beginsection = position;
- section_len = line_len;
- }
- while(blank(line) && readline(fd, &line, &position, &line_len)) {
- section_len += line_len;
- }
-
-
-newpage:
- while(DSCcomment(line) && iscomment(line + 2, "Page:")) {
- if(maxpages == 0) {
- maxpages = 1;
- doc->pages = pages_new(NULL, 0, maxpages);
- }
- label = get_next_text(line + length("%%Page:"), &next_char);
- if(sscanf(next_char, "%d", &thispage) != 1)
- thispage = 0;
- if(nextpage == 1) {
- ignore = thispage != 1;
- }
- if(!ignore && thispage != nextpage) {
- g_free(label);
- doc->numpages--;
- goto continuepage;
- }
- nextpage++;
- if(doc->numpages == maxpages) {
- maxpages++;
- doc->pages = pages_new(doc->pages, maxpages - 1, maxpages);
- }
- page_bb_set = NONE;
- doc->pages[doc->numpages].label = label;
- if(beginsection) {
- doc->pages[doc->numpages].begin = beginsection;
- beginsection = 0;
- }
- else {
- doc->pages[doc->numpages].begin = position;
- section_len = line_len;
- }
- continuepage:
- while(readline(fd, &line, &position, &line_len) &&
- !(DSCcomment(line) &&
- (iscomment(line + 2, "Page:") ||
- iscomment(line + 2, "Trailer") ||
- (respect_eof && iscomment(line + 2, "EOF"))))) {
- section_len += line_len;
- if(!DSCcomment(line)) {
- /* Do nothing */
- }
- else if(doc->pages[doc->numpages].orientation == NONE &&
- iscomment(line + 2, "PageOrientation:")) {
- sscanf(line + length("%%PageOrientation:"), "%256s", text);
- if(strcmp(text, "Portrait") == 0) {
- doc->pages[doc->numpages].orientation = GTK_GS_ORIENTATION_PORTRAIT;
- }
- else if(strcmp(text, "Landscape") == 0) {
- doc->pages[doc->numpages].orientation = GTK_GS_ORIENTATION_LANDSCAPE;
- }
- else if(strcmp(text, "Seascape") == 0) {
- doc->pages[doc->numpages].orientation = GTK_GS_ORIENTATION_SEASCAPE;
- }
- }
- else if(doc->pages[doc->numpages].size == NULL &&
- iscomment(line + 2, "PageMedia:")) {
- cp = get_next_text(line + length("%%PageMedia:"), NULL);
- for(dmp = doc->size, i = 0; i < doc->numsizes; i++, dmp++) {
- if(strcmp(cp, dmp->name) == 0) {
- doc->pages[doc->numpages].size = dmp;
- break;
- }
- }
- g_free(cp);
- }
- else if(doc->pages[doc->numpages].size == NULL &&
- iscomment(line + 2, "PaperSize:")) {
- cp = get_next_text(line + length("%%PaperSize:"), NULL);
- for(dmp = doc->size, i = 0; i < doc->numsizes; i++, dmp++) {
- /* Note: Paper size comment uses down cased paper size
- * name. Case insensitive compares are only used for
- * PaperSize comments.
- */
- if(strcasecmp(cp, dmp->name) == 0) {
- doc->pages[doc->numpages].size = dmp;
- break;
- }
- }
- g_free(cp);
- }
- else if((page_bb_set == NONE || page_bb_set == ATEND) &&
- iscomment(line + 2, "PageBoundingBox:")) {
- sscanf(line + length("%%PageBoundingBox:"), "%256s", text);
- if(strcmp(text, "(atend)") == 0) {
- page_bb_set = ATEND;
- }
- else {
- if(sscanf
- (line + length("%%PageBoundingBox:"), "%d %d %d %d",
- &(doc->pages[doc->numpages].boundingbox[LLX]),
- &(doc->pages[doc->numpages].boundingbox[LLY]),
- &(doc->pages[doc->numpages].boundingbox[URX]),
- &(doc->pages[doc->numpages].boundingbox[URY])) == 4) {
- if(page_bb_set == NONE)
- page_bb_set = 1;
- }
- else {
- float fllx, flly, furx, fury;
- if(sscanf(line + length("%%PageBoundingBox:"),
- "%f %f %f %f", &fllx, &flly, &furx, &fury) == 4) {
- if(page_bb_set == NONE)
- page_bb_set = 1;
- doc->pages[doc->numpages].boundingbox[LLX] = fllx;
- doc->pages[doc->numpages].boundingbox[LLY] = flly;
- doc->pages[doc->numpages].boundingbox[URX] = furx;
- doc->pages[doc->numpages].boundingbox[URY] = fury;
- if(fllx < doc->pages[doc->numpages].boundingbox[LLX])
- doc->pages[doc->numpages].boundingbox[LLX]--;
- if(flly < doc->pages[doc->numpages].boundingbox[LLY])
- doc->pages[doc->numpages].boundingbox[LLY]--;
- if(furx > doc->pages[doc->numpages].boundingbox[URX])
- doc->pages[doc->numpages].boundingbox[URX]++;
- if(fury > doc->pages[doc->numpages].boundingbox[URY])
- doc->pages[doc->numpages].boundingbox[URY]++;
- }
- }
- }
- }
- }
- section_len += line_len;
- doc->pages[doc->numpages].end = position;
- doc->pages[doc->numpages].len = section_len - line_len;
- doc->numpages++;
- }
-
- /* Document Trailer */
-
- if(beginsection) {
- doc->begintrailer = beginsection;
- beginsection = 0;
- }
- else {
- doc->begintrailer = position;
- section_len = line_len;
- }
-
- preread = 1;
- while((preread ||
- readline(fd, &line, &position, &line_len)) &&
- !(respect_eof && DSCcomment(line) && iscomment(line + 2, "EOF"))) {
- if(!preread)
- section_len += line_len;
- preread = 0;
- if(!DSCcomment(line)) {
- /* Do nothing */
- }
- else if(iscomment(line + 2, "Page:")) {
- g_free(get_next_text(line + length("%%Page:"), &next_char));
- if(sscanf(next_char, "%d", &thispage) != 1)
- thispage = 0;
- if(!ignore && thispage == nextpage) {
- if(doc->numpages > 0) {
- doc->pages[doc->numpages - 1].end = position;
- doc->pages[doc->numpages - 1].len += section_len - line_len;
- }
- else {
- if(doc->endsetup) {
- doc->endsetup = position;
- doc->endsetup += section_len - line_len;
- }
- else if(doc->endprolog) {
- doc->endprolog = position;
- doc->endprolog += section_len - line_len;
- }
- }
- goto newpage;
- }
- }
- else if(!respect_eof && iscomment(line + 2, "Trailer")) {
- /* What we thought was the start of the trailer was really */
- /* the trailer of an EPS on the page. */
- /* Set the end of the page to this trailer and keep scanning. */
- if(doc->numpages > 0) {
- doc->pages[doc->numpages - 1].end = position;
- doc->pages[doc->numpages - 1].len += section_len - line_len;
- }
- doc->begintrailer = position;
- section_len = line_len;
- }
- else if(bb_set == ATEND && iscomment(line + 2, "BoundingBox:")) {
- if(sscanf(line + length("%%BoundingBox:"), "%d %d %d %d",
- &(doc->boundingbox[LLX]),
- &(doc->boundingbox[LLY]),
- &(doc->boundingbox[URX]), &(doc->boundingbox[URY])) != 4) {
- float fllx, flly, furx, fury;
- if(sscanf(line + length("%%BoundingBox:"), "%f %f %f %f",
- &fllx, &flly, &furx, &fury) == 4) {
- doc->boundingbox[LLX] = fllx;
- doc->boundingbox[LLY] = flly;
- doc->boundingbox[URX] = furx;
- doc->boundingbox[URY] = fury;
- if(fllx < doc->boundingbox[LLX])
- doc->boundingbox[LLX]--;
- if(flly < doc->boundingbox[LLY])
- doc->boundingbox[LLY]--;
- if(furx > doc->boundingbox[URX])
- doc->boundingbox[URX]++;
- if(fury > doc->boundingbox[URY])
- doc->boundingbox[URY]++;
- }
- }
- }
- else if(orientation_set == ATEND && iscomment(line + 2, "Orientation:")) {
- sscanf(line + length("%%Orientation:"), "%256s", text);
- if(strcmp(text, "Portrait") == 0) {
- doc->orientation = GTK_GS_ORIENTATION_PORTRAIT;
- }
- else if(strcmp(text, "Landscape") == 0) {
- doc->orientation = GTK_GS_ORIENTATION_LANDSCAPE;
- }
- else if(strcmp(text, "Seascape") == 0) {
- doc->orientation = GTK_GS_ORIENTATION_SEASCAPE;
- }
- }
- else if(page_order_set == ATEND && iscomment(line + 2, "PageOrder:")) {
- sscanf(line + length("%%PageOrder:"), "%256s", text);
- if(strcmp(text, "Ascend") == 0) {
- doc->pageorder = ASCEND;
- }
- else if(strcmp(text, "Descend") == 0) {
- doc->pageorder = DESCEND;
- }
- else if(strcmp(text, "Special") == 0) {
- doc->pageorder = SPECIAL;
- }
- }
- else if(pages_set == ATEND && iscomment(line + 2, "Pages:")) {
- if(sscanf(line + length("%%Pages:"), "%*u %d", &i) == 1) {
- if(page_order_set == NONE) {
- if(i == -1)
- doc->pageorder = DESCEND;
- else if(i == 0)
- doc->pageorder = SPECIAL;
- else if(i == 1)
- doc->pageorder = ASCEND;
- }
- }
- }
- }
- section_len += line_len;
- if(DSCcomment(line) && iscomment(line + 2, "EOF")) {
- readline(fd, &line, &position, &line_len);
- section_len += line_len;
- }
- doc->endtrailer = position;
- doc->lentrailer = section_len - line_len;
-
-#if 0
- section_len = line_len;
- preread = 1;
- while(preread || readline(line, sizeof line, file, &position, &line_len)) {
- if(!preread)
- section_len += line_len;
- preread = 0;
- if(DSCcomment(line) && iscomment(line + 2, "Page:")) {
- g_free(get_next_text(line + length("%%Page:"), &next_char));
- if(sscanf(next_char, "%d", &thispage) != 1)
- thispage = 0;
- if(!ignore && thispage == nextpage) {
- if(doc->numpages > 0) {
- doc->pages[doc->numpages - 1].end = position;
- doc->pages[doc->numpages - 1].len += doc->lentrailer +
- section_len - line_len;
- }
- else {
- if(doc->endsetup) {
- doc->endsetup = position;
- doc->endsetup += doc->lentrailer + section_len - line_len;
- }
- else if(doc->endprolog) {
- doc->endprolog = position;
- doc->endprolog += doc->lentrailer + section_len - line_len;
- }
- }
- goto newpage;
- }
- }
- }
-#endif
- ps_io_exit(fd);
- return doc;
-}
-
-/*
- * psfree -- free dynamic storage associated with document structure.
- */
-
-void
-psfree(doc)
- struct document *doc;
-{
- int i;
-
- if(doc) {
- /*
- printf("This document exists\n");
- */
- for(i = 0; i < doc->numpages; i++) {
- if(doc->pages[i].label)
- g_free(doc->pages[i].label);
- }
- for(i = 0; i < doc->numsizes; i++) {
- if(doc->size[i].name)
- g_free(doc->size[i].name);
- }
- if(doc->title)
- g_free(doc->title);
- if(doc->date)
- g_free(doc->date);
- if(doc->creator)
- g_free(doc->creator);
- if(doc->pages)
- g_free(doc->pages);
- if(doc->size)
- g_free(doc->size);
- g_free(doc);
- }
-}
-
-/*
- * gettextine -- skip over white space and return the rest of the line.
- * If the text begins with '(' return the text string
- * using get_next_text().
- */
-
-static char *
-gettextline(char *line)
-{
- char *cp;
-
- while(*line && (*line == ' ' || *line == '\t'))
- line++;
- if(*line == '(') {
- return get_next_text(line, NULL);
- }
- else {
- if(strlen(line) == 0)
- return NULL;
-
- cp = g_strdup(line);
-
- /* Remove end of line */
- if(cp[strlen(line) - 2] == '\r' && cp[strlen(line) - 1] == '\n')
- /* Handle DOS \r\n */
- cp[strlen(line) - 2] = '\0';
- else if(cp[strlen(line) - 1] == '\n' || cp[strlen(line) - 1] == '\r')
- /* Handle mac and unix */
- cp[strlen(line) - 1] = '\0';
-
- return cp;
- }
-}
-
-/*
- * get_next_text -- return the next text string on the line.
- * return NULL if nothing is present.
- */
-
-static char *
-get_next_text(line, next_char)
- char *line;
- char **next_char;
-{
- char text[PSLINELENGTH]; /* Temporary storage for text */
- char *cp;
- int quoted = 0;
-
- while(*line && (*line == ' ' || *line == '\t'))
- line++;
- cp = text;
- if(*line == '(') {
- int level = 0;
- quoted = 1;
- line++;
- while(*line && !(*line == ')' && level == 0)
- && (cp - text) < PSLINELENGTH - 1) {
- if(*line == '\\') {
- if(*(line + 1) == 'n') {
- *cp++ = '\n';
- line += 2;
- }
- else if(*(line + 1) == 'r') {
- *cp++ = '\r';
- line += 2;
- }
- else if(*(line + 1) == 't') {
- *cp++ = '\t';
- line += 2;
- }
- else if(*(line + 1) == 'b') {
- *cp++ = '\b';
- line += 2;
- }
- else if(*(line + 1) == 'f') {
- *cp++ = '\f';
- line += 2;
- }
- else if(*(line + 1) == '\\') {
- *cp++ = '\\';
- line += 2;
- }
- else if(*(line + 1) == '(') {
- *cp++ = '(';
- line += 2;
- }
- else if(*(line + 1) == ')') {
- *cp++ = ')';
- line += 2;
- }
- else if(*(line + 1) >= '0' && *(line + 1) <= '9') {
- if(*(line + 2) >= '0' && *(line + 2) <= '9') {
- if(*(line + 3) >= '0' && *(line + 3) <= '9') {
- *cp++ =
- ((*(line + 1) - '0') * 8 + *(line + 2) -
- '0') * 8 + *(line + 3) - '0';
- line += 4;
- }
- else {
- *cp++ = (*(line + 1) - '0') * 8 + *(line + 2) - '0';
- line += 3;
- }
- }
- else {
- *cp++ = *(line + 1) - '0';
- line += 2;
- }
- }
- else {
- line++;
- *cp++ = *line++;
- }
- }
- else if(*line == '(') {
- level++;
- *cp++ = *line++;
- }
- else if(*line == ')') {
- level--;
- *cp++ = *line++;
- }
- else {
- *cp++ = *line++;
- }
- }
- }
- else {
- while(*line && !(*line == ' ' || *line == '\t' || *line == '\n')
- && (cp - text) < PSLINELENGTH - 1)
- *cp++ = *line++;
- }
- *cp = '\0';
- if(next_char)
- *next_char = line;
- if(!quoted && strlen(text) == 0)
- return NULL;
- return g_strdup(text);
-}
-
-/*
- * pscopy -- copy lines of Postscript from a section of one file
- * to another file.
- * Automatically switch to binary copying whenever
- * %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
- * comments are encountered.
- */
-
-void
-pscopy(from, to, begin, end)
- FILE *from;
- GtkGSDocSink *to;
- long begin; /* set negative to avoid initial seek */
- long end;
-{
- char line[PSLINELENGTH]; /* 255 characters + 1 newline + 1 NULL */
- char text[PSLINELENGTH]; /* Temporary storage for text */
- unsigned int num;
- int i;
- char buf[BUFSIZ];
-
- if(begin >= 0)
- fseek(from, begin, SEEK_SET);
- while(ftell(from) < end) {
- fgets(line, sizeof line, from);
- gtk_gs_doc_sink_write(to, line, strlen(line));
-
- if(!(DSCcomment(line) && iscomment(line + 2, "Begin"))) {
- /* Do nothing */
- }
- else if(iscomment(line + 7, "Data:")) {
- text[0] = '\0';
- if(sscanf(line + length("%%BeginData:"), "%d %*s %256s", &num, text) >= 1) {
- if(strcmp(text, "Lines") == 0) {
- for(i = 0; i < num; i++) {
- fgets(line, sizeof(line), from);
- gtk_gs_doc_sink_write(to, line, strlen(line));
- }
- }
- else {
- while(num > BUFSIZ) {
- fread(buf, sizeof(char), BUFSIZ, from);
- gtk_gs_doc_sink_write(to, buf, BUFSIZ);
- num -= BUFSIZ;
- }
- fread(buf, sizeof(char), num, from);
- gtk_gs_doc_sink_write(to, buf, num);
- }
- }
- }
- else if(iscomment(line + 7, "Binary:")) {
- if(sscanf(line + length("%%BeginBinary:"), "%d", &num) == 1) {
- while(num > BUFSIZ) {
- fread(buf, sizeof(char), BUFSIZ, from);
- gtk_gs_doc_sink_write(to, buf, BUFSIZ);
- num -= BUFSIZ;
- }
- fread(buf, sizeof(char), num, from);
- gtk_gs_doc_sink_write(to, buf, num);
- }
- }
- }
-}
-
-/*
- * pscopyuntil -- copy lines of Postscript from a section of one file
- * to another file until a particular comment is reached.
- * Automatically switch to binary copying whenever
- * %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
- * comments are encountered.
- */
-
-char *
-pscopyuntil(FILE * from, GtkGSDocSink * to, long begin, long end,
- const char *comment)
-{
- char line[PSLINELENGTH]; /* 255 characters + 1 newline + 1 NULL */
- char text[PSLINELENGTH]; /* Temporary storage for text */
- unsigned int num;
- int comment_length;
- int i;
- char buf[BUFSIZ];
-
- if(comment != NULL)
- comment_length = strlen(comment);
- else
- comment_length = 0;
- if(begin >= 0)
- fseek(from, begin, SEEK_SET);
-
- while(ftell(from) < end && !feof(from)) {
- fgets(line, sizeof line, from);
-
- /* iscomment cannot be used here,
- * because comment_length is not known at compile time. */
- if(comment != NULL && strncmp(line, comment, comment_length) == 0) {
- return g_strdup(line);
- }
- gtk_gs_doc_sink_write(to, line, strlen(line));
- if(!(DSCcomment(line) && iscomment(line + 2, "Begin"))) {
- /* Do nothing */
- }
- else if(iscomment(line + 7, "Data:")) {
- text[0] = '\0';
- if(sscanf(line + length("%%BeginData:"), "%d %*s %256s", &num, text) >= 1) {
- if(strcmp(text, "Lines") == 0) {
- for(i = 0; i < num; i++) {
- fgets(line, sizeof line, from);
- gtk_gs_doc_sink_write(to, line, strlen(line));
- }
- }
- else {
- while(num > BUFSIZ) {
- fread(buf, sizeof(char), BUFSIZ, from);
- gtk_gs_doc_sink_write(to, buf, BUFSIZ);
- num -= BUFSIZ;
- }
- fread(buf, sizeof(char), num, from);
- gtk_gs_doc_sink_write(to, buf, num);
- }
- }
- }
- else if(iscomment(line + 7, "Binary:")) {
- if(sscanf(line + length("%%BeginBinary:"), "%d", &num) == 1) {
- while(num > BUFSIZ) {
- fread(buf, sizeof(char), BUFSIZ, from);
- gtk_gs_doc_sink_write(to, buf, BUFSIZ);
- num -= BUFSIZ;
- }
- fread(buf, sizeof(char), num, from);
- gtk_gs_doc_sink_write(to, buf, num);
- }
- }
- }
- return NULL;
-}
-
-/*
- * blank -- determine whether the line contains nothing but whitespace.
- */
-
-static int
-blank(char *line)
-{
- char *cp = line;
-
- while(*cp == ' ' || *cp == '\t')
- cp++;
- return *cp == '\n' || (*cp == '%' && (line[0] != '%' || line[1] != '%'));
-}
-
-/*##########################################################*/
-/* pscopydoc */
-/* Copy the headers, marked pages, and trailer to fp */
-/*##########################################################*/
-
-void
-pscopydoc(GtkGSDocSink * dest,
- char *src_filename, struct document *d, gint * pagelist)
-{
- FILE *src_file;
- char text[PSLINELENGTH];
- char *comment;
- gboolean pages_written = FALSE;
- gboolean pages_atend = FALSE;
- int pages;
- int page = 1;
- int i, j;
- int here;
-
- src_file = fopen(src_filename, "r");
- i = 0;
- pages = 0;
- for(i = 0; i < d->numpages; i++) {
- if(pagelist[i])
- pages++;
- }
-
- here = d->beginheader;
-
- while((comment = pscopyuntil(src_file, dest, here, d->endheader, "%%Pages:"))) {
- here = ftell(src_file);
- if(pages_written || pages_atend) {
- g_free(comment);
- continue;
- }
- sscanf(comment + length("%%Pages:"), "%256s", text);
- if(strcmp(text, "(atend)") == 0) {
- gtk_gs_doc_sink_write(dest, comment, strlen(comment));
- pages_atend = TRUE;
- }
- else {
- switch (sscanf(comment + length("%%Pages:"), "%*d %d", &i)) {
- case 1:
- gtk_gs_doc_sink_printf(dest, "%%%%Pages: %d %d\n", pages, i);
- break;
- default:
- gtk_gs_doc_sink_printf(dest, "%%%%Pages: %d\n", pages);
- break;
- }
- pages_written = TRUE;
- }
- g_free(comment);
- }
- pscopyuntil(src_file, dest, d->beginpreview, d->endpreview, NULL);
- pscopyuntil(src_file, dest, d->begindefaults, d->enddefaults, NULL);
- pscopyuntil(src_file, dest, d->beginprolog, d->endprolog, NULL);
- pscopyuntil(src_file, dest, d->beginsetup, d->endsetup, NULL);
-
- for(i = 0; i < d->numpages; i++) {
- if(d->pageorder == DESCEND)
- j = (d->numpages - 1) - i;
- else
- j = i;
- j = i;
- if(pagelist[j]) {
- comment = pscopyuntil(src_file, dest,
- d->pages[i].begin, d->pages[i].end, "%%Page:");
- gtk_gs_doc_sink_printf(dest, "%%%%Page: %s %d\n",
- d->pages[i].label, page++);
- g_free(comment);
- pscopyuntil(src_file, dest, -1, d->pages[i].end, NULL);
- }
- }
-
- here = d->begintrailer;
- while((comment = pscopyuntil(src_file, dest, here, d->endtrailer,
- "%%Pages:"))) {
- here = ftell(src_file);
- if(pages_written) {
- g_free(comment);
- continue;
- }
- switch (sscanf(comment + length("%%Pages:"), "%*d %d", &i)) {
- case 1:
- gtk_gs_doc_sink_printf(dest, "%%%%Pages: %d %d\n", pages, i);
- break;
- default:
- gtk_gs_doc_sink_printf(dest, "%%%%Pages: %d\n", pages);
- break;
- }
- pages_written = TRUE;
- g_free(comment);
- }
-
- fclose(src_file);
-}
-
-/*----------------------------------------------------------*/
-/* ps_io_init */
-/*----------------------------------------------------------*/
-
-#define FD_FILE (fd->file)
-#define FD_FILE_DESC (fd->file_desc)
-#define FD_FILEPOS (fd->filepos)
-#define FD_LINE_BEGIN (fd->line_begin)
-#define FD_LINE_END (fd->line_end)
-#define FD_LINE_LEN (fd->line_len)
-#define FD_LINE_TERMCHAR (fd->line_termchar)
-#define FD_BUF (fd->buf)
-#define FD_BUF_END (fd->buf_end)
-#define FD_BUF_SIZE (fd->buf_size)
-#define FD_STATUS (fd->status)
-
-#define FD_STATUS_OKAY 0
-#define FD_STATUS_BUFTOOLARGE 1
-#define FD_STATUS_NOMORECHARS 2
-
-#define LINE_CHUNK_SIZE 4096
-#define MAX_PS_IO_FGETCHARS_BUF_SIZE 57344
-#define BREAK_PS_IO_FGETCHARS_BUF_SIZE 49152
-
-static FileData ps_io_init(file)
- FILE *file;
-{
- FileData fd;
- size_t size = sizeof(FileDataStruct);
-
- fd = (FileData) g_malloc(size);
- memset((void*) fd ,0,(size_t)size);
-
- rewind(file);
- FD_FILE = file;
- FD_FILE_DESC = fileno(file);
- FD_FILEPOS = ftell(file);
- FD_BUF_SIZE = (2*LINE_CHUNK_SIZE)+1;
- FD_BUF = g_malloc(FD_BUF_SIZE);
- FD_BUF[0] = '\0';
- return(fd);
-}
-
-/*----------------------------------------------------------*/
-/* ps_io_exit */
-/*----------------------------------------------------------*/
-
-static void
-ps_io_exit(fd)
- FileData fd;
-{
- g_free(FD_BUF);
- g_free(fd);
-}
-
-/*----------------------------------------------------------*/
-/* ps_io_fseek */
-/*----------------------------------------------------------*/
-
-/*static int
-ps_io_fseek(fd,offset)
- FileData fd;
- int offset;
-{
- int status;
- status=fseek(FD_FILE,(long)offset,SEEK_SET);
- FD_BUF_END = FD_LINE_BEGIN = FD_LINE_END = FD_LINE_LEN = 0;
- FD_FILEPOS = offset;
- FD_STATUS = FD_STATUS_OKAY;
- return(status);
-}*/
-
-/*----------------------------------------------------------*/
-/* ps_io_ftell */
-/*----------------------------------------------------------*/
-
-/*static int
-ps_io_ftell(fd)
- FileData fd;
-{
- return(FD_FILEPOS);
-}*/
-
-/*----------------------------------------------------------*/
-/* ps_io_fgetchars */
-/*----------------------------------------------------------*/
-
-#ifdef USE_MEMMOVE_CODE
-static void ps_memmove (d, s, l)
- char *d;
- const char *s;
- unsigned l;
-{
- if (s < d) for (s += l, d += l; l; --l) *--d = *--s;
- else if (s != d) for (; l; --l) *d++ = *s++;
-}
-#else
-# define ps_memmove memmove
-#endif
-
-static char * ps_io_fgetchars(fd,num)
- FileData fd;
- int num;
-{
- char *eol=NULL,*tmp;
- size_t size_of_char = sizeof(char);
-
- if (FD_STATUS != FD_STATUS_OKAY) {
- return(NULL);
- }
-
- FD_BUF[FD_LINE_END] = FD_LINE_TERMCHAR; /* restoring char previously exchanged against '\0' */
- FD_LINE_BEGIN = FD_LINE_END;
-
- do {
- if (num<0) { /* reading whole line */
- if (FD_BUF_END-FD_LINE_END) {
- /* strpbrk is faster but fails on lines with embedded NULLs
- eol = strpbrk(FD_BUF+FD_LINE_END,"\n\r");
- */
- tmp = FD_BUF + FD_BUF_END;
- eol = FD_BUF + FD_LINE_END;
- while (eol < tmp && *eol != '\n' && *eol != '\r') eol++;
- if (eol >= tmp) eol = NULL;
- if (eol) {
- if (*eol=='\r' && *(eol+1)=='\n') eol += 2;
- else eol++;
- break;
- }
- }
- } else { /* reading specified num of chars */
- if (FD_BUF_END >= FD_LINE_BEGIN+num) {
- eol = FD_BUF+FD_LINE_BEGIN+num;
- break;
- }
- }
-
- if (FD_BUF_END - FD_LINE_BEGIN > BREAK_PS_IO_FGETCHARS_BUF_SIZE) {
- eol = FD_BUF + FD_BUF_END - 1;
- break;
- }
-
- while (FD_BUF_SIZE < FD_BUF_END+LINE_CHUNK_SIZE+1) {
- if (FD_BUF_SIZE > MAX_PS_IO_FGETCHARS_BUF_SIZE) {
- /* we should never get here, since the line is broken
- artificially after BREAK_PS_IO_FGETCHARS_BUF_SIZE bytes. */
- fprintf(stderr, "gv: ps_io_fgetchars: Fatal Error: buffer became too large.\n");
- exit(-1);
- }
- if (FD_LINE_BEGIN) {
- ps_memmove((void*)FD_BUF,(void*)(FD_BUF+FD_LINE_BEGIN),
- ((size_t)(FD_BUF_END-FD_LINE_BEGIN+1))*size_of_char);
- FD_BUF_END -= FD_LINE_BEGIN;
- FD_LINE_BEGIN = 0;
- } else {
- FD_BUF_SIZE = FD_BUF_SIZE+LINE_CHUNK_SIZE+1;
- FD_BUF = g_realloc(FD_BUF,FD_BUF_SIZE);
- }
- }
-
- FD_LINE_END = FD_BUF_END;
-#ifdef VMS
- /* different existing VMS file formats require that we use read here ###jp###,10/12/96 */
- if (num<0) FD_BUF_END += read(FD_FILE_DESC,FD_BUF+FD_BUF_END,LINE_CHUNK_SIZE);
- else FD_BUF_END += fread(FD_BUF+FD_BUF_END,size_of_char,LINE_CHUNK_SIZE,FD_FILE);
-#else
- /* read() seems to fail sometimes (? ? ?) so we always use fread ###jp###,07/31/96*/
- FD_BUF_END += fread(FD_BUF+FD_BUF_END,size_of_char,LINE_CHUNK_SIZE,FD_FILE);
-#endif
-
- FD_BUF[FD_BUF_END] = '\0';
- if (FD_BUF_END-FD_LINE_END == 0) {
- FD_STATUS = FD_STATUS_NOMORECHARS;
- return(NULL);
- }
- }
- while (1);
-
- FD_LINE_END = eol - FD_BUF;
- FD_LINE_LEN = FD_LINE_END - FD_LINE_BEGIN;
- FD_LINE_TERMCHAR = FD_BUF[FD_LINE_END];
- FD_BUF[FD_LINE_END] = '\0';
-#ifdef USE_FTELL_FOR_FILEPOS
- if (FD_LINE_END==FD_BUF_END) {
- /*
- For VMS we cannot assume that the record is FD_LINE_LEN bytes long
- on the disk. For stream_lf and stream_cr that is true, but not for
- other formats, since VAXC/DECC converts the formatting into a single \n.
- eg. variable format files have a 2-byte length and padding to an even
- number of characters. So, we use ftell for each record.
- This still will not work if we need to fseek to a \n or \r inside a
- variable record (ftell always returns the start of the record in this
- case).
- (Tim Adye, adye@v2.rl.ac.uk)
- */
- FD_FILEPOS = ftell(FD_FILE);
- } else
-#endif /* USE_FTELL_FOR_FILEPOS */
- FD_FILEPOS += FD_LINE_LEN;
-
- return(FD_BUF+FD_LINE_BEGIN);
-}
-
-/*----------------------------------------------------------*/
-/*
- readline()
- Read the next line in the postscript file.
- Automatically skip over data (as indicated by
- %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
- comments.)
- Also, skip over included documents (as indicated by
- %%BeginDocument/%%EndDocument comments.)
-*/
-/*----------------------------------------------------------*/
-
-static char *readline (fd, lineP, positionP, line_lenP)
- FileData fd;
- char **lineP;
- long *positionP;
- unsigned int *line_lenP;
-{
- unsigned int nbytes=0;
- int skipped=0;
- char *line;
-
- if (positionP) *positionP = FD_FILEPOS;
- line = ps_io_fgetchars(fd,-1);
- if (!line) {
- *line_lenP = 0;
- *lineP = empty_string;
- return(NULL);
- }
-
- *line_lenP = FD_LINE_LEN;
-
-#define IS_COMMENT(comment) \
- (DSCcomment(line) && iscomment(line+2,(comment)))
-#define IS_BEGIN(comment) \
- (iscomment(line+7,(comment)))
-#define SKIP_WHILE(cond) \
- while (readline(fd, &line, NULL, &nbytes) && (cond)) *line_lenP += nbytes;\
- skipped=1;
-#define SKIP_UNTIL_1(comment) { \
- SKIP_WHILE((!IS_COMMENT(comment))) \
- }
-#define SKIP_UNTIL_2(comment1,comment2) { \
- SKIP_WHILE((!IS_COMMENT(comment1) && !IS_COMMENT(comment2)))\
- }
-
- if (!IS_COMMENT("Begin")) {} /* Do nothing */
- else if IS_BEGIN("Document:") SKIP_UNTIL_1("EndDocument")
- else if IS_BEGIN("Feature:") SKIP_UNTIL_1("EndFeature")
-#ifdef USE_ACROREAD_WORKAROUND
- else if IS_BEGIN("File") SKIP_UNTIL_2("EndFile","EOF")
-#else
- else if IS_BEGIN("File") SKIP_UNTIL_1("EndFile")
-#endif
- else if IS_BEGIN("Font") SKIP_UNTIL_1("EndFont")
- else if IS_BEGIN("ProcSet") SKIP_UNTIL_1("EndProcSet")
- else if IS_BEGIN("Resource") SKIP_UNTIL_1("EndResource")
- else if IS_BEGIN("Data:") {
- int num;
- char text[101];
- if (FD_LINE_LEN > 100) FD_BUF[100] = '\0';
- text[0] = '\0';
- if (sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text) >= 1) {
- if (strcmp(text, "Lines") == 0) {
- while (num) {
- line = ps_io_fgetchars(fd,-1);
- if (line) *line_lenP += FD_LINE_LEN;
- num--;
- }
- } else {
- int read_chunk_size = LINE_CHUNK_SIZE;
- while (num>0) {
- if (num <= LINE_CHUNK_SIZE) read_chunk_size=num;
- line = ps_io_fgetchars(fd,read_chunk_size);
- if (line) *line_lenP += FD_LINE_LEN;
- num -= read_chunk_size;
- }
- }
- }
- SKIP_UNTIL_1("EndData")
- }
- else if IS_BEGIN("Binary:") {
- int num;
- if (sscanf(line+length("%%BeginBinary:"), "%d", &num) == 1) {
- int read_chunk_size = LINE_CHUNK_SIZE;
- while (num>0) {
- if (num <= LINE_CHUNK_SIZE) read_chunk_size=num;
- line = ps_io_fgetchars(fd,read_chunk_size);
- if (line) *line_lenP += FD_LINE_LEN;
- num -= read_chunk_size;
- }
- SKIP_UNTIL_1("EndBinary")
- }
- }
-
- if (skipped) {
- *line_lenP += nbytes;
- *lineP = skipped_line;
- } else {
- *lineP = FD_BUF+FD_LINE_BEGIN;
- }
-
- return(FD_BUF+FD_LINE_BEGIN);
-}
-
-#define DEFAULT_PAGE_SIZE 1
-
-void
-psgetpagebox (const struct document *doc, int page, int *urx, int *ury, int *llx, int *lly)
-{
- gint new_llx = 0;
- gint new_lly = 0;
- gint new_urx = 0;
- gint new_ury = 0;
- GtkGSPaperSize *papersizes = gtk_gs_defaults_get_paper_sizes ();
- int new_pagesize = -1;
-
- if (new_pagesize == -1) {
- new_pagesize = DEFAULT_PAGE_SIZE;
- if (doc) {
- /* If we have a document:
- * We use -- the page size (if specified)
- * or the doc. size (if specified)
- * or the page bbox (if specified)
- * or the bounding box
- */
- if ((page >= 0) && (doc->numpages > page) &&
- (doc->pages) && (doc->pages[page].size)) {
- new_pagesize = doc->pages[page].size - doc->size;
- } else if (doc->default_page_size != NULL) {
- new_pagesize = doc->default_page_size - doc->size;
- } else if ((page >= 0) &&
- (doc->numpages > page) &&
- (doc->pages) &&
- (doc->pages[page].boundingbox[URX] >
- doc->pages[page].boundingbox[LLX]) &&
- (doc->pages[page].boundingbox[URY] >
- doc->pages[page].boundingbox[LLY])) {
- new_pagesize = -1;
- } else if ((doc->boundingbox[URX] > doc->boundingbox[LLX]) &&
- (doc->boundingbox[URY] > doc->boundingbox[LLY])) {
- new_pagesize = -1;
- }
- }
- }
-
- /* Compute bounding box */
- if (doc && (doc->epsf || new_pagesize == -1)) { /* epsf or bbox */
- if ((page >= 0) &&
- (doc->pages) &&
- (doc->pages[page].boundingbox[URX] >
- doc->pages[page].boundingbox[LLX]) &&
- (doc->pages[page].boundingbox[URY] >
- doc->pages[page].boundingbox[LLY])) {
- /* use page bbox */
- new_llx = doc->pages[page].boundingbox[LLX];
- new_lly = doc->pages[page].boundingbox[LLY];
- new_urx = doc->pages[page].boundingbox[URX];
- new_ury = doc->pages[page].boundingbox[URY];
- } else if ((doc->boundingbox[URX] > doc->boundingbox[LLX]) &&
- (doc->boundingbox[URY] > doc->boundingbox[LLY])) {
- /* use doc bbox */
- new_llx = doc->boundingbox[LLX];
- new_lly = doc->boundingbox[LLY];
- new_urx = doc->boundingbox[URX];
- new_ury = doc->boundingbox[URY];
- }
- } else {
- if (new_pagesize < 0)
- new_pagesize = DEFAULT_PAGE_SIZE;
- new_llx = new_lly = 0;
- if (doc && doc->size &&
- (new_pagesize < doc->numsizes)) {
- new_urx = doc->size[new_pagesize].width;
- new_ury = doc->size[new_pagesize].height;
- } else {
- new_urx = papersizes[new_pagesize].width;
- new_ury = papersizes[new_pagesize].height;
- }
- }
-
- if (new_urx <= new_llx)
- new_urx = papersizes[12].width;
- if (new_ury <= new_lly)
- new_ury = papersizes[12].height;
-
- *urx = new_urx;
- *ury = new_ury;
- *llx = new_llx;
- *lly = new_lly;
-}