summaryrefslogtreecommitdiffstats
path: root/kghostview/dscparse
diff options
context:
space:
mode:
Diffstat (limited to 'kghostview/dscparse')
-rw-r--r--kghostview/dscparse/CMakeLists.txt28
-rw-r--r--kghostview/dscparse/dscparse.cpp3432
-rw-r--r--kghostview/dscparse/dscparse.h473
-rw-r--r--kghostview/dscparse/dscparse_adapter.cpp420
-rw-r--r--kghostview/dscparse/dscparse_adapter.h386
5 files changed, 4739 insertions, 0 deletions
diff --git a/kghostview/dscparse/CMakeLists.txt b/kghostview/dscparse/CMakeLists.txt
new file mode 100644
index 00000000..a8136888
--- /dev/null
+++ b/kghostview/dscparse/CMakeLists.txt
@@ -0,0 +1,28 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ #${CMAKE_CURRENT_SOURCE_DIR}
+ #${CMAKE_BINARY_DIR}
+ #${CMAKE_SOURCE_DIR}
+ #${CMAKE_SOURCE_DIR}
+ #${CMAKE_SOURCE_DIR}
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+)
+
+
+#### dscparse (static) ##########################
+
+tde_add_library( dscparse STATIC_PIC
+ SOURCES dscparse.cpp dscparse_adapter.cpp
+)
diff --git a/kghostview/dscparse/dscparse.cpp b/kghostview/dscparse/dscparse.cpp
new file mode 100644
index 00000000..b5d2c3a7
--- /dev/null
+++ b/kghostview/dscparse/dscparse.cpp
@@ -0,0 +1,3432 @@
+/* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved.
+
+ This file is part of GSview.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
+ to anyone for the consequences of using it or for whether it serves any
+ particular purpose or works at all, unless he says so in writing. Refer
+ to the GNU General Public Licence for full details.
+
+ Everyone is granted permission to copy, modify and redistribute this
+ file, but only under the conditions described in the GNU General
+ Public Licence. A copy of this license is supposed to have been given
+ to you along with this file so you can know your rights and
+ responsibilities. It should be in a file named COPYING. Among other
+ things, the copyright notice and this notice must be preserved on all
+ copies.
+*/
+
+/* $Id$ */
+
+/* dscparse.c - DSC parser */
+
+/*
+ * This is a DSC parser, based on the DSC 3.0 spec,
+ * with a few DSC 2.1 additions for page size.
+ *
+ * Current limitations:
+ * %%+ may be used after any comment in the comment or trailer,
+ * but is currently only supported by
+ * %%DocumentMedia
+ *
+ * DSC 2.1 additions (discontinued in DSC 3.0):
+ * %%DocumentPaperColors:
+ * %%DocumentPaperForms:
+ * %%DocumentPaperSizes:
+ * %%DocumentPaperWeights:
+ * %%PaperColor: (ignored)
+ * %%PaperForm: (ignored)
+ * %%PaperSize:
+ * %%PaperWeight: (ignored)
+ *
+ * Other additions for defaults or page section
+ % %%ViewingOrientation: xx xy yx yy
+*/
+
+#include <stdio.h> /* for sprintf(), not file I/O */
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define MAXSTR 256
+
+#include "dscparse.h"
+
+/* Macros for comparing string literals
+ * For maximum speed, the length of the second macro argument is
+ * computed at compile time.
+ * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL.
+ */
+#define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
+#define IS_DSC(line, str) (COMPARE((line), (str)))
+
+/* Macros for comparing the first one or two characters */
+#define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
+#define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
+#define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
+#define IS_BLANK(str) (IS_EOL(str[0]))
+#define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
+
+/* Macros for document offset to start and end of line */
+#define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
+#define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)
+
+/* dsc_scan_SECTION() functions return one of
+ * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
+ * or one of the following
+ */
+/* The line should be passed on to the next section parser. */
+#define CDSC_PROPAGATE 10
+
+/* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
+#define CDSC_NEEDMORE 11
+
+template<class T>
+inline T min (T a, T b) { return a < b ? a : b; }
+
+/* local prototypes */
+dsc_private void * dsc_memalloc(P2(CDSC *dsc, size_t size));
+dsc_private void dsc_memfree(P2(CDSC*dsc, void *ptr));
+dsc_private CDSC * dsc_init2(P1(CDSC *dsc));
+dsc_private void dsc_reset(P1(CDSC *dsc));
+dsc_private void dsc_section_join(P3(unsigned long begin, unsigned long *pend, unsigned long **pplast));
+dsc_private int dsc_read_line(P1(CDSC *dsc));
+dsc_private int dsc_read_doseps(P1(CDSC *dsc));
+dsc_private char * dsc_alloc_string(P3(CDSC *dsc, const char *str, int len));
+dsc_private char * dsc_add_line(P3(CDSC *dsc, const char *line, unsigned int len));
+dsc_private char * dsc_copy_string(P5(char *str, unsigned int slen,
+ char *line, unsigned int len, unsigned int *offset));
+dsc_private GSDWORD dsc_get_dword(P1(const unsigned char *buf));
+dsc_private GSWORD dsc_get_word(P1(const unsigned char *buf));
+dsc_private int dsc_get_int(P3(const char *line, unsigned int len, unsigned int *offset));
+dsc_private float dsc_get_real(P3(const char *line, unsigned int len,
+ unsigned int *offset));
+dsc_private int dsc_stricmp(P2(const char *s, const char *t));
+dsc_private void dsc_unknown(P1(CDSC *dsc));
+dsc_private GSBOOL dsc_is_section(char *line);
+dsc_private int dsc_parse_pages(P1(CDSC *dsc));
+dsc_private int dsc_parse_bounding_box(P3(CDSC *dsc, CDSCBBOX** pbbox, int offset));
+dsc_private int dsc_parse_float_bounding_box(P3(CDSC *dsc, CDSCFBBOX** pfbbox, int offset));
+dsc_private int dsc_parse_orientation(P3(CDSC *dsc, unsigned int *porientation,
+ int offset));
+dsc_private int dsc_parse_order(P1(CDSC *dsc));
+dsc_private int dsc_parse_media(P2(CDSC *dsc, const CDSCMEDIA **page_media));
+dsc_private int dsc_parse_document_media(P1(CDSC *dsc));
+dsc_private int dsc_parse_viewing_orientation(P2(CDSC *dsc, CDSCCTM **pctm));
+dsc_private int dsc_parse_page(P1(CDSC *dsc));
+dsc_private void dsc_save_line(P1(CDSC *dsc));
+dsc_private int dsc_scan_type(P1(CDSC *dsc));
+dsc_private int dsc_scan_comments(P1(CDSC *dsc));
+dsc_private int dsc_scan_preview(P1(CDSC *dsc));
+dsc_private int dsc_scan_defaults(P1(CDSC *dsc));
+dsc_private int dsc_scan_prolog(P1(CDSC *dsc));
+dsc_private int dsc_scan_setup(P1(CDSC *dsc));
+dsc_private int dsc_scan_page(P1(CDSC *dsc));
+dsc_private int dsc_scan_trailer(P1(CDSC *dsc));
+dsc_private int dsc_error(P4(CDSC *dsc, unsigned int explanation,
+ char *line, unsigned int line_len));
+
+/* DSC error reporting */
+dsc_private const int dsc_severity[] = {
+ CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */
+ CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */
+ CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */
+ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */
+ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */
+ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */
+ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */
+ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */
+ CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */
+ CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */
+ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */
+ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */
+ CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */
+ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */
+ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */
+ CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */
+ 0
+};
+
+#define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
+
+const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = {
+ /* These sizes taken from Ghostscript gs_statd.ps */
+ {"11x17", 792, 1224, 0, NULL, NULL, NULL},
+ {"A0", 2380, 3368, 0, NULL, NULL, NULL},
+ {"A1", 1684, 2380, 0, NULL, NULL, NULL},
+ {"A2", 1190, 1684, 0, NULL, NULL, NULL},
+ {"A3", 842, 1190, 0, NULL, NULL, NULL},
+ {"A4", 595, 842, 0, NULL, NULL, NULL},
+ {"A5", 421, 595, 0, NULL, NULL, NULL},
+ {"A6", 297, 421, 0, NULL, NULL, NULL},
+ {"A7", 210, 297, 0, NULL, NULL, NULL},
+ {"A8", 148, 210, 0, NULL, NULL, NULL},
+ {"A9", 105, 148, 0, NULL, NULL, NULL},
+ {"A10", 74, 105, 0, NULL, NULL, NULL},
+ {"B0", 2836, 4008, 0, NULL, NULL, NULL},
+ {"B1", 2004, 2836, 0, NULL, NULL, NULL},
+ {"B2", 1418, 2004, 0, NULL, NULL, NULL},
+ {"B3", 1002, 1418, 0, NULL, NULL, NULL},
+ {"B4", 709, 1002, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */
+ {"B5", 501, 709, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */
+ {"B6", 354, 501, 0, NULL, NULL, NULL},
+ {"C0", 2600, 3677, 0, NULL, NULL, NULL},
+ {"C1", 1837, 2600, 0, NULL, NULL, NULL},
+ {"C2", 1298, 1837, 0, NULL, NULL, NULL},
+ {"C3", 918, 1298, 0, NULL, NULL, NULL},
+ {"C4", 649, 918, 0, NULL, NULL, NULL},
+ {"C5", 459, 649, 0, NULL, NULL, NULL},
+ {"C6", 323, 459, 0, NULL, NULL, NULL},
+ {"Ledger", 1224, 792, 0, NULL, NULL, NULL},
+ {"Legal", 612, 1008, 0, NULL, NULL, NULL},
+ {"Letter", 612, 792, 0, NULL, NULL, NULL},
+ {"Note", 612, 792, 0, NULL, NULL, NULL},
+// ISO and JIS B sizes are different....
+ {"jisb0", 2916, 4128, 0, NULL, NULL, NULL},
+ {"jisb1", 2064, 2916, 0, NULL, NULL, NULL},
+ {"jisb2", 1458, 2064, 0, NULL, NULL, NULL},
+ {"jisb3", 1032, 1458, 0, NULL, NULL, NULL},
+ {"jisb4", 729, 1032, 0, NULL, NULL, NULL},
+ {"jisb5", 516, 729, 0, NULL, NULL, NULL},
+ {"jisb6", 363, 516, 0, NULL, NULL, NULL},
+// U.S. CAD standard paper sizes
+ {"archE", 2592, 3456, 0, NULL, NULL, NULL},
+ {"archD", 1728, 2592, 0, NULL, NULL, NULL},
+ {"archC", 1296, 1728, 0, NULL, NULL, NULL},
+ {"archB", 864, 1296, 0, NULL, NULL, NULL},
+ {"archA", 648, 864, 0, NULL, NULL, NULL},
+// Other paper sizes
+ {"flsa", 612, 936, 0, NULL, NULL, NULL}, /* U.S. foolscap */
+ {"flse", 612, 936, 0, NULL, NULL, NULL}, /* European foolscap */
+ {"halfletter", 396, 612, 0, NULL, NULL, NULL},
+ {NULL, 0, 0, 0, NULL, NULL, NULL}
+};
+
+/* parser state */
+enum CDSC_SCAN_SECTION {
+ scan_none = 0,
+ scan_comments = 1,
+ scan_pre_preview = 2,
+ scan_preview = 3,
+ scan_pre_defaults = 4,
+ scan_defaults = 5,
+ scan_pre_prolog = 6,
+ scan_prolog = 7,
+ scan_pre_setup = 8,
+ scan_setup = 9,
+ scan_pre_pages = 10,
+ scan_pages = 11,
+ scan_pre_trailer = 12,
+ scan_trailer = 13,
+ scan_eof = 14
+};
+
+static const char * const dsc_scan_section_name[15] = {
+ "Type", "Comments",
+ "pre-Preview", "Preview",
+ "pre-Defaults", "Defaults",
+ "pre-Prolog", "Prolog",
+ "pre-Setup", "Setup",
+ "pre-Page", "Page",
+ "pre-Trailer", "Trailer",
+ "EOF"
+};
+
+/******************************************************************/
+/* Public functions */
+/******************************************************************/
+
+/* constructor */
+CDSC *
+dsc_init(void *caller_data)
+{
+ CDSC *dsc = (CDSC *)malloc(sizeof(CDSC));
+ if (dsc == NULL)
+ return NULL;
+ memset(dsc, 0, sizeof(CDSC));
+ dsc->caller_data = caller_data;
+
+ return dsc_init2(dsc);
+}
+
+/* constructor, with caller supplied memalloc */
+CDSC *
+dsc_init_with_alloc(
+ void *caller_data,
+ void *(*memalloc)(size_t size, void *closure_data),
+ void (*memfree)(void *ptr, void *closure_data),
+ void *closure_data)
+{
+ CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data);
+ if (dsc == NULL)
+ return NULL;
+ memset(dsc, 0, sizeof(CDSC));
+ dsc->caller_data = caller_data;
+
+ dsc->memalloc = memalloc;
+ dsc->memfree = memfree;
+ dsc->mem_closure_data = closure_data;
+
+ return dsc_init2(dsc);
+}
+
+
+
+/* destructor */
+void
+dsc_free(CDSC *dsc)
+{
+ if (dsc == NULL)
+ return;
+ dsc_reset(dsc);
+ dsc_memfree(dsc, dsc);
+}
+
+
+/* Tell DSC parser how long document will be, to allow ignoring
+ * of early %%Trailer and %%EOF. This is optional.
+ */
+void
+dsc_set_length(CDSC *dsc, unsigned long len)
+{
+ dsc->file_length = len;
+}
+
+/* Process a buffer containing DSC comments and PostScript */
+/* Return value is < 0 for error, >=0 for OK.
+ * CDSC_ERROR
+ * CDSC_OK
+ * CDSC_NOTDSC (DSC will be ignored)
+ * other values indicate the last DSC comment read
+ */
+int
+dsc_scan_data(CDSC *dsc, const char *data, int length)
+{
+ int bytes_read;
+ int code = 0;
+
+ if (dsc == NULL)
+ return CDSC_ERROR;
+
+ if (dsc->id == CDSC_NOTDSC)
+ return CDSC_NOTDSC;
+ dsc->id = CDSC_OK;
+ if (dsc->eof)
+ return CDSC_OK; /* ignore */
+
+ if (length == 0) {
+ /* EOF, so process what remains */
+ dsc->eof = TRUE;
+ }
+
+ do {
+ if (dsc->id == CDSC_NOTDSC)
+ break;
+
+ if (length != 0) {
+ /* move existing data if needed */
+ if (dsc->data_length > CDSC_DATA_LENGTH/2) {
+ memmove(dsc->data, dsc->data + dsc->data_index,
+ dsc->data_length - dsc->data_index);
+ dsc->data_offset += dsc->data_index;
+ dsc->data_length -= dsc->data_index;
+ dsc->data_index = 0;
+ }
+ /* append to buffer */
+ bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length));
+ memcpy(dsc->data + dsc->data_length, data, bytes_read);
+ dsc->data_length += bytes_read;
+ data += bytes_read;
+ length -= bytes_read;
+ }
+ if (dsc->scan_section == scan_none) {
+ code = dsc_scan_type(dsc);
+ if (code == CDSC_NEEDMORE) {
+ /* need more characters before we can identify type */
+ code = CDSC_OK;
+ break;
+ }
+ dsc->id = code;
+ }
+
+ if (code == CDSC_NOTDSC) {
+ dsc->id = CDSC_NOTDSC;
+ break;
+ }
+
+ while ((code = dsc_read_line(dsc)) > 0) {
+ if (dsc->id == CDSC_NOTDSC)
+ break;
+ if (dsc->doseps_end &&
+ (dsc->data_offset + dsc->data_index > dsc->doseps_end)) {
+ /* have read past end of DOS EPS PostScript section */
+ return CDSC_OK; /* ignore */
+ }
+ if (dsc->eof)
+ return CDSC_OK;
+ if (dsc->skip_document)
+ continue; /* embedded document */
+ if (dsc->skip_lines)
+ continue; /* embedded lines */
+ if (IS_DSC(dsc->line, "%%BeginData:"))
+ continue;
+ if (IS_DSC(dsc->line, "%%BeginBinary:"))
+ continue;
+ if (IS_DSC(dsc->line, "%%EndDocument"))
+ continue;
+ if (IS_DSC(dsc->line, "%%EndData"))
+ continue;
+ if (IS_DSC(dsc->line, "%%EndBinary"))
+ continue;
+
+ do {
+ switch (dsc->scan_section) {
+ case scan_comments:
+ code = dsc_scan_comments(dsc);
+ break;
+ case scan_pre_preview:
+ case scan_preview:
+ code = dsc_scan_preview(dsc);
+ break;
+ case scan_pre_defaults:
+ case scan_defaults:
+ code = dsc_scan_defaults(dsc);
+ break;
+ case scan_pre_prolog:
+ case scan_prolog:
+ code = dsc_scan_prolog(dsc);
+ break;
+ case scan_pre_setup:
+ case scan_setup:
+ code = dsc_scan_setup(dsc);
+ break;
+ case scan_pre_pages:
+ case scan_pages:
+ code = dsc_scan_page(dsc);
+ break;
+ case scan_pre_trailer:
+ case scan_trailer:
+ code = dsc_scan_trailer(dsc);
+ break;
+ case scan_eof:
+ code = CDSC_OK;
+ break;
+ default:
+ /* invalid state */
+ code = CDSC_ERROR;
+ }
+ /* repeat if line is start of next section */
+ } while (code == CDSC_PROPAGATE);
+
+ /* if DOS EPS header not complete, ask for more */
+ if (code == CDSC_NEEDMORE) {
+ code = CDSC_OK;
+ break;
+ }
+ if (code == CDSC_NOTDSC) {
+ dsc->id = CDSC_NOTDSC;
+ break;
+ }
+ }
+ } while (length != 0);
+
+ return (code < 0) ? code : dsc->id;
+}
+
+/* Tidy up from incorrect DSC comments */
+int
+dsc_fixup(CDSC *dsc)
+{
+ unsigned int i;
+ char buf[32];
+ unsigned long *last;
+
+ if (dsc->id == CDSC_NOTDSC)
+ return 0;
+
+ /* flush last partial line */
+ dsc_scan_data(dsc, NULL, 0);
+
+ /* Fix DSC error: code between %%EndSetup and %%Page */
+ if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup)
+ && (dsc->endsetup != dsc->beginsetup)) {
+ dsc->endsetup = dsc->page[0].begin;
+ dsc_debug_print(dsc, "Warning: code included between setup and first page\n");
+ }
+
+ /* Last page contained a false trailer, */
+ /* so extend last page to start of trailer */
+ if (dsc->page_count && (dsc->begintrailer != 0) &&
+ (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) {
+ dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n");
+ dsc_debug_print(dsc, "and extending last page to start of trailer\n");
+ dsc->page[dsc->page_count-1].end = dsc->begintrailer;
+ }
+
+ /*
+ * Join up all sections.
+ * There might be extra code between them, or we might have
+ * missed including the \n which followed \r.
+ */
+ last = &dsc->endcomments;
+ dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last);
+ dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last);
+ dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last);
+ dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last);
+ for (i=0; i<dsc->page_count; i++)
+ dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last);
+ if (dsc->begintrailer)
+ *last = dsc->begintrailer;
+
+ if ((dsc->page_pages == 0) && (dsc->page_count == 1)) {
+ /* don't flag an error if %%Pages absent but one %%Page found */
+ /* adjust incorrect page count */
+ dsc->page_pages = dsc->page_count;
+ }
+
+ /* Warnings and Errors that we can now identify */
+ if ((dsc->page_count != dsc->page_pages)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* adjust incorrect page count */
+ dsc->page_pages = dsc->page_count;
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ break;;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+
+ if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) {
+ /* EPS files MUST include a BoundingBox */
+ int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* Assume that it is EPS */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* Is NOT an EPS file */
+ dsc->epsf = FALSE;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+
+ if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* Is an EPS file */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* Is NOT an EPS file */
+ dsc->epsf = FALSE;
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+
+ if ((dsc->media_count == 1) && (dsc->page_media == NULL)) {
+ /* if one only media was specified, and default page media */
+ /* was not specified, assume that default is the only media. */
+ dsc->page_media = dsc->media[0];
+ }
+
+ if ((dsc->media_count != 0) && (dsc->page_media == NULL)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* default media is first listed */
+ dsc->page_media = dsc->media[0];
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* No default media */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+
+ /* make sure all pages have a label */
+ for (i=0; i<dsc->page_count; i++) {
+ if (strlen(dsc->page[i].label) == 0) {
+ sprintf(buf, "%d", i+1);
+ if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, strlen(buf)))
+ == (char *)NULL)
+ return CDSC_ERROR; /* no memory */
+ }
+ }
+ return CDSC_OK;
+}
+
+/* Install a function to be used for displaying messages about
+ * DSC errors and warnings, and to request advice from user.
+ * Installing an error function is optional.
+ */
+void
+dsc_set_error_function(CDSC *dsc,
+ int (*fn)(P5(void *caller_data, CDSC *dsc,
+ unsigned int explanation, const char *line, unsigned int line_len)))
+{
+ dsc->dsc_error_fn = fn;
+}
+
+
+/* Install a function for printing debug messages */
+/* This is optional */
+void
+dsc_set_debug_function(CDSC *dsc,
+ void (*debug_fn)(P2(void *caller_data, const char *str)))
+{
+ dsc->debug_print_fn = debug_fn;
+}
+
+/* Doesn't need to be public for PostScript documents */
+/* Made public so GSview can add pages when processing PDF files */
+int
+dsc_add_page(CDSC *dsc, int ordinal, char *label)
+{
+ dsc->page[dsc->page_count].ordinal = ordinal;
+ dsc->page[dsc->page_count].label =
+ dsc_alloc_string(dsc, label, strlen(label)+1);
+ dsc->page[dsc->page_count].begin = 0;
+ dsc->page[dsc->page_count].end = 0;
+ dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN;
+ dsc->page[dsc->page_count].media = NULL;
+ dsc->page[dsc->page_count].bbox = NULL;
+ dsc->page[dsc->page_count].viewing_orientation = NULL;
+
+ dsc->page_count++;
+ if (dsc->page_count >= dsc->page_chunk_length) {
+ CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc,
+ (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE));
+ if (new_page == NULL)
+ return CDSC_ERROR; /* out of memory */
+ memcpy(new_page, dsc->page,
+ dsc->page_count * sizeof(CDSCPAGE));
+ dsc_memfree(dsc, dsc->page);
+ dsc->page= new_page;
+ dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count;
+ }
+ return CDSC_OK;
+}
+
+/* Doesn't need to be public for PostScript documents */
+/* Made public so GSview can store PDF MediaBox */
+int
+dsc_add_media(CDSC *dsc, CDSCMEDIA *media)
+{
+ CDSCMEDIA **newmedia_array;
+ CDSCMEDIA *newmedia;
+
+ /* extend media array */
+ newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc,
+ (dsc->media_count + 1) * sizeof(CDSCMEDIA *));
+ if (newmedia_array == NULL)
+ return CDSC_ERROR; /* out of memory */
+ if (dsc->media != NULL) {
+ memcpy(newmedia_array, dsc->media,
+ dsc->media_count * sizeof(CDSCMEDIA *));
+ dsc_memfree(dsc, dsc->media);
+ }
+ dsc->media = newmedia_array;
+
+ /* allocate new media */
+ newmedia = dsc->media[dsc->media_count] =
+ (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA));
+ if (newmedia == NULL)
+ return CDSC_ERROR; /* out of memory */
+ newmedia->name = NULL;
+ newmedia->width = 595.0;
+ newmedia->height = 842.0;
+ newmedia->weight = 80.0;
+ newmedia->colour = NULL;
+ newmedia->type = NULL;
+ newmedia->mediabox = NULL;
+
+ dsc->media_count++;
+
+ if (media->name) {
+ newmedia->name = dsc_alloc_string(dsc, media->name,
+ strlen(media->name));
+ if (newmedia->name == NULL)
+ return CDSC_ERROR; /* no memory */
+ }
+ newmedia->width = media->width;
+ newmedia->height = media->height;
+ newmedia->weight = media->weight;
+ if (media->colour) {
+ newmedia->colour = dsc_alloc_string(dsc, media->colour,
+ strlen(media->colour));
+ if (newmedia->colour == NULL)
+ return CDSC_ERROR; /* no memory */
+ }
+ if (media->type) {
+ newmedia->type = dsc_alloc_string(dsc, media->type,
+ strlen(media->type));
+ if (newmedia->type == NULL)
+ return CDSC_ERROR; /* no memory */
+ }
+ newmedia->mediabox = NULL;
+
+ if (media->mediabox) {
+ newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
+ if (newmedia->mediabox == NULL)
+ return CDSC_ERROR; /* no memory */
+ *newmedia->mediabox = *media->mediabox;
+ }
+ return CDSC_OK;
+}
+
+/* Doesn't need to be public for PostScript documents */
+/* Made public so GSview can store PDF CropBox */
+int
+dsc_set_page_bbox(CDSC *dsc, unsigned int page_number,
+ int llx, int lly, int urx, int ury)
+{
+ CDSCBBOX *bbox;
+ if (page_number >= dsc->page_count)
+ return CDSC_ERROR;
+ bbox = dsc->page[page_number].bbox;
+ if (bbox == NULL)
+ dsc->page[page_number].bbox = bbox =
+ (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
+ if (bbox == NULL)
+ return CDSC_ERROR;
+ bbox->llx = llx;
+ bbox->lly = lly;
+ bbox->urx = urx;
+ bbox->ury = ury;
+ return CDSC_OK;
+}
+
+
+/******************************************************************/
+/* Private functions below here. */
+/******************************************************************/
+
+dsc_private void *
+dsc_memalloc(CDSC *dsc, size_t size)
+{
+ if (dsc->memalloc)
+ return dsc->memalloc(size, dsc->mem_closure_data);
+ return malloc(size);
+}
+
+dsc_private void
+dsc_memfree(CDSC*dsc, void *ptr)
+{
+ if (dsc->memfree)
+ dsc->memfree(ptr, dsc->mem_closure_data);
+ else
+ free(ptr);
+}
+
+/* private constructor */
+dsc_private CDSC *
+dsc_init2(CDSC *dsc)
+{
+ dsc_reset(dsc);
+
+ dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
+ if (dsc->string_head == NULL) {
+ dsc_free(dsc);
+ return NULL; /* no memory */
+ }
+ dsc->string = dsc->string_head;
+ dsc->string->next = NULL;
+ dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
+ if (dsc->string->data == NULL) {
+ dsc_free(dsc);
+ return NULL; /* no memory */
+ }
+ dsc->string->index = 0;
+ dsc->string->length = CDSC_STRING_CHUNK;
+
+ dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE));
+ if (dsc->page == NULL) {
+ dsc_free(dsc);
+ return NULL; /* no memory */
+ }
+ dsc->page_chunk_length = CDSC_PAGE_CHUNK;
+ dsc->page_count = 0;
+
+ dsc->line = NULL;
+ dsc->data_length = 0;
+ dsc->data_index = dsc->data_length;
+
+ return dsc;
+}
+
+
+dsc_private void
+dsc_reset(CDSC *dsc)
+{
+ unsigned int i;
+ /* Clear public members */
+ dsc->dsc = FALSE;
+ dsc->ctrld = FALSE;
+ dsc->pjl = FALSE;
+ dsc->epsf = FALSE;
+ dsc->pdf = FALSE;
+ dsc->epsf = FALSE;
+ dsc->preview = CDSC_NOPREVIEW;
+ dsc->dsc_version = NULL; /* stored in dsc->string */
+ dsc->language_level = 0;
+ dsc->document_data = CDSC_DATA_UNKNOWN;
+ dsc->begincomments = 0;
+ dsc->endcomments = 0;
+ dsc->beginpreview = 0;
+ dsc->endpreview = 0;
+ dsc->begindefaults = 0;
+ dsc->enddefaults = 0;
+ dsc->beginprolog = 0;
+ dsc->endprolog = 0;
+ dsc->beginsetup = 0;
+ dsc->endsetup = 0;
+ dsc->begintrailer = 0;
+ dsc->endtrailer = 0;
+
+ for (i=0; i<dsc->page_count; i++) {
+ /* page media is pointer to an element of media or dsc_known_media */
+ /* do not free it. */
+
+ if (dsc->page[i].bbox)
+ dsc_memfree(dsc, dsc->page[i].bbox);
+ if (dsc->page[i].viewing_orientation)
+ dsc_memfree(dsc, dsc->page[i].viewing_orientation);
+ }
+ if (dsc->page)
+ dsc_memfree(dsc, dsc->page);
+ dsc->page = NULL;
+
+ dsc->page_count = 0;
+ dsc->page_pages = 0;
+ dsc->page_order = CDSC_ORDER_UNKNOWN;
+ dsc->page_orientation = CDSC_ORIENT_UNKNOWN;
+ if (dsc->viewing_orientation)
+ dsc_memfree(dsc, dsc->viewing_orientation);
+ dsc->viewing_orientation = NULL;
+
+ if (dsc->media) {
+ for (i=0; i<dsc->media_count; i++) {
+ if (dsc->media[i]) {
+ if (dsc->media[i]->mediabox)
+ dsc_memfree(dsc, dsc->media[i]->mediabox);
+ dsc_memfree(dsc, dsc->media[i]);
+ }
+ }
+ dsc_memfree(dsc, dsc->media);
+ }
+ dsc->media_count = 0;
+ dsc->media = NULL;
+
+ /* page_media is pointer to an element of media or dsc_known_media */
+ /* do not free it. */
+ dsc->page_media = NULL;
+
+ if (dsc->bbox)
+ dsc_memfree(dsc, dsc->bbox);
+ dsc->bbox = NULL;
+ if (dsc->page_bbox)
+ dsc_memfree(dsc, dsc->page_bbox);
+ dsc->page_bbox = NULL;
+ if (dsc->doseps)
+ dsc_memfree(dsc, dsc->doseps);
+ dsc->doseps = NULL;
+
+ dsc->dsc_title = NULL;
+ dsc->dsc_creator = NULL;
+ dsc->dsc_date = NULL;
+ dsc->dsc_for = NULL;
+
+
+ dsc->max_error = DSC_MAX_ERROR;
+ dsc->severity = dsc_severity;
+
+ /* Clear private members */
+ /* Don't touch dsc->caller_data */
+ dsc->id = CDSC_OK;
+ dsc->scan_section = scan_none;
+ dsc->doseps_end = 0;
+ dsc->page_chunk_length = 0;
+ dsc->file_length = 0;
+ dsc->skip_document = 0;
+ dsc->skip_bytes = 0;
+ dsc->skip_lines = 0;
+ dsc->skip_pjl = 0;
+ dsc->begin_font_count = 0;
+ dsc->begin_feature_count = 0;
+ dsc->begin_resource_count = 0;
+ dsc->begin_procset_count = 0;
+
+ dsc->data_length = 0;
+ dsc->data_index = 0;
+ dsc->data_offset = 0;
+
+ dsc->eof = 0;
+
+ dsc->line = 0;
+ dsc->line_length = 0;
+ dsc->eol = 0;
+ dsc->last_cr = FALSE;
+ dsc->line_count = 1;
+ dsc->long_line = FALSE;
+ memset(dsc->last_line, 0, sizeof(dsc->last_line));
+
+ dsc->string = dsc->string_head;
+ while (dsc->string != (CDSCSTRING *)NULL) {
+ if (dsc->string->data)
+ dsc_memfree(dsc, dsc->string->data);
+ dsc->string_head = dsc->string;
+ dsc->string = dsc->string->next;
+ dsc_memfree(dsc, dsc->string_head);
+ }
+ dsc->string_head = NULL;
+ dsc->string = NULL;
+
+ /* don't touch caller functions */
+
+ /* public data */
+ if (dsc->hires_bbox)
+ dsc_memfree(dsc, dsc->hires_bbox);
+ dsc->hires_bbox = NULL;
+ if (dsc->crop_box)
+ dsc_memfree(dsc, dsc->crop_box);
+ dsc->crop_box = NULL;
+}
+
+/*
+* Join up all sections.
+* There might be extra code between them, or we might have
+* missed including the \n which followed \r.
+* begin is the start of this section
+* pend is a pointer to the end of this section
+* pplast is a pointer to a pointer of the end of the previous section
+*/
+dsc_private void
+dsc_section_join(unsigned long begin, unsigned long *pend, unsigned long **pplast)
+{
+ if (begin)
+ **pplast = begin;
+ if (*pend > begin)
+ *pplast = pend;
+}
+
+
+/* return value is 0 if no line available, or length of line */
+dsc_private int
+dsc_read_line(CDSC *dsc)
+{
+ char *p, *last;
+ dsc->line = NULL;
+
+ if (dsc->eof) {
+ /* return all that remains, even if line incomplete */
+ dsc->line = dsc->data + dsc->data_index;
+ dsc->line_length = dsc->data_length - dsc->data_index;
+ dsc->data_index = dsc->data_length;
+ return dsc->line_length;
+ }
+
+ /* ignore embedded bytes */
+ if (dsc->skip_bytes) {
+ int cnt = min(dsc->skip_bytes,
+ (int)(dsc->data_length - dsc->data_index));
+ dsc->skip_bytes -= cnt;
+ dsc->data_index += cnt;
+ if (dsc->skip_bytes != 0)
+ return 0;
+ }
+
+ do {
+ dsc->line = dsc->data + dsc->data_index;
+ last = dsc->data + dsc->data_length;
+ if (dsc->data_index == dsc->data_length) {
+ dsc->line_length = 0;
+ return 0;
+ }
+ if (dsc->eol) {
+ /* if previous line was complete, increment line count */
+ dsc->line_count++;
+ if (dsc->skip_lines)
+ dsc->skip_lines--;
+ }
+
+ /* skip over \n which followed \r */
+ if (dsc->last_cr && dsc->line[0] == '\n') {
+ dsc->data_index++;
+ dsc->line++;
+ }
+ dsc->last_cr = FALSE;
+
+ /* look for EOL */
+ dsc->eol = FALSE;
+ for (p = dsc->line; p < last; p++) {
+ if (*p == '\r') {
+ p++;
+ if ((p<last) && (*p == '\n'))
+ p++; /* include line feed also */
+ else
+ dsc->last_cr = TRUE; /* we might need to skip \n */
+ dsc->eol = TRUE; /* dsc->line is a complete line */
+ break;
+ }
+ if (*p == '\n') {
+ p++;
+ dsc->eol = TRUE; /* dsc->line is a complete line */
+ break;
+ }
+ if (*p == '\032') { /* MS-DOS Ctrl+Z */
+ dsc->eol = TRUE;
+ }
+ }
+ if (dsc->eol == FALSE) {
+ /* we haven't got a complete line yet */
+ if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) {
+ /* buffer is less than half full, ask for some more */
+ dsc->line_length = 0;
+ return 0;
+ }
+ }
+ dsc->data_index += dsc->line_length = (p - dsc->line);
+ } while (dsc->skip_lines && dsc->line_length);
+
+ if (dsc->line_length == 0)
+ return 0;
+
+ if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) {
+ /* handle recursive %%BeginDocument */
+ if ((dsc->skip_document) && dsc->line_length &&
+ COMPARE(dsc->line, "%%EndDocument")) {
+ dsc->skip_document--;
+ }
+
+ /* handle embedded lines or binary data */
+ if (COMPARE(dsc->line, "%%BeginData:")) {
+ /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ]
+ * <numberof> ::= <uint> (Lines or physical bytes)
+ * <type> ::= Hex | Binary | ASCII (Type of data)
+ * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines)
+ */
+ char begindata[MAXSTR+1];
+ int cnt;
+ unsigned int num;
+ const char *numberof, *bytesorlines;
+ if ((num = dsc->line_length) >= sizeof(begindata)-1)
+ num = sizeof(begindata)-1;
+
+ memcpy(begindata, dsc->line, num);
+ begindata[num] = '\0';
+ numberof = strtok(begindata+12, " \r\n");
+ strtok(NULL, " \r\n"); /* dump type */
+ bytesorlines = strtok(NULL, " \r\n");
+ if (bytesorlines == NULL)
+ bytesorlines = "Bytes";
+
+ if ( (numberof == NULL) || (bytesorlines == NULL) ) {
+ /* invalid usage of %%BeginData */
+ /* ignore that we ever saw it */
+ int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE,
+ dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return 0;
+ }
+ }
+ else {
+ cnt = atoi(numberof);
+ if (cnt) {
+ if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) {
+ /* skip cnt lines */
+ if (dsc->skip_lines == 0) {
+ /* we are not already skipping lines */
+ dsc->skip_lines = cnt+1;
+ }
+ }
+ else {
+ /* byte count doesn't includes \n or \r\n */
+ /* or \r of %%BeginData: */
+ /* skip cnt bytes */
+ if (dsc->skip_bytes == 0) {
+ /* we are not already skipping lines */
+ dsc->skip_bytes = cnt;
+ }
+
+ }
+ }
+ }
+ }
+ else if (COMPARE(dsc->line, "%%BeginBinary:")) {
+ /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/
+ unsigned long cnt = atoi(dsc->line + 14);
+ if (dsc->skip_bytes == 0) {
+ /* we are not already skipping lines */
+ dsc->skip_bytes = cnt;
+ }
+ }
+ }
+
+ if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
+ COMPARE(dsc->line, "%%BeginDocument:") ) {
+ /* Skip over embedded document, recursively */
+ dsc->skip_document++;
+ }
+
+ if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) {
+ dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length);
+ dsc->long_line = TRUE;
+ }
+
+ return dsc->line_length;
+}
+
+
+/* Save last DSC line, for use with %%+ */
+dsc_private void
+dsc_save_line(CDSC *dsc)
+{
+ int len = min((size_t) sizeof(dsc->last_line), (size_t) dsc->line_length);
+ memcpy(dsc->last_line, dsc->line, len);
+}
+
+/* display unknown DSC line */
+dsc_private void
+dsc_unknown(CDSC *dsc)
+{
+ if (dsc->debug_print_fn) {
+ char line[DSC_LINE_LENGTH];
+ unsigned int length = min((unsigned)DSC_LINE_LENGTH-1, dsc->line_length);
+ sprintf(line, "Unknown in %s section at line %d:\n ",
+ dsc_scan_section_name[dsc->scan_section], dsc->line_count);
+ dsc_debug_print(dsc, line);
+ strncpy(line, dsc->line, length);
+ line[length] = '\0';
+ dsc_debug_print(dsc, line);
+ }
+}
+
+
+dsc_private GSBOOL
+dsc_is_section(char *line)
+{
+ if ( !((line[0]=='%') && (line[1]=='%')) )
+ return FALSE;
+ if (IS_DSC(line, "%%BeginPreview"))
+ return TRUE;
+ if (IS_DSC(line, "%%BeginDefaults"))
+ return TRUE;
+ if (IS_DSC(line, "%%BeginProlog"))
+ return TRUE;
+ if (IS_DSC(line, "%%BeginSetup"))
+ return TRUE;
+ if (IS_DSC(line, "%%Page:"))
+ return TRUE;
+ if (IS_DSC(line, "%%Trailer"))
+ return TRUE;
+ if (IS_DSC(line, "%%EOF"))
+ return TRUE;
+ return FALSE;
+}
+
+
+dsc_private GSDWORD
+dsc_get_dword(const unsigned char *buf)
+{
+ GSDWORD dw;
+ dw = (GSDWORD)buf[0];
+ dw += ((GSDWORD)buf[1])<<8;
+ dw += ((GSDWORD)buf[2])<<16;
+ dw += ((GSDWORD)buf[3])<<24;
+ return dw;
+}
+
+dsc_private GSWORD
+dsc_get_word(const unsigned char *buf)
+{
+ GSWORD w;
+ w = (GSWORD)buf[0];
+ w |= (GSWORD)(buf[1]<<8);
+ return w;
+}
+
+dsc_private int
+dsc_read_doseps(CDSC *dsc)
+{
+ unsigned char *line = (unsigned char *)dsc->line;
+ if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL)
+ return CDSC_ERROR; /* no memory */
+
+ dsc->doseps->ps_begin = dsc_get_dword(line+4);
+ dsc->doseps->ps_length = dsc_get_dword(line+8);
+ dsc->doseps->wmf_begin = dsc_get_dword(line+12);
+ dsc->doseps->wmf_length = dsc_get_dword(line+16);
+ dsc->doseps->tiff_begin = dsc_get_dword(line+20);
+ dsc->doseps->tiff_length = dsc_get_dword(line+24);
+ dsc->doseps->checksum = dsc_get_word(line+28);
+
+ dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length;
+
+ /* move data_index backwards to byte after doseps header */
+ dsc->data_index -= dsc->line_length - 30;
+ /* we haven't read a line of PostScript code yet */
+ dsc->line_count = 0;
+ /* skip from current position to start of PostScript section */
+ dsc->skip_bytes = dsc->doseps->ps_begin - 30;
+
+ if (dsc->doseps->tiff_begin)
+ dsc->preview = CDSC_TIFF;
+ if (dsc->doseps->wmf_begin)
+ dsc->preview = CDSC_WMF;
+
+ return CDSC_OK;
+}
+
+
+
+dsc_private int
+dsc_parse_pages(CDSC *dsc)
+{
+ int ip, io;
+ unsigned int i;
+ char *p;
+ int n;
+ if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK; /* ignore duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ break; /* use duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+
+ n = IS_DSC(dsc->line, "%%+") ? 3 : 8;
+ while (IS_WHITE(dsc->line[n]))
+ n++;
+ p = dsc->line + n;
+ if (COMPARE(p, "atend")) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ else if (COMPARE(p, "(atend)")) {
+ /* do nothing */
+ /* we should mark it as deferred */
+ }
+ else {
+ ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
+ if (i) {
+ n+=i;
+ dsc->page_pages = ip;
+ io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
+ if (i) {
+ /* DSC 2 uses extra integer to indicate page order */
+ /* DSC 3 uses %%PageOrder: */
+ if (dsc->page_order == CDSC_ORDER_UNKNOWN)
+ switch (io) {
+ case -1:
+ dsc->page_order = CDSC_DESCEND;
+ break;
+ case 0:
+ dsc->page_order = CDSC_SPECIAL;
+ break;
+ case 1:
+ dsc->page_order = CDSC_ASCEND;
+ break;
+ }
+ }
+ }
+ else {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ }
+ return CDSC_OK;
+}
+
+dsc_private int
+dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
+{
+ unsigned int i, n;
+ int llx, lly, urx, ury;
+ float fllx, flly, furx, fury;
+ char *p;
+ /* Process first %%BoundingBox: in comments, and last in trailer */
+ if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK; /* ignore duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK; /* ignore duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ break; /* use duplicate comments in trailer */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if (*pbbox != NULL) {
+ dsc_memfree(dsc, *pbbox);
+ *pbbox = NULL;
+ }
+
+ /* should only process first %%BoundingBox: */
+
+ while (IS_WHITE(dsc->line[offset]))
+ offset++;
+ p = dsc->line + offset;
+
+ if (COMPARE(p, "atend")) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ else if (COMPARE(p, "(atend)")) {
+ /* do nothing */
+ /* we should mark it as deferred */
+ }
+ else {
+ /* llx = */ lly = urx = ury = 0;
+ n = offset;
+ llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
+ if (i) {
+ *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
+ if (*pbbox == NULL)
+ return CDSC_ERROR; /* no memory */
+ (*pbbox)->llx = llx;
+ (*pbbox)->lly = lly;
+ (*pbbox)->urx = urx;
+ (*pbbox)->ury = ury;
+ }
+ else {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* fllx = */ flly = furx = fury = 0.0;
+ n = offset;
+ n += i;
+ fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ if (i) {
+ *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
+ if (*pbbox == NULL)
+ return CDSC_ERROR; /* no memory */
+ (*pbbox)->llx = (int)fllx;
+ (*pbbox)->lly = (int)flly;
+ (*pbbox)->urx = (int)(furx+0.999);
+ (*pbbox)->ury = (int)(fury+0.999);
+ }
+ return CDSC_OK;
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ }
+ return CDSC_OK;
+}
+
+dsc_private int
+dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
+{
+ unsigned int i, n;
+ float fllx, flly, furx, fury;
+ char *p;
+ /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
+ * and last in trailer.
+ */
+ if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK; /* ignore duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK; /* ignore duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ break; /* use duplicate comments in trailer */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if (*pbbox != NULL) {
+ dsc_memfree(dsc, *pbbox);
+ *pbbox = NULL;
+ }
+
+ /* should only process first %%BoundingBox: */
+
+ while (IS_WHITE(dsc->line[offset]))
+ offset++;
+ p = dsc->line + offset;
+
+ if (COMPARE(p, "atend")) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ else if (COMPARE(p, "(atend)")) {
+ /* do nothing */
+ /* we should mark it as deferred */
+ }
+ else {
+ /* fllx = */ flly = furx = fury = 0.0;
+ n = offset;
+ fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ if (i) {
+ *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
+ if (*pbbox == NULL)
+ return CDSC_ERROR; /* no memory */
+ (*pbbox)->fllx = fllx;
+ (*pbbox)->flly = flly;
+ (*pbbox)->furx = furx;
+ (*pbbox)->fury = fury;
+ }
+ }
+ return CDSC_OK;
+}
+
+dsc_private int
+dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset)
+{
+ char *p;
+ if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
+ (dsc->scan_section == scan_comments)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK; /* ignore duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
+ (dsc->scan_section == scan_trailer)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ break; /* use duplicate comments in header; */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ p = dsc->line + offset;
+ while (IS_WHITE(*p))
+ p++;
+ if (COMPARE(p, "atend")) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ else if (COMPARE(p, "(atend)")) {
+ /* do nothing */
+ /* we should mark it as deferred */
+ }
+ else if (COMPARE(p, "Portrait")) {
+ *porientation = CDSC_PORTRAIT;
+ }
+ else if (COMPARE(p, "Landscape")) {
+ *porientation = CDSC_LANDSCAPE;
+ }
+ else {
+ dsc_unknown(dsc);
+ }
+ return CDSC_OK;
+}
+
+dsc_private int
+dsc_parse_order(CDSC *dsc)
+{
+ char *p;
+ if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
+ (dsc->scan_section == scan_comments)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ return CDSC_OK; /* ignore duplicate comments in header */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
+ (dsc->scan_section == scan_trailer)) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ case CDSC_RESPONSE_CANCEL:
+ break; /* use duplicate comments in trailer */
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+
+ p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13);
+ while (IS_WHITE(*p))
+ p++;
+ if (COMPARE(p, "atend")) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* assume (atend) */
+ /* we should mark it as deferred */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore it */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ else if (COMPARE(p, "(atend)")) {
+ /* do nothing */
+ /* we should mark it as deferred */
+ }
+ else if (COMPARE(p, "Ascend")) {
+ dsc->page_order = CDSC_ASCEND;
+ }
+ else if (COMPARE(p, "Descend")) {
+ dsc->page_order = CDSC_DESCEND;
+ }
+ else if (COMPARE(p, "Special")) {
+ dsc->page_order = CDSC_SPECIAL;
+ }
+ else {
+ dsc_unknown(dsc);
+ }
+ return CDSC_OK;
+}
+
+
+dsc_private int
+dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media)
+{
+ char media_name[MAXSTR];
+ int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */
+ unsigned int i;
+
+ if (dsc_copy_string(media_name, sizeof(media_name)-1,
+ dsc->line+n, dsc->line_length-n, NULL)) {
+ for (i=0; i<dsc->media_count; i++) {
+ if (dsc->media[i]->name &&
+ (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) {
+ *page_media = dsc->media[i];
+ return CDSC_OK;
+ }
+ }
+ }
+ dsc_unknown(dsc);
+
+ return CDSC_OK;
+}
+
+
+dsc_private int
+dsc_parse_document_media(CDSC *dsc)
+{
+ unsigned int i, n;
+ CDSCMEDIA lmedia;
+ GSBOOL blank_line;
+
+ if (IS_DSC(dsc->line, "%%DocumentMedia:"))
+ n = 16;
+ else if (IS_DSC(dsc->line, "%%+"))
+ n = 3;
+ else
+ return CDSC_ERROR; /* error */
+
+ /* check for blank remainder of line */
+ blank_line = TRUE;
+ for (i=n; i<dsc->line_length; i++) {
+ if (!IS_WHITE_OR_EOL(dsc->line[i])) {
+ blank_line = FALSE;
+ break;
+ }
+ }
+
+ if (!blank_line) {
+ char name[MAXSTR];
+ char colour[MAXSTR];
+ char type[MAXSTR];
+ lmedia.name = lmedia.colour = lmedia.type = (char *)NULL;
+ lmedia.width = lmedia.height = lmedia.weight = 0;
+ lmedia.mediabox = (CDSCBBOX *)NULL;
+ lmedia.name = dsc_copy_string(name, sizeof(name)-1,
+ dsc->line+n, dsc->line_length-n, &i);
+ n+=i;
+ if (i)
+ lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n+=i;
+ if (i)
+ lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n+=i;
+ if (i)
+ lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n+=i;
+ if (i)
+ lmedia.colour = dsc_copy_string(colour, sizeof(colour)-1,
+ dsc->line+n, dsc->line_length-n, &i);
+ n+=i;
+ if (i)
+ lmedia.type = dsc_copy_string(type, sizeof(type)-1,
+ dsc->line+n, dsc->line_length-n, &i);
+
+ if (i==0)
+ dsc_unknown(dsc); /* we didn't get all fields */
+ else {
+ if (dsc_add_media(dsc, &lmedia))
+ return CDSC_ERROR; /* out of memory */
+ }
+ }
+ return CDSC_OK;
+}
+
+/* viewing orientation is believed to be the first four elements of
+ * a CTM matrix
+ */
+dsc_private int
+dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm)
+{
+ CDSCCTM ctm;
+ unsigned int i, n;
+
+ if (*pctm != NULL) {
+ dsc_memfree(dsc, *pctm);
+ *pctm = NULL;
+ }
+
+ n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */
+ while (IS_WHITE(dsc->line[n]))
+ n++;
+
+ /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0;
+ ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ n += i;
+ if (i)
+ ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ if (i==0) {
+ dsc_unknown(dsc); /* we didn't get all fields */
+ }
+ else {
+ *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM));
+ if (*pctm == NULL)
+ return CDSC_ERROR; /* no memory */
+ **pctm = ctm;
+ }
+ return CDSC_OK;
+}
+
+
+/* This is called before dsc_read_line(), since we may
+ * need to skip a binary header which contains a new line
+ * character
+ */
+dsc_private int
+dsc_scan_type(CDSC *dsc)
+{
+ unsigned char *p;
+ unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index);
+ int length = dsc->data_length - dsc->data_index;
+
+ /* Types that should be known:
+ * DSC
+ * EPSF
+ * PJL + any of above
+ * ^D + any of above
+ * DOS EPS
+ * PDF
+ * non-DSC
+ */
+
+ /* First process any non PostScript headers */
+ /* At this stage we do not have a complete line */
+
+ if (length == 0)
+ return CDSC_NEEDMORE;
+
+ if (dsc->skip_pjl) {
+ /* skip until first PostScript comment */
+ while (length >= 2) {
+ while (length && !IS_EOL(line[0])) {
+ /* skip until EOL character */
+ line++;
+ dsc->data_index++;
+ length--;
+ }
+ while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) {
+ /* skip until EOL followed by non-EOL */
+ line++;
+ dsc->data_index++;
+ length--;
+ }
+ if (length < 2)
+ return CDSC_NEEDMORE;
+
+ if (IS_EOL(line[0]) && line[1]=='%') {
+ line++;
+ dsc->data_index++;
+ length--;
+ dsc->skip_pjl = FALSE;
+ break;
+ }
+ else {
+ /* line++; */
+ dsc->data_index++;
+ /* length--; */
+ return CDSC_NEEDMORE;
+ }
+ }
+ if (dsc->skip_pjl)
+ return CDSC_NEEDMORE;
+ }
+
+ if (length == 0)
+ return CDSC_NEEDMORE;
+
+ if (line[0] == '\004') {
+ line++;
+ dsc->data_index++;
+ length--;
+ dsc->ctrld = TRUE;
+ }
+
+ if (line[0] == '\033') {
+ /* possibly PJL */
+ if (length < 9)
+ return CDSC_NEEDMORE;
+ if (COMPARE(line, "\033%-12345X")) {
+ dsc->skip_pjl = TRUE; /* skip until first PostScript comment */
+ dsc->pjl = TRUE;
+ dsc->data_index += 9;
+ return dsc_scan_type(dsc);
+ }
+ }
+
+ if ((line[0]==0xc5) && (length < 4))
+ return CDSC_NEEDMORE;
+ if ((line[0]==0xc5) && (line[1]==0xd0) &&
+ (line[2]==0xd3) && (line[3]==0xc6) ) {
+ /* id is "EPSF" with bit 7 set */
+ /* read DOS EPS header, then ignore all bytes until the PS section */
+ if (length < 30)
+ return CDSC_NEEDMORE;
+ dsc->line = (char *)line;
+ if (dsc_read_doseps(dsc))
+ return CDSC_ERROR;
+ }
+ else {
+ if (length < 2)
+ return CDSC_NEEDMORE;
+ if ((line[0] == '%') && (line[1] == 'P')) {
+ if (length < 5)
+ return CDSC_NEEDMORE;
+ if (COMPARE(line, "%PDF-")) {
+ dsc->pdf = TRUE;
+ dsc->scan_section = scan_comments;
+ return CDSC_OK;
+ }
+ }
+ }
+
+ /* Finally process PostScript headers */
+
+ if (dsc_read_line(dsc) <= 0)
+ return CDSC_NEEDMORE;
+
+ dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
+ if (COMPARE(dsc->line, "%!PS-Adobe")) {
+ dsc->dsc = TRUE;
+ dsc->begincomments = DSC_START(dsc);
+ if (dsc->dsc_version == NULL)
+ return CDSC_ERROR; /* no memory */
+ p = (unsigned char *)dsc->line + 14;
+ while (IS_WHITE(*p))
+ p++;
+ if (COMPARE(p, "EPSF-"))
+ dsc->epsf = TRUE;
+ dsc->scan_section = scan_comments;
+ return CDSC_PSADOBE;
+ }
+ if (COMPARE(dsc->line, "%!")) {
+ dsc->scan_section = scan_comments;
+ return CDSC_NOTDSC;
+ }
+
+ dsc->scan_section = scan_comments;
+ return CDSC_NOTDSC; /* unrecognised */
+}
+
+
+
+dsc_private int
+dsc_scan_comments(CDSC *dsc)
+{
+ /* Comments section ends at */
+ /* %%EndComments */
+ /* another section */
+ /* line that does not start with %% */
+ /* Save a few important lines */
+
+ char *line = dsc->line;
+ GSBOOL continued = FALSE;
+ dsc->id = CDSC_OK;
+ if (IS_DSC(line, "%%EndComments")) {
+ dsc->id = CDSC_ENDCOMMENTS;
+ dsc->endcomments = DSC_END(dsc);
+ dsc->scan_section = scan_pre_preview;
+ return CDSC_OK;
+ }
+ else if (IS_DSC(line, "%%BeginComments")) {
+ /* ignore because we are in this section */
+ dsc->id = CDSC_BEGINCOMMENTS;
+ }
+ else if (dsc_is_section(line)) {
+ dsc->endcomments = DSC_START(dsc);
+ dsc->scan_section = scan_pre_preview;
+ return CDSC_PROPAGATE;
+ }
+ else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) {
+ dsc->endcomments = DSC_START(dsc);
+ dsc->scan_section = scan_pre_preview;
+ return CDSC_PROPAGATE;
+ }
+ else if (line[0] != '%') {
+ dsc->id = CDSC_OK;
+ dsc->endcomments = DSC_START(dsc);
+ dsc->scan_section = scan_pre_preview;
+ return CDSC_PROPAGATE;
+ }
+ else if (IS_DSC(line, "%%Begin")) {
+ dsc->endcomments = DSC_START(dsc);
+ dsc->scan_section = scan_pre_preview;
+ return CDSC_PROPAGATE;
+ }
+
+ /* Handle continuation lines.
+ * To simply processing, we assume that contination lines
+ * will only occur if repeat parameters are allowed and that
+ * a complete set of these parameters appears on each line.
+ * This is more restrictive than the DSC specification, but
+ * is valid for the DSC comments understood by this parser
+ * for all documents that we have seen.
+ */
+ if (IS_DSC(line, "%%+")) {
+ line = dsc->last_line;
+ continued = TRUE;
+ }
+ else
+ dsc_save_line(dsc);
+
+ if (IS_DSC(line, "%%Pages:")) {
+ dsc->id = CDSC_PAGES;
+ if (dsc_parse_pages(dsc) != 0)
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%Creator:")) {
+ dsc->id = CDSC_CREATOR;
+ dsc->dsc_creator = dsc_add_line(dsc, dsc->line+10, dsc->line_length-10);
+ if (dsc->dsc_creator==NULL)
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%CreationDate:")) {
+ dsc->id = CDSC_CREATIONDATE;
+ dsc->dsc_date = dsc_add_line(dsc, dsc->line+15, dsc->line_length-15);
+ if (dsc->dsc_date==NULL)
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%Title:")) {
+ dsc->id = CDSC_TITLE;
+ dsc->dsc_title = dsc_add_line(dsc, dsc->line+8, dsc->line_length-8);
+ if (dsc->dsc_title==NULL)
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%For:")) {
+ dsc->id = CDSC_FOR;
+ dsc->dsc_for = dsc_add_line(dsc, dsc->line+6, dsc->line_length-6);
+ if (dsc->dsc_for==NULL)
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%LanguageLevel:")) {
+ unsigned int n = continued ? 3 : 16;
+ unsigned int i;
+ int ll;
+ dsc->id = CDSC_LANGUAGELEVEL;
+ ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
+ if (i) {
+ if ( (ll==1) || (ll==2) || (ll==3) )
+ dsc->language_level = ll;
+ else {
+ dsc_unknown(dsc);
+ }
+ }
+ else
+ dsc_unknown(dsc);
+ }
+ else if (IS_DSC(line, "%%BoundingBox:")) {
+ dsc->id = CDSC_BOUNDINGBOX;
+ if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%HiResBoundingBox:")) {
+ dsc->id = CDSC_HIRESBOUNDINGBOX;
+ if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
+ continued ? 3 : 19))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%CropBox:")) {
+ dsc->id = CDSC_CROPBOX;
+ if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
+ continued ? 3 : 10))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%Orientation:")) {
+ dsc->id = CDSC_ORIENTATION;
+ if (dsc_parse_orientation(dsc, &(dsc->page_orientation),
+ continued ? 3 : 14))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%PageOrder:")) {
+ dsc->id = CDSC_PAGEORDER;
+ if (dsc_parse_order(dsc))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%DocumentMedia:")) {
+ dsc->id = CDSC_DOCUMENTMEDIA;
+ if (dsc_parse_document_media(dsc))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%DocumentPaperSizes:")) {
+ /* DSC 2.1 */
+ unsigned int n = continued ? 3 : 21;
+ unsigned int count = 0;
+ unsigned int i = 1;
+ char name[MAXSTR];
+ char *p;
+ dsc->id = CDSC_DOCUMENTPAPERSIZES;
+ while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
+ p = dsc_copy_string(name, sizeof(name)-1,
+ dsc->line+n, dsc->line_length-n, &i);
+ if (i && p) {
+ const CDSCMEDIA *m = dsc_known_media;
+ if (count >= dsc->media_count) {
+ /* set some default values */
+ CDSCMEDIA lmedia;
+ lmedia.name = p;
+ lmedia.width = 595.0;
+ lmedia.height = 842.0;
+ lmedia.weight = 80.0;
+ lmedia.colour = NULL;
+ lmedia.type = NULL;
+ lmedia.mediabox = NULL;
+ if (dsc_add_media(dsc, &lmedia))
+ return CDSC_ERROR;
+ }
+ else
+ dsc->media[count]->name =
+ dsc_alloc_string(dsc, p, strlen(p));
+ /* find in list of known media */
+ while (m && m->name) {
+ if (dsc_stricmp(p, m->name)==0) {
+ dsc->media[count]->width = m->width;
+ dsc->media[count]->height = m->height;
+ break;
+ }
+ m++;
+ }
+ }
+ n+=i;
+ count++;
+ }
+ }
+ else if (IS_DSC(line, "%%DocumentPaperForms:")) {
+ /* DSC 2.1 */
+ unsigned int n = continued ? 3 : 21;
+ unsigned int count = 0;
+ unsigned int i = 1;
+ char type[MAXSTR];
+ char *p;
+ dsc->id = CDSC_DOCUMENTPAPERFORMS;
+ while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
+ p = dsc_copy_string(type, sizeof(type)-1,
+ dsc->line+n, dsc->line_length-n, &i);
+ if (i && p) {
+ if (count >= dsc->media_count) {
+ /* set some default values */
+ CDSCMEDIA lmedia;
+ lmedia.name = NULL;
+ lmedia.width = 595.0;
+ lmedia.height = 842.0;
+ lmedia.weight = 80.0;
+ lmedia.colour = NULL;
+ lmedia.type = p;
+ lmedia.mediabox = NULL;
+ if (dsc_add_media(dsc, &lmedia))
+ return CDSC_ERROR;
+ }
+ else
+ dsc->media[count]->type =
+ dsc_alloc_string(dsc, p, strlen(p));
+ }
+ n+=i;
+ count++;
+ }
+ }
+ else if (IS_DSC(line, "%%DocumentPaperColors:")) {
+ /* DSC 2.1 */
+ unsigned int n = continued ? 3 : 22;
+ unsigned int count = 0;
+ unsigned int i = 1;
+ char colour[MAXSTR];
+ char *p;
+ dsc->id = CDSC_DOCUMENTPAPERCOLORS;
+ while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
+ p = dsc_copy_string(colour, sizeof(colour)-1,
+ dsc->line+n, dsc->line_length-n, &i);
+ if (i && p) {
+ if (count >= dsc->media_count) {
+ /* set some default values */
+ CDSCMEDIA lmedia;
+ lmedia.name = NULL;
+ lmedia.width = 595.0;
+ lmedia.height = 842.0;
+ lmedia.weight = 80.0;
+ lmedia.colour = p;
+ lmedia.type = NULL;
+ lmedia.mediabox = NULL;
+ if (dsc_add_media(dsc, &lmedia))
+ return CDSC_ERROR;
+ }
+ else
+ dsc->media[count]->colour =
+ dsc_alloc_string(dsc, p, strlen(p));
+ }
+ n+=i;
+ count++;
+ }
+ }
+ else if (IS_DSC(line, "%%DocumentPaperWeights:")) {
+ /* DSC 2.1 */
+ unsigned int n = continued ? 3 : 23;
+ unsigned int count = 0;
+ unsigned int i = 1;
+ float w;
+ dsc->id = CDSC_DOCUMENTPAPERWEIGHTS;
+ while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
+ w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
+ if (i) {
+ if (count >= dsc->media_count) {
+ /* set some default values */
+ CDSCMEDIA lmedia;
+ lmedia.name = NULL;
+ lmedia.width = 595.0;
+ lmedia.height = 842.0;
+ lmedia.weight = w;
+ lmedia.colour = NULL;
+ lmedia.type = NULL;
+ lmedia.mediabox = NULL;
+ if (dsc_add_media(dsc, &lmedia))
+ return CDSC_ERROR;
+ }
+ else
+ dsc->media[count]->weight = w;
+ }
+ n+=i;
+ count++;
+ }
+ }
+ else if (IS_DSC(line, "%%DocumentData:")) {
+ unsigned int n = continued ? 3 : 15;
+ char *p = dsc->line + n;
+ while (IS_WHITE(*p))
+ p++;
+ dsc->id = CDSC_DOCUMENTDATA;
+ if (COMPARE(p, "Clean7Bit"))
+ dsc->document_data = CDSC_CLEAN7BIT;
+ else if (COMPARE(p, "Clean8Bit"))
+ dsc->document_data = CDSC_CLEAN8BIT;
+ else if (COMPARE(p, "Binary"))
+ dsc->document_data = CDSC_BINARY;
+ else
+ dsc_unknown(dsc);
+ }
+ else if (IS_DSC(line, "%%Requirements:")) {
+ dsc->id = CDSC_REQUIREMENTS;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
+ dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
+ dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
+ /* ignore */
+ }
+ else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) {
+ dsc->id = CDSC_OK;
+ /* ignore */
+ }
+ else {
+ dsc->id = CDSC_UNKNOWNDSC;
+ dsc_unknown(dsc);
+ }
+
+ dsc->endcomments = DSC_END(dsc);
+ return CDSC_OK;
+}
+
+
+dsc_private int
+dsc_scan_preview(CDSC *dsc)
+{
+ /* Preview section ends at */
+ /* %%EndPreview */
+ /* another section */
+ /* Preview section must start with %%BeginPreview */
+ char *line = dsc->line;
+ dsc->id = CDSC_OK;
+
+ if (dsc->scan_section == scan_pre_preview) {
+ if (IS_BLANK(line))
+ return CDSC_OK; /* ignore blank lines before preview */
+ else if (IS_DSC(line, "%%BeginPreview")) {
+ dsc->id = CDSC_BEGINPREVIEW;
+ dsc->beginpreview = DSC_START(dsc);
+ dsc->endpreview = DSC_END(dsc);
+ dsc->scan_section = scan_preview;
+ /* Don't mark the preview as EPSI if a DOS EPS header is present */
+ if (dsc->preview == CDSC_NOPREVIEW)
+ dsc->preview = CDSC_EPSI;
+ return CDSC_OK;
+ }
+ else {
+ dsc->scan_section = scan_pre_defaults;
+ return CDSC_PROPAGATE;
+ }
+ }
+
+ if (IS_DSC(line, "%%BeginPreview")) {
+ /* ignore because we are in this section */
+ }
+ else if (dsc_is_section(line)) {
+ dsc->endpreview = DSC_START(dsc);
+ dsc->scan_section = scan_pre_defaults;
+ return CDSC_PROPAGATE;
+ }
+ else if (IS_DSC(line, "%%EndPreview")) {
+ dsc->id = CDSC_ENDPREVIEW;
+ dsc->endpreview = DSC_END(dsc);
+ dsc->scan_section = scan_pre_defaults;
+ return CDSC_OK;
+ }
+ else if (line[0] == '%' && line[1] != '%') {
+ /* Ordinary comments are OK */
+ }
+ else {
+ dsc->id = CDSC_UNKNOWNDSC;
+ /* DSC comments should not occur in preview */
+ dsc_unknown(dsc);
+ }
+
+ dsc->endpreview = DSC_END(dsc);
+ return CDSC_OK;
+}
+
+dsc_private int
+dsc_scan_defaults(CDSC *dsc)
+{
+ /* Defaults section ends at */
+ /* %%EndDefaults */
+ /* another section */
+ /* Defaults section must start with %%BeginDefaults */
+ char *line = dsc->line;
+ dsc->id = CDSC_OK;
+
+ if (dsc->scan_section == scan_pre_defaults) {
+ if (IS_BLANK(line))
+ return CDSC_OK; /* ignore blank lines before defaults */
+ else if (IS_DSC(line, "%%BeginDefaults")) {
+ dsc->id = CDSC_BEGINDEFAULTS;
+ dsc->begindefaults = DSC_START(dsc);
+ dsc->enddefaults = DSC_END(dsc);
+ dsc->scan_section = scan_defaults;
+ return CDSC_OK;
+ }
+ else {
+ dsc->scan_section = scan_pre_prolog;
+ return CDSC_PROPAGATE;
+ }
+ }
+
+ if (NOT_DSC_LINE(line)) {
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%BeginPreview")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginDefaults")) {
+ /* ignore because we are in this section */
+ }
+ else if (dsc_is_section(line)) {
+ dsc->enddefaults = DSC_START(dsc);
+ dsc->scan_section = scan_pre_prolog;
+ return CDSC_PROPAGATE;
+ }
+ else if (IS_DSC(line, "%%EndDefaults")) {
+ dsc->id = CDSC_ENDDEFAULTS;
+ dsc->enddefaults = DSC_END(dsc);
+ dsc->scan_section = scan_pre_prolog;
+ return CDSC_OK;
+ }
+ else if (IS_DSC(line, "%%PageMedia:")) {
+ dsc->id = CDSC_PAGEMEDIA;
+ dsc_parse_media(dsc, &dsc->page_media);
+ }
+ else if (IS_DSC(line, "%%PageOrientation:")) {
+ dsc->id = CDSC_PAGEORIENTATION;
+ /* This can override %%Orientation: */
+ if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%PageBoundingBox:")) {
+ dsc->id = CDSC_PAGEBOUNDINGBOX;
+ if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%ViewingOrientation:")) {
+ dsc->id = CDSC_VIEWINGORIENTATION;
+ if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation))
+ return CDSC_ERROR;
+ }
+ else {
+ dsc->id = CDSC_UNKNOWNDSC;
+ /* All other DSC comments are unknown, but not an error */
+ dsc_unknown(dsc);
+ }
+ dsc->enddefaults = DSC_END(dsc);
+ return CDSC_OK;
+}
+
+/* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the
+ * mismatch (default) */
+dsc_private int
+dsc_check_match_prompt(CDSC *dsc, const char *str, int count)
+{
+ if (count != 0) {
+ char buf[MAXSTR+MAXSTR] = "";
+ if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1)) {
+ strncpy(buf, dsc->line, dsc->line_length);
+ buf[dsc->line_length] = '\0';
+ }
+ sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
+ return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, strlen(buf));
+ }
+ return CDSC_RESPONSE_CANCEL;
+}
+
+dsc_private int
+dsc_check_match_type(CDSC *dsc, const char *str, int count)
+{
+ if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL)
+ return CDSC_NOTDSC;
+ return CDSC_OK;
+}
+
+/* complain if Begin/End blocks didn't match */
+/* return non-zero if we should ignore all DSC */
+dsc_private int
+dsc_check_match(CDSC *dsc)
+{
+ int rc = 0;
+ const char *font = "Font";
+ const char *feature = "Feature";
+ const char *resource = "Resource";
+ const char *procset = "ProcSet";
+
+ if (!rc)
+ rc = dsc_check_match_type(dsc, font, dsc->begin_font_count);
+ if (!rc)
+ rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count);
+ if (!rc)
+ rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count);
+ if (!rc)
+ rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count);
+
+ dsc->begin_font_count = 0;
+ dsc->begin_feature_count = 0;
+ dsc->begin_resource_count = 0;
+ dsc->begin_procset_count = 0;
+ return rc;
+}
+
+
+dsc_private int
+dsc_scan_prolog(CDSC *dsc)
+{
+ /* Prolog section ends at */
+ /* %%EndProlog */
+ /* another section */
+ /* Prolog section may start with %%BeginProlog or non-dsc line */
+ char *line = dsc->line;
+ dsc->id = CDSC_OK;
+
+ if (dsc->scan_section == scan_pre_prolog) {
+ if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) {
+ dsc->scan_section = scan_pre_setup;
+ return CDSC_PROPAGATE;
+ }
+ dsc->id = CDSC_BEGINPROLOG;
+ dsc->beginprolog = DSC_START(dsc);
+ dsc->endprolog = DSC_END(dsc);
+ dsc->scan_section = scan_prolog;
+ if (IS_DSC(line, "%%BeginProlog"))
+ return CDSC_OK;
+ }
+
+ if (NOT_DSC_LINE(line)) {
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%BeginPreview")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginDefaults")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginProlog")) {
+ /* ignore because we are in this section */
+ }
+ else if (dsc_is_section(line)) {
+ dsc->endprolog = DSC_START(dsc);
+ dsc->scan_section = scan_pre_setup;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_PROPAGATE;
+ }
+ else if (IS_DSC(line, "%%EndProlog")) {
+ dsc->id = CDSC_ENDPROLOG;
+ dsc->endprolog = DSC_END(dsc);
+ dsc->scan_section = scan_pre_setup;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_OK;
+ }
+ else if (IS_DSC(line, "%%BeginFont:")) {
+ dsc->id = CDSC_BEGINFONT;
+ /* ignore Begin/EndFont, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_font_count++;
+ }
+ else if (IS_DSC(line, "%%EndFont")) {
+ dsc->id = CDSC_ENDFONT;
+ dsc->begin_font_count--;
+ }
+ else if (IS_DSC(line, "%%BeginFeature:")) {
+ dsc->id = CDSC_BEGINFEATURE;
+ /* ignore Begin/EndFeature, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_feature_count++;
+ }
+ else if (IS_DSC(line, "%%EndFeature")) {
+ dsc->id = CDSC_ENDFEATURE;
+ dsc->begin_feature_count--;
+ }
+ else if (IS_DSC(line, "%%BeginResource:")) {
+ dsc->id = CDSC_BEGINRESOURCE;
+ /* ignore Begin/EndResource, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_resource_count++;
+ }
+ else if (IS_DSC(line, "%%EndResource")) {
+ dsc->id = CDSC_ENDRESOURCE;
+ dsc->begin_resource_count--;
+ }
+ else if (IS_DSC(line, "%%BeginProcSet:")) {
+ dsc->id = CDSC_BEGINPROCSET;
+ /* ignore Begin/EndProcSet, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_procset_count++;
+ }
+ else if (IS_DSC(line, "%%EndProcSet")) {
+ dsc->id = CDSC_ENDPROCSET;
+ dsc->begin_procset_count--;
+ }
+ else {
+ /* All other DSC comments are unknown, but not an error */
+ dsc->id = CDSC_UNKNOWNDSC;
+ dsc_unknown(dsc);
+ }
+
+ dsc->endprolog = DSC_END(dsc);
+ return CDSC_OK;
+}
+
+dsc_private int
+dsc_scan_setup(CDSC *dsc)
+{
+ /* Setup section ends at */
+ /* %%EndSetup */
+ /* another section */
+ /* Setup section must start with %%BeginSetup */
+
+ char *line = dsc->line;
+ dsc->id = CDSC_OK;
+
+ if (dsc->scan_section == scan_pre_setup) {
+ if (IS_BLANK(line))
+ return CDSC_OK; /* ignore blank lines before setup */
+ else if (IS_DSC(line, "%%BeginSetup")) {
+ dsc->id = CDSC_BEGINSETUP;
+ dsc->beginsetup = DSC_START(dsc);
+ dsc->endsetup = DSC_END(dsc);
+ dsc->scan_section = scan_setup;
+ return CDSC_OK;
+ }
+ else {
+ dsc->scan_section = scan_pre_pages;
+ return CDSC_PROPAGATE;
+ }
+ }
+
+ if (NOT_DSC_LINE(line)) {
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%BeginPreview")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginDefaults")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginProlog")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginSetup")) {
+ /* ignore because we are in this section */
+ }
+ else if (dsc_is_section(line)) {
+ dsc->endsetup = DSC_START(dsc);
+ dsc->scan_section = scan_pre_pages;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_PROPAGATE;
+ }
+ else if (IS_DSC(line, "%%EndSetup")) {
+ dsc->id = CDSC_ENDSETUP;
+ dsc->endsetup = DSC_END(dsc);
+ dsc->scan_section = scan_pre_pages;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_OK;
+ }
+ else if (IS_DSC(line, "%%BeginFeature:")) {
+ dsc->id = CDSC_BEGINFEATURE;
+ /* ignore Begin/EndFeature, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_feature_count++;
+ }
+ else if (IS_DSC(line, "%%EndFeature")) {
+ dsc->id = CDSC_ENDFEATURE;
+ dsc->begin_feature_count--;
+ }
+ else if (IS_DSC(line, "%%Feature:")) {
+ dsc->id = CDSC_FEATURE;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%BeginResource:")) {
+ dsc->id = CDSC_BEGINRESOURCE;
+ /* ignore Begin/EndResource, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_resource_count++;
+ }
+ else if (IS_DSC(line, "%%EndResource")) {
+ dsc->id = CDSC_ENDRESOURCE;
+ dsc->begin_resource_count--;
+ }
+ else if (IS_DSC(line, "%%PaperColor:")) {
+ dsc->id = CDSC_PAPERCOLOR;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%PaperForm:")) {
+ dsc->id = CDSC_PAPERFORM;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%PaperWeight:")) {
+ dsc->id = CDSC_PAPERWEIGHT;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%PaperSize:")) {
+ /* DSC 2.1 */
+ GSBOOL found_media = FALSE;
+ int i;
+ int n = 12;
+ char buf[MAXSTR];
+ buf[0] = '\0';
+ dsc->id = CDSC_PAPERSIZE;
+ dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n,
+ NULL);
+ for (i=0; i<(int)dsc->media_count; i++) {
+ if (dsc->media[i] && dsc->media[i]->name &&
+ (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
+ dsc->page_media = dsc->media[i];
+ found_media = TRUE;
+ break;
+ }
+ }
+ if (!found_media) {
+ /* It didn't match %%DocumentPaperSizes: */
+ /* Try our known media */
+ const CDSCMEDIA *m = dsc_known_media;
+ while (m->name) {
+ if (dsc_stricmp(buf, m->name)==0) {
+ dsc->page_media = m;
+ break;
+ }
+ m++;
+ }
+ if (m->name == NULL)
+ dsc_unknown(dsc);
+ }
+ }
+ else {
+ /* All other DSC comments are unknown, but not an error */
+ dsc->id = CDSC_UNKNOWNDSC;
+ dsc_unknown(dsc);
+ }
+
+ dsc->endsetup = DSC_END(dsc);
+ return CDSC_OK;
+}
+
+dsc_private int
+dsc_scan_page(CDSC *dsc)
+{
+ /* Page section ends at */
+ /* %%Page */
+ /* %%Trailer */
+ /* %%EOF */
+ char *line = dsc->line;
+ dsc->id = CDSC_OK;
+
+ if (dsc->scan_section == scan_pre_pages) {
+ if (IS_DSC(line, "%%Page:")) {
+ dsc->scan_section = scan_pages;
+ /* fall through */
+ }
+ else {
+ /* %%Page: didn't follow %%EndSetup
+ * Keep reading until reach %%Page or %%Trailer
+ * and add it to previous section.
+ */
+ unsigned long *last;
+ if (dsc->endsetup != 0)
+ last = &dsc->endsetup;
+ else if (dsc->endprolog != 0)
+ last = &dsc->endprolog;
+ else if (dsc->enddefaults != 0)
+ last = &dsc->enddefaults;
+ else if (dsc->endpreview != 0)
+ last = &dsc->endpreview;
+ else if (dsc->endcomments != 0)
+ last = &dsc->endcomments;
+ else
+ last = &dsc->begincomments;
+ *last = DSC_START(dsc);
+ if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) {
+ dsc->scan_section = scan_pre_trailer;
+ return CDSC_PROPAGATE;
+ }
+ return CDSC_OK;
+ }
+ }
+
+ if (NOT_DSC_LINE(line)) {
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%Page:")) {
+ dsc->id = CDSC_PAGE;
+ if (dsc->page_count) {
+ dsc->page[dsc->page_count-1].end = DSC_START(dsc);
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ }
+
+ if (dsc_parse_page(dsc) != 0)
+ return CDSC_ERROR;
+
+ return CDSC_OK;
+ }
+ else if (IS_DSC(line, "%%BeginPreview")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginDefaults")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginProlog")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (IS_DSC(line, "%%BeginSetup")) {
+ /* ignore because we have already processed this section */
+ }
+ else if (dsc_is_section(line)) {
+ if (IS_DSC(line, "%%Trailer")) {
+ dsc->page[dsc->page_count-1].end = DSC_START(dsc);
+ if (dsc->file_length) {
+ if ((!dsc->doseps &&
+ ((DSC_END(dsc) + 32768) < dsc->file_length)) ||
+ ((dsc->doseps) &&
+ ((DSC_END(dsc) + 32768) < dsc->doseps_end))) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER,
+ dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* ignore early trailer */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* this is the trailer */
+ dsc->scan_section = scan_pre_trailer;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_PROPAGATE;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ else {
+ dsc->scan_section = scan_pre_trailer;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_PROPAGATE;
+ }
+ }
+ else {
+ dsc->scan_section = scan_pre_trailer;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_PROPAGATE;
+ }
+ }
+ else if (IS_DSC(line, "%%EOF")) {
+ dsc->page[dsc->page_count-1].end = DSC_START(dsc);
+ if (dsc->file_length) {
+ if ((DSC_END(dsc)+100 < dsc->file_length) ||
+ (dsc->doseps && (DSC_END(dsc) + 100 < dsc->doseps_end))) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF,
+ dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* %%EOF is wrong, ignore it */
+ break;
+ case CDSC_RESPONSE_CANCEL:
+ /* %%EOF is correct */
+ dsc->scan_section = scan_eof;
+ dsc->eof = TRUE;
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_PROPAGATE;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ }
+ else {
+ /* ignore it */
+ if (dsc_check_match(dsc))
+ return CDSC_NOTDSC;
+ return CDSC_OK;
+ }
+ }
+ else {
+ /* Section comment, probably from a badly */
+ /* encapsulated EPS file. */
+ int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION,
+ dsc->line, dsc->line_length);
+ if (rc == CDSC_RESPONSE_IGNORE_ALL)
+ return CDSC_NOTDSC;
+ }
+ }
+ else if (IS_DSC(line, "%%PageTrailer")) {
+ dsc->id = CDSC_PAGETRAILER;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%BeginPageSetup")) {
+ dsc->id = CDSC_BEGINPAGESETUP;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%EndPageSetup")) {
+ dsc->id = CDSC_ENDPAGESETUP;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%PageMedia:")) {
+ dsc->id = CDSC_PAGEMEDIA;
+ dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media));
+ }
+ else if (IS_DSC(line, "%%PaperColor:")) {
+ dsc->id = CDSC_PAPERCOLOR;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%PaperForm:")) {
+ dsc->id = CDSC_PAPERFORM;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%PaperWeight:")) {
+ dsc->id = CDSC_PAPERWEIGHT;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%PaperSize:")) {
+ /* DSC 2.1 */
+ GSBOOL found_media = FALSE;
+ int i;
+ int n = 12;
+ char buf[MAXSTR];
+ buf[0] = '\0';
+ dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n,
+ dsc->line_length-n, NULL);
+ for (i=0; i<(int)dsc->media_count; i++) {
+ if (dsc->media[i] && dsc->media[i]->name &&
+ (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
+ dsc->page_media = dsc->media[i];
+ found_media = TRUE;
+ break;
+ }
+ }
+ if (!found_media) {
+ /* It didn't match %%DocumentPaperSizes: */
+ /* Try our known media */
+ const CDSCMEDIA *m = dsc_known_media;
+ while (m->name) {
+ if (dsc_stricmp(buf, m->name)==0) {
+ dsc->page[dsc->page_count-1].media = m;
+ break;
+ }
+ m++;
+ }
+ if (m->name == NULL)
+ dsc_unknown(dsc);
+ }
+ }
+ else if (IS_DSC(line, "%%PageOrientation:")) {
+ dsc->id = CDSC_PAGEORIENTATION;
+ if (dsc_parse_orientation(dsc,
+ &(dsc->page[dsc->page_count-1].orientation) ,18))
+ return CDSC_NOTDSC;
+ }
+ else if (IS_DSC(line, "%%PageBoundingBox:")) {
+ dsc->id = CDSC_PAGEBOUNDINGBOX;
+ if (dsc_parse_bounding_box(dsc, &dsc->page[dsc->page_count-1].bbox, 18))
+ return CDSC_NOTDSC;
+ }
+ else if (IS_DSC(line, "%%ViewingOrientation:")) {
+ dsc->id = CDSC_VIEWINGORIENTATION;
+ if (dsc_parse_viewing_orientation(dsc,
+ &dsc->page[dsc->page_count-1].viewing_orientation))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%BeginFont:")) {
+ dsc->id = CDSC_BEGINFONT;
+ /* ignore Begin/EndFont, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_font_count++;
+ }
+ else if (IS_DSC(line, "%%EndFont")) {
+ dsc->id = CDSC_BEGINFONT;
+ dsc->begin_font_count--;
+ }
+ else if (IS_DSC(line, "%%BeginFeature:")) {
+ dsc->id = CDSC_BEGINFEATURE;
+ /* ignore Begin/EndFeature, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_feature_count++;
+ }
+ else if (IS_DSC(line, "%%EndFeature")) {
+ dsc->id = CDSC_ENDFEATURE;
+ dsc->begin_feature_count--;
+ }
+ else if (IS_DSC(line, "%%BeginResource:")) {
+ dsc->id = CDSC_BEGINRESOURCE;
+ /* ignore Begin/EndResource, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_resource_count++;
+ }
+ else if (IS_DSC(line, "%%EndResource")) {
+ dsc->id = CDSC_ENDRESOURCE;
+ dsc->begin_resource_count--;
+ }
+ else if (IS_DSC(line, "%%BeginProcSet:")) {
+ dsc->id = CDSC_BEGINPROCSET;
+ /* ignore Begin/EndProcSet, apart form making sure */
+ /* that they are matched. */
+ dsc->begin_procset_count++;
+ }
+ else if (IS_DSC(line, "%%EndProcSet")) {
+ dsc->id = CDSC_ENDPROCSET;
+ dsc->begin_procset_count--;
+ }
+ else if (IS_DSC(line, "%%IncludeFont:")) {
+ dsc->id = CDSC_INCLUDEFONT;
+ /* ignore */
+ }
+ else {
+ /* All other DSC comments are unknown, but not an error */
+ dsc->id = CDSC_UNKNOWNDSC;
+ dsc_unknown(dsc);
+ }
+
+ dsc->page[dsc->page_count-1].end = DSC_END(dsc);
+ return CDSC_OK;
+}
+
+/* Valid Trailer comments are
+ * %%Trailer
+ * %%EOF
+ * or the following deferred with (atend)
+ * %%BoundingBox:
+ * %%DocumentCustomColors:
+ * %%DocumentFiles:
+ * %%DocumentFonts:
+ * %%DocumentNeededFiles:
+ * %%DocumentNeededFonts:
+ * %%DocumentNeededProcSets:
+ * %%DocumentNeededResources:
+ * %%DocumentProcSets:
+ * %%DocumentProcessColors:
+ * %%DocumentSuppliedFiles:
+ * %%DocumentSuppliedFonts:
+ * %%DocumentSuppliedProcSets:
+ * %%DocumentSuppliedResources:
+ * %%Orientation:
+ * %%Pages:
+ * %%PageOrder:
+ *
+ * Our supported subset is
+ * %%Trailer
+ * %%EOF
+ * %%BoundingBox:
+ * %%Orientation:
+ * %%Pages:
+ * %%PageOrder:
+ * In addition to these, we support
+ * %%DocumentMedia:
+ *
+ * A %%PageTrailer can have the following:
+ * %%PageBoundingBox:
+ * %%PageCustomColors:
+ * %%PageFiles:
+ * %%PageFonts:
+ * %%PageOrientation:
+ * %%PageProcessColors:
+ * %%PageResources:
+ */
+
+dsc_private int
+dsc_scan_trailer(CDSC *dsc)
+{
+ /* Trailer section start at */
+ /* %%Trailer */
+ /* and ends at */
+ /* %%EOF */
+ char *line = dsc->line;
+ GSBOOL continued = FALSE;
+ dsc->id = CDSC_OK;
+
+ if (dsc->scan_section == scan_pre_trailer) {
+ if (IS_DSC(line, "%%Trailer")) {
+ dsc->id = CDSC_TRAILER;
+ dsc->begintrailer = DSC_START(dsc);
+ dsc->endtrailer = DSC_END(dsc);
+ dsc->scan_section = scan_trailer;
+ return CDSC_OK;
+ }
+ else if (IS_DSC(line, "%%EOF")) {
+ dsc->id = CDSC_EOF;
+ dsc->begintrailer = DSC_START(dsc);
+ dsc->endtrailer = DSC_END(dsc);
+ dsc->scan_section = scan_trailer;
+ /* Continue, in case we found %%EOF in an embedded document */
+ return CDSC_OK;
+ }
+ else {
+ /* %%Page: didn't follow %%EndSetup
+ * Keep reading until reach %%Page or %%Trailer
+ * and add it to setup section
+ */
+ /* append to previous section */
+ if (dsc->beginsetup)
+ dsc->endsetup = DSC_END(dsc);
+ else if (dsc->beginprolog)
+ dsc->endprolog = DSC_END(dsc);
+ else {
+ /* horribly confused */
+ }
+ return CDSC_OK;
+ }
+ }
+
+ /* Handle continuation lines.
+ * See comment above about our restrictive processing of
+ * continuation lines
+ */
+ if (IS_DSC(line, "%%+")) {
+ line = dsc->last_line;
+ continued = TRUE;
+ }
+ else
+ dsc_save_line(dsc);
+
+ if (NOT_DSC_LINE(line)) {
+ /* ignore */
+ }
+ else if (IS_DSC(dsc->line, "%%EOF")) {
+ /* Keep scanning, in case we have a false trailer */
+ dsc->id = CDSC_EOF;
+ }
+ else if (IS_DSC(dsc->line, "%%Trailer")) {
+ /* Cope with no pages with code after setup and before trailer. */
+ /* Last trailer is the correct one. */
+ dsc->id = CDSC_TRAILER;
+ dsc->begintrailer = DSC_START(dsc);
+ }
+ else if (IS_DSC(line, "%%Pages:")) {
+ dsc->id = CDSC_PAGES;
+ if (dsc_parse_pages(dsc) != 0)
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%BoundingBox:")) {
+ dsc->id = CDSC_BOUNDINGBOX;
+ if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%HiResBoundingBox:")) {
+ dsc->id = CDSC_HIRESBOUNDINGBOX;
+ if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
+ continued ? 3 : 19))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%CropBox:")) {
+ dsc->id = CDSC_CROPBOX;
+ if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
+ continued ? 3 : 10))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%Orientation:")) {
+ dsc->id = CDSC_ORIENTATION;
+ if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%PageOrder:")) {
+ dsc->id = CDSC_PAGEORDER;
+ if (dsc_parse_order(dsc))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(line, "%%DocumentMedia:")) {
+ dsc->id = CDSC_DOCUMENTMEDIA;
+ if (dsc_parse_document_media(dsc))
+ return CDSC_ERROR;
+ }
+ else if (IS_DSC(dsc->line, "%%Page:")) {
+ /* This should not occur in the trailer, but we might see
+ * this if a document has been incorrectly embedded.
+ */
+ int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER,
+ dsc->line, dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* Assume that we are really in the previous */
+ /* page, not the trailer */
+ dsc->scan_section = scan_pre_pages;
+ if (dsc->page_count)
+ dsc->page[dsc->page_count-1].end = DSC_START(dsc);
+ return CDSC_PROPAGATE; /* try again */
+ case CDSC_RESPONSE_CANCEL:
+ /* ignore pages in trailer */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+ else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
+ dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
+ /* ignore */
+ }
+ else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
+ dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
+ /* ignore */
+ }
+ else {
+ /* All other DSC comments are unknown, but not an error */
+ dsc->id = CDSC_UNKNOWNDSC;
+ dsc_unknown(dsc);
+ }
+
+ dsc->endtrailer = DSC_END(dsc);
+ return CDSC_OK;
+}
+
+
+dsc_private char *
+dsc_alloc_string(CDSC *dsc, const char *str, int len)
+{
+ char *p;
+ if (dsc->string_head == NULL) {
+ dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
+ if (dsc->string_head == NULL)
+ return NULL; /* no memory */
+ dsc->string = dsc->string_head;
+ dsc->string->next = NULL;
+ dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
+ if (dsc->string->data == NULL) {
+ dsc_reset(dsc);
+ return NULL; /* no memory */
+ }
+ dsc->string->index = 0;
+ dsc->string->length = CDSC_STRING_CHUNK;
+ }
+ if ( dsc->string->index + len + 1 > dsc->string->length) {
+ /* allocate another string block */
+ CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
+ if (newstring == NULL) {
+ dsc_debug_print(dsc, "Out of memory\n");
+ return NULL;
+ }
+ newstring->next = NULL;
+ newstring->length = 0;
+ newstring->index = 0;
+ newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
+ if (newstring->data == NULL) {
+ dsc_memfree(dsc, newstring);
+ dsc_debug_print(dsc, "Out of memory\n");
+ return NULL; /* no memory */
+ }
+ newstring->length = CDSC_STRING_CHUNK;
+ dsc->string->next = newstring;
+ dsc->string = newstring;
+ }
+ if ( dsc->string->index + len + 1 > dsc->string->length)
+ return NULL; /* failed */
+ p = dsc->string->data + dsc->string->index;
+ memcpy(p, str, len);
+ *(p+len) = '\0';
+ dsc->string->index += len + 1;
+ return p;
+}
+
+/* store line, ignoring leading spaces */
+dsc_private char *
+dsc_add_line(CDSC *dsc, const char *line, unsigned int len)
+{
+ char *newline;
+ unsigned int i;
+ while (len && (IS_WHITE(*line))) {
+ len--;
+ line++;
+ }
+ newline = dsc_alloc_string(dsc, line, len);
+ if (newline == NULL)
+ return NULL;
+
+ for (i=0; i<len; i++) {
+ if (newline[i] == '\r') {
+ newline[i]='\0';
+ break;
+ }
+ if (newline[i] == '\n') {
+ newline[i]='\0';
+ break;
+ }
+ }
+ return newline;
+}
+
+
+/* Copy string on line to new allocated string str */
+/* String is always null terminated */
+/* String is no longer than len */
+/* Return pointer to string */
+/* Store number of used characters from line */
+/* Don't copy enclosing () */
+dsc_private char *
+dsc_copy_string(char *str, unsigned int slen, char *line,
+ unsigned int len, unsigned int *offset)
+{
+ int quoted = FALSE;
+ int instring=0;
+ unsigned int newlength = 0;
+ unsigned int i = 0;
+ unsigned char ch;
+ if (len > slen)
+ len = slen-1;
+ while ( (i<len) && IS_WHITE(line[i]))
+ i++; /* skip leading spaces */
+ if (line[i]=='(') {
+ quoted = TRUE;
+ instring++;
+ i++; /* don't copy outside () */
+ }
+ while (i < len) {
+ str[newlength] = ch = line[i];
+ i++;
+ if (quoted) {
+ if (ch == '(')
+ instring++;
+ if (ch == ')')
+ instring--;
+ if (instring==0)
+ break;
+ }
+ else if (ch == ' ')
+ break;
+
+ if (ch == '\r')
+ break;
+ if (ch == '\n')
+ break;
+ else if ( (ch == '\\') && (i+1 < len) ) {
+ ch = line[i];
+ if ((ch >= '0') && (ch <= '9')) {
+ /* octal coded character */
+ int j = 3;
+ ch = 0;
+ while (j && (i < len) && line[i]>='0' && line[i]<='7') {
+ ch = (unsigned char)((ch<<3) + (line[i]-'0'));
+ i++;
+ j--;
+ }
+ str[newlength] = ch;
+ }
+ else if (ch == '(') {
+ str[newlength] = ch;
+ i++;
+ }
+ else if (ch == ')') {
+ str[newlength] = ch;
+ i++;
+ }
+ else if (ch == 'b') {
+ str[newlength] = '\b';
+ i++;
+ }
+ else if (ch == 'f') {
+ str[newlength] = '\b';
+ i++;
+ }
+ else if (ch == 'n') {
+ str[newlength] = '\n';
+ i++;
+ }
+ else if (ch == 'r') {
+ str[newlength] = '\r';
+ i++;
+ }
+ else if (ch == 't') {
+ str[newlength] = '\t';
+ i++;
+ }
+ else if (ch == '\\') {
+ str[newlength] = '\\';
+ i++;
+ }
+ }
+ newlength++;
+ }
+ str[newlength] = '\0';
+ if (offset != (unsigned int *)NULL)
+ *offset = i;
+ return str;
+}
+
+dsc_private int
+dsc_get_int(const char *line, unsigned int len, unsigned int *offset)
+{
+ char newline[MAXSTR];
+ int newlength = 0;
+ unsigned int i = 0;
+ unsigned char ch;
+
+ len = min((size_t) len, (size_t) sizeof(newline)-1);
+ while ((i<len) && IS_WHITE(line[i]))
+ i++; /* skip leading spaces */
+ while (i < len) {
+ newline[newlength] = ch = line[i];
+ if (!(isdigit(ch) || (ch=='-') || (ch=='+')))
+ break; /* not part of an integer number */
+ i++;
+ newlength++;
+ }
+ while ((i<len) && IS_WHITE(line[i]))
+ i++; /* skip trailing spaces */
+ newline[newlength] = '\0';
+ if (offset != (unsigned int *)NULL)
+ *offset = i;
+ return atoi(newline);
+}
+
+dsc_private float
+dsc_get_real(const char *line, unsigned int len, unsigned int *offset)
+{
+ char newline[MAXSTR];
+ int newlength = 0;
+ unsigned int i = 0;
+ unsigned char ch;
+
+ len = min((size_t) len, (size_t) sizeof(newline)-1);
+ while ((i<len) && IS_WHITE(line[i]))
+ i++; /* skip leading spaces */
+ while (i < len) {
+ newline[newlength] = ch = line[i];
+ if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+')
+ || (ch=='e') || (ch=='E')))
+ break; /* not part of a real number */
+ i++;
+ newlength++;
+ }
+ while ((i<len) && IS_WHITE(line[i]))
+ i++; /* skip trailing spaces */
+
+ newline[newlength] = '\0';
+
+ if (offset != (unsigned int *)NULL)
+ *offset = i;
+ return (float)atof(newline);
+}
+
+dsc_private int
+dsc_stricmp(const char *s, const char *t)
+{
+ while (toupper(*s) == toupper(*t)) {
+ if (*s == '\0')
+ return 0;
+ s++;
+ t++;
+ }
+ return (toupper(*s) - toupper(*t));
+}
+
+
+dsc_private int
+dsc_parse_page(CDSC *dsc)
+{
+ char *p;
+ unsigned int i;
+ char page_label[MAXSTR];
+ char *pl;
+ int page_ordinal;
+ int page_number;
+
+ p = dsc->line + 7;
+ pl = dsc_copy_string(page_label, sizeof(page_label)-1, p, dsc->line_length-7, &i);
+ if (pl == NULL)
+ return CDSC_ERROR;
+ p += i;
+ page_ordinal = atoi(p);
+
+ if ( (page_ordinal == 0) || (strlen(page_label) == 0) ||
+ (dsc->page_count &&
+ (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) {
+ int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line,
+ dsc->line_length);
+ switch (rc) {
+ case CDSC_RESPONSE_OK:
+ /* ignore this page */
+ return CDSC_OK;
+ case CDSC_RESPONSE_CANCEL:
+ /* accept the page */
+ break;
+ case CDSC_RESPONSE_IGNORE_ALL:
+ return CDSC_NOTDSC;
+ }
+ }
+
+ page_number = dsc->page_count;
+ dsc_add_page(dsc, page_ordinal, page_label);
+ dsc->page[page_number].begin = DSC_START(dsc);
+ dsc->page[page_number].end = DSC_START(dsc);
+
+ if (dsc->page[page_number].label == NULL)
+ return CDSC_ERROR; /* no memory */
+
+ return CDSC_OK;
+}
+
+
+
+/* DSC error reporting */
+
+void
+dsc_debug_print(CDSC *dsc, const char *str)
+{
+ if (dsc->debug_print_fn)
+ dsc->debug_print_fn(dsc->caller_data, str);
+}
+
+
+/* Display a message about a problem with the DSC comments.
+ *
+ * explanation = an index to to a multiline explanation in dsc_message[]
+ * line = pointer to the offending DSC line (if any)
+ * return code =
+ * CDSC_RESPONSE_OK DSC was wrong, make a guess about what
+ * was really meant.
+ * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it
+ * is misplaced.
+ * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC.
+ */
+/* Silent operation. Don't display errors. */
+dsc_private int
+dsc_error(CDSC *dsc, unsigned int explanation,
+ char *line, unsigned int line_len)
+{
+ /* if error function provided, use it */
+ if (dsc->dsc_error_fn)
+ return dsc->dsc_error_fn(dsc->caller_data, dsc,
+ explanation, line, line_len);
+
+ /* treat DSC as being correct */
+ return CDSC_RESPONSE_CANCEL;
+}
+
+
+// vim:sw=4:sts=4:ts=8:noet
diff --git a/kghostview/dscparse/dscparse.h b/kghostview/dscparse/dscparse.h
new file mode 100644
index 00000000..10d2746c
--- /dev/null
+++ b/kghostview/dscparse/dscparse.h
@@ -0,0 +1,473 @@
+/* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved.
+
+ This file is part of GSview.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
+ to anyone for the consequences of using it or for whether it serves any
+ particular purpose or works at all, unless he says so in writing. Refer
+ to the GNU General Public Licence for full details.
+
+ Everyone is granted permission to copy, modify and redistribute this
+ file, but only under the conditions described in the GNU General
+ Public Licence. A copy of this license is supposed to have been given
+ to you along with this file so you can know your rights and
+ responsibilities. It should be in a file named COPYING. Among other
+ things, the copyright notice and this notice must be preserved on all
+ copies.
+*/
+
+/* $Id$ */
+
+/* dscparse.h */
+/* Interface for the DSC parser. */
+
+#ifndef _DSCPARSE_H_
+#define _DSCPARSE_H_
+
+/* Some local types that may need modification */
+typedef bool GSBOOL;
+typedef unsigned long GSDWORD; /* must be at least 32 bits */
+typedef unsigned int GSWORD; /* must be at least 16 bits */
+
+#ifndef FALSE
+# define FALSE ((GSBOOL)0)
+# define TRUE ((GSBOOL)(!FALSE))
+#endif
+
+#ifndef dsc_private
+# ifdef private
+# define dsc_private private
+# else
+# define dsc_private static
+# endif
+#endif
+
+/* macros to allow conversion of function declarations to K&R */
+#ifndef P0
+#define P0() void
+#define P1(t1) t1
+#define P2(t1,t2) t1,t2
+#define P3(t1,t2,t3) t1,t2,t3
+#define P4(t1,t2,t3,t4) t1,t2,t3,t4
+#define P5(t1,t2,t3,t4,t5) t1,t2,t3,t4,t5
+#define P6(t1,t2,t3,t4,t5,t6) t1,t2,t3,t4,t5,t6
+#endif
+
+/* maximum legal length of lines in a DSC compliant file */
+#define DSC_LINE_LENGTH 255
+
+/* memory for strings is allocated in chunks of this length */
+#define CDSC_STRING_CHUNK 4096
+
+/* page array is allocated in chunks of this many pages */
+#define CDSC_PAGE_CHUNK 128
+
+/* buffer length for storing lines passed to dsc_scan_data() */
+/* must be at least 2 * DSC_LINE_LENGTH */
+/* We choose 8192 as twice the length passed to us by GSview */
+#define CDSC_DATA_LENGTH 8192
+
+/* Return codes from dsc_scan_data()
+ * < 0 = error
+ * >=0 = OK
+ *
+ * -1 = error, usually insufficient memory.
+ * 0-9 = normal
+ * 10-99 = internal codes, should not be seen.
+ * 100-999 = identifier of last DSC comment processed.
+ */
+
+typedef enum {
+ CDSC_ERROR = -1, /* Fatal error, usually insufficient memory */
+
+ CDSC_OK = 0, /* OK, no DSC comment found */
+ CDSC_NOTDSC = 1, /* Not DSC, or DSC is being ignored */
+
+/* Any section */
+ CDSC_UNKNOWNDSC = 100, /* DSC comment not recognised */
+
+/* Header section */
+ CDSC_PSADOBE = 200, /* %!PS-Adobe- */
+ CDSC_BEGINCOMMENTS = 201, /* %%BeginComments */
+ CDSC_ENDCOMMENTS = 202, /* %%EndComments */
+ CDSC_PAGES = 203, /* %%Pages: */
+ CDSC_CREATOR = 204, /* %%Creator: */
+ CDSC_CREATIONDATE = 205, /* %%CreationDate: */
+ CDSC_TITLE = 206, /* %%Title: */
+ CDSC_FOR = 207, /* %%For: */
+ CDSC_LANGUAGELEVEL = 208, /* %%LanguageLevel: */
+ CDSC_BOUNDINGBOX = 209, /* %%BoundingBox: */
+ CDSC_ORIENTATION = 210, /* %%Orientation: */
+ CDSC_PAGEORDER = 211, /* %%PageOrder: */
+ CDSC_DOCUMENTMEDIA = 212, /* %%DocumentMedia: */
+ CDSC_DOCUMENTPAPERSIZES = 213, /* %%DocumentPaperSizes: */
+ CDSC_DOCUMENTPAPERFORMS = 214, /* %%DocumentPaperForms: */
+ CDSC_DOCUMENTPAPERCOLORS = 215, /* %%DocumentPaperColors: */
+ CDSC_DOCUMENTPAPERWEIGHTS = 216, /* %%DocumentPaperWeights: */
+ CDSC_DOCUMENTDATA = 217, /* %%DocumentData: */
+ CDSC_REQUIREMENTS = 218, /* IGNORED %%Requirements: */
+ CDSC_DOCUMENTNEEDEDFONTS = 219, /* IGNORED %%DocumentNeededFonts: */
+ CDSC_DOCUMENTSUPPLIEDFONTS = 220, /* IGNORED %%DocumentSuppliedFonts: */
+ CDSC_HIRESBOUNDINGBOX = 221, /* %%HiResBoundingBox: */
+ CDSC_CROPBOX = 222, /* %%CropBox: */
+
+/* Preview section */
+ CDSC_BEGINPREVIEW = 301, /* %%BeginPreview */
+ CDSC_ENDPREVIEW = 302, /* %%EndPreview */
+
+/* Defaults section */
+ CDSC_BEGINDEFAULTS = 401, /* %%BeginDefaults */
+ CDSC_ENDDEFAULTS = 402, /* %%EndDefaults */
+/* also %%PageMedia, %%PageOrientation, %%PageBoundingBox */
+
+/* Prolog section */
+ CDSC_BEGINPROLOG = 501, /* %%BeginProlog */
+ CDSC_ENDPROLOG = 502, /* %%EndProlog */
+ CDSC_BEGINFONT = 503, /* IGNORED %%BeginFont */
+ CDSC_ENDFONT = 504, /* IGNORED %%EndFont */
+ CDSC_BEGINFEATURE = 505, /* IGNORED %%BeginFeature */
+ CDSC_ENDFEATURE = 506, /* IGNORED %%EndFeature */
+ CDSC_BEGINRESOURCE = 507, /* IGNORED %%BeginResource */
+ CDSC_ENDRESOURCE = 508, /* IGNORED %%EndResource */
+ CDSC_BEGINPROCSET = 509, /* IGNORED %%BeginProcSet */
+ CDSC_ENDPROCSET = 510, /* IGNORED %%EndProcSet */
+
+/* Setup section */
+ CDSC_BEGINSETUP = 601, /* %%BeginSetup */
+ CDSC_ENDSETUP = 602, /* %%EndSetup */
+ CDSC_FEATURE = 603, /* IGNORED %%Feature: */
+ CDSC_PAPERCOLOR = 604, /* IGNORED %%PaperColor: */
+ CDSC_PAPERFORM = 605, /* IGNORED %%PaperForm: */
+ CDSC_PAPERWEIGHT = 606, /* IGNORED %%PaperWeight: */
+ CDSC_PAPERSIZE = 607, /* %%PaperSize: */
+/* also %%Begin/EndFeature, %%Begin/EndResource */
+
+/* Page section */
+ CDSC_PAGE = 700, /* %%Page: */
+ CDSC_PAGETRAILER = 701, /* IGNORED %%PageTrailer */
+ CDSC_BEGINPAGESETUP = 702, /* IGNORED %%BeginPageSetup */
+ CDSC_ENDPAGESETUP = 703, /* IGNORED %%EndPageSetup */
+ CDSC_PAGEMEDIA = 704, /* %%PageMedia: */
+/* also %%PaperColor, %%PaperForm, %%PaperWeight, %%PaperSize */
+ CDSC_PAGEORIENTATION = 705, /* %%PageOrientation: */
+ CDSC_PAGEBOUNDINGBOX = 706, /* %%PageBoundingBox: */
+/* also %%Begin/EndFont, %%Begin/EndFeature */
+/* also %%Begin/EndResource, %%Begin/EndProcSet */
+ CDSC_INCLUDEFONT = 707, /* IGNORED %%IncludeFont: */
+ CDSC_VIEWINGORIENTATION = 708, /* %%ViewingOrientation: */
+
+/* Trailer section */
+ CDSC_TRAILER = 800, /* %%Trailer */
+/* also %%Pages, %%BoundingBox, %%Orientation, %%PageOrder, %%DocumentMedia */
+/* %%Page is recognised as an error */
+/* also %%DocumentNeededFonts, %%DocumentSuppliedFonts */
+
+/* End of File */
+ CDSC_EOF = 900 /* %%EOF */
+} CDSC_RETURN_CODE;
+
+
+/* stored in dsc->preview */
+typedef enum {
+ CDSC_NOPREVIEW = 0,
+ CDSC_EPSI = 1,
+ CDSC_TIFF = 2,
+ CDSC_WMF = 3,
+ CDSC_PICT = 4
+} CDSC_PREVIEW_TYPE;
+
+/* stored in dsc->page_order */
+typedef enum {
+ CDSC_ORDER_UNKNOWN = 0,
+ CDSC_ASCEND = 1,
+ CDSC_DESCEND = 2,
+ CDSC_SPECIAL = 3
+} CDSC_PAGE_ORDER;
+
+/* stored in dsc->page_orientation and dsc->page[pagenum-1].orientation */
+typedef enum {
+ CDSC_ORIENT_UNKNOWN = 0,
+ CDSC_PORTRAIT = 1,
+ CDSC_LANDSCAPE = 2,
+ CDSC_UPSIDEDOWN = 3,
+ CDSC_SEASCAPE = 4
+} CDSC_ORIENTATION_ENUM;
+
+/* stored in dsc->document_data */
+typedef enum {
+ CDSC_DATA_UNKNOWN = 0,
+ CDSC_CLEAN7BIT = 1,
+ CDSC_CLEAN8BIT = 2,
+ CDSC_BINARY = 3
+} CDSC_DOCUMENT_DATA ;
+
+typedef struct CDSCBBOX_S {
+ int llx;
+ int lly;
+ int urx;
+ int ury;
+} CDSCBBOX;
+
+typedef struct CDSCFBBOX_S {
+ float fllx;
+ float flly;
+ float furx;
+ float fury;
+} CDSCFBBOX;
+
+typedef struct CDSCMEDIA_S {
+ const char *name;
+ float width; /* PostScript points */
+ float height;
+ float weight; /* GSM */
+ const char *colour;
+ const char *type;
+ CDSCBBOX *mediabox; /* Used by GSview for PDF MediaBox */
+} CDSCMEDIA;
+
+#define CDSC_KNOWN_MEDIA 46
+extern const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA];
+
+typedef struct CDSCCTM_S { /* used for %%ViewingOrientation */
+ float xx;
+ float xy;
+ float yx;
+ float yy;
+ /* float ty; */
+ /* float ty; */
+} CDSCCTM;
+
+typedef struct CDSCPAGE_S {
+ int ordinal;
+ const char *label;
+ unsigned long begin;
+ unsigned long end;
+ unsigned int orientation;
+ const CDSCMEDIA *media;
+ CDSCBBOX *bbox; /* PageBoundingBox, also used by GSview for PDF CropBox */
+ CDSCCTM *viewing_orientation;
+} CDSCPAGE;
+
+/* binary DOS EPS header */
+typedef struct CDSCDOSEPS_S {
+ GSDWORD ps_begin;
+ GSDWORD ps_length;
+ GSDWORD wmf_begin;
+ GSDWORD wmf_length;
+ GSDWORD tiff_begin;
+ GSDWORD tiff_length;
+ GSWORD checksum;
+} CDSCDOSEPS;
+
+/* rather than allocated every string with malloc, we allocate
+ * chunks of 4k and place the (usually) short strings in these
+ * chunks.
+ */
+typedef struct CDSCSTRING_S CDSCSTRING;
+struct CDSCSTRING_S {
+ unsigned int index;
+ unsigned int length;
+ char *data;
+ CDSCSTRING *next;
+};
+
+
+/* DSC error reporting */
+
+typedef enum {
+ CDSC_MESSAGE_BBOX = 0,
+ CDSC_MESSAGE_EARLY_TRAILER = 1,
+ CDSC_MESSAGE_EARLY_EOF = 2,
+ CDSC_MESSAGE_PAGE_IN_TRAILER = 3,
+ CDSC_MESSAGE_PAGE_ORDINAL = 4,
+ CDSC_MESSAGE_PAGES_WRONG = 5,
+ CDSC_MESSAGE_EPS_NO_BBOX = 6,
+ CDSC_MESSAGE_EPS_PAGES = 7,
+ CDSC_MESSAGE_NO_MEDIA = 8,
+ CDSC_MESSAGE_ATEND = 9,
+ CDSC_MESSAGE_DUP_COMMENT = 10,
+ CDSC_MESSAGE_DUP_TRAILER = 11,
+ CDSC_MESSAGE_BEGIN_END = 12,
+ CDSC_MESSAGE_BAD_SECTION = 13,
+ CDSC_MESSAGE_LONG_LINE = 14,
+ CDSC_MESSAGE_INCORRECT_USAGE = 15
+} CDSC_MESSAGE_ERROR;
+
+/* severity */
+typedef enum {
+ CDSC_ERROR_INFORM = 0, /* Not an error */
+ CDSC_ERROR_WARN = 1, /* Not a DSC error itself, */
+ CDSC_ERROR_ERROR = 2 /* DSC error */
+} CDSC_MESSAGE_SEVERITY;
+
+/* response */
+typedef enum {
+ CDSC_RESPONSE_OK = 0,
+ CDSC_RESPONSE_CANCEL = 1,
+ CDSC_RESPONSE_IGNORE_ALL = 2
+} CDSC_RESPONSE;
+
+extern const char * const dsc_message[];
+
+typedef struct CDSC_S CDSC;
+struct CDSC_S {
+ /* public data */
+ GSBOOL dsc; /* TRUE if DSC comments found */
+ GSBOOL ctrld; /* TRUE if has CTRLD at start of stream */
+ GSBOOL pjl; /* TRUE if has HP PJL at start of stream */
+ GSBOOL epsf; /* TRUE if EPSF */
+ GSBOOL pdf; /* TRUE if Portable Document Format */
+ unsigned int preview; /* enum CDSC_PREVIEW_TYPE */
+ char *dsc_version; /* first line of file */
+ unsigned int language_level;
+ unsigned int document_data; /* Clean7Bit, Clean8Bit, Binary */
+ /* enum CDSC_DOCUMENT_DATA */
+ /* DSC sections */
+ unsigned long begincomments;
+ unsigned long endcomments;
+ unsigned long beginpreview;
+ unsigned long endpreview;
+ unsigned long begindefaults;
+ unsigned long enddefaults;
+ unsigned long beginprolog;
+ unsigned long endprolog;
+ unsigned long beginsetup;
+ unsigned long endsetup;
+ unsigned long begintrailer;
+ unsigned long endtrailer;
+ CDSCPAGE *page;
+ unsigned int page_count; /* number of %%Page: pages in document */
+ unsigned int page_pages; /* number of pages in document from %%Pages: */
+ unsigned int page_order; /* enum CDSC_PAGE_ORDER */
+ unsigned int page_orientation; /* the default page orientation */
+ /* enum CDSC_ORIENTATION */
+ CDSCCTM *viewing_orientation;
+ unsigned int media_count; /* number of media items */
+ CDSCMEDIA **media; /* the array of media */
+ const CDSCMEDIA *page_media;/* the default page media */
+ CDSCBBOX *bbox; /* the document bounding box */
+ CDSCBBOX *page_bbox; /* the default page bounding box */
+ CDSCDOSEPS *doseps; /* DOS binary header */
+ char *dsc_title;
+ char *dsc_creator;
+ char *dsc_date;
+ char *dsc_for;
+
+ unsigned int max_error; /* highest error number that will be reported */
+ const int *severity; /* array of severity values, one per error */
+
+
+ /* private data */
+ void *caller_data; /* pointer to be provided when calling */
+ /* error and debug callbacks */
+ int id; /* last DSC comment found */
+ int scan_section; /* section currently being scanned */
+ /* enum CDSC_SECTION */
+
+ unsigned long doseps_end; /* ps_begin+ps_length, otherwise 0 */
+ unsigned int page_chunk_length; /* number of pages allocated */
+ unsigned long file_length; /* length of document */
+ /* If provided we try to recognise %%Trailer and %%EOF */
+ /* incorrectly embedded inside document. */
+ /* Can be left set to default value of 0 */
+ int skip_document; /* recursion level of %%BeginDocument: */
+ int skip_bytes; /* #bytes to ignore from BeginData: */
+ /* or DOSEPS preview section */
+ int skip_lines; /* #lines to ignore from BeginData: */
+ GSBOOL skip_pjl; /* TRUE if skip PJL until first PS comment */
+ int begin_font_count; /* recursion level of %%BeginFont */
+ int begin_feature_count; /* recursion level of %%BeginFeature */
+ int begin_resource_count; /* recursion level of %%BeginResource */
+ int begin_procset_count; /* recursion level of %%BeginProcSet */
+
+ /* buffer for input */
+ char data[CDSC_DATA_LENGTH];/* start of buffer */
+ unsigned int data_length; /* length of data in buffer */
+ unsigned int data_index; /* offset to next char in buffer */
+ unsigned long data_offset; /* offset from start of document */
+ /* to byte in data[0] */
+ GSBOOL eof; /* TRUE if there is no more data */
+
+ /* information about DSC line */
+ char *line; /* pointer to last read DSC line */
+ /* not null terminated */
+ unsigned int line_length; /* number of characters in line */
+ GSBOOL eol; /* TRUE if dsc_line contains EOL */
+ GSBOOL last_cr; /* TRUE if last line ended in \r */
+ /* check next time for \n */
+ unsigned int line_count; /* line number */
+ GSBOOL long_line; /* TRUE if found a line longer than 255 characters */
+ char last_line[256]; /* previous DSC line, used for %%+ */
+
+ /* more efficient string storage (for short strings) than malloc */
+ CDSCSTRING *string_head; /* linked list head */
+ CDSCSTRING *string; /* current list item */
+
+ /* memory allocation routines */
+ void *(*memalloc)(P2(size_t size, void *closure_data));
+ void (*memfree)(P2(void *ptr, void *closure_data));
+ void *mem_closure_data;
+
+ /* function for printing debug messages */
+ void (*debug_print_fn)(P2(void *caller_data, const char *str));
+
+ /* function for reporting errors in DSC comments */
+ int (*dsc_error_fn)(P5(void *caller_data, CDSC *dsc,
+ unsigned int explanation, const char *line, unsigned int line_len));
+
+ /* public data */
+ /* Added 2001-10-01 */
+ CDSCFBBOX *hires_bbox; /* the hires document bounding box */
+ CDSCFBBOX *crop_box; /* the size of the trimmed page */
+};
+
+
+/* Public functions */
+
+/* Create and initialise DSC parser */
+CDSC *dsc_init(P1(void *caller_data));
+
+CDSC *dsc_init_with_alloc(P4(
+ void *caller_data,
+ void *(*memalloc)(size_t size, void *closure_data),
+ void (*memfree)(void *ptr, void *closure_data),
+ void *closure_data));
+
+/* Free the DSC parser */
+void dsc_free(P1(CDSC *dsc));
+
+/* Tell DSC parser how long document will be, to allow ignoring
+ * of early %%Trailer and %%EOF. This is optional.
+ */
+void dsc_set_length(P2(CDSC *dsc, unsigned long len));
+
+/* Process a buffer containing DSC comments and PostScript */
+int dsc_scan_data(P3(CDSC *dsc, const char *data, int len));
+
+/* All data has been processed, fixup any DSC errors */
+int dsc_fixup(P1(CDSC *dsc));
+
+/* Install error query function */
+void dsc_set_error_function(P2(CDSC *dsc,
+ int (*dsc_error_fn)(P5(void *caller_data, CDSC *dsc,
+ unsigned int explanation, const char *line, unsigned int line_len))));
+
+/* Install print function for debug messages */
+void dsc_set_debug_function(P2(CDSC *dsc,
+ void (*debug_fn)(P2(void *caller_data, const char *str))));
+
+/* Print a message to debug output, if provided */
+void dsc_debug_print(P2(CDSC *dsc, const char *str));
+
+/* should be internal only functions, but made available to
+ * GSview for handling PDF
+ */
+int dsc_add_page(P3(CDSC *dsc, int ordinal, char *label));
+int dsc_add_media(P2(CDSC *dsc, CDSCMEDIA *media));
+int dsc_set_page_bbox(P6(CDSC *dsc, unsigned int page_number,
+ int llx, int lly, int urx, int ury));
+
+#endif
+
+// vim:sw=4:sts=4:ts=8:noet
diff --git a/kghostview/dscparse/dscparse_adapter.cpp b/kghostview/dscparse/dscparse_adapter.cpp
new file mode 100644
index 00000000..b04e89bc
--- /dev/null
+++ b/kghostview/dscparse/dscparse_adapter.cpp
@@ -0,0 +1,420 @@
+/**
+ * Copyright (C) 2001 the KGhostView authors. See file AUTHORS.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "dscparse_adapter.h"
+
+using namespace std;
+
+/*-- KDSCBBOX implementation -----------------------------------------------*/
+
+KDSCBBOX::KDSCBBOX() :
+ _llx( 0 ), _lly( 0 ),
+ _urx( 0 ), _ury( 0 )
+{}
+
+KDSCBBOX::KDSCBBOX( const KDSCBBOX& b ) :
+ _llx( b._llx ), _lly( b._lly ),
+ _urx( b._urx ), _ury( b._ury )
+{}
+
+KDSCBBOX::KDSCBBOX( int llx, int lly, int urx, int ury ) :
+ _llx( llx ), _lly( lly ),
+ _urx( urx ), _ury( ury )
+{}
+
+KDSCBBOX::KDSCBBOX( const CDSCBBOX& bbox ) :
+ _llx( bbox.llx ), _lly( bbox.lly ),
+ _urx( bbox.urx ), _ury( bbox.ury )
+{}
+
+KDSCBBOX& KDSCBBOX::operator = ( const KDSCBBOX& b )
+{
+ _llx = b._llx; _lly = b._lly; _urx = b._urx; _ury = b._ury;
+ return *this;
+}
+
+bool KDSCBBOX::operator == ( const KDSCBBOX& b )
+{
+ return ( _llx == b._llx && _lly == b._lly
+ && _urx == b._urx && _ury == b._ury );
+}
+
+bool KDSCBBOX::operator != ( const KDSCBBOX& b )
+{
+ return !( *this == b );
+}
+
+int KDSCBBOX::llx() const { return _llx; }
+int KDSCBBOX::lly() const { return _lly; }
+int KDSCBBOX::urx() const { return _urx; }
+int KDSCBBOX::ury() const { return _ury; }
+
+int KDSCBBOX::width() const { return _urx - _llx; }
+int KDSCBBOX::height() const { return _ury - _lly; }
+
+TQSize KDSCBBOX::size() const { return TQSize( width(), height() ); }
+
+ostream& operator << ( ostream& os, const KDSCBBOX& source )
+{
+ os << "{ llx: "<< source.llx() << ", lly: " << source.lly()
+ << " urx: "<< source.urx() << ", ury: " << source.ury() << " }";
+ return os;
+}
+
+/*-- KDSCError implementation ----------------------------------------------*/
+
+KDSCError::KDSCError( Type type, Severity severity, const TQCString& line,
+ unsigned int lineNumber ) :
+ _type( type ),
+ _severity( severity ),
+ _line( line ),
+ _lineNumber( lineNumber )
+{}
+
+KDSCError::Type KDSCError::type() const
+{
+ return _type;
+}
+
+KDSCError::Severity KDSCError::severity() const
+{
+ return _severity;
+}
+
+TQCString KDSCError::line() const
+{
+ return _line;
+}
+
+unsigned int KDSCError::lineNumber() const
+{
+ return _lineNumber;
+}
+
+/*-- KDSCOkErrorHandler implementation -------------------------------------*/
+
+KDSCErrorHandler::Response KDSCOkErrorHandler::error( const KDSCError& err )
+{
+ cout << "KDSC: error in line " << err.lineNumber() << endl;
+ cout << err.line() << endl;
+ return Ok;
+}
+
+/*-- KDSC implementation ---------------------------------------------------*/
+
+KDSC::KDSC() :
+ _errorHandler( 0 ),
+ _commentHandler( 0 )
+{
+ _cdsc = dsc_init( this );
+ Q_ASSERT( _cdsc != 0 );
+ _scanHandler = new KDSCScanHandler( _cdsc );
+}
+
+KDSC::~KDSC()
+{
+ dsc_free( _cdsc );
+ delete _scanHandler;
+}
+
+TQString KDSC::dsc_version() const
+{
+ return TQString( _cdsc->dsc_version );
+}
+
+bool KDSC::dsc() const
+{
+ return ( _cdsc->dsc == TRUE );
+}
+
+bool KDSC::ctrld() const
+{
+ return ( _cdsc->ctrld == TRUE );
+}
+
+bool KDSC::pjl() const
+{
+ return ( _cdsc->pjl == TRUE );
+}
+
+bool KDSC::epsf() const
+{
+ return ( _cdsc->epsf == TRUE );
+}
+
+bool KDSC::pdf() const
+{
+ return ( _cdsc->pdf == TRUE );
+}
+
+unsigned int KDSC::preview() const
+{
+ return _cdsc->preview;
+}
+
+unsigned int KDSC::language_level() const
+{
+ return _cdsc->language_level;
+}
+
+unsigned int KDSC::document_data() const
+{
+ return _cdsc->document_data;
+}
+
+unsigned long KDSC::begincomments() const
+{
+ return _cdsc->begincomments;
+}
+
+unsigned long KDSC::endcomments() const
+{
+ return _cdsc->endcomments;
+}
+
+unsigned long KDSC::beginpreview() const
+{
+ return _cdsc->beginpreview;
+}
+
+unsigned long KDSC::endpreview() const
+{
+ return _cdsc->endpreview;
+}
+
+unsigned long KDSC::begindefaults() const
+{
+ return _cdsc->begindefaults;
+}
+
+unsigned long KDSC::enddefaults() const
+{
+ return _cdsc->enddefaults;
+}
+
+unsigned long KDSC::beginprolog() const
+{
+ return _cdsc->beginprolog;
+}
+
+unsigned long KDSC::endprolog() const
+{
+ return _cdsc->endprolog;
+}
+
+unsigned long KDSC::beginsetup() const
+{
+ return _cdsc->beginsetup;
+}
+
+unsigned long KDSC::endsetup() const
+{
+ return _cdsc->endsetup;
+}
+
+unsigned long KDSC::begintrailer() const
+{
+ return _cdsc->begintrailer;
+}
+
+unsigned long KDSC::endtrailer() const
+{
+ return _cdsc->endtrailer;
+}
+
+CDSCPAGE* KDSC::page() const
+{
+ return _cdsc->page;
+}
+
+unsigned int KDSC::page_count() const
+{
+ return _cdsc->page_count;
+}
+
+unsigned int KDSC::page_pages() const
+{
+ return _cdsc->page_pages;
+}
+
+unsigned int KDSC::page_order() const
+{
+ return _cdsc->page_order;
+}
+
+unsigned int KDSC::page_orientation() const
+{
+ return _cdsc->page_orientation;
+}
+
+CDSCCTM* KDSC::viewing_orientation() const
+{
+ return _cdsc->viewing_orientation;
+}
+
+unsigned int KDSC::media_count() const
+{
+ return _cdsc->media_count;
+}
+
+CDSCMEDIA** KDSC::media() const
+{
+ return _cdsc->media;
+}
+
+const CDSCMEDIA* KDSC::page_media() const
+{
+ return _cdsc->page_media;
+}
+
+auto_ptr<KDSCBBOX> KDSC::bbox() const
+{
+ if( _cdsc->bbox == 0 )
+ return auto_ptr<KDSCBBOX>( 0 );
+ else
+ return auto_ptr<KDSCBBOX>( new KDSCBBOX( *_cdsc->bbox ) );
+}
+
+auto_ptr<KDSCBBOX> KDSC::page_bbox() const
+{
+ if( _cdsc->page_bbox == 0 )
+ return auto_ptr<KDSCBBOX>( 0 );
+ else
+ return auto_ptr<KDSCBBOX>( new KDSCBBOX( *_cdsc->page_bbox ) );
+}
+
+TQString KDSC::dsc_title() const
+{
+ return TQString( _cdsc->dsc_title );
+}
+
+TQString KDSC::dsc_creator() const
+{
+ return TQString( _cdsc->dsc_creator );
+}
+
+TQString KDSC::dsc_date() const
+{
+ return TQString( _cdsc->dsc_date );
+}
+
+TQString KDSC::dsc_for() const
+{
+ return TQString( _cdsc->dsc_for );
+}
+
+bool KDSC::scanData( char* buffer, unsigned int count )
+{
+ return _scanHandler->scanData( buffer, count );
+}
+
+int KDSC::fixup()
+{
+ return dsc_fixup( _cdsc );
+}
+
+KDSCErrorHandler* KDSC::errorHandler() const
+{
+ return _errorHandler;
+}
+
+void KDSC::setErrorHandler( KDSCErrorHandler* errorHandler )
+{
+ _errorHandler = errorHandler;
+ if( errorHandler == 0 )
+ dsc_set_error_function( _cdsc, 0 );
+ else
+ dsc_set_error_function( _cdsc, &errorFunction );
+}
+
+KDSCCommentHandler* KDSC::commentHandler() const
+{
+ return _commentHandler;
+}
+
+void KDSC::setCommentHandler( KDSCCommentHandler* commentHandler )
+{
+ if( _commentHandler != 0 && commentHandler == 0 )
+ {
+ delete _scanHandler;
+ _scanHandler = new KDSCScanHandler( _cdsc );
+ }
+ else if( _commentHandler == 0 && commentHandler != 0 )
+ {
+ delete _scanHandler;
+ _scanHandler = new KDSCScanHandlerByLine( _cdsc, commentHandler );
+ }
+ _commentHandler = commentHandler;
+}
+
+bool KDSC::isStructured() const
+{
+ return epsf() ? ( page_count() > 1 ) : ( page_count() > 0 );
+}
+
+CDSC* KDSC::cdsc() const
+{
+ return _cdsc;
+}
+
+int KDSC::errorFunction( void* caller_data, CDSC* dsc,
+ unsigned int explanation, const char* line, unsigned int line_len )
+{
+ KDSCError error(
+ static_cast< KDSCError::Type >( explanation ),
+ static_cast< KDSCError::Severity >( dsc->severity[explanation] ),
+ TQCString( line, line_len + 1 ),
+ dsc->line_count
+ );
+
+ KDSC* kdsc = static_cast< KDSC* >( caller_data );
+ Q_ASSERT( kdsc );
+
+ return kdsc->errorHandler()->error( error );
+}
+
+bool KDSCScanHandlerByLine::scanData( char* buf, unsigned int count )
+{
+ char* lineStart = buf;
+ char* it = buf;
+ while( it < buf + count )
+ {
+ if( *it++ == '\n' )
+ {
+ int retval = dsc_scan_data( _cdsc, lineStart, it - lineStart );
+ if( retval < 0 )
+ return false;
+ else if( retval > 0 )
+ {
+ _commentHandler->comment(
+ static_cast<KDSCCommentHandler::Name>( retval ) );
+ }
+ lineStart = it;
+ }
+ }
+
+ if( it != lineStart )
+ {
+ // Scan the remaining part of the string.
+ return ( dsc_scan_data( _cdsc, lineStart, it - lineStart ) < 0 );
+ }
+ else
+ return true;
+}
+
+// vim:sw=4:sts=4:ts=8:noet
diff --git a/kghostview/dscparse/dscparse_adapter.h b/kghostview/dscparse/dscparse_adapter.h
new file mode 100644
index 00000000..c5c1cbf9
--- /dev/null
+++ b/kghostview/dscparse/dscparse_adapter.h
@@ -0,0 +1,386 @@
+/**
+ * Copyright (C) 2001 the KGhostView authors. See file AUTHORS.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef DSCPARSE_ADAPTER_H
+#define DSCPARSE_ADAPTER_H
+
+#include <iostream>
+#include <map>
+#include <memory>
+
+#include <tqsize.h>
+#include <tqstring.h>
+
+#include "dscparse.h"
+
+#if defined(__GNUC__)
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 93)
+/*
+ * We add a quick 'n' dirty inline implementation of auto_ptr for older
+ * releases of GCC, which don't include an auto_ptr implementation in
+ * <memory>.
+ */
+
+template <class T> class auto_ptr {
+private:
+ T* _ptr;
+
+public:
+ typedef T element_type;
+ explicit auto_ptr(T* p = 0) : _ptr(p) {}
+ auto_ptr(auto_ptr& a) : _ptr(a.release()) {}
+ template <class T1> auto_ptr(auto_ptr<T1>& a) : _ptr(a.release()) {}
+ auto_ptr& operator=(auto_ptr& a) {
+ if (&a != this) {
+ delete _ptr;
+ _ptr = a.release();
+ }
+ return *this;
+ }
+ template <class T1>
+ auto_ptr& operator=(auto_ptr<T1>& a) {
+ if (a.get() != this->get()) {
+ delete _ptr;
+ _ptr = a.release();
+ }
+ return *this;
+ }
+ ~auto_ptr() { delete _ptr; }
+
+ T& operator*() const { return *_ptr; }
+ T* operator->() const { return _ptr; }
+ T* get() const { return _ptr; }
+ T* release() { T* tmp = _ptr; _ptr = 0; return tmp; }
+ void reset(T* p = 0) { delete _ptr; _ptr = p; }
+};
+
+#endif
+#endif
+
+
+class KDSCBBOX
+{
+public:
+ KDSCBBOX();
+ KDSCBBOX( const KDSCBBOX& b );
+ KDSCBBOX( int llx, int lly, int urx, int ury );
+ KDSCBBOX( const CDSCBBOX& bbox );
+
+ KDSCBBOX& operator = ( const KDSCBBOX& b );
+
+ bool operator == ( const KDSCBBOX& b );
+ bool operator != ( const KDSCBBOX& b );
+
+ int llx() const;
+ int lly() const;
+ int urx() const;
+ int ury() const;
+
+ int width() const;
+ int height() const;
+
+ TQSize size() const;
+
+private:
+ int _llx, _lly, _urx, _ury;
+};
+
+std::ostream& operator << ( std::ostream&, const KDSCBBOX& );
+
+
+class KDSCError
+{
+public:
+ enum Type
+ {
+ BBox = CDSC_MESSAGE_BBOX,
+ EarlyTrailer = CDSC_MESSAGE_EARLY_TRAILER,
+ EarlyEOF = CDSC_MESSAGE_EARLY_EOF,
+ PageInTrailer = CDSC_MESSAGE_PAGE_IN_TRAILER,
+ PageOrdinal = CDSC_MESSAGE_PAGE_ORDINAL,
+ PagesWrong = CDSC_MESSAGE_PAGES_WRONG,
+ EPSNoBBox = CDSC_MESSAGE_EPS_NO_BBOX,
+ EPSPages = CDSC_MESSAGE_EPS_PAGES,
+ NoMedia = CDSC_MESSAGE_NO_MEDIA,
+ AtEnd = CDSC_MESSAGE_ATEND,
+ DuplicateComment = CDSC_MESSAGE_DUP_COMMENT,
+ DuplicateTrailer = CDSC_MESSAGE_DUP_TRAILER,
+ BeginEnd = CDSC_MESSAGE_BEGIN_END,
+ BadSection = CDSC_MESSAGE_BAD_SECTION,
+ LongLine = CDSC_MESSAGE_LONG_LINE,
+ IncorrectUsage = CDSC_MESSAGE_INCORRECT_USAGE
+ };
+
+ enum Severity
+ {
+ Information = CDSC_ERROR_INFORM,
+ Warning = CDSC_ERROR_WARN,
+ Error = CDSC_ERROR_ERROR
+ };
+
+ KDSCError( Type, Severity, const TQCString& line,
+ unsigned int lineNumber );
+
+ Type type() const;
+ Severity severity() const;
+ TQCString line() const;
+ unsigned int lineNumber() const;
+
+private:
+ Type _type;
+ Severity _severity;
+ TQCString _line;
+ unsigned int _lineNumber;
+};
+
+
+class KDSCErrorHandler
+{
+public:
+ virtual ~KDSCErrorHandler() {}
+ enum Response
+ {
+ Ok = CDSC_RESPONSE_OK,
+ Cancel = CDSC_RESPONSE_CANCEL,
+ IgnoreAll = CDSC_RESPONSE_IGNORE_ALL
+ };
+
+ virtual Response error( const KDSCError& ) = 0;
+};
+
+class KDSCOkErrorHandler : public KDSCErrorHandler
+{
+ Response error( const KDSCError& );
+};
+
+class KDSCCommentHandler
+{
+public:
+ virtual ~KDSCCommentHandler() {}
+ enum Name
+ {
+ // Header section
+ PSAdobe = CDSC_PSADOBE,
+ BeginComments = CDSC_BEGINCOMMENTS,
+ EndComments = CDSC_ENDCOMMENTS,
+ Pages = CDSC_PAGES,
+ Creator = CDSC_CREATOR,
+ CreationDate = CDSC_CREATIONDATE,
+ Title = CDSC_TITLE,
+ For = CDSC_FOR,
+ LanguageLevel = CDSC_LANGUAGELEVEL,
+ BoundingBox = CDSC_BOUNDINGBOX,
+ Orientation = CDSC_ORIENTATION,
+ PageOrder = CDSC_PAGEORDER,
+ DocumentMedia = CDSC_DOCUMENTMEDIA,
+ DocumentPaperSizes = CDSC_DOCUMENTPAPERSIZES,
+ DocumentPaperForms = CDSC_DOCUMENTPAPERFORMS,
+ DocumentPaperColors = CDSC_DOCUMENTPAPERCOLORS,
+ DocumentPaperWeights = CDSC_DOCUMENTPAPERWEIGHTS,
+ DocumentData = CDSC_DOCUMENTDATA,
+ Requirements = CDSC_REQUIREMENTS,
+ DocumentNeededFonts = CDSC_DOCUMENTNEEDEDFONTS,
+ DocumentSuppliedFonts = CDSC_DOCUMENTSUPPLIEDFONTS,
+ HiResBoundingBox = CDSC_HIRESBOUNDINGBOX,
+ CropBox = CDSC_CROPBOX,
+
+ // Preview section
+ BeginPreview = CDSC_BEGINPREVIEW,
+ EndPreview = CDSC_ENDPREVIEW,
+
+ // Defaults section
+ BeginDefaults = CDSC_BEGINDEFAULTS,
+ EndDefaults = CDSC_ENDDEFAULTS,
+ // also %%PageMedia, %%PageOrientation, %%PageBoundingBox
+
+ // Prolog section
+ BeginProlog = CDSC_BEGINPROLOG,
+ EndProlog = CDSC_ENDPROLOG,
+ BeginFont = CDSC_BEGINFONT,
+ EndFont = CDSC_ENDFONT,
+ BeginFeature = CDSC_BEGINFEATURE,
+ EndFeature = CDSC_ENDFEATURE,
+ BeginResource = CDSC_BEGINRESOURCE,
+ EndResource = CDSC_ENDRESOURCE,
+ BeginProcset = CDSC_BEGINPROCSET,
+ EndProcset = CDSC_ENDPROCSET,
+
+ // Setup section
+ BeginSetup = CDSC_BEGINSETUP,
+ EndSetup = CDSC_ENDSETUP,
+ Feature = CDSC_FEATURE,
+ PaperColor = CDSC_PAPERCOLOR,
+ PaperForm = CDSC_PAPERFORM,
+ PaperWeight = CDSC_PAPERWEIGHT,
+ PaperSize = CDSC_PAPERSIZE,
+ // also %%Begin/EndFeature, %%Begin/EndResource
+
+ // Page section
+ Page = CDSC_PAGE,
+ PageTrailer = CDSC_PAGETRAILER,
+ BeginPageSetup = CDSC_BEGINPAGESETUP,
+ EndPageSetup = CDSC_ENDPAGESETUP,
+ PageMedia = CDSC_PAGEMEDIA,
+ // also %%PaperColor, %%PaperForm, %%PaperWeight, %%PaperSize
+ PageOrientation = CDSC_PAGEORIENTATION,
+ PageBoundingBox = CDSC_PAGEBOUNDINGBOX,
+ // also %%Begin/EndFont, %%Begin/EndFeature
+ // also %%Begin/EndResource, %%Begin/EndProcSet
+ IncludeFont = CDSC_INCLUDEFONT,
+ ViewingOrientation = CDSC_VIEWINGORIENTATION,
+
+ // Trailer section
+ Trailer = CDSC_TRAILER,
+ // also %%Pages, %%BoundingBox, %%Orientation, %%PageOrder,
+ // %%DocumentMedia
+ // %%Page is recognised as an error
+ // also %%DocumentNeededFonts, %%DocumentSuppliedFonts
+
+ // End of File */
+ Eof = CDSC_EOF
+ };
+
+ virtual void comment( Name name ) { std::cout << name << std::endl; }
+};
+
+class KDSCScanHandler;
+class KDSC
+{
+public:
+ KDSC();
+ ~KDSC();
+
+ /*--- Adapter for CDSC ------------------------------------------------*/
+ TQString dsc_version() const;
+
+ bool dsc() const;
+ bool ctrld() const;
+ bool pjl() const;
+ bool epsf() const;
+ bool pdf() const;
+
+ unsigned int preview() const;
+ unsigned int language_level() const;
+ unsigned int document_data() const;
+
+ unsigned long begincomments() const;
+ unsigned long endcomments() const;
+ unsigned long beginpreview() const;
+ unsigned long endpreview() const;
+ unsigned long begindefaults() const;
+ unsigned long enddefaults() const;
+ unsigned long beginprolog() const;
+ unsigned long endprolog() const;
+ unsigned long beginsetup() const;
+ unsigned long endsetup() const;
+ unsigned long begintrailer() const;
+ unsigned long endtrailer() const;
+
+ CDSCPAGE* page() const;
+
+ unsigned int page_count() const;
+ unsigned int page_pages() const;
+ unsigned int page_order() const;
+ unsigned int page_orientation() const;
+
+ CDSCCTM* viewing_orientation() const;
+
+ unsigned int media_count() const;
+ CDSCMEDIA** media() const;
+ const CDSCMEDIA* page_media() const;
+
+#if defined(__GNUC__) && (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 93))
+ auto_ptr<KDSCBBOX> bbox() const;
+ auto_ptr<KDSCBBOX> page_bbox() const;
+#else
+ std::auto_ptr<KDSCBBOX> bbox() const;
+ std::auto_ptr<KDSCBBOX> page_bbox() const;
+#endif
+
+ // CDSCDOSEPS *doseps;
+
+ TQString dsc_title() const;
+ TQString dsc_creator() const;
+ TQString dsc_date() const;
+ TQString dsc_for() const;
+
+ // unsigned int max_error
+
+ bool scanData( char*, unsigned int );
+
+ /**
+ * Tidy up from incorrect DSC comments.
+ */
+ int fixup();
+
+ KDSCErrorHandler* errorHandler() const;
+ void setErrorHandler( KDSCErrorHandler* );
+
+ KDSCCommentHandler* commentHandler() const;
+ void setCommentHandler( KDSCCommentHandler* );
+
+ /*--- Extra methods for convenience -----------------------------------*/
+ bool isStructured() const;
+
+ /*--- Temporary -------------------------------------------------------*/
+ CDSC* cdsc() const;
+
+protected:
+ static int errorFunction( void* caller_data, CDSC* dsc,
+ unsigned int explanation,
+ const char* line, unsigned int line_len );
+
+private:
+ CDSC* _cdsc;
+ KDSCErrorHandler* _errorHandler;
+ KDSCCommentHandler* _commentHandler;
+ KDSCScanHandler* _scanHandler;
+};
+
+class KDSCScanHandler
+{
+public:
+ virtual ~KDSCScanHandler() {}
+ KDSCScanHandler( CDSC* cdsc ) : _cdsc( cdsc ) {}
+
+ virtual bool scanData( char* buf, unsigned int count )
+ {
+ return ( dsc_scan_data( _cdsc, buf, count ) >= 0 );
+ }
+
+protected:
+ CDSC* _cdsc;
+};
+
+class KDSCScanHandlerByLine : public KDSCScanHandler
+{
+public:
+ KDSCScanHandlerByLine( CDSC* cdsc, KDSCCommentHandler* commentHandler ) :
+ KDSCScanHandler( cdsc ),
+ _commentHandler( commentHandler )
+ {}
+
+ virtual bool scanData( char* buf, unsigned int count );
+
+protected:
+ KDSCCommentHandler* _commentHandler;
+};
+
+#endif
+
+// vim:sw=4:sts=4:ts=8:noet