/*
- * "$Id: pstops.c 5092 2006-02-09 00:54:31Z mike $"
+ * "$Id: pstops.c 7006 2007-10-04 17:43:38Z mike $"
*
* PostScript filter for the Common UNIX Printing System (CUPS).
*
- * Copyright 1993-2006 by Easy Software Products.
+ * Copyright 2007-2008 by Apple Inc.
+ * Copyright 1993-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* This file is subject to the Apple OS-Developed Software exception.
*
* Contents:
*
- * main() - Main entry...
- * add_page() - Add a page to the Pages array...
- * check_range() - Check to see if the current page is selected for
- * copy_bytes() - Copy bytes from the input file to stdout...
- * do_prolog() - Send the necessary document prolog commands...
- * do_setup() - Send the necessary document setup commands...
- * end_nup() - End processing for N-up printing...
- * include_feature() - Include a printer option/feature command.
- * psgets() - Get a line from a file.
- * start_nup() - Start processing for N-up printing...
+ * main() - Main entry...
+ * add_page() - Add a page to the pages array...
+ * cancel_job() - Flag the job as canceled.
+ * check_range() - Check to see if the current page is selected for
+ * copy_bytes() - Copy bytes from the input file to stdout...
+ * copy_comments() - Copy all of the comments section...
+ * copy_dsc() - Copy a DSC-conforming document...
+ * copy_non_dsc() - Copy a document that does not conform to the DSC...
+ * copy_page() - Copy a page description...
+ * copy_prolog() - Copy the document prolog section...
+ * copy_setup() - Copy the document setup section...
+ * copy_trailer() - Copy the document trailer...
+ * do_prolog() - Send the necessary document prolog commands...
+ * do_setup() - Send the necessary document setup commands...
+ * doc_printf() - Send a formatted string to stdout and/or the temp
+ * file.
+ * doc_puts() - Send a nul-terminated string to stdout and/or the
+ * temp file.
+ * doc_write() - Send data to stdout and/or the temp file.
+ * end_nup() - End processing for N-up printing...
+ * include_feature() - Include a printer option/feature command.
+ * parse_text() - Parse a text value in a comment...
+ * set_pstops_options() - Set pstops options...
+ * skip_page() - Skip past a page that won't be printed...
+ * start_nup() - Start processing for N-up printing...
+ * write_labels() - Write the actual page labels.
*/
/*
*/
#include "common.h"
+#include <limits.h>
#include <math.h>
#include <cups/file.h>
#include <cups/array.h>
+#include <cups/i18n.h>
+#include <signal.h>
/*
* Constants...
*/
-#define BORDER_NONE 0 /* No border or hairline border */
-#define BORDER_THICK 1 /* Think border */
-#define BORDER_SINGLE 2 /* Single-line hairline border */
-#define BORDER_SINGLE2 3 /* Single-line thick border */
-#define BORDER_DOUBLE 4 /* Double-line hairline border */
-#define BORDER_DOUBLE2 5 /* Double-line thick border */
+#define PSTOPS_BORDERNONE 0 /* No border or hairline border */
+#define PSTOPS_BORDERTHICK 1 /* Think border */
+#define PSTOPS_BORDERSINGLE 2 /* Single-line hairline border */
+#define PSTOPS_BORDERSINGLE2 3 /* Single-line thick border */
+#define PSTOPS_BORDERDOUBLE 4 /* Double-line hairline border */
+#define PSTOPS_BORDERDOUBLE2 5 /* Double-line thick border */
-#define LAYOUT_LRBT 0 /* Left to right, bottom to top */
-#define LAYOUT_LRTB 1 /* Left to right, top to bottom */
-#define LAYOUT_RLBT 2 /* Right to left, bottom to top */
-#define LAYOUT_RLTB 3 /* Right to left, top to bottom */
-#define LAYOUT_BTLR 4 /* Bottom to top, left to right */
-#define LAYOUT_TBLR 5 /* Top to bottom, left to right */
-#define LAYOUT_BTRL 6 /* Bottom to top, right to left */
-#define LAYOUT_TBRL 7 /* Top to bottom, right to left */
+#define PSTOPS_LAYOUT_LRBT 0 /* Left to right, bottom to top */
+#define PSTOPS_LAYOUT_LRTB 1 /* Left to right, top to bottom */
+#define PSTOPS_LAYOUT_RLBT 2 /* Right to left, bottom to top */
+#define PSTOPS_LAYOUT_RLTB 3 /* Right to left, top to bottom */
+#define PSTOPS_LAYOUT_BTLR 4 /* Bottom to top, left to right */
+#define PSTOPS_LAYOUT_TBLR 5 /* Top to bottom, left to right */
+#define PSTOPS_LAYOUT_BTRL 6 /* Bottom to top, right to left */
+#define PSTOPS_LAYOUT_TBRL 7 /* Top to bottom, right to left */
-#define LAYOUT_NEGATEY 1 /* The bits for the layout */
-#define LAYOUT_NEGATEX 2 /* definitions above... */
-#define LAYOUT_VERTICAL 4
-
-#define PROT_STANDARD 0 /* Adobe standard protocol */
-#define PROT_BCP 1 /* Adobe BCP protocol */
-#define PROT_TBCP 2 /* Adobe TBCP protocol */
+#define PSTOPS_LAYOUT_NEGATEY 1 /* The bits for the layout */
+#define PSTOPS_LAYOUT_NEGATEX 2 /* definitions above... */
+#define PSTOPS_LAYOUT_VERTICAL 4
/*
typedef struct /**** Page information ****/
{
char *label; /* Page label */
+ int bounding_box[4]; /* PageBoundingBox */
off_t offset; /* Offset to start of page */
ssize_t length; /* Number of bytes for page */
- int lbrt[4]; /* PageBoundingBox */
- const char *input_slot, /* Input slot option or NULL */
- *manual_feed; /* Manual feed option or NULL */
-} page_info_t;
+ int num_options; /* Number of options for this page */
+ cups_option_t *options; /* Options for this page */
+} pstops_page_t;
+
+typedef struct /**** Document information ****/
+{
+ int page; /* Current page */
+ int bounding_box[4]; /* BoundingBox from header */
+ int new_bounding_box[4]; /* New composite bounding box */
+ int num_options; /* Number of document-wide options */
+ cups_option_t *options; /* Document-wide options */
+ int normal_landscape, /* Normal rotation for landscape? */
+ saw_eof, /* Saw the %%EOF comment? */
+ slow_collate, /* Collate copies by hand? */
+ slow_duplex, /* Duplex pages slowly? */
+ slow_order, /* Reverse pages slowly? */
+ use_ESPshowpage; /* Use ESPshowpage? */
+ cups_array_t *pages; /* Pages in document */
+ cups_file_t *temp; /* Temporary file, if any */
+ char tempfile[1024]; /* Temporary filename */
+ int job_id; /* Job ID */
+ const char *user, /* User name */
+ *title; /* Job name */
+ int copies; /* Number of copies */
+ const char *ap_input_slot, /* AP_FIRSTPAGE_InputSlot value */
+ *ap_manual_feed; /* AP_FIRSTPAGE_ManualFeed value */
+ float brightness; /* brightness value */
+ int collate, /* Collate copies? */
+ emit_jcl, /* Emit JCL commands? */
+ fitplot; /* Fit pages to media */
+ float gamma; /* gamma value */
+ const char *input_slot, /* InputSlot value */
+ *manual_feed; /* ManualFeed value */
+ int mirror, /* doc->mirror/mirror pages */
+ number_up, /* Number of pages on each sheet */
+ number_up_layout, /* doc->number_up_layout of N-up pages */
+ output_order, /* Requested reverse output order? */
+ page_border; /* doc->page_border around pages */
+ const char *page_label, /* page-label option, if any */
+ *page_ranges, /* page-ranges option, if any */
+ *page_set; /* page-set option, if any */
+} pstops_doc_t;
+
+
+/*
+ * Convenience macros...
+ */
+
+#define is_first_page(p) (doc->number_up == 1 || \
+ ((p) % doc->number_up) == 1)
+#define is_last_page(p) (doc->number_up == 1 || \
+ ((p) % doc->number_up) == 0)
+#define is_not_last_page(p) (doc->number_up > 1 && \
+ ((p) % doc->number_up) != 0)
/*
- * Globals...
+ * Local globals...
*/
-int NumPages = 0; /* Number of pages in file */
-cups_array_t *Pages; /* Info on each page */
-const char *PageRanges = NULL; /* Range of pages selected */
-const char *PageSet = NULL; /* All, Even, Odd pages */
-int Order = 0, /* 0 = normal, 1 = reverse pages */
- Flip = 0, /* Flip/mirror pages */
- FitPlot = 0, /* Fit pages to media */
- NUp = 1, /* Number of pages on each sheet (1, 2, 4) */
- Collate = 0, /* Collate copies? */
- Copies = 1, /* Number of copies */
- UseESPsp = 0, /* Use ESPshowpage? */
- Border = BORDER_NONE, /* Border around pages */
- Layout = LAYOUT_LRTB, /* Layout of N-up pages */
- NormalLandscape = 0; /* Normal rotation for landscape? */
+static int JobCanceled = 0;/* Set to 1 on SIGTERM */
/*
* Local functions...
*/
-static page_info_t *add_page(const char *label, off_t offset,
- const int *lbrt);
-static int check_range(int page);
+static pstops_page_t *add_page(pstops_doc_t *doc, const char *label);
+static void cancel_job(int sig);
+static int check_range(pstops_doc_t *doc, int page);
static void copy_bytes(cups_file_t *fp, off_t offset,
size_t length);
-static void do_prolog(ppd_file_t *ppd);
-static void do_setup(ppd_file_t *ppd, int copies, int collate,
- int slowcollate, float g, float b);
-static void end_nup(int number);
-static void include_feature(ppd_file_t *ppd, const char *line,
- cups_file_t *out);
-#define is_first_page(p) (NUp == 1 || (((p)+1) % NUp) == 1)
-#define is_last_page(p) (NUp > 1 && (((p)+1) % NUp) == 0)
-#define is_not_last_page(p) (NUp > 1 && ((p) % NUp) != 0)
-static char *psgets(char *buf, size_t *bytes, FILE *fp);
-static void start_nup(int number, int show_border, const int *lbrt);
+static ssize_t copy_comments(cups_file_t *fp, pstops_doc_t *doc,
+ ppd_file_t *ppd, char *line,
+ ssize_t linelen, size_t linesize);
+static void copy_dsc(cups_file_t *fp, pstops_doc_t *doc,
+ ppd_file_t *ppd, char *line, ssize_t linelen,
+ size_t linesize);
+static void copy_non_dsc(cups_file_t *fp, pstops_doc_t *doc,
+ ppd_file_t *ppd, char *line,
+ ssize_t linelen, size_t linesize);
+static ssize_t copy_page(cups_file_t *fp, pstops_doc_t *doc,
+ ppd_file_t *ppd, int number, char *line,
+ ssize_t linelen, size_t linesize);
+static ssize_t copy_prolog(cups_file_t *fp, pstops_doc_t *doc,
+ ppd_file_t *ppd, char *line,
+ ssize_t linelen, size_t linesize);
+static ssize_t copy_setup(cups_file_t *fp, pstops_doc_t *doc,
+ ppd_file_t *ppd, char *line,
+ ssize_t linelen, size_t linesize);
+static ssize_t copy_trailer(cups_file_t *fp, pstops_doc_t *doc,
+ ppd_file_t *ppd, int number, char *line,
+ ssize_t linelen, size_t linesize);
+static void do_prolog(pstops_doc_t *doc, ppd_file_t *ppd);
+static void do_setup(pstops_doc_t *doc, ppd_file_t *ppd);
+static void doc_printf(pstops_doc_t *doc, const char *format, ...)
+#ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 2, 3)))
+#endif /* __GNUC__ */
+;
+static void doc_puts(pstops_doc_t *doc, const char *s);
+static void doc_write(pstops_doc_t *doc, const char *s, size_t len);
+static void end_nup(pstops_doc_t *doc, int number);
+static int include_feature(ppd_file_t *ppd, const char *line,
+ int num_options,
+ cups_option_t **options);
+static char *parse_text(const char *start, char **end, char *buffer,
+ size_t bufsize);
+static void set_pstops_options(pstops_doc_t *doc, ppd_file_t *ppd,
+ char *argv[], int num_options,
+ cups_option_t *options);
+static ssize_t skip_page(cups_file_t *fp, char *line, ssize_t linelen,
+ size_t linesize);
+static void start_nup(pstops_doc_t *doc, int number,
+ int show_border, const int *bounding_box);
+static void write_label_prolog(pstops_doc_t *doc, const char *label,
+ float bottom, float top,
+ float width);
+static void write_labels(pstops_doc_t *doc, int orient);
/*
main(int argc, /* I - Number of command-line args */
char *argv[]) /* I - Command-line arguments */
{
- FILE *fp; /* Print file */
+ pstops_doc_t doc; /* Document information */
+ cups_file_t *fp; /* Print file */
ppd_file_t *ppd; /* PPD file */
- ppd_attr_t *attr; /* Attribute in PPD file */
- ppd_option_t *option; /* Option */
- ppd_choice_t *choice; /* Marked option choice */
int num_options; /* Number of print options */
cups_option_t *options; /* Print options */
- const char *val; /* Option value */
- char tempfile[255]; /* Temporary file name */
- cups_file_t *temp; /* Temporary file */
- int number; /* Page number */
- int slowcollate; /* 1 if we need to collate manually */
- int sloworder; /* 1 if we need to order manually */
- int slowduplex; /* 1 if we need an even page count */
char line[8192]; /* Line buffer */
- int lbrt[4], /* BoundingBox */
- pagelbrt[4]; /* PageBoundingBox */
size_t len; /* Length of line buffer */
- float g; /* Gamma correction value */
- float b; /* Brightness factor */
- int level; /* Nesting level for embedded files */
- int nbytes, /* Number of bytes read */
- tbytes; /* Bytes to read for binary data */
- int page; /* Current page sequence number */
- int real_page; /* "Real" page number in document */
- int page_count; /* Page count for NUp */
- int basepage; /* Base page number */
- int subpage; /* Sub-page number */
- int copy; /* Current copy */
- int saweof; /* Did we see a %%EOF tag? */
- int sent_espsp, /* Did we send ESPshowpage commands? */
- sent_prolog, /* Did we send the prolog commands? */
- sent_setup, /* Did we send the setup commands? */
- emit_jcl; /* Emit JCL? */
- float min_order; /* Minimum output order for selection */
- char label[256]; /* Page label */
- page_info_t *pageinfo; /* Page information */
- const char *ap_input_slot, /* First page InputSlot option */
- *ap_manual_feed, /* First page ManualFeed option */
- *input_slot, /* Original InputSlot option */
- *manual_feed; /* Original ManualFeed option */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
/*
* Make sure status messages are not buffered...
if (argc < 6 || argc > 7)
{
- fputs("ERROR: pstops job-id user title copies options [file]\n", stderr);
+ fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
+ argv[0]);
return (1);
}
+ /*
+ * Register a signal handler to cleanly cancel a job.
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, cancel_job);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = cancel_job;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, cancel_job);
+#endif /* HAVE_SIGSET */
+
/*
* If we have 7 arguments, print the file named on the command-line.
* Otherwise, send stdin instead...
*/
if (argc == 6)
- fp = stdin;
+ fp = cupsFileStdin();
else
{
/*
* Try to open the print file...
*/
- if ((fp = fopen(argv[6], "rb")) == NULL)
+ if ((fp = cupsFileOpen(argv[6], "r")) == NULL)
{
- fprintf(stderr, "ERROR: unable to open print file \"%s\" - %s\n",
+ fprintf(stderr, _("ERROR: Unable to open file \"%s\" - %s\n"),
argv[6], strerror(errno));
return (1);
}
}
/*
- * Process command-line options and write the prolog...
+ * Read the first line to see if we have DSC comments...
*/
- g = 1.0;
- b = 1.0;
+ if ((len = cupsFileGetLine(fp, line, sizeof(line))) == 0)
+ {
+ fputs(_("ERROR: Empty print file!\n"), stderr);
+ return (1);
+ }
- Copies = atoi(argv[4]);
+ /*
+ * Process command-line options...
+ */
options = NULL;
num_options = cupsParseOptions(argv[5], 0, &options);
+ ppd = SetCommonOptions(num_options, options, 1);
- ppd = SetCommonOptions(num_options, options, 1);
-
- if (ppd && ppd->landscape > 0)
- NormalLandscape = 1;
-
- if ((val = cupsGetOption("page-ranges", num_options, options)) != NULL)
- PageRanges = val;
-
- if ((val = cupsGetOption("page-set", num_options, options)) != NULL)
- PageSet = val;
-
- if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
- {
- /*
- * This IPP attribute is unnecessarily complicated...
- *
- * single-document, separate-documents-collated-copies, and
- * single-document-new-sheet all require collated copies.
- *
- * separate-documents-uncollated-copies allows for uncollated copies.
- */
+ set_pstops_options(&doc, ppd, argv, num_options, options);
- Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
- }
+ /*
+ * Write any "exit server" options that have been selected...
+ */
- if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
- (!strcasecmp(val, "true") ||!strcasecmp(val, "on") ||
- !strcasecmp(val, "yes")))
- Collate = 1;
+ ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
- if ((val = cupsGetOption("OutputOrder", num_options, options)) != NULL)
- {
- if (!strcasecmp(val, "Reverse"))
- Order = 1;
- }
- else if (ppd)
- {
- /*
- * Figure out the right default output order from the PPD file...
- */
+ /*
+ * Write any JCL commands that are needed to print PostScript code...
+ */
- if ((choice = ppdFindMarkedChoice(ppd, "OutputBin")) != NULL &&
- (attr = ppdFindAttr(ppd, "PageStackOrder", choice->choice)) != NULL &&
- attr->value)
- Order = !strcasecmp(attr->value, "Reverse");
- else if ((attr = ppdFindAttr(ppd, "DefaultOutputOrder", NULL)) != NULL &&
- attr->value)
- Order = !strcasecmp(attr->value, "Reverse");
- }
+ if (doc.emit_jcl)
+ ppdEmitJCL(ppd, stdout, doc.job_id, doc.user, doc.title);
- if ((val = cupsGetOption("number-up", num_options, options)) != NULL)
- NUp = atoi(val);
+ /*
+ * Start with a DSC header...
+ */
- if ((val = cupsGetOption("page-border", num_options, options)) != NULL)
- {
- if (!strcasecmp(val, "none"))
- Border = BORDER_NONE;
- else if (!strcasecmp(val, "single"))
- Border = BORDER_SINGLE;
- else if (!strcasecmp(val, "single-thick"))
- Border = BORDER_SINGLE2;
- else if (!strcasecmp(val, "double"))
- Border = BORDER_DOUBLE;
- else if (!strcasecmp(val, "double-thick"))
- Border = BORDER_DOUBLE2;
- }
+ puts("%!PS-Adobe-3.0");
- if ((val = cupsGetOption("number-up-layout", num_options, options)) != NULL)
- {
- if (!strcasecmp(val, "lrtb"))
- Layout = LAYOUT_LRTB;
- else if (!strcasecmp(val, "lrbt"))
- Layout = LAYOUT_LRBT;
- else if (!strcasecmp(val, "rltb"))
- Layout = LAYOUT_RLTB;
- else if (!strcasecmp(val, "rlbt"))
- Layout = LAYOUT_RLBT;
- else if (!strcasecmp(val, "tblr"))
- Layout = LAYOUT_TBLR;
- else if (!strcasecmp(val, "tbrl"))
- Layout = LAYOUT_TBRL;
- else if (!strcasecmp(val, "btlr"))
- Layout = LAYOUT_BTLR;
- else if (!strcasecmp(val, "btrl"))
- Layout = LAYOUT_BTRL;
- }
+ /*
+ * Skip leading PJL in the document...
+ */
- if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
+ while (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5))
{
/*
- * Get gamma value from 1 to 10000...
+ * Yup, we have leading PJL fun, so skip it until we hit the line
+ * with "ENTER LANGUAGE"...
*/
- g = atoi(val) * 0.001f;
-
- if (g < 0.001f)
- g = 0.001f;
- else if (g > 10.0f)
- g = 10.0f;
- }
+ fputs("DEBUG: Skipping PJL header...\n", stderr);
- if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
- {
- /*
- * Get brightness value from 10 to 1000.
- */
+ while (strstr(line, "ENTER LANGUAGE") == NULL && strncmp(line, "%!", 2))
+ if ((len = cupsFileGetLine(fp, line, sizeof(line))) == 0)
+ break;
- b = atoi(val) * 0.01f;
+ if (!strncmp(line, "%!", 2))
+ break;
- if (b < 0.1f)
- b = 0.1f;
- else if (b > 10.0f)
- b = 10.0f;
+ if ((len = cupsFileGetLine(fp, line, sizeof(line))) == 0)
+ break;
}
- if ((val = cupsGetOption("mirror", num_options, options)) != NULL &&
- (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
- !strcasecmp(val, "yes")))
- Flip = 1;
-
- if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
- (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
- !strcasecmp(val, "yes")))
- FitPlot = 1;
-
- if ((val = cupsGetOption("emit-jcl", num_options, options)) != NULL &&
- (!strcasecmp(val, "false") || !strcasecmp(val, "off") ||
- !strcasecmp(val, "no") || !strcmp(val, "0")))
- emit_jcl = 0;
- else
- emit_jcl = 1;
-
/*
- * Handle input slot/manual feed selections...
+ * Now see if the document conforms to the Adobe Document Structuring
+ * Conventions...
*/
- if ((choice = ppdFindMarkedChoice(ppd, "InputSlot")) != NULL)
- input_slot = choice->choice;
- else
- input_slot = NULL;
-
- if ((choice = ppdFindMarkedChoice(ppd, "ManualFeed")) != NULL)
- manual_feed = choice->choice;
- else
- manual_feed = NULL;
-
- ap_input_slot = cupsGetOption("AP_FIRSTPAGE_InputSlot", num_options,
- options);
- ap_manual_feed = cupsGetOption("AP_FIRSTPAGE_ManualFeed", num_options,
- options);
- min_order = 999.0f;
-
- if (ppd && (ap_input_slot || ap_manual_feed))
+ if (!strncmp(line, "%!PS-Adobe-", 11))
{
/*
- * The first page/sheet will be using different options than
- * the rest, so figure out the minimum order dependency for
- * each of the options...
+ * Yes, filter the document...
*/
- if ((option = ppdFindOption(ppd, "PageRegion")) != NULL &&
- option->order < min_order)
- min_order = option->order;
-
- if ((option = ppdFindOption(ppd, "InputSlot")) != NULL &&
- option->order < min_order)
- min_order = option->order;
-
- if ((option = ppdFindOption(ppd, "ManualFeed")) != NULL &&
- option->order < min_order)
- min_order = option->order;
+ copy_dsc(fp, &doc, ppd, line, len, sizeof(line));
}
-
- if (ppd && ppd->manual_copies && Duplex && Copies > 1)
+ else
{
/*
- * Force collated copies when printing a duplexed document to
- * a non-PS printer that doesn't do hardware copy generation.
- * Otherwise the copies will end up on the front/back side of
- * each page.
+ * No, display an error message and treat the file as if it contains
+ * a single page...
*/
- Collate = 1;
+ copy_non_dsc(fp, &doc, ppd, line, len, sizeof(line));
}
/*
- * See if we have to filter the fast or slow way...
+ * Send %%EOF as needed...
*/
- if (Collate && Copies > 1)
- {
- /*
- * See if we need to manually collate the pages...
- */
-
- slowcollate = 1;
-
- if ((choice = ppdFindMarkedChoice(ppd, "Collate")) != NULL &&
- !strcasecmp(choice->choice, "True"))
- {
- /*
- * Hardware collate option is selected, see if the option is
- * conflicting - if not, collate in hardware. Otherwise,
- * turn the hardware collate option off...
- */
-
- if ((option = ppdFindOption(ppd, "Option")) != NULL &&
- !option->conflicted)
- slowcollate = 0;
- else
- ppdMarkOption(ppd, "Collate", "False");
- }
- }
- else
- slowcollate = 0;
-
- if (ppdFindOption(ppd, "OutputOrder") == NULL && Order)
- sloworder = 1;
- else
- sloworder = 0;
-
- if ((slowcollate || sloworder) && Duplex)
- slowduplex = 1;
- else
- slowduplex = 0;
+ if (!doc.saw_eof)
+ puts("%%EOF");
/*
- * If we need to filter slowly, then create a temporary file for page data...
- *
- * If the temp file can't be created, then we'll ignore the collating/output
- * order options...
+ * End the job with the appropriate JCL command or CTRL-D...
*/
- if (sloworder || slowcollate)
+ if (doc.emit_jcl)
{
- if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
- slowcollate = sloworder = 0;
+ if (ppd && ppd->jcl_end)
+ ppdEmitJCLEnd(ppd, stdout);
+ else
+ putchar(0x04);
}
- else
- temp = NULL;
/*
- * Write any "exit server" options that have been selected...
+ * Close files and remove the temporary file if needed...
*/
- ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
+ if (doc.temp)
+ {
+ cupsFileClose(doc.temp);
+ unlink(doc.tempfile);
+ }
- /*
- * Write any JCL commands that are needed to print PostScript code...
- */
+ ppdClose(ppd);
+ cupsFreeOptions(num_options, options);
- if (emit_jcl)
- ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]);
+ cupsFileClose(fp);
- /*
- * Read the first line to see if we have DSC comments...
- */
+ return (0);
+}
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- {
- fputs("ERROR: Empty print file!\n", stderr);
- ppdClose(ppd);
- return (1);
- }
- /*
- * Handle leading PJL fun...
- */
+/*
+ * 'add_page()' - Add a page to the pages array...
+ */
- while (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5))
- {
- /*
- * Yup, we have leading PJL fun, so skip it until we hit the line
- * with "ENTER LANGUAGE"...
- */
+static pstops_page_t * /* O - New page info object */
+add_page(pstops_doc_t *doc, /* I - Document information */
+ const char *label) /* I - Page label */
+{
+ pstops_page_t *pageinfo; /* New page info object */
- fputs("DEBUG: Skipping PJL header...\n", stderr);
- while (strstr(line, "ENTER LANGUAGE") == NULL)
- {
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- break;
- }
+ if (!doc->pages)
+ doc->pages = cupsArrayNew(NULL, NULL);
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- break;
+ if (!doc->pages)
+ {
+ fprintf(stderr, _("EMERG: Unable to allocate memory for pages array: %s\n"),
+ strerror(errno));
+ exit(1);
}
- /*
- * Start sending the document with any commands needed...
- */
+ if ((pageinfo = calloc(1, sizeof(pstops_page_t))) == NULL)
+ {
+ fprintf(stderr, _("EMERG: Unable to allocate memory for page info: %s\n"),
+ strerror(errno));
+ exit(1);
+ }
- fwrite(line, 1, len, stdout);
+ pageinfo->label = strdup(label);
+ pageinfo->offset = cupsFileTell(doc->temp);
- saweof = 0;
- sent_espsp = 0;
- sent_prolog = 0;
- sent_setup = 0;
+ cupsArrayAdd(doc->pages, pageinfo);
- if (Copies != 1 && (!Collate || !slowcollate))
- {
- /*
- * Tell the document processor the copy and duplex options
- * that are required...
- */
+ doc->page ++;
- printf("%%%%Requirements: numcopies(%d)%s%s\n", Copies,
- Collate ? " collate" : "",
- Duplex ? " duplex" : "");
+ return (pageinfo);
+}
- /*
- * Apple uses RBI comments for various non-PPD options...
- */
- printf("%%RBINumCopies: %d\n", Copies);
- }
- else
- {
- /*
- * Tell the document processor the duplex option that is required...
- */
+/*
+ * 'cancel_job()' - Flag the job as canceled.
+ */
- if (Duplex)
- puts("%%Requirements: duplex");
+static void
+cancel_job(int sig) /* I - Signal number (unused) */
+{
+ (void)sig;
- /*
- * Apple uses RBI comments for various non-PPD options...
- */
+ JobCanceled = 1;
+}
- puts("%RBINumCopies: 1");
- }
- /*
- * Figure out if we should use ESPshowpage or not...
- */
+/*
+ * 'check_range()' - Check to see if the current page is selected for
+ * printing.
+ */
+
+static int /* O - 1 if selected, 0 otherwise */
+check_range(pstops_doc_t *doc, /* I - Document information */
+ int page) /* I - Page number */
+{
+ const char *range; /* Pointer into range string */
+ int lower, upper; /* Lower and upper page numbers */
- val = cupsGetOption("page-label", num_options, options);
- if (val != NULL || getenv("CLASSIFICATION") != NULL || NUp > 1 ||
- Border || strstr(line, "EPS") != NULL)
+ if (doc->page_set)
{
/*
- * Yes, use ESPshowpage...
+ * See if we only print even or odd pages...
*/
- UseESPsp = 1;
+ if (!strcasecmp(doc->page_set, "even") && (page & 1))
+ return (0);
+
+ if (!strcasecmp(doc->page_set, "odd") && !(page & 1))
+ return (0);
}
- fprintf(stderr, "DEBUG: slowcollate=%d, slowduplex=%d, sloworder=%d\n",
- slowcollate, slowduplex, sloworder);
+ if (!doc->page_ranges)
+ return (1); /* No range, print all pages... */
- if (!strncmp(line, "%!PS-Adobe-", 11) && !strstr(line, "EPSF"))
+ for (range = doc->page_ranges; *range != '\0';)
{
- /*
- * OK, we have DSC comments and this isn't an EPS file; read until we
- * find a %%Page comment...
- */
-
- puts("%%Pages: (atend)");
- printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
- PageRight, PageTop);
-
- level = 0;
- lbrt[0] = 0;
- lbrt[1] = 0;
- lbrt[2] = (int)PageWidth;
- lbrt[3] = (int)PageLength;
-
- while (!feof(fp))
+ if (*range == '-')
{
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- break;
-
- if (!strncmp(line, "%%", 2))
- fprintf(stderr, "DEBUG: %d %s", level, line);
- else if (line[0] != '%' && line[0] && !sent_espsp && UseESPsp)
- {
- /*
- * Send ESPshowpage stuff...
- */
-
- sent_espsp = 1;
-
- puts("userdict/ESPshowpage/showpage load put\n"
- "userdict/showpage{}put");
- }
+ lower = 1;
+ range ++;
+ upper = strtol(range, (char **)&range, 10);
+ }
+ else
+ {
+ lower = strtol(range, (char **)&range, 10);
- if (!strncmp(line, "%%BeginDocument:", 16) ||
- !strncmp(line, "%%BeginDocument ", 16) || /* Adobe Acrobat BUG */
- !strncmp(line, "%ADO_BeginApplication", 21))
- {
- fputs(line, stdout);
- level ++;
- }
- else if ((!strncmp(line, "%%EndDocument", 13) ||
- !strncmp(line, "%ADO_EndApplication", 19)) && level > 0)
- {
- fputs(line, stdout);
- level --;
- }
- else if (!strncmp(line, "%cupsRotation:", 14) && level == 0)
+ if (*range == '-')
{
- /*
- * Reset orientation of document?
- */
-
- int orient = (atoi(line + 14) / 90) & 3;
-
- if (orient != Orientation)
- {
- Orientation = (4 - Orientation + orient) & 3;
- UpdatePageVars();
- Orientation = orient;
- }
+ range ++;
+ if (!isdigit(*range & 255))
+ upper = 65535;
+ else
+ upper = strtol(range, (char **)&range, 10);
}
- else if (!strncmp(line, "%%BeginProlog", 13) && level == 0)
- {
- /*
- * Write the existing comment line, and then follow with patches
- * and prolog commands...
- */
+ else
+ upper = lower;
+ }
- fputs(line, stdout);
+ if (page >= lower && page <= upper)
+ return (1);
- if (!sent_prolog)
- {
- sent_prolog = 1;
- do_prolog(ppd);
- }
- }
- else if (!strncmp(line, "%%BeginSetup", 12) && level == 0)
- {
- /*
- * Write the existing comment line, and then follow with document
- * setup commands...
- */
+ if (*range == ',')
+ range ++;
+ else
+ break;
+ }
- fputs(line, stdout);
+ return (0);
+}
- if (!sent_prolog)
- {
- sent_prolog = 1;
- do_prolog(ppd);
- }
- if (!sent_setup)
- {
- sent_setup = 1;
- do_setup(ppd, Copies, Collate, slowcollate, g, b);
- }
- }
- else if (!strncmp(line, "%%BoundingBox:", 14) && level == 0)
- {
- if (sscanf(line + 14, "%d%d%d%d", pagelbrt + 0, pagelbrt + 1,
- pagelbrt + 2, pagelbrt + 3) == 4)
- memcpy(lbrt, pagelbrt, sizeof(lbrt));
- }
- else if (!strncmp(line, "%%Page:", 7) && level == 0)
- break;
- else if (!strncmp(line, "%%IncludeFeature:", 17) && level == 0 &&
- NUp == 1 && !FitPlot)
- include_feature(ppd, line, NULL);
- else if (!strncmp(line, "%%BeginBinary:", 14) ||
- (!strncmp(line, "%%BeginData:", 12) &&
- !strstr(line, "ASCII") && !strstr(line, "Hex")))
- {
- /*
- * Copy binary data...
- */
+/*
+ * 'copy_bytes()' - Copy bytes from the input file to stdout...
+ */
- tbytes = atoi(strchr(line, ':') + 1);
- fputs(line, stdout);
+static void
+copy_bytes(cups_file_t *fp, /* I - File to read from */
+ off_t offset, /* I - Offset to page data */
+ size_t length) /* I - Length of page data */
+{
+ char buffer[8192]; /* Data buffer */
+ ssize_t nbytes; /* Number of bytes read */
+ size_t nleft; /* Number of bytes left/remaining */
- while (tbytes > 0)
- {
- if (tbytes > sizeof(line))
- nbytes = fread(line, 1, sizeof(line), fp);
- else
- nbytes = fread(line, 1, tbytes, fp);
- if (nbytes < 1)
- {
- perror("ERROR: Early end-of-file while reading binary data");
- return (1);
- }
+ nleft = length;
- fwrite(line, 1, nbytes, stdout);
- tbytes -= nbytes;
- }
- }
- else if (strncmp(line, "%%Pages:", 8) != 0)
- fwrite(line, 1, len, stdout);
- }
+ if (cupsFileSeek(fp, offset) < 0)
+ {
+ fprintf(stderr,
+#ifdef HAVE_LONG_LONG
+ _("ERROR: Unable to seek to offset %lld in file - %s\n"),
+#else
+ _("ERROR: Unable to seek to offset %ld in file - %s\n"),
+#endif /* HAVE_LONG_LONG */
+ CUPS_LLCAST offset, strerror(errno));
+ return;
+ }
- /*
- * Make sure we have the prolog and setup commands written...
- */
+ while (nleft > 0 || length == 0)
+ {
+ if (nleft > sizeof(buffer) || length == 0)
+ nbytes = sizeof(buffer);
+ else
+ nbytes = nleft;
- if (!sent_prolog)
- {
- puts("%%BeginProlog");
+ if ((nbytes = cupsFileRead(fp, buffer, nbytes)) < 1)
+ return;
- sent_prolog = 1;
- do_prolog(ppd);
+ nleft -= nbytes;
- puts("%%EndProlog");
- }
+ fwrite(buffer, 1, nbytes, stdout);
+ }
+}
- if (!sent_setup)
- {
- puts("%%BeginSetup");
- sent_setup = 1;
- do_setup(ppd, Copies, Collate, slowcollate, g, b);
+/*
+ * 'copy_comments()' - Copy all of the comments section...
+ *
+ * This function expects "line" to be filled with a comment line.
+ * On return, "line" will contain the next line in the file, if any.
+ */
- puts("%%EndSetup");
- }
+static ssize_t /* O - Length of next line */
+copy_comments(cups_file_t *fp, /* I - File to read from */
+ pstops_doc_t *doc, /* I - Document info */
+ ppd_file_t *ppd, /* I - PPD file */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
+{
+ int saw_bounding_box, /* Saw %%BoundingBox: comment? */
+ saw_for, /* Saw %%For: comment? */
+ saw_pages, /* Saw %%Pages: comment? */
+ saw_title; /* Saw %%Title: comment? */
- if (!sent_espsp && UseESPsp)
- {
- /*
- * Send ESPshowpage stuff...
- */
- sent_espsp = 1;
+ /*
+ * Loop until we see %%EndComments or a non-comment line...
+ */
- puts("userdict/ESPshowpage/showpage load put\n"
- "userdict/showpage{}put");
- }
+ saw_bounding_box = 0;
+ saw_for = 0;
+ saw_pages = 0;
+ saw_title = 0;
+ while (line[0] == '%')
+ {
/*
- * Write the page and label prologs...
+ * Strip trailing whitespace...
*/
- if (NUp == 2 || NUp == 6)
+ while (linelen > 0)
{
- /*
- * For 2- and 6-up output, rotate the labels to match the orientation
- * of the pages...
- */
+ linelen --;
- if (Orientation & 1)
- WriteLabelProlog(val, PageBottom, PageWidth - PageLength + PageTop,
- PageLength);
+ if (!isspace(line[linelen] & 255))
+ break;
else
- WriteLabelProlog(val, PageLeft, PageRight, PageLength);
+ line[linelen] = '\0';
}
- else
- WriteLabelProlog(val, PageBottom, PageTop, PageWidth);
/*
- * Then read all of the pages, filtering as needed...
+ * Log the header...
*/
- for (page = 1, real_page = 1, pageinfo = NULL;;)
- {
- if (!strncmp(line, "%%", 2))
- fprintf(stderr, "DEBUG: %d %s", level, line);
-
- if (!strncmp(line, "%%BeginDocument:", 16) ||
- !strncmp(line, "%%BeginDocument ", 16) || /* Adobe Acrobat BUG */
- !strncmp(line, "%ADO_BeginApplication", 21))
- {
- level ++;
-
- if (!sloworder)
- fputs(line, stdout);
-
- if (slowcollate || sloworder)
- cupsFilePuts(temp, line);
- }
- else if ((!strncmp(line, "%%EndDocument", 13) ||
- !strncmp(line, "%ADO_EndApplication", 19)) && level > 0)
- {
- level --;
-
- if (!sloworder)
- fputs(line, stdout);
-
- if (slowcollate || sloworder)
- cupsFilePuts(temp, line);
- }
- else if (!strcmp(line, "\004") && len == 1)
- break;
- else if (!strncmp(line, "%%EOF", 5) && level == 0)
- {
- fputs("DEBUG: Saw EOF!\n", stderr);
- saweof = 1;
- break;
- }
- else if (!strncmp(line, "%%Page:", 7) && level == 0)
- {
- if (!check_range(real_page))
- {
- while (!feof(fp))
- {
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- break;
-
- if (!strncmp(line, "%%", 2))
- fprintf(stderr, "DEBUG: %d %s", level, line);
-
- if (!strncmp(line, "%%BeginDocument:", 16) ||
- !strncmp(line, "%%BeginDocument ", 16) || /* Adobe Acrobat BUG */
- !strncmp(line, "%ADO_BeginApplication", 21))
- level ++;
- else if ((!strncmp(line, "%%EndDocument", 13) ||
- !strncmp(line, "%ADO_EndApplication", 19)) && level > 0)
- level --;
- else if (!strncmp(line, "%%Page:", 7) && level == 0)
- {
- real_page ++;
- break;
- }
- else if (!strncmp(line, "%%BeginBinary:", 14) ||
- (!strncmp(line, "%%BeginData:", 12) &&
- !strstr(line, "ASCII") && !strstr(line, "Hex")))
- {
- /*
- * Skip binary data...
- */
-
- tbytes = atoi(strchr(line, ':') + 1);
-
- while (tbytes > 0)
- {
- if (tbytes > sizeof(line))
- nbytes = fread(line, 1, sizeof(line), fp);
- else
- nbytes = fread(line, 1, tbytes, fp);
-
- if (nbytes < 1)
- {
- perror("ERROR: Early end-of-file while reading binary data");
- return (1);
- }
-
- tbytes -= nbytes;
- }
- }
- }
-
- continue;
- }
-
- if (!sloworder && NumPages > 0)
- end_nup(NumPages - 1);
+ fprintf(stderr, "DEBUG: %s\n", line);
- if (sscanf(line, "%%%%Page:%255s%*d", label) != 1)
- sprintf(label, "%d", page);
+ /*
+ * Pull the headers out...
+ */
- if (slowcollate || sloworder)
- {
- pageinfo = add_page(label, cupsFileTell(temp), lbrt);
+ if (!strncmp(line, "%%Pages:", 8))
+ {
+ int pages; /* Number of pages */
- if (ap_input_slot || ap_manual_feed)
- {
- if (page == 0)
- {
- pageinfo->input_slot = ap_input_slot;
- pageinfo->manual_feed = ap_manual_feed;
- }
- else if (page == (1 + Duplex))
- {
- pageinfo->input_slot = input_slot;
- pageinfo->manual_feed = manual_feed;
- }
- }
- }
- else
- pageinfo = NULL;
- if (!sloworder)
- {
- if (is_first_page(NumPages))
- {
- if (ppd == NULL || ppd->num_filters == 0)
- fprintf(stderr, "PAGE: %d %d\n", page, slowcollate ? 1 : Copies);
-
- if (NUp > 1)
- printf("%%%%Page: %d %d\n", page, page);
- else
- printf("%%%%Page: %s %d\n", label, page);
-
- if (ap_input_slot || ap_manual_feed)
- {
- if (page == 0)
- {
- if (ap_input_slot)
- ppdMarkOption(ppd, "InputSlot", ap_input_slot);
- if (ap_manual_feed)
- ppdMarkOption(ppd, "ManualFeed", ap_manual_feed);
- }
- else if (page == (1 + Duplex))
- {
- if (input_slot)
- ppdMarkOption(ppd, "InputSlot", input_slot);
- if (manual_feed)
- ppdMarkOption(ppd, "ManualFeed", manual_feed);
- }
-
- ppdEmitAfterOrder(ppd, stdout, PPD_ORDER_DOCUMENT, 1, min_order);
- ppdEmitAfterOrder(ppd, stdout, PPD_ORDER_ANY, 1, min_order);
- }
-
- page ++;
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
- }
+ if (saw_pages)
+ fputs(_("ERROR: Duplicate %%Pages: comment seen!\n"), stderr);
- start_nup(NumPages, 1, lbrt);
- }
+ saw_pages = 1;
- NumPages ++;
- real_page ++;
- }
- else if (!strncmp(line, "%%PageBoundingBox:", 18) && level == 0 &&
- pageinfo)
- {
- if (sscanf(line + 18, "%d%d%d%d", pagelbrt + 0, pagelbrt + 1,
- pagelbrt + 2, pagelbrt + 3) == 4)
- memcpy(pageinfo->lbrt, pagelbrt, sizeof(pageinfo->lbrt));
- }
- else if (!strncmp(line, "%%BeginBinary:", 14) ||
- (!strncmp(line, "%%BeginData:", 12) &&
- !strstr(line, "ASCII") && !strstr(line, "Hex")))
+ if (Duplex && (pages = atoi(line + 8)) > 0 && pages <= doc->number_up)
{
/*
- * Copy binary data...
+ * Since we will only be printing on a single page, disable duplexing.
*/
- tbytes = atoi(strchr(line, ':') + 1);
-
- if (!sloworder)
- fputs(line, stdout);
- if (slowcollate || sloworder)
- cupsFilePuts(temp, line);
+ Duplex = 0;
+ doc->slow_duplex = 0;
- while (tbytes > 0)
- {
- if (tbytes > sizeof(line))
- nbytes = fread(line, 1, sizeof(line), fp);
- else
- nbytes = fread(line, 1, tbytes, fp);
+ if (cupsGetOption("sides", doc->num_options, doc->options))
+ doc->num_options = cupsAddOption("sides", "one-sided",
+ doc->num_options, &(doc->options));
- if (nbytes < 1)
- {
- perror("ERROR: Early end-of-file while reading binary data");
- return (1);
- }
+ if (cupsGetOption("Duplex", doc->num_options, doc->options))
+ doc->num_options = cupsAddOption("Duplex", "None",
+ doc->num_options, &(doc->options));
- if (!sloworder)
- fwrite(line, 1, nbytes, stdout);
+ if (cupsGetOption("EFDuplex", doc->num_options, doc->options))
+ doc->num_options = cupsAddOption("EFDuplex", "None",
+ doc->num_options, &(doc->options));
- if (slowcollate || sloworder)
- cupsFileWrite(temp, line, nbytes);
+ if (cupsGetOption("EFDuplexing", doc->num_options, doc->options))
+ doc->num_options = cupsAddOption("EFDuplexing", "False",
+ doc->num_options, &(doc->options));
- tbytes -= nbytes;
- }
- }
- else if (!strncmp(line, "%%IncludeFeature:", 17) && level == 0 &&
- NUp == 1 && !FitPlot)
- {
- /*
- * Embed printer commands as needed...
- */
+ if (cupsGetOption("KD03Duplex", doc->num_options, doc->options))
+ doc->num_options = cupsAddOption("KD03Duplex", "None",
+ doc->num_options, &(doc->options));
- if (level == 0 && NUp == 1)
- {
- include_feature(ppd, line, NULL);
+ if (cupsGetOption("JCLDuplex", doc->num_options, doc->options))
+ doc->num_options = cupsAddOption("JCLDuplex", "None",
+ doc->num_options, &(doc->options));
- if (slowcollate || sloworder)
- include_feature(ppd, line, temp);
- }
+ ppdMarkOption(ppd, "Duplex", "None");
+ ppdMarkOption(ppd, "EFDuplex", "None");
+ ppdMarkOption(ppd, "EFDuplexing", "False");
+ ppdMarkOption(ppd, "KD03Duplex", "None");
+ ppdMarkOption(ppd, "JCLDuplex", "None");
}
- else if (!strncmp(line, "%%BeginFeature:", 15) && (NUp > 1 || FitPlot))
+ }
+ else if (!strncmp(line, "%%BoundingBox:", 14))
+ {
+ if (saw_bounding_box)
+ fputs(_("ERROR: Duplicate %%BoundingBox: comment seen!\n"), stderr);
+ else if (strstr(line + 14, "(atend)"))
{
/*
- * Strip page options for N-up > 1 or "fitplot"...
+ * Do nothing for now but use the default imageable area...
*/
-
- do
- {
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- break;
- }
- while (strncmp(line, "%%EndFeature", 12));
- }
- else if (!strncmp(line, "%%Trailer", 9) && level == 0)
- {
- fputs("DEBUG: Saw Trailer!\n", stderr);
- break;
}
- else
+ else if (sscanf(line + 14, "%d%d%d%d", doc->bounding_box + 0,
+ doc->bounding_box + 1, doc->bounding_box + 2,
+ doc->bounding_box + 3) != 4)
{
- if (!sloworder)
- fwrite(line, 1, len, stdout);
+ fputs(_("ERROR: Bad %%BoundingBox: comment seen!\n"), stderr);
- if (slowcollate || sloworder)
- cupsFileWrite(temp, line, len);
+ doc->bounding_box[0] = (int)PageLeft;
+ doc->bounding_box[1] = (int)PageBottom;
+ doc->bounding_box[2] = (int)PageRight;
+ doc->bounding_box[3] = (int)PageTop;
}
- /*
- * Get next line from file...
- */
-
- if (pageinfo)
- pageinfo->length = cupsFileTell(temp) - pageinfo->offset;
-
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- break;
+ saw_bounding_box = 1;
}
-
- if (!sloworder)
+ else if (!strncmp(line, "%%For:", 6))
{
- end_nup(NumPages - 1);
+ saw_for = 1;
+ doc_printf(doc, "%s\n", line);
+ }
+ else if (!strncmp(line, "%%Title:", 8))
+ {
+ saw_title = 1;
+ doc_printf(doc, "%s\n", line);
+ }
+ else if (!strncmp(line, "%cupsRotation:", 14))
+ {
+ /*
+ * Reset orientation of document?
+ */
- if (is_not_last_page(NumPages))
- {
- start_nup(NUp - 1, 0, lbrt);
- end_nup(NUp - 1);
- }
+ int orient = (atoi(line + 14) / 90) & 3;
- if (slowduplex && !(page & 1))
+ if (orient != Orientation)
{
/*
- * Make sure we have an even number of pages...
+ * Yes, update things so that the pages come out right...
*/
- if (ppd == NULL || ppd->num_filters == 0)
- fprintf(stderr, "PAGE: %d %d\n", page, slowcollate ? 1 : Copies);
-
- printf("%%%%Page: %d %d\n", page, page);
- page ++;
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
-
- start_nup(NUp - 1, 0, lbrt);
- puts("showpage");
- end_nup(NUp - 1);
+ Orientation = (4 - Orientation + orient) & 3;
+ UpdatePageVars();
+ Orientation = orient;
}
}
-
- if (slowcollate || sloworder)
+ else if (!strcmp(line, "%%EndComments"))
{
- if (!sloworder)
- {
- while (Copies > 1)
- {
- for (number = 0, pageinfo = (page_info_t *)cupsArrayFirst(Pages);
- number < NumPages && pageinfo;
- number ++, pageinfo = (page_info_t *)cupsArrayNext(Pages))
- {
- if (is_first_page(number))
- {
- if (ppd == NULL || ppd->num_filters == 0)
- fprintf(stderr, "PAGE: %d 1\n", page);
-
- if (NUp == 1)
- printf("%%%%Page: %s %d\n", pageinfo->label, page);
- else
- printf("%%%%Page: %d %d\n", page, page);
-
- if (pageinfo->input_slot || pageinfo->manual_feed)
- {
- if (pageinfo->input_slot)
- ppdMarkOption(ppd, "InputSlot", pageinfo->input_slot);
- if (pageinfo->manual_feed)
- ppdMarkOption(ppd, "ManualFeed", pageinfo->manual_feed);
-
- ppdEmitAfterOrder(ppd, stdout, PPD_ORDER_DOCUMENT, 1, min_order);
- ppdEmitAfterOrder(ppd, stdout, PPD_ORDER_ANY, 1, min_order);
- }
-
- page ++;
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
- }
-
- start_nup(number, 1, pageinfo->lbrt);
- copy_bytes(temp, pageinfo->offset, pageinfo->length);
- end_nup(number);
- }
-
- if (is_not_last_page(NumPages))
- {
- start_nup(NUp - 1, 0, lbrt);
- end_nup(NUp - 1);
- }
-
- if (slowduplex && !(page & 1))
- {
- /*
- * Make sure we have an even number of pages...
- */
-
- if (ppd == NULL || ppd->num_filters == 0)
- fprintf(stderr, "PAGE: %d 1\n", page);
-
- printf("%%%%Page: %d %d\n", page, page);
- page ++;
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
-
- start_nup(NUp - 1, 0, lbrt);
- puts("showpage");
- end_nup(NUp - 1);
- }
+ linelen = cupsFileGetLine(fp, line, linesize);
+ break;
+ }
+ else if (strncmp(line, "%!", 2) && strncmp(line, "%cups", 5))
+ doc_printf(doc, "%s\n", line);
- Copies --;
- }
- }
- else
- {
- page_count = (NumPages + NUp - 1) / NUp;
- copy = 0;
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+ }
- fprintf(stderr, "DEBUG: page_count=%d\n", page_count);
+ if (!saw_bounding_box)
+ fputs(_("ERROR: No %%BoundingBox: comment in header!\n"), stderr);
- do
- {
- if (slowduplex && (page_count & 1))
- basepage = page_count;
- else
- basepage = page_count - 1;
+ if (!saw_pages)
+ fputs(_("ERROR: No %%Pages: comment in header!\n"), stderr);
- for (; basepage >= 0; basepage --)
- {
- if (ppd == NULL || ppd->num_filters == 0)
- fprintf(stderr, "PAGE: %d %d\n", page,
- slowcollate ? 1 : Copies);
-
- pageinfo = (page_info_t *)cupsArrayIndex(Pages, basepage);
-
- if (NUp == 1)
- printf("%%%%Page: %s %d\n", pageinfo->label, page);
- else
- printf("%%%%Page: %d %d\n", page, page);
-
- if (pageinfo->input_slot || pageinfo->manual_feed)
- {
- if (pageinfo->input_slot)
- ppdMarkOption(ppd, "InputSlot", pageinfo->input_slot);
- if (pageinfo->manual_feed)
- ppdMarkOption(ppd, "ManualFeed", pageinfo->manual_feed);
-
- ppdEmitAfterOrder(ppd, stdout, PPD_ORDER_DOCUMENT, 1, min_order);
- ppdEmitAfterOrder(ppd, stdout, PPD_ORDER_ANY, 1, min_order);
- }
-
- page ++;
-
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
-
- if (basepage >= page_count)
- {
- start_nup(NUp - 1, 0, pageinfo->lbrt);
- puts("showpage");
- end_nup(NUp - 1);
- }
- else
- {
- for (subpage = 0, number = basepage * NUp;
- subpage < NUp && number < NumPages;
- subpage ++, number ++)
- {
- pageinfo = (page_info_t *)cupsArrayIndex(Pages, number);
-
- start_nup(number, 1, pageinfo->lbrt);
- copy_bytes(temp, pageinfo->offset, pageinfo->length);
- end_nup(number);
- }
-
- if (is_not_last_page(number))
- {
- start_nup(NUp - 1, 0, lbrt);
- end_nup(NUp - 1);
- }
- }
- }
+ if (!saw_for)
+ WriteTextComment("For", doc->user);
- copy ++;
- }
- while (copy < Copies && slowcollate);
- }
- }
+ if (!saw_title)
+ WriteTextComment("Title", doc->title);
+ if (doc->copies != 1 && (!doc->collate || !doc->slow_collate))
+ {
/*
- * Copy the trailer, if any...
+ * Tell the document processor the copy and duplex options
+ * that are required...
*/
- puts("%%Trailer");
- printf("%%%%Pages: %d\n", page - 1);
-
- if (UseESPsp)
- puts("userdict/showpage/ESPshowpage load put\n");
-
- while (!feof(fp))
- {
- len = sizeof(line);
- if (psgets(line, &len, fp) == NULL)
- break;
+ doc_printf(doc, "%%%%Requirements: numcopies(%d)%s%s\n", doc->copies,
+ doc->collate ? " collate" : "",
+ Duplex ? " duplex" : "");
- if (!(!strcmp(line, "\004") && len == 1) &&
- strncmp(line, "%%Pages:", 8) != 0)
- fwrite(line, 1, len, stdout);
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
- if (!strncmp(line, "%%EOF", 5))
- {
- fputs("DEBUG: Saw EOF!\n", stderr);
- saweof = 1;
- break;
- }
- }
+ doc_printf(doc, "%%RBINumCopies: %d\n", doc->copies);
}
else
{
/*
- * No DSC comments - write any page commands and then the rest of the file...
+ * Tell the document processor the duplex option that is required...
*/
- if (slowcollate && Copies > 1)
- printf("%%%%Pages: %d\n", Copies);
- else
- puts("%%Pages: 1");
+ if (Duplex)
+ doc_puts(doc, "%%Requirements: duplex\n");
- if (UseESPsp)
- puts("userdict/ESPshowpage/showpage load put\n"
- "userdict/showpage{}put");
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
- puts("%%BeginProlog");
- WriteLabelProlog(val, PageBottom, PageTop, PageWidth);
- do_prolog(ppd);
- puts("%%EndProlog");
+ doc_puts(doc, "%RBINumCopies: 1\n");
+ }
- puts("%%BeginSetup");
- do_setup(ppd, Copies, Collate, slowcollate, g, b);
- puts("%%EndSetup");
+ doc_puts(doc, "%%Pages: (atend)\n");
+ doc_puts(doc, "%%BoundingBox: (atend)\n");
+ doc_puts(doc, "%%EndComments\n");
- if (ppd == NULL || ppd->num_filters == 0)
- fprintf(stderr, "PAGE: 1 %d\n", slowcollate ? 1 : Copies);
+ return (linelen);
+}
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
- saweof = 1;
+/*
+ * 'copy_dsc()' - Copy a DSC-conforming document...
+ *
+ * This function expects "line" to be filled with the %!PS-Adobe comment line.
+ */
- while ((nbytes = fread(line, 1, sizeof(line), fp)) > 0)
- {
- fwrite(line, 1, nbytes, stdout);
+static void
+copy_dsc(cups_file_t *fp, /* I - File to read from */
+ pstops_doc_t *doc, /* I - Document info */
+ ppd_file_t *ppd, /* I - PPD file */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
+{
+ int number; /* Page number */
+ pstops_page_t *pageinfo; /* Page information */
- if (slowcollate)
- cupsFileWrite(temp, line, nbytes);
- }
- if (UseESPsp)
- {
- WriteLabels(Orientation);
- puts("ESPshowpage");
- }
+ /*
+ * Make sure we use ESPshowpage for EPS files...
+ */
- if (slowcollate)
- {
- while (Copies > 1)
- {
- if (ppd == NULL || ppd->num_filters == 0)
- fputs("PAGE: 1 1\n", stderr);
+ if (strstr(line, "EPSF"))
+ {
+ doc->use_ESPshowpage = 1;
+ doc->number_up = 1;
+ }
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
- copy_bytes(temp, 0, 0);
- Copies --;
+ /*
+ * Start sending the document with any commands needed...
+ */
- if (UseESPsp)
- {
- WriteLabels(Orientation);
- puts("ESPshowpage");
- }
- }
- }
- }
+ fprintf(stderr, "DEBUG: Before copy_comments - %s", line);
+ linelen = copy_comments(fp, doc, ppd, line, linelen, linesize);
/*
- * Send %%EOF if needed...
+ * Now find the prolog section, if any...
*/
- if (!saweof)
- puts("%%EOF");
+ fprintf(stderr, "DEBUG: Before copy_prolog - %s", line);
+ linelen = copy_prolog(fp, doc, ppd, line, linelen, linesize);
/*
- * End the job with the appropriate JCL command or CTRL-D otherwise.
+ * Then the document setup section...
*/
- if (emit_jcl)
+ fprintf(stderr, "DEBUG: Before copy_setup - %s", line);
+ linelen = copy_setup(fp, doc, ppd, line, linelen, linesize);
+
+ /*
+ * Copy until we see %%Page:...
+ */
+
+ while (strncmp(line, "%%Page:", 7) && strncmp(line, "%%Trailer", 9))
{
- if (ppd && ppd->jcl_end)
- ppdEmitJCLEnd(ppd, stdout);
+ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+ }
+
+ /*
+ * Then process pages until we have no more...
+ */
+
+ number = 0;
+
+ fprintf(stderr, "DEBUG: Before page loop - %s", line);
+ while (!strncmp(line, "%%Page:", 7))
+ {
+ if (JobCanceled)
+ break;
+
+ number ++;
+
+ if (check_range(doc, (number - 1) / doc->number_up + 1))
+ {
+ fprintf(stderr, "DEBUG: Copying page %d...\n", number);
+ linelen = copy_page(fp, doc, ppd, number, line, linelen, linesize);
+ }
else
- putchar(0x04);
+ {
+ fprintf(stderr, "DEBUG: Skipping page %d...\n", number);
+ linelen = skip_page(fp, line, linelen, linesize);
+ }
}
/*
- * Close files and remove the temporary file if needed...
+ * Finish up the last page(s)...
*/
- if (slowcollate || sloworder)
+ if (number && is_not_last_page(number) && cupsArrayLast(doc->pages) &&
+ check_range(doc, (number - 1) / doc->number_up + 1))
{
- cupsFileClose(temp);
- unlink(tempfile);
+ pageinfo = (pstops_page_t *)cupsArrayLast(doc->pages);
+
+ start_nup(doc, doc->number_up, 0, doc->bounding_box);
+ doc_puts(doc, "showpage\n");
+ end_nup(doc, doc->number_up);
+
+ pageinfo->length = cupsFileTell(doc->temp) - pageinfo->offset;
}
- ppdClose(ppd);
+ if (doc->slow_duplex && (doc->page & 1))
+ {
+ /*
+ * Make sure we have an even number of pages...
+ */
- if (fp != stdin)
- fclose(fp);
+ pageinfo = add_page(doc, "(filler)");
- return (0);
-}
+ if (!doc->slow_order)
+ {
+ if (!ppd || !ppd->num_filters)
+ fprintf(stderr, "PAGE: %d %d\n", doc->page,
+ doc->slow_collate ? 1 : doc->copies);
+ printf("%%%%Page: (filler) %d\n", doc->page);
+ }
-/*
- * 'check_range()' - Check to see if the current page is selected for
- * printing.
- */
+ start_nup(doc, doc->number_up, 0, doc->bounding_box);
+ doc_puts(doc, "showpage\n");
+ end_nup(doc, doc->number_up);
-static int /* O - 1 if selected, 0 otherwise */
-check_range(int page) /* I - Page number */
-{
- const char *range; /* Pointer into range string */
- int lower, upper; /* Lower and upper page numbers */
+ pageinfo->length = cupsFileTell(doc->temp) - pageinfo->offset;
+ }
+ /*
+ * Make additional copies as necessary...
+ */
- if (PageSet != NULL)
+ number = doc->slow_order ? 0 : doc->page;
+
+ if (doc->temp && !JobCanceled && cupsArrayCount(doc->pages) > 0)
{
+ int copy; /* Current copy */
+
+
/*
- * See if we only print even or odd pages...
+ * Reopen the temporary file for reading...
*/
- if (!strcasecmp(PageSet, "even") && ((page - 1) % (NUp << 1)) < NUp)
- return (0);
- if (!strcasecmp(PageSet, "odd") && ((page - 1) % (NUp << 1)) >= NUp)
- return (0);
- }
+ cupsFileClose(doc->temp);
- if (PageRanges == NULL)
- return (1); /* No range, print all pages... */
+ doc->temp = cupsFileOpen(doc->tempfile, "r");
- for (range = PageRanges; *range != '\0';)
- {
- if (*range == '-')
- {
- lower = 1;
- range ++;
- upper = strtol(range, (char **)&range, 10);
- }
+ /*
+ * Make the copies...
+ */
+
+ if (doc->slow_collate)
+ copy = !doc->slow_order;
else
+ copy = doc->copies - 1;
+
+ for (; copy < doc->copies; copy ++)
{
- lower = strtol(range, (char **)&range, 10);
+ if (JobCanceled)
+ break;
- if (*range == '-')
+ /*
+ * Send end-of-job stuff followed by any start-of-job stuff required
+ * for the JCL options...
+ */
+
+ if (number && doc->emit_jcl && ppd && ppd->jcl_end)
{
- range ++;
- if (!isdigit(*range & 255))
- upper = 65535;
+ /*
+ * Send the trailer...
+ */
+
+ puts("%%Trailer");
+ printf("%%%%Pages: %d\n", cupsArrayCount(doc->pages));
+ if (doc->number_up > 1 || doc->fitplot)
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
+ PageLeft, PageBottom, PageRight, PageTop);
else
- upper = strtol(range, (char **)&range, 10);
+ printf("%%%%BoundingBox: %d %d %d %d\n",
+ doc->new_bounding_box[0], doc->new_bounding_box[1],
+ doc->new_bounding_box[2], doc->new_bounding_box[3]);
+ puts("%%EOF");
+
+ /*
+ * Start a new document...
+ */
+
+ ppdEmitJCLEnd(ppd, stdout);
+ ppdEmitJCL(ppd, stdout, doc->job_id, doc->user, doc->title);
+
+ puts("%!PS-Adobe-3.0");
+
+ number = 0;
}
- else
- upper = lower;
- }
- if (page >= lower && page <= upper)
- return (1);
+ /*
+ * Copy the prolog as needed...
+ */
- if (*range == ',')
- range ++;
- else
- break;
+ if (!number)
+ {
+ pageinfo = (pstops_page_t *)cupsArrayFirst(doc->pages);
+ copy_bytes(doc->temp, 0, pageinfo->offset);
+ }
+
+ /*
+ * Then copy all of the pages...
+ */
+
+ pageinfo = doc->slow_order ? (pstops_page_t *)cupsArrayLast(doc->pages) :
+ (pstops_page_t *)cupsArrayFirst(doc->pages);
+
+ while (pageinfo)
+ {
+ if (JobCanceled)
+ break;
+
+ number ++;
+
+ if (!ppd || !ppd->num_filters)
+ fprintf(stderr, "PAGE: %d %d\n", number,
+ doc->slow_collate ? 1 : doc->copies);
+
+ if (doc->number_up > 1)
+ {
+ printf("%%%%Page: (%d) %d\n", number, number);
+ printf("%%%%PageBoundingBox: %.0f %.0f %.0f %.0f\n",
+ PageLeft, PageBottom, PageRight, PageTop);
+ }
+ else
+ {
+ printf("%%%%Page: %s %d\n", pageinfo->label, number);
+ printf("%%%%PageBoundingBox: %d %d %d %d\n",
+ pageinfo->bounding_box[0], pageinfo->bounding_box[1],
+ pageinfo->bounding_box[2], pageinfo->bounding_box[3]);
+ }
+
+ copy_bytes(doc->temp, pageinfo->offset, pageinfo->length);
+
+ pageinfo = doc->slow_order ? (pstops_page_t *)cupsArrayPrev(doc->pages) :
+ (pstops_page_t *)cupsArrayNext(doc->pages);
+ }
+ }
}
- return (0);
+ /*
+ * Restore the old showpage operator as needed...
+ */
+
+ if (doc->use_ESPshowpage)
+ puts("userdict/showpage/ESPshowpage load put\n");
+
+ /*
+ * Write/copy the trailer...
+ */
+
+ if (!JobCanceled)
+ linelen = copy_trailer(fp, doc, ppd, number, line, linelen, linesize);
}
/*
- * 'add_page()' - Add a page to the Pages array...
+ * 'copy_non_dsc()' - Copy a document that does not conform to the DSC...
+ *
+ * This function expects "line" to be filled with the %! comment line.
*/
-static page_info_t * /* O - New page info object */
-add_page(const char *label, /* I - Page label */
- off_t offset, /* I - Offset in file */
- const int *lbrt) /* I - BoundingBox for page */
+static void
+copy_non_dsc(cups_file_t *fp, /* I - File to read from */
+ pstops_doc_t *doc, /* I - Document info */
+ ppd_file_t *ppd, /* I - PPD file */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
{
- page_info_t *pageinfo; /* New page info object */
+ int copy; /* Current copy */
+ char buffer[8192]; /* Copy buffer */
+ int bytes; /* Number of bytes copied */
+
+
+ /*
+ * First let the user know that they are attempting to print a file
+ * that may not print correctly...
+ */
+
+ fputs(_("WARNING: This document does not conform to the Adobe Document "
+ "Structuring Conventions and may not print correctly!\n"), stderr);
+
+ /*
+ * Then write a standard DSC comment section...
+ */
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
+ PageRight, PageTop);
- if (!Pages)
- Pages = cupsArrayNew(NULL, NULL);
+ if (doc->slow_collate && doc->copies > 1)
+ printf("%%%%Pages: %d\n", doc->copies);
+ else
+ puts("%%Pages: 1");
+
+ WriteTextComment("For", doc->user);
+ WriteTextComment("Title", doc->title);
- if (!Pages)
+ if (doc->copies != 1 && (!doc->collate || !doc->slow_collate))
{
- fprintf(stderr, "EMERG: Unable to allocate memory for pages array: %s\n",
- strerror(errno));
- exit(1);
- }
+ /*
+ * Tell the document processor the copy and duplex options
+ * that are required...
+ */
+
+ printf("%%%%Requirements: numcopies(%d)%s%s\n", doc->copies,
+ doc->collate ? " collate" : "",
+ Duplex ? " duplex" : "");
+
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
- if ((pageinfo = calloc(1, sizeof(page_info_t))) == NULL)
+ printf("%%RBINumCopies: %d\n", doc->copies);
+ }
+ else
{
- fprintf(stderr, "EMERG: Unable to allocate memory for page info: %s\n",
- strerror(errno));
- exit(1);
+ /*
+ * Tell the document processor the duplex option that is required...
+ */
+
+ if (Duplex)
+ puts("%%Requirements: duplex");
+
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
+
+ puts("%RBINumCopies: 1");
}
- pageinfo->label = strdup(label);
- pageinfo->offset = offset;
+ puts("%%EndComments");
- memcpy(pageinfo->lbrt, lbrt, sizeof(pageinfo->lbrt));
+ /*
+ * Then the prolog...
+ */
- cupsArrayAdd(Pages, pageinfo);
+ puts("%%BeginProlog");
- return (pageinfo);
-}
+ do_prolog(doc, ppd);
+ puts("%%EndProlog");
-/*
- * 'copy_bytes()' - Copy bytes from the input file to stdout...
- */
+ /*
+ * Then the setup section...
+ */
-static void
-copy_bytes(cups_file_t *fp, /* I - File to read from */
- off_t offset, /* I - Offset to page data */
- size_t length) /* I - Length of page data */
-{
- char buffer[8192]; /* Data buffer */
- ssize_t nbytes; /* Number of bytes read */
- size_t nleft; /* Number of bytes left/remaining */
+ puts("%%BeginSetup");
+ do_setup(doc, ppd);
- nleft = length;
+ puts("%%EndSetup");
+
+ /*
+ * Finally, embed a copy of the file inside a %%Page...
+ */
- cupsFileSeek(fp, offset);
+ if (!ppd || !ppd->num_filters)
+ fprintf(stderr, "PAGE: 1 %d\n", doc->temp ? 1 : doc->copies);
- while (nleft > 0 || length == 0)
+ puts("%%Page: 1 1");
+ puts("%%BeginPageSetup");
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+ puts("%%EndPageSetup");
+ puts("%%BeginDocument: nondsc");
+
+ fwrite(line, linelen, 1, stdout);
+
+ if (doc->temp)
+ cupsFileWrite(doc->temp, line, linelen);
+
+ while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
{
- if (nleft > sizeof(buffer) || length == 0)
- nbytes = sizeof(buffer);
- else
- nbytes = nleft;
+ fwrite(buffer, 1, bytes, stdout);
- if ((nbytes = cupsFileRead(fp, buffer, nbytes)) < 1)
- return;
+ if (doc->temp)
+ cupsFileWrite(doc->temp, buffer, bytes);
+ }
- nleft -= nbytes;
+ puts("%%EndDocument");
- fwrite(buffer, 1, nbytes, stdout);
+ if (doc->use_ESPshowpage)
+ {
+ WriteLabels(Orientation);
+ puts("ESPshowpage");
+ }
+
+ if (doc->temp && !JobCanceled)
+ {
+ /*
+ * Reopen the temporary file for reading...
+ */
+
+ cupsFileClose(doc->temp);
+
+ doc->temp = cupsFileOpen(doc->tempfile, "r");
+
+ /*
+ * Make the additional copies as needed...
+ */
+
+ for (copy = 1; copy < doc->copies; copy ++)
+ {
+ if (JobCanceled)
+ break;
+
+ if (!ppd || !ppd->num_filters)
+ fputs("PAGE: 1 1\n", stderr);
+
+ printf("%%%%Page: %d %d\n", copy + 1, copy + 1);
+ puts("%%BeginPageSetup");
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+ puts("%%EndPageSetup");
+ puts("%%BeginDocument: nondsc");
+
+ copy_bytes(doc->temp, 0, 0);
+
+ puts("%%EndDocument");
+
+ if (doc->use_ESPshowpage)
+ {
+ WriteLabels(Orientation);
+ puts("ESPshowpage");
+ }
+ }
}
+
+ /*
+ * Restore the old showpage operator as needed...
+ */
+
+ if (doc->use_ESPshowpage)
+ puts("userdict/showpage/ESPshowpage load put\n");
}
/*
- * 'do_prolog()' - Send the necessary document prolog commands...
+ * 'copy_page()' - Copy a page description...
+ *
+ * This function expects "line" to be filled with a %%Page comment line.
+ * On return, "line" will contain the next line in the file, if any.
*/
-static void
-do_prolog(ppd_file_t *ppd) /* I - PPD file */
+static ssize_t /* O - Length of next line */
+copy_page(cups_file_t *fp, /* I - File to read from */
+ pstops_doc_t *doc, /* I - Document info */
+ ppd_file_t *ppd, /* I - PPD file */
+ int number, /* I - Current page number */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
{
+ char label[256], /* Page label string */
+ *ptr; /* Pointer into line */
+ int level; /* Embedded document level */
+ pstops_page_t *pageinfo; /* Page information */
+ int first_page; /* First page on N-up output? */
+ int bounding_box[4]; /* PageBoundingBox */
+
+
/*
- * Send the document prolog commands...
+ * Get the page label for this page...
*/
- if (ppd && ppd->patches)
+ first_page = is_first_page(number);
+
+ if (!parse_text(line + 7, &ptr, label, sizeof(label)))
{
- puts("%%BeginFeature: *JobPatchFile 1");
- puts(ppd->patches);
- puts("%%EndFeature");
+ fputs(_("ERROR: Bad %%Page: comment in file!\n"), stderr);
+ label[0] = '\0';
+ number = doc->page;
+ }
+ else if (strtol(ptr, &ptr, 10) == LONG_MAX || !isspace(*ptr & 255))
+ {
+ fputs(_("ERROR: Bad %%Page: comment in file!\n"), stderr);
+ number = doc->page;
}
- ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
-}
+ /*
+ * Create or update the current output page...
+ */
+ if (first_page)
+ pageinfo = add_page(doc, label);
+ else
+ pageinfo = (pstops_page_t *)cupsArrayLast(doc->pages);
-/*
- * 'do_setup()' - Send the necessary document setup commands...
- */
+ /*
+ * Handle first page override...
+ */
+
+ if (doc->ap_input_slot || doc->ap_manual_feed)
+ {
+ if (doc->page == 1)
+ {
+ /*
+ * First page/sheet gets AP_FIRSTPAGE_* options...
+ */
+
+ pageinfo->num_options = cupsAddOption("InputSlot", doc->ap_input_slot,
+ pageinfo->num_options,
+ &(pageinfo->options));
+ pageinfo->num_options = cupsAddOption("ManualFeed",
+ doc->ap_input_slot ? "False" :
+ doc->ap_manual_feed,
+ pageinfo->num_options,
+ &(pageinfo->options));
+ }
+ else if (doc->page == (Duplex + 2))
+ {
+ /*
+ * Second page/sheet gets default options...
+ */
+
+ pageinfo->num_options = cupsAddOption("InputSlot", doc->input_slot,
+ pageinfo->num_options,
+ &(pageinfo->options));
+ pageinfo->num_options = cupsAddOption("ManualFeed",
+ doc->input_slot ? "False" :
+ doc->manual_feed,
+ pageinfo->num_options,
+ &(pageinfo->options));
+ }
+ }
+
+ /*
+ * Scan comments until we see something other than %%Page*: or
+ * %%Include*...
+ */
+
+ memcpy(bounding_box, doc->bounding_box, sizeof(bounding_box));
+
+ while ((linelen = cupsFileGetLine(fp, line, linesize)) > 0)
+ {
+ if (!strncmp(line, "%%PageBoundingBox:", 18))
+ {
+ /*
+ * %%PageBoundingBox: llx lly urx ury
+ */
+
+ if (sscanf(line + 18, "%d%d%d%d", bounding_box + 0,
+ bounding_box + 1, bounding_box + 2,
+ bounding_box + 3) != 4)
+ {
+ fputs(_("ERROR: Bad %%PageBoundingBox: comment in file!\n"), stderr);
+ memcpy(bounding_box, doc->bounding_box,
+ sizeof(bounding_box));
+ }
+ else if (doc->number_up == 1 && !doc->fitplot && Orientation)
+ {
+ int temp_bbox[4]; /* Temporary bounding box */
+
+
+ memcpy(temp_bbox, bounding_box, sizeof(temp_bbox));
+
+ fprintf(stderr, "DEBUG: Orientation = %d\n", Orientation);
+ fprintf(stderr, "DEBUG: original bounding_box = [ %d %d %d %d ]\n",
+ bounding_box[0], bounding_box[1],
+ bounding_box[2], bounding_box[3]);
+ fprintf(stderr, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n",
+ PageWidth, PageLength);
+
+ switch (Orientation)
+ {
+ case 1 : /* Landscape */
+ bounding_box[0] = PageLength - temp_bbox[3];
+ bounding_box[1] = temp_bbox[0];
+ bounding_box[2] = PageLength - temp_bbox[1];
+ bounding_box[3] = temp_bbox[2];
+ break;
+
+ case 2 : /* Reverse Portrait */
+ bounding_box[0] = PageWidth - temp_bbox[2];
+ bounding_box[1] = PageLength - temp_bbox[3];
+ bounding_box[2] = PageWidth - temp_bbox[0];
+ bounding_box[3] = PageLength - temp_bbox[1];
+ break;
+
+ case 3 : /* Reverse Landscape */
+ bounding_box[0] = temp_bbox[1];
+ bounding_box[1] = PageWidth - temp_bbox[2];
+ bounding_box[2] = temp_bbox[3];
+ bounding_box[3] = PageWidth - temp_bbox[0];
+ break;
+ }
+
+ fprintf(stderr, "DEBUG: updated bounding_box = [ %d %d %d %d ]\n",
+ bounding_box[0], bounding_box[1],
+ bounding_box[2], bounding_box[3]);
+ }
+ }
+#if 0
+ else if (!strncmp(line, "%%PageCustomColors:", 19) ||
+ !strncmp(line, "%%PageMedia:", 12) ||
+ !strncmp(line, "%%PageOrientation:", 18) ||
+ !strncmp(line, "%%PageProcessColors:", 20) ||
+ !strncmp(line, "%%PageRequirements:", 18) ||
+ !strncmp(line, "%%PageResources:", 16))
+ {
+ /*
+ * Copy literal...
+ */
+ }
+#endif /* 0 */
+ else if (!strncmp(line, "%%PageCustomColors:", 19))
+ {
+ /*
+ * %%PageCustomColors: ...
+ */
+ }
+ else if (!strncmp(line, "%%PageMedia:", 12))
+ {
+ /*
+ * %%PageMedia: ...
+ */
+ }
+ else if (!strncmp(line, "%%PageOrientation:", 18))
+ {
+ /*
+ * %%PageOrientation: ...
+ */
+ }
+ else if (!strncmp(line, "%%PageProcessColors:", 20))
+ {
+ /*
+ * %%PageProcessColors: ...
+ */
+ }
+ else if (!strncmp(line, "%%PageRequirements:", 18))
+ {
+ /*
+ * %%PageRequirements: ...
+ */
+ }
+ else if (!strncmp(line, "%%PageResources:", 16))
+ {
+ /*
+ * %%PageResources: ...
+ */
+ }
+ else if (!strncmp(line, "%%IncludeFeature:", 17))
+ {
+ /*
+ * %%IncludeFeature: *MainKeyword OptionKeyword
+ */
+
+ if (doc->number_up == 1 &&!doc->fitplot)
+ pageinfo->num_options = include_feature(ppd, line,
+ pageinfo->num_options,
+ &(pageinfo->options));
+ }
+ else if (strncmp(line, "%%Include", 9))
+ break;
+ }
+
+ if (doc->number_up == 1)
+ {
+ /*
+ * Update the document's composite and page bounding box...
+ */
+
+ memcpy(pageinfo->bounding_box, bounding_box,
+ sizeof(pageinfo->bounding_box));
+
+ if (bounding_box[0] < doc->new_bounding_box[0])
+ doc->new_bounding_box[0] = bounding_box[0];
+ if (bounding_box[1] < doc->new_bounding_box[1])
+ doc->new_bounding_box[1] = bounding_box[1];
+ if (bounding_box[2] > doc->new_bounding_box[2])
+ doc->new_bounding_box[2] = bounding_box[2];
+ if (bounding_box[3] > doc->new_bounding_box[3])
+ doc->new_bounding_box[3] = bounding_box[3];
+ }
+
+ /*
+ * Output the page header as needed...
+ */
+
+ if (!doc->slow_order && first_page)
+ {
+ if (!ppd || !ppd->num_filters)
+ fprintf(stderr, "PAGE: %d %d\n", doc->page,
+ doc->slow_collate ? 1 : doc->copies);
+
+ if (doc->number_up > 1)
+ {
+ printf("%%%%Page: (%d) %d\n", doc->page, doc->page);
+ printf("%%%%PageBoundingBox: %.0f %.0f %.0f %.0f\n",
+ PageLeft, PageBottom, PageRight, PageTop);
+ }
+ else
+ {
+ printf("%%%%Page: %s %d\n", pageinfo->label, doc->page);
+ printf("%%%%PageBoundingBox: %d %d %d %d\n",
+ pageinfo->bounding_box[0], pageinfo->bounding_box[1],
+ pageinfo->bounding_box[2], pageinfo->bounding_box[3]);
+ }
+ }
+
+ /*
+ * Copy any page setup commands...
+ */
+
+ if (first_page)
+ {
+ char *page_setup; /* PageSetup commands to send */
+
+
+ doc_puts(doc, "%%BeginPageSetup\n");
+
+ if (pageinfo->num_options > 0)
+ {
+ int i; /* Looping var */
+ ppd_option_t *option; /* PPD option */
+ int min_order; /* Minimum OrderDependency value */
+ char *doc_setup, /* DocumentSetup commands to send */
+ *any_setup; /* AnySetup commands to send */
+
+
+ /*
+ * Yes, figure out the minimum OrderDependency value...
+ */
+
+ if ((option = ppdFindOption(ppd, "PageRegion")) != NULL)
+ min_order = option->order;
+ else
+ min_order = 999.0f;
+
+ for (i = 0; i < pageinfo->num_options; i ++)
+ if ((option = ppdFindOption(ppd, pageinfo->options[i].name)) != NULL &&
+ option->order < min_order)
+ min_order = option->order;
+
+ /*
+ * Mark and extract them...
+ */
+
+ cupsMarkOptions(ppd, pageinfo->num_options, pageinfo->options);
+
+ doc_setup = ppdEmitString(ppd, PPD_ORDER_DOCUMENT, min_order);
+ any_setup = ppdEmitString(ppd, PPD_ORDER_ANY, min_order);
+
+ /*
+ * Then send them out...
+ */
+
+ if (doc_setup)
+ {
+ doc_puts(doc, doc_setup);
+ free(doc_setup);
+ }
+
+ if (any_setup)
+ {
+ doc_puts(doc, any_setup);
+ free(any_setup);
+ }
+ }
+
+ /*
+ * Output commands for the current page...
+ */
+
+ page_setup = ppdEmitString(ppd, PPD_ORDER_PAGE, 0);
+
+ if (page_setup)
+ {
+ doc_puts(doc, page_setup);
+ free(page_setup);
+ }
+ }
+
+ /*
+ * Prep for the start of the page description...
+ */
+
+ start_nup(doc, number, 1, bounding_box);
+
+ /*
+ * Copy page setup commands as needed...
+ */
+
+ if (!strncmp(line, "%%BeginPageSetup", 16))
+ {
+ int feature = 0; /* In a Begin/EndFeature block? */
+
+
+ while ((linelen = cupsFileGetLine(fp, line, linesize)) > 0)
+ {
+ if (!strncmp(line, "%%EndPageSetup", 14))
+ break;
+ else if (!strncmp(line, "%%BeginFeature:", 15))
+ {
+ feature = 1;
+
+ if (doc->number_up > 1 || doc->fitplot)
+ continue;
+ }
+ else if (!strncmp(line, "%%EndFeature", 12))
+ {
+ feature = 0;
+
+ if (doc->number_up > 1 || doc->fitplot)
+ continue;
+ }
+ else if (!strncmp(line, "%%Include", 9))
+ continue;
+
+ if (!feature || (doc->number_up == 1 && !doc->fitplot))
+ doc_write(doc, line, linelen);
+ }
+
+ /*
+ * Skip %%EndPageSetup...
+ */
+
+ if (linelen > 0)
+ linelen = cupsFileGetLine(fp, line, linesize);
+ }
+
+ /*
+ * Finish the PageSetup section as needed...
+ */
+
+ if (first_page)
+ doc_puts(doc, "%%EndPageSetup\n");
+
+ /*
+ * Read the rest of the page description...
+ */
+
+ level = 0;
+
+ do
+ {
+ if (level == 0 &&
+ (!strncmp(line, "%%Page:", 7) ||
+ !strncmp(line, "%%Trailer", 9) ||
+ !strncmp(line, "%%EOF", 5)))
+ break;
+ else if (!strncmp(line, "%%BeginDocument", 15) ||
+ !strncmp(line, "%ADO_BeginApplication", 21))
+ {
+ doc_write(doc, line, linelen);
+
+ level ++;
+ }
+ else if ((!strncmp(line, "%%EndDocument", 13) ||
+ !strncmp(line, "%ADO_EndApplication", 19)) && level > 0)
+ {
+ doc_write(doc, line, linelen);
+
+ level --;
+ }
+ else if (!strncmp(line, "%%BeginBinary:", 14) ||
+ (!strncmp(line, "%%BeginData:", 12) &&
+ !strstr(line, "ASCII") && !strstr(line, "Hex")))
+ {
+ /*
+ * Copy binary data...
+ */
+
+ int bytes; /* Bytes of data */
+
+
+ doc_write(doc, line, linelen);
+
+ bytes = atoi(strchr(line, ':') + 1);
+
+ while (bytes > 0)
+ {
+ if (bytes > linesize)
+ linelen = cupsFileRead(fp, line, linesize);
+ else
+ linelen = cupsFileRead(fp, line, bytes);
+
+ if (linelen < 1)
+ {
+ line[0] = '\0';
+ perror("ERROR: Early end-of-file while reading binary data");
+ return (0);
+ }
+
+ doc_write(doc, line, linelen);
+
+ bytes -= linelen;
+ }
+ }
+ else
+ doc_write(doc, line, linelen);
+ }
+ while ((linelen = cupsFileGetLine(fp, line, linesize)) > 0);
+
+ /*
+ * Finish up this page and return...
+ */
+
+ end_nup(doc, number);
+
+ pageinfo->length = cupsFileTell(doc->temp) - pageinfo->offset;
+
+ return (linelen);
+}
+
+
+/*
+ * 'copy_prolog()' - Copy the document prolog section...
+ *
+ * This function expects "line" to be filled with a %%BeginProlog comment line.
+ * On return, "line" will contain the next line in the file, if any.
+ */
+
+static ssize_t /* O - Length of next line */
+copy_prolog(cups_file_t *fp, /* I - File to read from */
+ pstops_doc_t *doc, /* I - Document info */
+ ppd_file_t *ppd, /* I - PPD file */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
+{
+ while (strncmp(line, "%%BeginProlog", 13))
+ {
+ if (!strncmp(line, "%%BeginSetup", 12) || !strncmp(line, "%%Page:", 7))
+ break;
+
+ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+ }
+
+ doc_puts(doc, "%%BeginProlog\n");
+
+ do_prolog(doc, ppd);
+
+ if (!strncmp(line, "%%BeginProlog", 13))
+ {
+ while ((linelen = cupsFileGetLine(fp, line, linesize)) > 0)
+ {
+ if (!strncmp(line, "%%EndProlog", 11) ||
+ !strncmp(line, "%%BeginSetup", 12) ||
+ !strncmp(line, "%%Page:", 7))
+ break;
+
+ doc_write(doc, line, linelen);
+ }
+
+ if (!strncmp(line, "%%EndProlog", 11))
+ linelen = cupsFileGetLine(fp, line, linesize);
+ else
+ fputs(_("ERROR: Missing %%EndProlog!\n"), stderr);
+ }
+
+ doc_puts(doc, "%%EndProlog\n");
+
+ return (linelen);
+}
+
+
+/*
+ * 'copy_setup()' - Copy the document setup section...
+ *
+ * This function expects "line" to be filled with a %%BeginSetup comment line.
+ * On return, "line" will contain the next line in the file, if any.
+ */
+
+static ssize_t /* O - Length of next line */
+copy_setup(cups_file_t *fp, /* I - File to read from */
+ pstops_doc_t *doc, /* I - Document info */
+ ppd_file_t *ppd, /* I - PPD file */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
+{
+ while (strncmp(line, "%%BeginSetup", 12))
+ {
+ if (!strncmp(line, "%%Page:", 7))
+ break;
+
+ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+ }
+
+ doc_puts(doc, "%%BeginSetup\n");
+
+ do_setup(doc, ppd);
+
+ if (!strncmp(line, "%%BeginSetup", 12))
+ {
+ while (strncmp(line, "%%EndSetup", 10))
+ {
+ if (!strncmp(line, "%%Page:", 7))
+ break;
+ else if (!strncmp(line, "%%IncludeFeature:", 17))
+ {
+ /*
+ * %%IncludeFeature: *MainKeyword OptionKeyword
+ */
+
+ if (doc->number_up == 1 && !doc->fitplot)
+ doc->num_options = include_feature(ppd, line, doc->num_options,
+ &(doc->options));
+ }
+ else if (strncmp(line, "%%BeginSetup", 12))
+ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+ }
+
+ if (!strncmp(line, "%%EndSetup", 10))
+ linelen = cupsFileGetLine(fp, line, linesize);
+ else
+ fputs(_("ERROR: Missing %%EndSetup!\n"), stderr);
+ }
+
+ doc_puts(doc, "%%EndSetup\n");
+
+ return (linelen);
+}
+
+
+/*
+ * 'copy_trailer()' - Copy the document trailer...
+ *
+ * This function expects "line" to be filled with a %%Trailer comment line.
+ * On return, "line" will contain the next line in the file, if any.
+ */
+
+static ssize_t /* O - Length of next line */
+copy_trailer(cups_file_t *fp, /* I - File to read from */
+ pstops_doc_t *doc, /* I - Document info */
+ ppd_file_t *ppd, /* I - PPD file */
+ int number, /* I - Number of pages */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
+{
+ /*
+ * Write the trailer comments...
+ */
+
+ puts("%%Trailer");
+
+ while (linelen > 0)
+ {
+ if (!strncmp(line, "%%EOF", 5))
+ break;
+ else if (strncmp(line, "%%Trailer", 9) &&
+ strncmp(line, "%%Pages:", 8) &&
+ strncmp(line, "%%BoundingBox:", 14))
+ fwrite(line, 1, linelen, stdout);
+
+ linelen = cupsFileGetLine(fp, line, linesize);
+ }
+
+ fprintf(stderr, "DEBUG: Wrote %d pages...\n", number);
+
+ printf("%%%%Pages: %d\n", number);
+ if (doc->number_up > 1 || doc->fitplot)
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
+ PageLeft, PageBottom, PageRight, PageTop);
+ else
+ printf("%%%%BoundingBox: %d %d %d %d\n",
+ doc->new_bounding_box[0], doc->new_bounding_box[1],
+ doc->new_bounding_box[2], doc->new_bounding_box[3]);
+
+ return (linelen);
+}
+
+
+/*
+ * 'do_prolog()' - Send the necessary document prolog commands...
+ */
+
+static void
+do_prolog(pstops_doc_t *doc, /* I - Document information */
+ ppd_file_t *ppd) /* I - PPD file */
+{
+ char *ps; /* PS commands */
+
+
+ /*
+ * Send the document prolog commands...
+ */
+
+ if (ppd && ppd->patches)
+ {
+ doc_puts(doc, "%%BeginFeature: *JobPatchFile 1\n");
+ doc_puts(doc, ppd->patches);
+ doc_puts(doc, "\n%%EndFeature\n");
+ }
+
+ if ((ps = ppdEmitString(ppd, PPD_ORDER_PROLOG, 0.0)) != NULL)
+ {
+ doc_puts(doc, ps);
+ free(ps);
+ }
+
+ /*
+ * Define ESPshowpage here so that applications that define their
+ * own procedure to do a showpage pick it up...
+ */
+
+ if (doc->use_ESPshowpage)
+ doc_puts(doc, "userdict/ESPshowpage/showpage load put\n"
+ "userdict/showpage{}put\n");
+}
+
+
+/*
+ * 'do_setup()' - Send the necessary document setup commands...
+ */
+
+static void
+do_setup(pstops_doc_t *doc, /* I - Document information */
+ ppd_file_t *ppd) /* I - PPD file */
+{
+ char *ps; /* PS commands */
+
+
+ /*
+ * Disable CTRL-D so that embedded files don't cause printing
+ * errors...
+ */
+
+ doc_puts(doc, "% Disable CTRL-D as an end-of-file marker...\n");
+ doc_puts(doc, "userdict dup(\\004)cvn{}put (\\004\\004)cvn{}put\n");
+
+ /*
+ * Mark any options from %%IncludeFeature: comments...
+ */
+
+ cupsMarkOptions(ppd, doc->num_options, doc->options);
+
+ /*
+ * Send all the printer-specific setup commands...
+ */
+
+ if ((ps = ppdEmitString(ppd, PPD_ORDER_DOCUMENT, 0.0)) != NULL)
+ {
+ doc_puts(doc, ps);
+ free(ps);
+ }
+
+ if ((ps = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL)
+ {
+ doc_puts(doc, ps);
+ free(ps);
+ }
+
+ /*
+ * Set the number of copies for the job...
+ */
+
+ if (doc->copies != 1 && (!doc->collate || !doc->slow_collate))
+ {
+ doc_printf(doc, "%%RBIBeginNonPPDFeature: *NumCopies %d\n", doc->copies);
+ doc_printf(doc,
+ "%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse\n"
+ "{1 dict begin/NumCopies exch def currentdict end "
+ "setpagedevice}\n"
+ "{userdict/#copies 3 -1 roll put}ifelse\n", doc->copies);
+ doc_puts(doc, "%RBIEndNonPPDFeature\n");
+ }
+
+ /*
+ * If we are doing N-up printing, disable setpagedevice...
+ */
+
+ if (doc->number_up > 1)
+ doc_puts(doc, "userdict/setpagedevice{pop}bind put\n");
+
+ /*
+ * Changes to the transfer function must be made AFTER any
+ * setpagedevice code...
+ */
+
+ if (doc->gamma != 1.0f || doc->brightness != 1.0f)
+ doc_printf(doc, "{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
+ "ifelse %.3f mul } bind settransfer\n",
+ doc->gamma, doc->brightness);
+
+ /*
+ * Make sure we have rectclip and rectstroke procedures of some sort...
+ */
+
+ doc_puts(doc,
+ "% x y w h ESPrc - Clip to a rectangle.\n"
+ "userdict/ESPrc/rectclip where{pop/rectclip load}\n"
+ "{{newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+ "neg 0 rlineto closepath clip newpath}bind}ifelse put\n");
+
+ doc_puts(doc,
+ "% x y w h ESPrf - Fill a rectangle.\n"
+ "userdict/ESPrf/rectfill where{pop/rectfill load}\n"
+ "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+ "neg 0 rlineto closepath fill grestore}bind}ifelse put\n");
+
+ doc_puts(doc,
+ "% x y w h ESPrs - Stroke a rectangle.\n"
+ "userdict/ESPrs/rectstroke where{pop/rectstroke load}\n"
+ "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+ "neg 0 rlineto closepath stroke grestore}bind}ifelse put\n");
+
+ /*
+ * Write the page and label prologs...
+ */
+
+ if (doc->number_up == 2 || doc->number_up == 6)
+ {
+ /*
+ * For 2- and 6-up output, rotate the labels to match the orientation
+ * of the pages...
+ */
+
+ if (Orientation & 1)
+ write_label_prolog(doc, doc->page_label, PageBottom,
+ PageWidth - PageLength + PageTop, PageLength);
+ else
+ write_label_prolog(doc, doc->page_label, PageLeft, PageRight,
+ PageLength);
+ }
+ else
+ write_label_prolog(doc, doc->page_label, PageBottom, PageTop, PageWidth);
+}
+
+
+/*
+ * 'doc_printf()' - Send a formatted string to stdout and/or the temp file.
+ *
+ * This function should be used for all page-level output that is affected
+ * by ordering, collation, etc.
+ */
+
+static void
+doc_printf(pstops_doc_t *doc, /* I - Document information */
+ const char *format, /* I - Printf-style format string */
+ ...) /* I - Additional arguments as needed */
+{
+ va_list ap; /* Pointer to arguments */
+ char buffer[1024]; /* Output buffer */
+ size_t bytes; /* Number of bytes to write */
+
+
+ va_start(ap, format);
+ bytes = vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_end(ap);
+
+ if (bytes > sizeof(buffer))
+ {
+ fprintf(stderr,
+ _("ERROR: doc_printf overflow (%d bytes) detected, aborting!\n"),
+ (int)bytes);
+ exit(1);
+ }
+
+ doc_write(doc, buffer, bytes);
+}
+
+
+/*
+ * 'doc_puts()' - Send a nul-terminated string to stdout and/or the temp file.
+ *
+ * This function should be used for all page-level output that is affected
+ * by ordering, collation, etc.
+ */
+
+static void
+doc_puts(pstops_doc_t *doc, /* I - Document information */
+ const char *s) /* I - String to send */
+{
+ doc_write(doc, s, strlen(s));
+}
+
+
+/*
+ * 'doc_write()' - Send data to stdout and/or the temp file.
+ */
+
+static void
+doc_write(pstops_doc_t *doc, /* I - Document information */
+ const char *s, /* I - Data to send */
+ size_t len) /* I - Number of bytes to send */
+{
+ if (!doc->slow_order)
+ fwrite(s, 1, len, stdout);
+
+ if (doc->temp)
+ cupsFileWrite(doc->temp, s, len);
+}
+
+
+/*
+ * 'end_nup()' - End processing for N-up printing...
+ */
+
+static void
+end_nup(pstops_doc_t *doc, /* I - Document information */
+ int number) /* I - Page number */
+{
+ if (doc->number_up > 1)
+ doc_puts(doc, "userdict/ESPsave get restore\n");
+
+ switch (doc->number_up)
+ {
+ case 1 :
+ if (doc->use_ESPshowpage)
+ {
+ write_labels(doc, Orientation);
+ doc_puts(doc, "ESPshowpage\n");
+ }
+ break;
+
+ case 2 :
+ case 6 :
+ if (is_last_page(number) && doc->use_ESPshowpage)
+ {
+ if (Orientation & 1)
+ {
+ /*
+ * Rotate the labels back to portrait...
+ */
+
+ write_labels(doc, Orientation - 1);
+ }
+ else if (Orientation == 0)
+ {
+ /*
+ * Rotate the labels to landscape...
+ */
+
+ write_labels(doc, doc->normal_landscape ? 1 : 3);
+ }
+ else
+ {
+ /*
+ * Rotate the labels to landscape...
+ */
+
+ write_labels(doc, doc->normal_landscape ? 3 : 1);
+ }
+
+ doc_puts(doc, "ESPshowpage\n");
+ }
+ break;
+
+ default :
+ if (is_last_page(number) && doc->use_ESPshowpage)
+ {
+ write_labels(doc, Orientation);
+ doc_puts(doc, "ESPshowpage\n");
+ }
+ break;
+ }
+
+ fflush(stdout);
+}
+
+
+/*
+ * 'include_feature()' - Include a printer option/feature command.
+ */
+
+static int /* O - New number of options */
+include_feature(
+ ppd_file_t *ppd, /* I - PPD file */
+ const char *line, /* I - DSC line */
+ int num_options, /* I - Number of options */
+ cups_option_t **options) /* IO - Options */
+{
+ char name[255], /* Option name */
+ value[255]; /* Option value */
+ ppd_option_t *option; /* Option in file */
+ ppd_choice_t *choice; /* Choice */
+
+
+ /*
+ * Get the "%%IncludeFeature: *Keyword OptionKeyword" values...
+ */
+
+ if (sscanf(line + 17, "%254s%254s", name, value) != 2)
+ {
+ fputs(_("ERROR: Bad %%IncludeFeature: comment!\n"), stderr);
+ return (num_options);
+ }
+
+ /*
+ * Find the option and choice...
+ */
+
+ if ((option = ppdFindOption(ppd, name + 1)) == NULL)
+ {
+ fprintf(stderr, _("WARNING: Unknown option \"%s\"!\n"), name + 1);
+ return (num_options);
+ }
+
+ if (option->section == PPD_ORDER_EXIT ||
+ option->section == PPD_ORDER_JCL)
+ {
+ fprintf(stderr, _("WARNING: Option \"%s\" cannot be included via "
+ "IncludeFeature!\n"), name + 1);
+ return (num_options);
+ }
+
+ if ((choice = ppdFindChoice(option, value)) == NULL)
+ {
+ fprintf(stderr, _("WARNING: Unknown choice \"%s\" for option \"%s\"!\n"),
+ value, name + 1);
+ return (num_options);
+ }
+
+ /*
+ * Add the option to the option array and return...
+ */
+
+ return (cupsAddOption(name + 1, value, num_options, options));
+}
+
+
+/*
+ * 'parse_text()' - Parse a text value in a comment...
+ *
+ * This function parses a DSC text value as defined on page 36 of the
+ * DSC specification. Text values are either surrounded by parenthesis
+ * or whitespace-delimited.
+ *
+ * The value returned is the literal characters for the entire text
+ * string, including any parenthesis and escape characters.
+ */
+
+static char * /* O - Value or NULL on error */
+parse_text(const char *start, /* I - Start of text value */
+ char **end, /* O - End of text value */
+ char *buffer, /* I - Buffer */
+ size_t bufsize) /* I - Size of buffer */
+{
+ char *bufptr, /* Pointer in buffer */
+ *bufend; /* End of buffer */
+ int level; /* Parenthesis level */
+
+
+ /*
+ * Skip leading whitespace...
+ */
+
+ while (isspace(*start & 255))
+ start ++;
+
+ /*
+ * Then copy the value...
+ */
+
+ level = 0;
+ bufptr = buffer;
+ bufend = buffer + bufsize - 1;
+
+ while (bufptr < bufend)
+ {
+ if (isspace(*start & 255) && !level)
+ break;
+
+ *bufptr++ = *start;
+
+ if (*start == '(')
+ level ++;
+ else if (*start == ')')
+ {
+ if (!level)
+ {
+ start ++;
+ break;
+ }
+ else
+ level --;
+ }
+ else if (*start == '\\')
+ {
+ /*
+ * Copy escaped character...
+ */
+
+ int i; /* Looping var */
+
+
+ for (i = 1;
+ i <= 3 && isdigit(start[i] & 255) && bufptr < bufend;
+ *bufptr++ = start[i], i ++);
+ }
+
+ start ++;
+ }
+
+ *bufptr = '\0';
+
+ /*
+ * Return the value and new pointer into the line...
+ */
+
+ if (end)
+ *end = (char *)start;
+
+ if (bufptr == bufend)
+ return (NULL);
+ else
+ return (buffer);
+}
+
+
+/*
+ * 'set_pstops_options()' - Set pstops options...
+ */
+
+static void
+set_pstops_options(
+ pstops_doc_t *doc, /* I - Document information */
+ ppd_file_t *ppd, /* I - PPD file */
+ char *argv[], /* I - Command-line arguments */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ const char *val; /* Option value */
+ int intval; /* Integer option value */
+ ppd_attr_t *attr; /* PPD attribute */
+ ppd_option_t *option; /* PPD option */
+ ppd_choice_t *choice; /* PPD choice */
+
+
+ /*
+ * Initialize document information structure...
+ */
+
+ memset(doc, 0, sizeof(pstops_doc_t));
+
+ doc->job_id = atoi(argv[1]);
+ doc->user = argv[2];
+ doc->title = argv[3];
+ doc->copies = atoi(argv[4]);
+
+ if (ppd && ppd->landscape > 0)
+ doc->normal_landscape = 1;
+
+ doc->bounding_box[0] = (int)PageLeft;
+ doc->bounding_box[1] = (int)PageBottom;
+ doc->bounding_box[2] = (int)PageRight;
+ doc->bounding_box[3] = (int)PageTop;
+
+ doc->new_bounding_box[0] = INT_MAX;
+ doc->new_bounding_box[1] = INT_MAX;
+ doc->new_bounding_box[2] = INT_MIN;
+ doc->new_bounding_box[3] = INT_MIN;
+
+ /*
+ * AP_FIRSTPAGE_InputSlot
+ */
+
+ doc->ap_input_slot = cupsGetOption("AP_FIRSTPAGE_InputSlot", num_options,
+ options);
+
+ /*
+ * AP_FIRSTPAGE_ManualFeed
+ */
+
+ doc->ap_manual_feed = cupsGetOption("AP_FIRSTPAGE_ManualFeed", num_options,
+ options);
+
+ /*
+ * brightness
+ */
+
+ if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
+ {
+ /*
+ * Get brightness value from 10 to 1000.
+ */
+
+ intval = atoi(val);
+
+ if (intval < 10 || intval > 1000)
+ {
+ fprintf(stderr, _("ERROR: Unsupported brightness value %s, using "
+ "brightness=100!\n"), val);
+ doc->brightness = 1.0f;
+ }
+ else
+ doc->brightness = intval * 0.01f;
+ }
+ else
+ doc->brightness = 1.0f;
+
+ /*
+ * collate, multiple-document-handling
+ */
+
+ if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
+ {
+ /*
+ * This IPP attribute is unnecessarily complicated...
+ *
+ * single-document, separate-documents-collated-copies, and
+ * single-document-new-sheet all require collated copies.
+ *
+ * separate-documents-uncollated-copies allows for uncollated copies.
+ */
+
+ doc->collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
+ }
+
+ if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
+ (!strcasecmp(val, "true") ||!strcasecmp(val, "on") ||
+ !strcasecmp(val, "yes")))
+ doc->collate = 1;
+
+ /*
+ * emit-jcl
+ */
+
+ if ((val = cupsGetOption("emit-jcl", num_options, options)) != NULL &&
+ (!strcasecmp(val, "false") || !strcasecmp(val, "off") ||
+ !strcasecmp(val, "no") || !strcmp(val, "0")))
+ doc->emit_jcl = 0;
+ else
+ doc->emit_jcl = 1;
+
+ /*
+ * fitplot
+ */
+
+ if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
+ (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
+ !strcasecmp(val, "yes")))
+ doc->fitplot = 1;
+
+ /*
+ * gamma
+ */
+
+ if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
+ {
+ /*
+ * Get gamma value from 1 to 10000...
+ */
+
+ intval = atoi(val);
+
+ if (intval < 1 || intval > 10000)
+ {
+ fprintf(stderr, _("ERROR: Unsupported gamma value %s, using "
+ "gamma=1000!\n"), val);
+ doc->gamma = 1.0f;
+ }
+ else
+ doc->gamma = intval * 0.001f;
+ }
+ else
+ doc->gamma = 1.0f;
+
+ /*
+ * InputSlot
+ */
+
+ if ((choice = ppdFindMarkedChoice(ppd, "InputSlot")) != NULL)
+ doc->input_slot = choice->choice;
+
+ /*
+ * ManualFeed
+ */
+
+ if ((choice = ppdFindMarkedChoice(ppd, "ManualFeed")) != NULL)
+ doc->manual_feed = choice->choice;
+
+ if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
+ {
+ val = choice->choice;
+ choice->marked = 0;
+ }
+ else
+ val = cupsGetOption("mirror", num_options, options);
+
+ if (val && (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
+ !strcasecmp(val, "yes")))
+ doc->mirror = 1;
+
+ /*
+ * number-up
+ */
+
+ if ((val = cupsGetOption("number-up", num_options, options)) != NULL)
+ {
+ switch (intval = atoi(val))
+ {
+ case 1 :
+ case 2 :
+ case 4 :
+ case 6 :
+ case 9 :
+ case 16 :
+ doc->number_up = intval;
+ break;
+ default :
+ fprintf(stderr,
+ _("ERROR: Unsupported number-up value %d, using "
+ "number-up=1!\n"), intval);
+ doc->number_up = 1;
+ break;
+ }
+ }
+ else
+ doc->number_up = 1;
+
+ /*
+ * number-up-layout
+ */
+
+ if ((val = cupsGetOption("number-up-layout", num_options, options)) != NULL)
+ {
+ if (!strcasecmp(val, "lrtb"))
+ doc->number_up_layout = PSTOPS_LAYOUT_LRTB;
+ else if (!strcasecmp(val, "lrbt"))
+ doc->number_up_layout = PSTOPS_LAYOUT_LRBT;
+ else if (!strcasecmp(val, "rltb"))
+ doc->number_up_layout = PSTOPS_LAYOUT_RLTB;
+ else if (!strcasecmp(val, "rlbt"))
+ doc->number_up_layout = PSTOPS_LAYOUT_RLBT;
+ else if (!strcasecmp(val, "tblr"))
+ doc->number_up_layout = PSTOPS_LAYOUT_TBLR;
+ else if (!strcasecmp(val, "tbrl"))
+ doc->number_up_layout = PSTOPS_LAYOUT_TBRL;
+ else if (!strcasecmp(val, "btlr"))
+ doc->number_up_layout = PSTOPS_LAYOUT_BTLR;
+ else if (!strcasecmp(val, "btrl"))
+ doc->number_up_layout = PSTOPS_LAYOUT_BTRL;
+ else
+ {
+ fprintf(stderr, _("ERROR: Unsupported number-up-layout value %s, using "
+ "number-up-layout=lrtb!\n"), val);
+ doc->number_up_layout = PSTOPS_LAYOUT_LRTB;
+ }
+ }
+ else
+ doc->number_up_layout = PSTOPS_LAYOUT_LRTB;
+
+ /*
+ * OutputOrder
+ */
+
+ if ((val = cupsGetOption("OutputOrder", num_options, options)) != NULL)
+ {
+ if (!strcasecmp(val, "Reverse"))
+ doc->output_order = 1;
+ }
+ else if (ppd)
+ {
+ /*
+ * Figure out the right default output order from the PPD file...
+ */
+
+ if ((choice = ppdFindMarkedChoice(ppd, "OutputBin")) != NULL &&
+ (attr = ppdFindAttr(ppd, "PageStackOrder", choice->choice)) != NULL &&
+ attr->value)
+ doc->output_order = !strcasecmp(attr->value, "Reverse");
+ else if ((attr = ppdFindAttr(ppd, "DefaultOutputOrder", NULL)) != NULL &&
+ attr->value)
+ doc->output_order = !strcasecmp(attr->value, "Reverse");
+ }
+
+ /*
+ * page-border
+ */
+
+ if ((val = cupsGetOption("page-border", num_options, options)) != NULL)
+ {
+ if (!strcasecmp(val, "none"))
+ doc->page_border = PSTOPS_BORDERNONE;
+ else if (!strcasecmp(val, "single"))
+ doc->page_border = PSTOPS_BORDERSINGLE;
+ else if (!strcasecmp(val, "single-thick"))
+ doc->page_border = PSTOPS_BORDERSINGLE2;
+ else if (!strcasecmp(val, "double"))
+ doc->page_border = PSTOPS_BORDERDOUBLE;
+ else if (!strcasecmp(val, "double-thick"))
+ doc->page_border = PSTOPS_BORDERDOUBLE2;
+ else
+ {
+ fprintf(stderr, _("ERROR: Unsupported page-border value %s, using "
+ "page-border=none!\n"), val);
+ doc->page_border = PSTOPS_BORDERNONE;
+ }
+ }
+ else
+ doc->page_border = PSTOPS_BORDERNONE;
-static void
-do_setup(ppd_file_t *ppd, /* I - PPD file */
- int copies, /* I - Number of copies */
- int collate, /* I - Collate output? */
- int slowcollate, /* I - Slow collate */
- float g, /* I - Gamma value */
- float b) /* I - Brightness value */
-{
/*
- * Send all the printer-specific setup commands...
+ * page-label
*/
- ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
- ppdEmit(ppd, stdout, PPD_ORDER_ANY);
+ doc->page_label = cupsGetOption("page-label", num_options, options);
/*
- * Set the number of copies for the job...
+ * page-ranges
*/
- if (copies != 1 && (!collate || !slowcollate))
- {
- printf("%%RBIBeginNonPPDFeature: *NumCopies %d\n", copies);
- printf("%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse{1 dict begin"
- "/NumCopies exch def currentdict end "
- "setpagedevice}{userdict/#copies 3 -1 roll put}ifelse\n", copies);
- printf("%%RBIEndNonPPDFeature\n");
- }
+ doc->page_ranges = cupsGetOption("page-ranges", num_options, options);
/*
- * If we are doing N-up printing, disable setpagedevice...
+ * page-set
*/
- if (NUp > 1)
- puts("userdict/setpagedevice{pop}bind put");
+ doc->page_set = cupsGetOption("page-set", num_options, options);
/*
- * Changes to the transfer function must be made AFTER any
- * setpagedevice code...
+ * Now figure out if we have to force collated copies, etc.
*/
- if (g != 1.0 || b != 1.0)
- printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
- "ifelse %.3f mul } bind settransfer\n", g, b);
+ if (ppd && ppd->manual_copies && Duplex && doc->copies > 1)
+ {
+ /*
+ * Force collated copies when printing a duplexed document to
+ * a non-PS printer that doesn't do hardware copy generation.
+ * Otherwise the copies will end up on the front/back side of
+ * each page.
+ */
+
+ doc->collate = 1;
+ }
/*
- * Make sure we have rectclip and rectstroke procedures of some sort...
+ * See if we have to filter the fast or slow way...
*/
- WriteCommon();
-}
-
-
-/*
- * 'end_nup()' - End processing for N-up printing...
- */
-
-static void
-end_nup(int number) /* I - Page number */
-{
- puts("");
-
- if (Flip || Orientation || NUp > 1)
- puts("userdict /ESPsave get restore");
-
- switch (NUp)
+ if (doc->collate && doc->copies > 1)
{
- case 1 :
- if (UseESPsp)
- {
- WriteLabels(Orientation);
- puts("ESPshowpage");
- }
- break;
-
- case 2 :
- case 6 :
- if (is_last_page(number) && UseESPsp)
- {
- if (Orientation & 1)
- {
- /*
- * Rotate the labels back to portrait...
- */
-
- WriteLabels(Orientation - 1);
- }
- else if (Orientation == 0)
- {
- /*
- * Rotate the labels to landscape...
- */
-
- WriteLabels(NormalLandscape ? 1 : 3);
- }
- else
- {
- /*
- * Rotate the labels to landscape...
- */
+ /*
+ * See if we need to manually collate the pages...
+ */
- WriteLabels(NormalLandscape ? 3 : 1);
- }
+ doc->slow_collate = 1;
- puts("ESPshowpage");
- }
- break;
+ if ((choice = ppdFindMarkedChoice(ppd, "Collate")) != NULL &&
+ !strcasecmp(choice->choice, "True"))
+ {
+ /*
+ * Hardware collate option is selected, see if the option is
+ * conflicting - if not, collate in hardware. Otherwise,
+ * turn the hardware collate option off...
+ */
- default :
- if (is_last_page(number) && UseESPsp)
- {
- WriteLabels(Orientation);
- puts("ESPshowpage");
- }
- break;
+ if ((option = ppdFindOption(ppd, "Collate")) != NULL &&
+ !option->conflicted)
+ doc->slow_collate = 0;
+ else
+ ppdMarkOption(ppd, "Collate", "False");
+ }
}
+ else
+ doc->slow_collate = 0;
- fflush(stdout);
-}
-
-
-/*
- * 'include_feature()' - Include a printer option/feature command.
- */
-
-static void
-include_feature(ppd_file_t *ppd, /* I - PPD file */
- const char *line, /* I - DSC line */
- cups_file_t *out) /* I - Output file */
-{
- char name[255], /* Option name */
- value[255]; /* Option value */
- ppd_option_t *option; /* Option in file */
- ppd_choice_t *choice; /* Choice */
+ if (!ppdFindOption(ppd, "OutputOrder") && doc->output_order)
+ doc->slow_order = 1;
+ else
+ doc->slow_order = 0;
+ if (Duplex &&
+ (doc->slow_collate || doc->slow_order ||
+ ((attr = ppdFindAttr(ppd, "cupsEvenDuplex", NULL)) != NULL &&
+ attr->value && !strcasecmp(attr->value, "true"))))
+ doc->slow_duplex = 1;
+ else
+ doc->slow_duplex = 0;
/*
- * Get the "%%IncludeFeature: *Keyword OptionKeyword" values...
+ * Create a temporary file for page data if we need to filter slowly...
*/
- if (sscanf(line + 17, "%254s%254s", name, value) != 2)
+ if (doc->slow_order || doc->slow_collate)
{
- fprintf(stderr, "ERROR: Bad line: \"%s\"!\n", line);
- return;
+ if ((doc->temp = cupsTempFile2(doc->tempfile,
+ sizeof(doc->tempfile))) == NULL)
+ {
+ fprintf(stderr, _("ERROR: Unable to create temporary file: %s\n"),
+ strerror(errno));
+ exit(1);
+ }
}
/*
- * Find the option and choice...
+ * Figure out if we should use ESPshowpage or not...
*/
- if ((option = ppdFindOption(ppd, name + 1)) == NULL)
- {
- fprintf(stderr, "WARNING: Unknown option \"%s\"!\n", name + 1);
- return;
- }
-
- if (option->section == PPD_ORDER_EXIT ||
- option->section == PPD_ORDER_JCL)
+ if (doc->page_label || getenv("CLASSIFICATION") || doc->number_up > 1 ||
+ doc->page_border)
{
- fprintf(stderr, "WARNING: Option \"%s\" cannot be included via "
- "IncludeFeature!\n", name + 1);
- return;
- }
+ /*
+ * Yes, use ESPshowpage...
+ */
- if ((choice = ppdFindChoice(option, value)) == NULL)
- {
- fprintf(stderr, "WARNING: Unknown choice \"%s\" for option \"%s\"!\n",
- value, name + 1);
- return;
+ doc->use_ESPshowpage = 1;
}
- /*
- * Emit the option...
- */
-
- if (out)
- {
- cupsFilePuts(out, "[{\n");
- cupsFilePrintf(out, "%%%%BeginFeature: %s %s\n", name, value);
- if (choice->code && choice->code[0])
- {
- if (choice->code[strlen(choice->code) - 1] != '\n')
- cupsFilePrintf(out, "%s\n", choice->code);
- else
- cupsFilePuts(out, choice->code);
- }
- cupsFilePuts(out, "%%EndFeature\n");
- cupsFilePuts(out, "} stopped cleartomark\n");
- }
- else
- {
- puts("[{");
- printf("%%%%BeginFeature: %s %s\n", name, value);
- if (choice->code && choice->code[0])
- {
- if (choice->code[strlen(choice->code) - 1] != '\n')
- printf("%s\n", choice->code);
- else
- fputs(choice->code, stdout);
- }
- puts("%%EndFeature");
- puts("} stopped cleartomark");
- }
+ fprintf(stderr, "DEBUG: slow_collate=%d, slow_duplex=%d, slow_order=%d\n",
+ doc->slow_collate, doc->slow_duplex, doc->slow_order);
}
/*
- * 'psgets()' - Get a line from a file.
- *
- * Note:
- *
- * This function differs from the gets() function in that it
- * handles any combination of CR, LF, or CR LF to end input
- * lines.
+ * 'skip_page()' - Skip past a page that won't be printed...
*/
-static char * /* O - String or NULL if EOF */
-psgets(char *buf, /* I - Buffer to read into */
- size_t *bytes, /* IO - Length of buffer */
- FILE *fp) /* I - File to read from */
+static ssize_t /* O - Length of next line */
+skip_page(cups_file_t *fp, /* I - File to read from */
+ char *line, /* I - Line buffer */
+ ssize_t linelen, /* I - Length of initial line */
+ size_t linesize) /* I - Size of line buffer */
{
- char *bufptr; /* Pointer into buffer */
- int ch; /* Character from file */
- size_t len; /* Max length of string */
+ int level; /* Embedded document level */
- len = *bytes - 1;
- bufptr = buf;
- ch = EOF;
+ level = 0;
- while ((bufptr - buf) < len)
+ while ((linelen = cupsFileGetLine(fp, line, linesize)) > 0)
{
- if ((ch = getc(fp)) == EOF)
+ if (level == 0 &&
+ (!strncmp(line, "%%Page:", 7) || !strncmp(line, "%%Trailer", 9)))
break;
-
- if (ch == '\r')
+ else if (!strncmp(line, "%%BeginDocument", 15) ||
+ !strncmp(line, "%ADO_BeginApplication", 21))
+ level ++;
+ else if ((!strncmp(line, "%%EndDocument", 13) ||
+ !strncmp(line, "%ADO_EndApplication", 19)) && level > 0)
+ level --;
+ else if (!strncmp(line, "%%BeginBinary:", 14) ||
+ (!strncmp(line, "%%BeginData:", 12) &&
+ !strstr(line, "ASCII") && !strstr(line, "Hex")))
{
/*
- * Got a CR; see if there is a LF as well...
+ * Skip binary data...
*/
- ch = getc(fp);
+ int bytes; /* Bytes of data */
- if (ch != EOF && ch != '\n')
- {
- ungetc(ch, fp); /* Nope, save it for later... */
- ch = '\r';
- }
- else
- *bufptr++ = '\r';
- break;
- }
- else if (ch == '\n')
- break;
- else
- *bufptr++ = ch;
- }
- /*
- * Add a trailing newline if it is there...
- */
+ bytes = atoi(strchr(line, ':') + 1);
- if (ch == '\n' || ch == '\r')
- {
- if ((bufptr - buf) < len)
- *bufptr++ = ch;
- else
- ungetc(ch, fp);
- }
+ while (bytes > 0)
+ {
+ if (bytes > linesize)
+ linelen = cupsFileRead(fp, line, linesize);
+ else
+ linelen = cupsFileRead(fp, line, bytes);
- /*
- * Nul-terminate the string and return it (or NULL for EOF).
- */
+ if (linelen < 1)
+ {
+ line[0] = '\0';
+ perror("ERROR: Early end-of-file while reading binary data");
+ return (0);
+ }
- *bufptr = '\0';
- *bytes = bufptr - buf;
+ bytes -= linelen;
+ }
+ }
+ }
- if (ch == EOF && bufptr == buf)
- return (NULL);
- else
- return (buf);
+ return (linelen);
}
*/
static void
-start_nup(int number, /* I - Page number */
- int show_border, /* I - Show the page border? */
- const int *lbrt) /* I - Page BoundingBox */
+start_nup(pstops_doc_t *doc, /* I - Document information */
+ int number, /* I - Page number */
+ int show_border, /* I - Show the border? */
+ const int *bounding_box) /* I - BoundingBox value */
{
- int pos; /* Position on page */
- int x, y; /* Relative position of subpage */
- float w, l, /* Width and length of subpage */
- tx, ty; /* Translation values for subpage */
- float pw, pl; /* Printable width and length of full page */
-
-
- if (Flip || Orientation || NUp > 1)
- puts("userdict/ESPsave save put");
-
- if (Flip)
- printf("%.1f 0.0 translate -1 1 scale\n", PageWidth);
-
- pos = number % NUp;
- pw = lbrt[2] - lbrt[0];
- pl = lbrt[3] - lbrt[1];
+ int pos; /* Position on page */
+ int x, y; /* Relative position of subpage */
+ float w, l, /* Width and length of subpage */
+ tx, ty; /* Translation values for subpage */
+ float pagew, /* Printable width of page */
+ pagel; /* Printable height of page */
+ int bboxx, /* BoundingBox X origin */
+ bboxy, /* BoundingBox Y origin */
+ bboxw, /* BoundingBox width */
+ bboxl; /* BoundingBox height */
+ float margin = 0; /* Current margin for border */
+
+
+ if (doc->number_up > 1)
+ doc_puts(doc, "userdict/ESPsave save put\n");
+
+ if (doc->mirror)
+ doc_printf(doc, "%.1f 0.0 translate -1 1 scale\n", PageWidth);
+
+ pos = (number - 1) % doc->number_up;
+ pagew = PageRight - PageLeft;
+ pagel = PageTop - PageBottom;
+
+ if (doc->fitplot)
+ {
+ bboxx = bounding_box[0];
+ bboxy = bounding_box[1];
+ bboxw = bounding_box[2] - bounding_box[0];
+ bboxl = bounding_box[3] - bounding_box[1];
+ }
+ else
+ {
+ bboxx = 0;
+ bboxy = 0;
+ bboxw = PageWidth;
+ bboxl = PageLength;
+ }
- fprintf(stderr, "DEBUG: pw = %.1f, pl = %.1f\n", pw, pl);
- fprintf(stderr, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n", PageLeft, PageRight);
- fprintf(stderr, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n", PageTop, PageBottom);
- fprintf(stderr, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n", PageWidth, PageLength);
+ fprintf(stderr, "DEBUG: pagew = %.1f, pagel = %.1f\n", pagew, pagel);
+ fprintf(stderr, "DEBUG: bboxx = %d, bboxy = %d, bboxw = %d, bboxl = %d\n",
+ bboxx, bboxy, bboxw, bboxl);
+ fprintf(stderr, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n",
+ PageLeft, PageRight);
+ fprintf(stderr, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n",
+ PageTop, PageBottom);
+ fprintf(stderr, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n",
+ PageWidth, PageLength);
switch (Orientation)
{
case 1 : /* Landscape */
- printf("%.1f 0.0 translate 90 rotate\n", PageLength);
+ doc_printf(doc, "%.1f 0.0 translate 90 rotate\n", PageLength);
break;
case 2 : /* Reverse Portrait */
- printf("%.1f %.1f translate 180 rotate\n", PageWidth, PageLength);
+ doc_printf(doc, "%.1f %.1f translate 180 rotate\n", PageWidth,
+ PageLength);
break;
case 3 : /* Reverse Landscape */
- printf("0.0 %.1f translate -90 rotate\n", PageWidth);
+ doc_printf(doc, "0.0 %.1f translate -90 rotate\n", PageWidth);
break;
}
- if (Duplex && NUp > 1 && ((number / NUp) & 1))
- printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom);
- else if (NUp > 1 || FitPlot)
- printf("%.1f %.1f translate\n", PageLeft, PageBottom);
+ if (Duplex && doc->number_up > 1 && ((number / doc->number_up) & 1))
+ doc_printf(doc, "%.1f %.1f translate\n", PageWidth - PageRight, PageBottom);
+ else if (doc->number_up > 1 || doc->fitplot)
+ doc_printf(doc, "%.1f %.1f translate\n", PageLeft, PageBottom);
- switch (NUp)
+ switch (doc->number_up)
{
default :
- if (FitPlot)
+ if (doc->fitplot)
{
- w = PageRight - PageLeft;
- l = w * pl / pw;
+ w = pagew;
+ l = w * bboxl / bboxw;
- if (l > (PageTop - PageBottom))
+ if (l > pagel)
{
- l = PageTop - PageBottom;
- w = l * pw / pl;
+ l = pagel;
+ w = l * bboxw / bboxl;
}
- tx = 0.5 * (PageRight - PageLeft - w);
- ty = 0.5 * (PageTop - PageBottom - l);
+ tx = 0.5 * (pagew - w);
+ ty = 0.5 * (pagel - l);
- printf("%.1f %.1f translate %.3f %.3f scale\n", tx, ty, w / pw,
- l / pl);
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n", tx, ty,
+ w / bboxw, l / bboxl);
}
else
{
{
x = pos & 1;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
x = 1 - x;
- w = pl;
- l = w * PageLength / PageWidth;
+ w = pagel;
+ l = w * bboxl / bboxw;
- if (l > (pw * 0.5))
+ if (l > (pagew * 0.5))
{
- l = pw * 0.5;
- w = l * PageWidth / PageLength;
+ l = pagew * 0.5;
+ w = l * bboxw / bboxl;
}
- tx = 0.5 * (pw * 0.5 - l);
- ty = 0.5 * (pl - w);
+ tx = 0.5 * (pagew * 0.5 - l);
+ ty = 0.5 * (pagel - w);
- if (NormalLandscape)
- printf("0.0 %.1f translate -90 rotate\n", pl);
+ if (doc->normal_landscape)
+ doc_printf(doc, "0.0 %.1f translate -90 rotate\n", pagel);
else
- printf("%.1f 0.0 translate 90 rotate\n", pw);
+ doc_printf(doc, "%.1f 0.0 translate 90 rotate\n", pagew);
- printf("%.1f %.1f translate %.3f %.3f scale\n",
- ty, tx + l * x, w / PageWidth, l / PageLength);
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n",
+ ty, tx + pagew * 0.5 * x, w / bboxw, l / bboxl);
}
else
{
x = pos & 1;
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 1 - x;
- l = pw;
- w = l * PageWidth / PageLength;
+ l = pagew;
+ w = l * bboxw / bboxl;
- if (w > (pl * 0.5))
+ if (w > (pagel * 0.5))
{
- w = pl * 0.5;
- l = w * PageLength / PageWidth;
+ w = pagel * 0.5;
+ l = w * bboxl / bboxw;
}
- tx = 0.5 * (pl * 0.5 - w);
- ty = 0.5 * (pw - l);
+ tx = 0.5 * (pagel * 0.5 - w);
+ ty = 0.5 * (pagew - l);
- if (NormalLandscape)
- printf("%.1f 0.0 translate 90 rotate\n", pw);
+ if (doc->normal_landscape)
+ doc_printf(doc, "%.1f 0.0 translate 90 rotate\n", pagew);
else
- printf("0.0 %.1f translate -90 rotate\n", pl);
+ doc_printf(doc, "0.0 %.1f translate -90 rotate\n", pagel);
- printf("%.1f %.1f translate %.3f %.3f scale\n",
- tx + w * x, ty, w / PageWidth, l / PageLength);
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n",
+ tx + pagel * 0.5 * x, ty, w / bboxw, l / bboxl);
}
break;
case 4 :
- if (Layout & LAYOUT_VERTICAL)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL)
{
x = (pos / 2) & 1;
y = pos & 1;
y = (pos / 2) & 1;
}
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 1 - x;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
y = 1 - y;
- w = pw * 0.5;
- l = w * PageLength / PageWidth;
+ w = pagew * 0.5;
+ l = w * bboxl / bboxw;
- if (l > (pl * 0.5))
+ if (l > (pagel * 0.5))
{
- l = pl * 0.5;
- w = l * PageWidth / PageLength;
+ l = pagel * 0.5;
+ w = l * bboxw / bboxl;
}
- tx = 0.5 * (pw * 0.5 - w);
- ty = 0.5 * (pl * 0.5 - l);
+ tx = 0.5 * (pagew * 0.5 - w);
+ ty = 0.5 * (pagel * 0.5 - l);
- printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l,
- w / PageWidth, l / PageLength);
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n",
+ tx + x * pagew * 0.5, ty + y * pagel * 0.5,
+ w / bboxw, l / bboxl);
break;
case 6 :
if (Orientation & 1)
{
- if (Layout & LAYOUT_VERTICAL)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL)
{
x = pos / 3;
y = pos % 3;
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 1 - x;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
y = 2 - y;
}
else
x = pos & 1;
y = pos / 2;
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 1 - x;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
y = 2 - y;
}
- w = pl * 0.5;
- l = w * PageLength / PageWidth;
+ w = pagel * 0.5;
+ l = w * bboxl / bboxw;
- if (l > (pw * 0.333))
+ if (l > (pagew * 0.333))
{
- l = pw * 0.333;
- w = l * PageWidth / PageLength;
+ l = pagew * 0.333;
+ w = l * bboxw / bboxl;
}
- tx = 0.5 * (pl - 2 * w);
- ty = 0.5 * (pw - 3 * l);
+ tx = 0.5 * (pagel - 2 * w);
+ ty = 0.5 * (pagew - 3 * l);
- if (NormalLandscape)
- printf("0.0 %.1f translate -90 rotate\n", pl);
+ if (doc->normal_landscape)
+ doc_printf(doc, "0 %.1f translate -90 rotate\n", pagel);
else
- printf("%.1f 0.0 translate 90 rotate\n", pw);
+ doc_printf(doc, "%.1f 0 translate 90 rotate\n", pagew);
- printf("%.1f %.1f translate %.3f %.3f scale\n",
- tx + x * w, ty + y * l, w / PageWidth, l / PageLength);
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n",
+ tx + x * w, ty + y * l, l / bboxl, w / bboxw);
}
else
{
- if (Layout & LAYOUT_VERTICAL)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL)
{
x = pos / 2;
y = pos & 1;
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 2 - x;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
y = 1 - y;
}
else
x = pos % 3;
y = pos / 3;
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 2 - x;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
y = 1 - y;
}
- l = pw * 0.5;
- w = l * PageWidth / PageLength;
+ l = pagew * 0.5;
+ w = l * bboxw / bboxl;
- if (w > (pl * 0.333))
+ if (w > (pagel * 0.333))
{
- w = pl * 0.333;
- l = w * PageLength / PageWidth;
+ w = pagel * 0.333;
+ l = w * bboxl / bboxw;
}
- tx = 0.5 * (pl - 3 * w);
- ty = 0.5 * (pw - 2 * l);
+ tx = 0.5 * (pagel - 3 * w);
+ ty = 0.5 * (pagew - 2 * l);
- if (NormalLandscape)
- printf("%.1f 0.0 translate 90 rotate\n", pw);
+ if (doc->normal_landscape)
+ doc_printf(doc, "%.1f 0 translate 90 rotate\n", pagew);
else
- printf("0.0 %.1f translate -90 rotate\n", pl);
+ doc_printf(doc, "0 %.1f translate -90 rotate\n", pagel);
+
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n",
+ tx + w * x, ty + l * y, w / bboxw, l / bboxl);
- printf("%.1f %.1f translate %.3f %.3f scale\n",
- tx + w * x, ty + l * y, w / PageWidth, l / PageLength);
}
break;
case 9 :
- if (Layout & LAYOUT_VERTICAL)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL)
{
x = (pos / 3) % 3;
y = pos % 3;
y = (pos / 3) % 3;
}
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 2 - x;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
y = 2 - y;
- w = pw * 0.333;
- l = w * PageLength / PageWidth;
+ w = pagew * 0.333;
+ l = w * bboxl / bboxw;
- if (l > (pl * 0.333))
+ if (l > (pagel * 0.333))
{
- l = pl * 0.333;
- w = l * PageWidth / PageLength;
+ l = pagel * 0.333;
+ w = l * bboxw / bboxl;
}
- tx = 0.5 * (pw * 0.333 - w);
- ty = 0.5 * (pl * 0.333 - l);
+ tx = 0.5 * (pagew * 0.333 - w);
+ ty = 0.5 * (pagel * 0.333 - l);
- printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l,
- w / PageWidth, l / PageLength);
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n",
+ tx + x * pagew * 0.333, ty + y * pagel * 0.333,
+ w / bboxw, l / bboxl);
break;
case 16 :
- if (Layout & LAYOUT_VERTICAL)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_VERTICAL)
{
x = (pos / 4) & 3;
y = pos & 3;
y = (pos / 4) & 3;
}
- if (Layout & LAYOUT_NEGATEX)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEX)
x = 3 - x;
- if (Layout & LAYOUT_NEGATEY)
+ if (doc->number_up_layout & PSTOPS_LAYOUT_NEGATEY)
y = 3 - y;
- w = pw * 0.25;
- l = w * PageLength / PageWidth;
+ w = pagew * 0.25;
+ l = w * bboxl / bboxw;
- if (l > (pl * 0.25))
+ if (l > (pagel * 0.25))
{
- l = pl * 0.25;
- w = l * PageWidth / PageLength;
+ l = pagel * 0.25;
+ w = l * bboxw / bboxl;
}
- tx = 0.5 * (pw * 0.25 - w);
- ty = 0.5 * (pl * 0.25 - l);
+ tx = 0.5 * (pagew * 0.25 - w);
+ ty = 0.5 * (pagel * 0.25 - l);
- printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l,
- w / PageWidth, l / PageLength);
+ doc_printf(doc, "%.1f %.1f translate %.3f %.3f scale\n",
+ tx + x * pagew * 0.25, ty + y * pagel * 0.25,
+ w / bboxw, l / bboxl);
break;
}
* Draw borders as necessary...
*/
- if (Border && show_border)
+ if (doc->page_border && show_border)
{
- int rects; /* Number of border rectangles */
- float fscale, /* Scaling value for points */
- margin; /* Current margin for borders */
+ int rects; /* Number of border rectangles */
+ float fscale; /* Scaling value for points */
- rects = (Border & BORDER_DOUBLE) ? 2 : 1;
+ rects = (doc->page_border & PSTOPS_BORDERDOUBLE) ? 2 : 1;
fscale = PageWidth / w;
margin = 2.25 * fscale;
* Set the line width and color...
*/
- puts("gsave");
- printf("%.3f setlinewidth 0 setgray newpath\n",
- (Border & BORDER_THICK) ? 0.5 * fscale : 0.24 * fscale);
+ doc_puts(doc, "gsave\n");
+ doc_printf(doc, "%.3f setlinewidth 0 setgray newpath\n",
+ (doc->page_border & PSTOPS_BORDERTHICK) ? 0.5 * fscale :
+ 0.24 * fscale);
/*
* Draw border boxes...
*/
for (; rects > 0; rects --, margin += 2 * fscale)
- if (NUp > 1)
- printf("%.1f %.1f %.1f %.1f ESPrs\n",
- margin,
- margin,
- PageWidth - 2 * margin,
- PageLength - 2 * margin);
+ if (doc->number_up > 1)
+ doc_printf(doc, "%.1f %.1f %.1f %.1f ESPrs\n",
+ margin,
+ margin,
+ bboxw - 2 * margin,
+ bboxl - 2 * margin);
else
- printf("%.1f %.1f %.1f %.1f ESPrs\n",
- PageLeft + margin,
- PageBottom + margin,
- PageRight - PageLeft - 2 * margin,
- PageTop - PageBottom - 2 * margin);
+ doc_printf(doc, "%.1f %.1f %.1f %.1f ESPrs\n",
+ PageLeft + margin,
+ PageBottom + margin,
+ PageRight - PageLeft - 2 * margin,
+ PageTop - PageBottom - 2 * margin);
/*
* Restore pen settings...
*/
- puts("grestore");
+ doc_puts(doc, "grestore\n");
+ }
+
+ if (doc->fitplot)
+ {
+ /*
+ * Offset the page by its bounding box...
+ */
+
+ doc_printf(doc, "%d %d translate\n", -bounding_box[0],
+ -bounding_box[1]);
+ }
+
+ if (doc->fitplot || doc->number_up > 1)
+ {
+ /*
+ * Clip the page to the page's bounding box...
+ */
+
+ doc_printf(doc, "%.1f %.1f %.1f %.1f ESPrc\n",
+ bboxx + margin, bboxy + margin,
+ bboxw - 2 * margin, bboxl - 2 * margin);
+ }
+}
+
+
+/*
+ * 'write_label_prolog()' - Write the prolog with the classification
+ * and page label.
+ */
+
+static void
+write_label_prolog(pstops_doc_t *doc, /* I - Document info */
+ const char *label, /* I - Page label */
+ float bottom, /* I - Bottom position in points */
+ float top, /* I - Top position in points */
+ float width) /* I - Width in points */
+{
+ const char *classification; /* CLASSIFICATION environment variable */
+ const char *ptr; /* Temporary string pointer */
+
+
+ /*
+ * First get the current classification...
+ */
+
+ if ((classification = getenv("CLASSIFICATION")) == NULL)
+ classification = "";
+ if (strcmp(classification, "none") == 0)
+ classification = "";
+
+ /*
+ * If there is nothing to show, bind an empty 'write labels' procedure
+ * and return...
+ */
+
+ if (!classification[0] && (label == NULL || !label[0]))
+ {
+ doc_puts(doc, "userdict/ESPwl{}bind put\n");
+ return;
+ }
+
+ /*
+ * Set the classification + page label string...
+ */
+
+ doc_puts(doc, "userdict");
+ if (!strcmp(classification, "confidential"))
+ doc_puts(doc, "/ESPpl(CONFIDENTIAL");
+ else if (!strcmp(classification, "classified"))
+ doc_puts(doc, "/ESPpl(CLASSIFIED");
+ else if (!strcmp(classification, "secret"))
+ doc_puts(doc, "/ESPpl(SECRET");
+ else if (!strcmp(classification, "topsecret"))
+ doc_puts(doc, "/ESPpl(TOP SECRET");
+ else if (!strcmp(classification, "unclassified"))
+ doc_puts(doc, "/ESPpl(UNCLASSIFIED");
+ else
+ {
+ doc_puts(doc, "/ESPpl(");
+
+ for (ptr = classification; *ptr; ptr ++)
+ {
+ if (*ptr < 32 || *ptr > 126)
+ doc_printf(doc, "\\%03o", *ptr);
+ else if (*ptr == '_')
+ doc_puts(doc, " ");
+ else if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
+ doc_printf(doc, "\\%c", *ptr);
+ else
+ doc_printf(doc, "%c", *ptr);
+ }
}
- if (NUp > 1)
+ if (label)
{
+ if (classification[0])
+ doc_puts(doc, " - ");
+
/*
- * Clip the page that follows to the bounding box of the page...
+ * Quote the label string as needed...
*/
- printf("%d %d translate\n", -lbrt[0], -lbrt[1]);
- printf("0 0 %.1f %.1f ESPrc\n", w, l);
+ for (ptr = label; *ptr; ptr ++)
+ {
+ if (*ptr < 32 || *ptr > 126)
+ doc_printf(doc, "\\%03o", *ptr);
+ else if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
+ doc_printf(doc, "\\%c", *ptr);
+ else
+ doc_printf(doc, "%c", *ptr);
+ }
+ }
+
+ doc_puts(doc, ")put\n");
+
+ /*
+ * Then get a 14 point Helvetica-Bold font...
+ */
+
+ doc_puts(doc, "userdict/ESPpf /Helvetica-Bold findfont 14 scalefont put\n");
+
+ /*
+ * Finally, the procedure to write the labels on the page...
+ */
+
+ doc_puts(doc, "userdict/ESPwl{\n");
+ doc_puts(doc, " ESPpf setfont\n");
+ doc_printf(doc, " ESPpl stringwidth pop dup 12 add exch -0.5 mul %.0f add\n",
+ width * 0.5f);
+ doc_puts(doc, " 1 setgray\n");
+ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrf\n", bottom - 2.0);
+ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrf\n", top - 18.0);
+ doc_puts(doc, " 0 setgray\n");
+ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrs\n", bottom - 2.0);
+ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrs\n", top - 18.0);
+ doc_printf(doc, " dup %.0f moveto ESPpl show\n", bottom + 2.0);
+ doc_printf(doc, " %.0f moveto ESPpl show\n", top - 14.0);
+ doc_puts(doc, "pop\n");
+ doc_puts(doc, "}bind put\n");
+}
+
+
+/*
+ * 'write_labels()' - Write the actual page labels.
+ *
+ * This function is a copy of the one in common.c since we need to
+ * use doc_puts/doc_printf instead of puts/printf...
+ */
+
+static void
+write_labels(pstops_doc_t *doc, /* I - Document information */
+ int orient) /* I - Orientation of the page */
+{
+ float width, /* Width of page */
+ length; /* Length of page */
+
+
+ doc_puts(doc, "gsave\n");
+
+ if ((orient ^ Orientation) & 1)
+ {
+ width = PageLength;
+ length = PageWidth;
+ }
+ else
+ {
+ width = PageWidth;
+ length = PageLength;
+ }
+
+ switch (orient & 3)
+ {
+ case 1 : /* Landscape */
+ doc_printf(doc, "%.1f 0.0 translate 90 rotate\n", length);
+ break;
+ case 2 : /* Reverse Portrait */
+ doc_printf(doc, "%.1f %.1f translate 180 rotate\n", width, length);
+ break;
+ case 3 : /* Reverse Landscape */
+ doc_printf(doc, "0.0 %.1f translate -90 rotate\n", width);
+ break;
}
+
+ doc_puts(doc, "ESPwl\n");
+ doc_puts(doc, "grestore\n");
}
/*
- * End of "$Id: pstops.c 5092 2006-02-09 00:54:31Z mike $".
+ * End of "$Id: pstops.c 7006 2007-10-04 17:43:38Z mike $".
*/