]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
2 | * "$Id: pstops.c 4672 2005-09-18 04:25:46Z mike $" | |
3 | * | |
4 | * PostScript filter for the Common UNIX Printing System (CUPS). | |
5 | * | |
6 | * Copyright 1993-2005 by Easy Software Products. | |
7 | * | |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
17 | * 44141 Airport View Drive, Suite 204 | |
18 | * Hollywood, Maryland 20636 USA | |
19 | * | |
20 | * Voice: (301) 373-9600 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * This file is subject to the Apple OS-Developed Software exception. | |
25 | * | |
26 | * Contents: | |
27 | * | |
28 | * main() - Main entry... | |
29 | * check_range() - Check to see if the current page is selected for | |
30 | * copy_bytes() - Copy bytes from the input file to stdout... | |
31 | * do_prolog() - Send the necessary document prolog commands... | |
32 | * do_setup() - Send the necessary document setup commands... | |
33 | * end_nup() - End processing for N-up printing... | |
34 | * include_feature() - Include a printer option/feature command. | |
35 | * psbcp() - Enable the binary communications protocol on the printer. | |
36 | * psgets() - Get a line from a file. | |
37 | * pswrite() - Write data from a file. | |
38 | * start_nup() - Start processing for N-up printing... | |
39 | */ | |
40 | ||
41 | /* | |
42 | * Include necessary headers... | |
43 | */ | |
44 | ||
45 | #include "common.h" | |
46 | ||
47 | ||
48 | /* | |
49 | * Constants... | |
50 | */ | |
51 | ||
52 | #define MAX_PAGES 10000 | |
53 | ||
54 | #define BORDER_NONE 0 /* No border or hairline border */ | |
55 | #define BORDER_THICK 1 /* Think border */ | |
56 | #define BORDER_SINGLE 2 /* Single-line hairline border */ | |
57 | #define BORDER_SINGLE2 3 /* Single-line thick border */ | |
58 | #define BORDER_DOUBLE 4 /* Double-line hairline border */ | |
59 | #define BORDER_DOUBLE2 5 /* Double-line thick border */ | |
60 | ||
61 | #define LAYOUT_LRBT 0 /* Left to right, bottom to top */ | |
62 | #define LAYOUT_LRTB 1 /* Left to right, top to bottom */ | |
63 | #define LAYOUT_RLBT 2 /* Right to left, bottom to top */ | |
64 | #define LAYOUT_RLTB 3 /* Right to left, top to bottom */ | |
65 | #define LAYOUT_BTLR 4 /* Bottom to top, left to right */ | |
66 | #define LAYOUT_TBLR 5 /* Top to bottom, left to right */ | |
67 | #define LAYOUT_BTRL 6 /* Bottom to top, right to left */ | |
68 | #define LAYOUT_TBRL 7 /* Top to bottom, right to left */ | |
69 | ||
70 | #define LAYOUT_NEGATEY 1 /* The bits for the layout */ | |
71 | #define LAYOUT_NEGATEX 2 /* definitions above... */ | |
72 | #define LAYOUT_VERTICAL 4 | |
73 | ||
74 | #define PROT_STANDARD 0 /* Adobe standard protocol */ | |
75 | #define PROT_BCP 1 /* Adobe BCP protocol */ | |
76 | #define PROT_TBCP 2 /* Adobe TBCP protocol */ | |
77 | ||
78 | ||
79 | /* | |
80 | * Globals... | |
81 | */ | |
82 | ||
83 | int NumPages = 0; /* Number of pages in file */ | |
84 | long Pages[MAX_PAGES]; /* Offsets to each page */ | |
85 | const char *PageRanges = NULL; /* Range of pages selected */ | |
86 | const char *PageSet = NULL; /* All, Even, Odd pages */ | |
87 | int Order = 0, /* 0 = normal, 1 = reverse pages */ | |
88 | Flip = 0, /* Flip/mirror pages */ | |
89 | NUp = 1, /* Number of pages on each sheet (1, 2, 4) */ | |
90 | Collate = 0, /* Collate copies? */ | |
91 | Copies = 1, /* Number of copies */ | |
92 | UseESPsp = 0, /* Use ESPshowpage? */ | |
93 | Border = BORDER_NONE, /* Border around pages */ | |
94 | Layout = LAYOUT_LRTB, /* Layout of N-up pages */ | |
95 | NormalLandscape = 0, /* Normal rotation for landscape? */ | |
96 | Protocol = PROT_STANDARD; | |
97 | /* Transmission protocol to use */ | |
98 | ||
99 | ||
100 | /* | |
101 | * Local functions... | |
102 | */ | |
103 | ||
104 | static int check_range(int page); | |
105 | static void copy_bytes(FILE *fp, size_t length); | |
106 | static void do_prolog(ppd_file_t *ppd); | |
107 | static void do_setup(ppd_file_t *ppd, int copies, int collate, | |
108 | int slowcollate, float g, float b); | |
109 | static void end_nup(int number); | |
110 | static void include_feature(ppd_file_t *ppd, const char *line, FILE *out); | |
111 | #define is_first_page(p) (NUp == 1 || (((p)+1) % NUp) == 1) | |
112 | #define is_last_page(p) (NUp > 1 && (((p)+1) % NUp) == 0) | |
113 | #define is_not_last_page(p) (NUp > 1 && ((p) % NUp) != 0) | |
114 | static void psbcp(ppd_file_t *ppd); | |
115 | static char *psgets(char *buf, size_t *bytes, FILE *fp); | |
116 | static size_t pswrite(const char *buf, size_t bytes, FILE *fp); | |
117 | static void start_nup(int number, int show_border); | |
118 | ||
119 | ||
120 | /* | |
121 | * 'main()' - Main entry... | |
122 | */ | |
123 | ||
124 | int /* O - Exit status */ | |
125 | main(int argc, /* I - Number of command-line arguments */ | |
126 | char *argv[]) /* I - Command-line arguments */ | |
127 | { | |
128 | FILE *fp; /* Print file */ | |
129 | ppd_file_t *ppd; /* PPD file */ | |
130 | ppd_attr_t *attr; /* Attribute in PPD file */ | |
131 | int num_options; /* Number of print options */ | |
132 | cups_option_t *options; /* Print options */ | |
133 | const char *val; /* Option value */ | |
134 | char tempfile[255]; /* Temporary file name */ | |
135 | FILE *temp; /* Temporary file */ | |
136 | int tempfd; /* Temporary file descriptor */ | |
137 | int number; /* Page number */ | |
138 | int slowcollate; /* 1 if we need to collate manually */ | |
139 | int sloworder; /* 1 if we need to order manually */ | |
140 | int slowduplex; /* 1 if we need an even number of pages */ | |
141 | char line[8192]; /* Line buffer */ | |
142 | size_t len; /* Length of line buffer */ | |
143 | float g; /* Gamma correction value */ | |
144 | float b; /* Brightness factor */ | |
145 | int level; /* Nesting level for embedded files */ | |
146 | int nbytes, /* Number of bytes read */ | |
147 | tbytes; /* Total bytes to read for binary data */ | |
148 | int page; /* Current page sequence number */ | |
149 | int real_page; /* "Real" page number in document */ | |
150 | int page_count; /* Page count for NUp */ | |
151 | int basepage; /* Base page number */ | |
152 | int subpage; /* Sub-page number */ | |
153 | int copy; /* Current copy */ | |
154 | int saweof; /* Did we see a %%EOF tag? */ | |
155 | int sent_espsp, /* Did we send the ESPshowpage commands? */ | |
156 | sent_prolog, /* Did we send the prolog commands? */ | |
157 | sent_setup; /* Did we send the setup commands? */ | |
158 | ||
159 | ||
160 | /* | |
161 | * Make sure status messages are not buffered... | |
162 | */ | |
163 | ||
164 | setbuf(stderr, NULL); | |
165 | ||
166 | /* | |
167 | * Check command-line... | |
168 | */ | |
169 | ||
170 | if (argc < 6 || argc > 7) | |
171 | { | |
172 | fputs("ERROR: pstops job-id user title copies options [file]\n", stderr); | |
173 | return (1); | |
174 | } | |
175 | ||
176 | /* | |
177 | * If we have 7 arguments, print the file named on the command-line. | |
178 | * Otherwise, send stdin instead... | |
179 | */ | |
180 | ||
181 | if (argc == 6) | |
182 | fp = stdin; | |
183 | else | |
184 | { | |
185 | /* | |
186 | * Try to open the print file... | |
187 | */ | |
188 | ||
189 | if ((fp = fopen(argv[6], "rb")) == NULL) | |
190 | { | |
191 | fprintf(stderr, "ERROR: unable to open print file \"%s\" - %s\n", | |
192 | argv[6], strerror(errno)); | |
193 | return (1); | |
194 | } | |
195 | } | |
196 | ||
197 | /* | |
198 | * Process command-line options and write the prolog... | |
199 | */ | |
200 | ||
201 | g = 1.0; | |
202 | b = 1.0; | |
203 | ||
204 | Copies = atoi(argv[4]); | |
205 | ||
206 | options = NULL; | |
207 | num_options = cupsParseOptions(argv[5], 0, &options); | |
208 | ||
209 | ppd = SetCommonOptions(num_options, options, 1); | |
210 | ||
211 | if (ppd && ppd->landscape > 0) | |
212 | NormalLandscape = 1; | |
213 | ||
214 | if ((val = cupsGetOption("page-ranges", num_options, options)) != NULL) | |
215 | PageRanges = val; | |
216 | ||
217 | if ((val = cupsGetOption("page-set", num_options, options)) != NULL) | |
218 | PageSet = val; | |
219 | ||
220 | if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL) | |
221 | { | |
222 | /* | |
223 | * This IPP attribute is unnecessarily complicated... | |
224 | * | |
225 | * single-document, separate-documents-collated-copies, and | |
226 | * single-document-new-sheet all require collated copies. | |
227 | * | |
228 | * separate-documents-uncollated-copies allows for uncollated copies. | |
229 | */ | |
230 | ||
231 | Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0; | |
232 | } | |
233 | ||
234 | if ((val = cupsGetOption("Collate", num_options, options)) != NULL && | |
235 | (!strcasecmp(val, "true") ||!strcasecmp(val, "on") || | |
236 | !strcasecmp(val, "yes"))) | |
237 | Collate = 1; | |
238 | ||
239 | if ((val = cupsGetOption("OutputOrder", num_options, options)) != NULL && | |
240 | !strcasecmp(val, "Reverse")) | |
241 | Order = 1; | |
242 | ||
243 | if ((val = cupsGetOption("number-up", num_options, options)) != NULL) | |
244 | NUp = atoi(val); | |
245 | ||
246 | if ((val = cupsGetOption("page-border", num_options, options)) != NULL) | |
247 | { | |
248 | if (!strcasecmp(val, "none")) | |
249 | Border = BORDER_NONE; | |
250 | else if (!strcasecmp(val, "single")) | |
251 | Border = BORDER_SINGLE; | |
252 | else if (!strcasecmp(val, "single-thick")) | |
253 | Border = BORDER_SINGLE2; | |
254 | else if (!strcasecmp(val, "double")) | |
255 | Border = BORDER_DOUBLE; | |
256 | else if (!strcasecmp(val, "double-thick")) | |
257 | Border = BORDER_DOUBLE2; | |
258 | } | |
259 | ||
260 | if ((val = cupsGetOption("number-up-layout", num_options, options)) != NULL) | |
261 | { | |
262 | if (!strcasecmp(val, "lrtb")) | |
263 | Layout = LAYOUT_LRTB; | |
264 | else if (!strcasecmp(val, "lrbt")) | |
265 | Layout = LAYOUT_LRBT; | |
266 | else if (!strcasecmp(val, "rltb")) | |
267 | Layout = LAYOUT_RLTB; | |
268 | else if (!strcasecmp(val, "rlbt")) | |
269 | Layout = LAYOUT_RLBT; | |
270 | else if (!strcasecmp(val, "tblr")) | |
271 | Layout = LAYOUT_TBLR; | |
272 | else if (!strcasecmp(val, "tbrl")) | |
273 | Layout = LAYOUT_TBRL; | |
274 | else if (!strcasecmp(val, "btlr")) | |
275 | Layout = LAYOUT_BTLR; | |
276 | else if (!strcasecmp(val, "btrl")) | |
277 | Layout = LAYOUT_BTRL; | |
278 | } | |
279 | ||
280 | if ((val = cupsGetOption("gamma", num_options, options)) != NULL) | |
281 | g = atoi(val) * 0.001f; | |
282 | ||
283 | if ((val = cupsGetOption("brightness", num_options, options)) != NULL) | |
284 | b = atoi(val) * 0.01f; | |
285 | ||
286 | if ((val = cupsGetOption("mirror", num_options, options)) != NULL && | |
287 | (!strcasecmp(val, "true") ||!strcasecmp(val, "on") || | |
288 | !strcasecmp(val, "yes"))) | |
289 | Flip = 1; | |
290 | ||
291 | /* | |
292 | * See if we have to filter the fast or slow way... | |
293 | */ | |
294 | ||
295 | if (ppd && ppd->manual_copies && Duplex && Copies > 1) | |
296 | { | |
297 | /* | |
298 | * Force collated copies when printing a duplexed document to | |
299 | * a non-PS printer that doesn't do hardware copy generation. | |
300 | * Otherwise the copies will end up on the front/back side of | |
301 | * each page. Also, set the "slowduplex" option to make sure | |
302 | * that we output an even number of pages... | |
303 | */ | |
304 | ||
305 | Collate = 1; | |
306 | slowduplex = 1; | |
307 | } | |
308 | else | |
309 | slowduplex = 0; | |
310 | ||
311 | if (ppdFindOption(ppd, "Collate") == NULL && Collate && Copies > 1) | |
312 | slowcollate = 1; | |
313 | else | |
314 | slowcollate = 0; | |
315 | ||
316 | if (ppdFindOption(ppd, "OutputOrder") == NULL && Order) | |
317 | sloworder = 1; | |
318 | else | |
319 | sloworder = 0; | |
320 | ||
321 | /* | |
322 | * If we need to filter slowly, then create a temporary file for page data... | |
323 | * | |
324 | * If the temp file can't be created, then we'll ignore the collating/output | |
325 | * order options... | |
326 | */ | |
327 | ||
328 | if (sloworder || slowcollate) | |
329 | { | |
330 | tempfd = cupsTempFd(tempfile, sizeof(tempfile)); | |
331 | if (tempfd < 0) | |
332 | { | |
333 | perror("ERROR: Unable to open temp file"); | |
334 | temp = NULL; | |
335 | } | |
336 | else | |
337 | temp = fdopen(tempfd, "wb+"); | |
338 | ||
339 | if (temp == NULL) | |
340 | slowcollate = sloworder = 0; | |
341 | } | |
342 | else | |
343 | temp = NULL; | |
344 | ||
345 | /* | |
346 | * See if we should use a binary transmission protocol... | |
347 | */ | |
348 | ||
349 | if ((attr = ppdFindAttr(ppd, "cupsProtocol", NULL)) != NULL && | |
350 | attr->value != NULL) | |
351 | { | |
352 | if (!strcasecmp(attr->value, "TBCP")) | |
353 | Protocol = PROT_TBCP; | |
354 | else if (!strcasecmp(attr->value, "BCP")) | |
355 | { | |
356 | Protocol = PROT_BCP; | |
357 | ||
358 | psbcp(ppd); | |
359 | } | |
360 | } | |
361 | ||
362 | /* | |
363 | * Write any "exit server" options that have been selected... | |
364 | */ | |
365 | ||
366 | ppdEmit(ppd, stdout, PPD_ORDER_EXIT); | |
367 | ||
368 | /* | |
369 | * Write any JCL commands that are needed to print PostScript code... | |
370 | */ | |
371 | ||
372 | ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]); | |
373 | ||
374 | /* | |
375 | * Read the first line to see if we have DSC comments... | |
376 | */ | |
377 | ||
378 | len = sizeof(line); | |
379 | if (psgets(line, &len, fp) == NULL) | |
380 | { | |
381 | fputs("ERROR: Empty print file!\n", stderr); | |
382 | ppdClose(ppd); | |
383 | return (1); | |
384 | } | |
385 | ||
386 | /* | |
387 | * Handle leading PJL fun... | |
388 | */ | |
389 | ||
390 | while (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5)) | |
391 | { | |
392 | /* | |
393 | * Yup, we have leading PJL fun, so skip it until we hit the line | |
394 | * with "ENTER LANGUAGE"... | |
395 | */ | |
396 | ||
397 | fputs("DEBUG: Skipping PJL header...\n", stderr); | |
398 | ||
399 | while (strstr(line, "ENTER LANGUAGE") == NULL) | |
400 | { | |
401 | len = sizeof(line); | |
402 | if (psgets(line, &len, fp) == NULL) | |
403 | break; | |
404 | } | |
405 | ||
406 | len = sizeof(line); | |
407 | if (psgets(line, &len, fp) == NULL) | |
408 | break; | |
409 | } | |
410 | ||
411 | /* | |
412 | * Switch to TBCP mode as needed... | |
413 | */ | |
414 | ||
415 | if (Protocol == PROT_TBCP) | |
416 | fputs("\001M", stdout); | |
417 | ||
418 | /* | |
419 | * Start sending the document with any commands needed... | |
420 | */ | |
421 | ||
422 | fwrite(line, 1, len, stdout); | |
423 | ||
424 | saweof = 0; | |
425 | sent_espsp = 0; | |
426 | sent_prolog = 0; | |
427 | sent_setup = 0; | |
428 | ||
429 | if (Copies != 1 && (!Collate || !slowcollate)) | |
430 | { | |
431 | /* | |
432 | * Tell the document processor the copy and duplex options | |
433 | * that are required... | |
434 | */ | |
435 | ||
436 | printf("%%%%Requirements: numcopies(%d)%s%s\n", Copies, | |
437 | Collate ? " collate" : "", | |
438 | Duplex ? " duplex" : ""); | |
439 | ||
440 | /* | |
441 | * Apple uses RBI comments for various non-PPD options... | |
442 | */ | |
443 | ||
444 | printf("%%RBINumCopies: %d\n", Copies); | |
445 | } | |
446 | else | |
447 | { | |
448 | /* | |
449 | * Tell the document processor the duplex option that is required... | |
450 | */ | |
451 | ||
452 | if (Duplex) | |
453 | puts("%%Requirements: duplex"); | |
454 | ||
455 | /* | |
456 | * Apple uses RBI comments for various non-PPD options... | |
457 | */ | |
458 | ||
459 | puts("%RBINumCopies: 1"); | |
460 | } | |
461 | ||
462 | /* | |
463 | * Figure out if we should use ESPshowpage or not... | |
464 | */ | |
465 | ||
466 | val = cupsGetOption("page-label", num_options, options); | |
467 | ||
468 | if (val != NULL || getenv("CLASSIFICATION") != NULL || NUp > 1 || | |
469 | Border || strstr(line, "EPS") != NULL) | |
470 | { | |
471 | /* | |
472 | * Yes, use ESPshowpage... | |
473 | */ | |
474 | ||
475 | UseESPsp = 1; | |
476 | } | |
477 | ||
478 | fprintf(stderr, "DEBUG: slowcollate=%d, slowduplex=%d, sloworder=%d\n", | |
479 | slowcollate, slowduplex, sloworder); | |
480 | ||
481 | if (!strncmp(line, "%!PS-Adobe-", 11) && !strstr(line, "EPSF")) | |
482 | { | |
483 | /* | |
484 | * OK, we have DSC comments and this isn't an EPS file; read until we | |
485 | * find a %%Page comment... | |
486 | */ | |
487 | ||
488 | puts("%%Pages: (atend)"); | |
489 | ||
490 | level = 0; | |
491 | ||
492 | while (!feof(fp)) | |
493 | { | |
494 | len = sizeof(line); | |
495 | if (psgets(line, &len, fp) == NULL) | |
496 | break; | |
497 | ||
498 | if (!strncmp(line, "%%", 2)) | |
499 | fprintf(stderr, "DEBUG: %d %s", level, line); | |
500 | else if (line[0] != '%' && line[0] && !sent_espsp && UseESPsp) | |
501 | { | |
502 | /* | |
503 | * Send ESPshowpage stuff... | |
504 | */ | |
505 | ||
506 | sent_espsp = 1; | |
507 | ||
508 | puts("userdict/ESPshowpage/showpage load put\n" | |
509 | "userdict/showpage{}put"); | |
510 | } | |
511 | ||
512 | if (!strncmp(line, "%%BeginDocument:", 16) || | |
513 | !strncmp(line, "%%BeginDocument ", 16) || /* Adobe Acrobat BUG */ | |
514 | !strncmp(line, "%ADO_BeginApplication", 21)) | |
515 | { | |
516 | fputs(line, stdout); | |
517 | level ++; | |
518 | } | |
519 | else if ((!strncmp(line, "%%EndDocument", 13) || | |
520 | !strncmp(line, "%ADO_EndApplication", 19)) && level > 0) | |
521 | { | |
522 | fputs(line, stdout); | |
523 | level --; | |
524 | } | |
525 | else if (!strncmp(line, "%cupsRotation:", 14) && level == 0) | |
526 | { | |
527 | /* | |
528 | * Reset orientation of document? | |
529 | */ | |
530 | ||
531 | int orient = (atoi(line + 14) / 90) & 3; | |
532 | ||
533 | if (orient != Orientation) | |
534 | { | |
535 | Orientation = (4 - Orientation + orient) & 3; | |
536 | UpdatePageVars(); | |
537 | Orientation = orient; | |
538 | } | |
539 | } | |
540 | else if (!strncmp(line, "%%BeginProlog", 13) && level == 0) | |
541 | { | |
542 | /* | |
543 | * Write the existing comment line, and then follow with patches | |
544 | * and prolog commands... | |
545 | */ | |
546 | ||
547 | fputs(line, stdout); | |
548 | ||
549 | if (!sent_prolog) | |
550 | { | |
551 | sent_prolog = 1; | |
552 | do_prolog(ppd); | |
553 | } | |
554 | } | |
555 | else if (!strncmp(line, "%%BeginSetup", 12) && level == 0) | |
556 | { | |
557 | /* | |
558 | * Write the existing comment line, and then follow with document | |
559 | * setup commands... | |
560 | */ | |
561 | ||
562 | fputs(line, stdout); | |
563 | ||
564 | if (!sent_prolog) | |
565 | { | |
566 | sent_prolog = 1; | |
567 | do_prolog(ppd); | |
568 | } | |
569 | ||
570 | if (!sent_setup) | |
571 | { | |
572 | sent_setup = 1; | |
573 | do_setup(ppd, Copies, Collate, slowcollate, g, b); | |
574 | } | |
575 | } | |
576 | else if (!strncmp(line, "%%Page:", 7) && level == 0) | |
577 | break; | |
578 | else if (!strncmp(line, "%%IncludeFeature:", 17) && level == 0 && NUp == 1) | |
579 | include_feature(ppd, line, stdout); | |
580 | else if (!strncmp(line, "%%BeginBinary:", 14) || | |
581 | (!strncmp(line, "%%BeginData:", 12) && | |
582 | !strstr(line, "ASCII") && !strstr(line, "Hex"))) | |
583 | { | |
584 | /* | |
585 | * Copy binary data... | |
586 | */ | |
587 | ||
588 | tbytes = atoi(strchr(line, ':') + 1); | |
589 | fputs(line, stdout); | |
590 | ||
591 | while (tbytes > 0) | |
592 | { | |
593 | if (tbytes > sizeof(line)) | |
594 | nbytes = fread(line, 1, sizeof(line), fp); | |
595 | else | |
596 | nbytes = fread(line, 1, tbytes, fp); | |
597 | ||
598 | if (nbytes < 1) | |
599 | { | |
600 | perror("ERROR: Early end-of-file while reading binary data"); | |
601 | return (1); | |
602 | } | |
603 | ||
604 | pswrite(line, nbytes, stdout); | |
605 | tbytes -= nbytes; | |
606 | } | |
607 | } | |
608 | else if (strncmp(line, "%%Pages:", 8) != 0) | |
609 | pswrite(line, len, stdout); | |
610 | } | |
611 | ||
612 | /* | |
613 | * Make sure we have the prolog and setup commands written... | |
614 | */ | |
615 | ||
616 | if (!sent_prolog) | |
617 | { | |
618 | puts("%%BeginProlog"); | |
619 | ||
620 | sent_prolog = 1; | |
621 | do_prolog(ppd); | |
622 | ||
623 | puts("%%EndProlog"); | |
624 | } | |
625 | ||
626 | if (!sent_setup) | |
627 | { | |
628 | puts("%%BeginSetup"); | |
629 | ||
630 | sent_setup = 1; | |
631 | do_setup(ppd, Copies, Collate, slowcollate, g, b); | |
632 | ||
633 | puts("%%EndSetup"); | |
634 | } | |
635 | ||
636 | if (!sent_espsp && UseESPsp) | |
637 | { | |
638 | /* | |
639 | * Send ESPshowpage stuff... | |
640 | */ | |
641 | ||
642 | sent_espsp = 1; | |
643 | ||
644 | puts("userdict/ESPshowpage/showpage load put\n" | |
645 | "userdict/showpage{}put"); | |
646 | } | |
647 | ||
648 | /* | |
649 | * Write the page and label prologs... | |
650 | */ | |
651 | ||
652 | if (NUp == 2 || NUp == 6) | |
653 | { | |
654 | /* | |
655 | * For 2- and 6-up output, rotate the labels to match the orientation | |
656 | * of the pages... | |
657 | */ | |
658 | ||
659 | if (Orientation & 1) | |
660 | WriteLabelProlog(val, PageBottom, PageWidth - PageLength + PageTop, | |
661 | PageLength); | |
662 | else | |
663 | WriteLabelProlog(val, PageLeft, PageRight, PageLength); | |
664 | } | |
665 | else | |
666 | WriteLabelProlog(val, PageBottom, PageTop, PageWidth); | |
667 | ||
668 | /* | |
669 | * Then read all of the pages, filtering as needed... | |
670 | */ | |
671 | ||
672 | for (page = 1, real_page = 1;;) | |
673 | { | |
674 | if (!strncmp(line, "%%", 2)) | |
675 | fprintf(stderr, "DEBUG: %d %s", level, line); | |
676 | ||
677 | if (!strncmp(line, "%%BeginDocument:", 16) || | |
678 | !strncmp(line, "%%BeginDocument ", 16)) /* Adobe Acrobat BUG */ | |
679 | level ++; | |
680 | else if (!strncmp(line, "%%EndDocument", 13) && level > 0) | |
681 | level --; | |
682 | else if (!strcmp(line, "\004") && len == 1) | |
683 | break; | |
684 | else if (!strncmp(line, "%%EOF", 5) && level == 0) | |
685 | { | |
686 | fputs("DEBUG: Saw EOF!\n", stderr); | |
687 | saweof = 1; | |
688 | break; | |
689 | } | |
690 | else if (!strncmp(line, "%%Page:", 7) && level == 0) | |
691 | { | |
692 | if (!check_range(real_page)) | |
693 | { | |
694 | while (!feof(fp)) | |
695 | { | |
696 | len = sizeof(line); | |
697 | if (psgets(line, &len, fp) == NULL) | |
698 | break; | |
699 | ||
700 | if (!strncmp(line, "%%", 2)) | |
701 | fprintf(stderr, "DEBUG: %d %s", level, line); | |
702 | ||
703 | if (!strncmp(line, "%%BeginDocument:", 16) || | |
704 | !strncmp(line, "%%BeginDocument ", 16)) /* Adobe Acrobat BUG */ | |
705 | level ++; | |
706 | else if (!strncmp(line, "%%EndDocument", 13) && level > 0) | |
707 | level --; | |
708 | else if (!strncmp(line, "%%Page:", 7) && level == 0) | |
709 | { | |
710 | real_page ++; | |
711 | break; | |
712 | } | |
713 | else if (!strncmp(line, "%%BeginBinary:", 14) || | |
714 | (!strncmp(line, "%%BeginData:", 12) && | |
715 | !strstr(line, "ASCII") && !strstr(line, "Hex"))) | |
716 | { | |
717 | /* | |
718 | * Skip binary data... | |
719 | */ | |
720 | ||
721 | tbytes = atoi(strchr(line, ':') + 1); | |
722 | ||
723 | while (tbytes > 0) | |
724 | { | |
725 | if (tbytes > sizeof(line)) | |
726 | nbytes = fread(line, 1, sizeof(line), fp); | |
727 | else | |
728 | nbytes = fread(line, 1, tbytes, fp); | |
729 | ||
730 | if (nbytes < 1) | |
731 | { | |
732 | perror("ERROR: Early end-of-file while reading binary data"); | |
733 | return (1); | |
734 | } | |
735 | ||
736 | tbytes -= nbytes; | |
737 | } | |
738 | } | |
739 | } | |
740 | ||
741 | continue; | |
742 | } | |
743 | ||
744 | if (!sloworder && NumPages > 0) | |
745 | end_nup(NumPages - 1); | |
746 | ||
747 | if (slowcollate || sloworder) | |
748 | Pages[NumPages] = ftell(temp); | |
749 | ||
750 | if (!sloworder) | |
751 | { | |
752 | if (is_first_page(NumPages)) | |
753 | { | |
754 | if (ppd == NULL || ppd->num_filters == 0) | |
755 | fprintf(stderr, "PAGE: %d %d\n", page, slowcollate ? 1 : Copies); | |
756 | ||
757 | printf("%%%%Page: %d %d\n", page, page); | |
758 | page ++; | |
759 | ppdEmit(ppd, stdout, PPD_ORDER_PAGE); | |
760 | } | |
761 | ||
762 | start_nup(NumPages, 1); | |
763 | } | |
764 | ||
765 | NumPages ++; | |
766 | real_page ++; | |
767 | } | |
768 | else if (!strncmp(line, "%%BeginBinary:", 14) || | |
769 | (!strncmp(line, "%%BeginData:", 12) && | |
770 | !strstr(line, "ASCII") && !strstr(line, "Hex"))) | |
771 | { | |
772 | /* | |
773 | * Copy binary data... | |
774 | */ | |
775 | ||
776 | tbytes = atoi(strchr(line, ':') + 1); | |
777 | ||
778 | if (!sloworder) | |
779 | fputs(line, stdout); | |
780 | if (slowcollate || sloworder) | |
781 | fputs(line, temp); | |
782 | ||
783 | while (tbytes > 0) | |
784 | { | |
785 | if (tbytes > sizeof(line)) | |
786 | nbytes = fread(line, 1, sizeof(line), fp); | |
787 | else | |
788 | nbytes = fread(line, 1, tbytes, fp); | |
789 | ||
790 | if (nbytes < 1) | |
791 | { | |
792 | perror("ERROR: Early end-of-file while reading binary data"); | |
793 | return (1); | |
794 | } | |
795 | ||
796 | if (!sloworder) | |
797 | pswrite(line, nbytes, stdout); | |
798 | ||
799 | if (slowcollate || sloworder) | |
800 | fwrite(line, 1, nbytes, temp); | |
801 | ||
802 | tbytes -= nbytes; | |
803 | } | |
804 | } | |
805 | else if (!strncmp(line, "%%IncludeFeature:", 17)) | |
806 | { | |
807 | /* | |
808 | * Embed printer commands as needed... | |
809 | */ | |
810 | ||
811 | if (level == 0 && NUp == 1) | |
812 | { | |
813 | include_feature(ppd, line, stdout); | |
814 | ||
815 | if (slowcollate || sloworder) | |
816 | include_feature(ppd, line, temp); | |
817 | } | |
818 | } | |
819 | else if (!strncmp(line, "%%BeginFeature:", 15) && NUp > 1) | |
820 | { | |
821 | /* | |
822 | * Strip page options for N-up > 1... | |
823 | */ | |
824 | ||
825 | do | |
826 | { | |
827 | len = sizeof(line); | |
828 | if (psgets(line, &len, fp) == NULL) | |
829 | break; | |
830 | } | |
831 | while (strncmp(line, "%%EndFeature", 12)); | |
832 | } | |
833 | else if (!strncmp(line, "%%Trailer", 9) && level == 0) | |
834 | { | |
835 | fputs("DEBUG: Saw Trailer!\n", stderr); | |
836 | break; | |
837 | } | |
838 | else | |
839 | { | |
840 | if (!sloworder) | |
841 | pswrite(line, len, stdout); | |
842 | ||
843 | if (slowcollate || sloworder) | |
844 | fwrite(line, 1, len, temp); | |
845 | } | |
846 | ||
847 | len = sizeof(line); | |
848 | if (psgets(line, &len, fp) == NULL) | |
849 | break; | |
850 | } | |
851 | ||
852 | if (!sloworder) | |
853 | { | |
854 | end_nup(NumPages - 1); | |
855 | ||
856 | if (is_not_last_page(NumPages)) | |
857 | { | |
858 | start_nup(NUp - 1, 0); | |
859 | end_nup(NUp - 1); | |
860 | } | |
861 | ||
862 | if (Duplex && !(page & 1)) | |
863 | { | |
864 | /* | |
865 | * Make sure we have an even number of pages... | |
866 | */ | |
867 | ||
868 | if (ppd == NULL || ppd->num_filters == 0) | |
869 | fprintf(stderr, "PAGE: %d %d\n", page, slowcollate ? 1 : Copies); | |
870 | ||
871 | printf("%%%%Page: %d %d\n", page, page); | |
872 | page ++; | |
873 | ppdEmit(ppd, stdout, PPD_ORDER_PAGE); | |
874 | ||
875 | start_nup(NUp - 1, 0); | |
876 | puts("showpage"); | |
877 | end_nup(NUp - 1); | |
878 | } | |
879 | } | |
880 | ||
881 | if (slowcollate || sloworder) | |
882 | { | |
883 | Pages[NumPages] = ftell(temp); | |
884 | ||
885 | if (!sloworder) | |
886 | { | |
887 | while (Copies > 1) | |
888 | { | |
889 | rewind(temp); | |
890 | ||
891 | for (number = 0; number < NumPages; number ++) | |
892 | { | |
893 | if (is_first_page(number)) | |
894 | { | |
895 | if (ppd == NULL || ppd->num_filters == 0) | |
896 | fprintf(stderr, "PAGE: %d 1\n", page); | |
897 | ||
898 | printf("%%%%Page: %d %d\n", page, page); | |
899 | page ++; | |
900 | ppdEmit(ppd, stdout, PPD_ORDER_PAGE); | |
901 | } | |
902 | ||
903 | start_nup(number, 1); | |
904 | copy_bytes(temp, Pages[number + 1] - Pages[number]); | |
905 | end_nup(number); | |
906 | } | |
907 | ||
908 | if (is_not_last_page(NumPages)) | |
909 | { | |
910 | start_nup(NUp - 1, 0); | |
911 | end_nup(NUp - 1); | |
912 | } | |
913 | ||
914 | if (Duplex && !(page & 1)) | |
915 | { | |
916 | /* | |
917 | * Make sure we have an even number of pages... | |
918 | */ | |
919 | ||
920 | if (ppd == NULL || ppd->num_filters == 0) | |
921 | fprintf(stderr, "PAGE: %d 1\n", page); | |
922 | ||
923 | printf("%%%%Page: %d %d\n", page, page); | |
924 | page ++; | |
925 | ppdEmit(ppd, stdout, PPD_ORDER_PAGE); | |
926 | ||
927 | start_nup(NUp - 1, 0); | |
928 | puts("showpage"); | |
929 | end_nup(NUp - 1); | |
930 | } | |
931 | ||
932 | Copies --; | |
933 | } | |
934 | } | |
935 | else | |
936 | { | |
937 | page_count = (NumPages + NUp - 1) / NUp; | |
938 | copy = 0; | |
939 | ||
940 | fprintf(stderr, "DEBUG: page_count=%d\n", page_count); | |
941 | ||
942 | do | |
943 | { | |
944 | if (Duplex && (page_count & 1)) | |
945 | basepage = page_count; | |
946 | else | |
947 | basepage = page_count - 1; | |
948 | ||
949 | for (; basepage >= 0; basepage --) | |
950 | { | |
951 | if (ppd == NULL || ppd->num_filters == 0) | |
952 | fprintf(stderr, "PAGE: %d %d\n", page, | |
953 | slowcollate ? 1 : Copies); | |
954 | ||
955 | printf("%%%%Page: %d %d\n", page, page); | |
956 | page ++; | |
957 | ||
958 | ppdEmit(ppd, stdout, PPD_ORDER_PAGE); | |
959 | ||
960 | if (basepage >= page_count) | |
961 | { | |
962 | start_nup(NUp - 1, 0); | |
963 | puts("showpage"); | |
964 | end_nup(NUp - 1); | |
965 | } | |
966 | else | |
967 | { | |
968 | for (subpage = 0, number = basepage * NUp; | |
969 | subpage < NUp && number < NumPages; | |
970 | subpage ++, number ++) | |
971 | { | |
972 | start_nup(number, 1); | |
973 | fseek(temp, Pages[number], SEEK_SET); | |
974 | copy_bytes(temp, Pages[number + 1] - Pages[number]); | |
975 | end_nup(number); | |
976 | } | |
977 | ||
978 | if (is_not_last_page(number)) | |
979 | { | |
980 | start_nup(NUp - 1, 0); | |
981 | end_nup(NUp - 1); | |
982 | } | |
983 | } | |
984 | } | |
985 | ||
986 | copy ++; | |
987 | } | |
988 | while (copy < Copies && slowcollate); | |
989 | } | |
990 | } | |
991 | ||
992 | /* | |
993 | * Copy the trailer, if any... | |
994 | */ | |
995 | ||
996 | puts("%%Trailer"); | |
997 | printf("%%%%Pages: %d\n", page - 1); | |
998 | ||
999 | if (UseESPsp) | |
1000 | puts("userdict/showpage/ESPshowpage load put\n"); | |
1001 | ||
1002 | while (!feof(fp)) | |
1003 | { | |
1004 | len = sizeof(line); | |
1005 | if (psgets(line, &len, fp) == NULL) | |
1006 | break; | |
1007 | ||
1008 | if (!(!strcmp(line, "\004") && len == 1) && | |
1009 | strncmp(line, "%%Pages:", 8) != 0) | |
1010 | pswrite(line, len, stdout); | |
1011 | ||
1012 | if (!strncmp(line, "%%EOF", 5)) | |
1013 | { | |
1014 | fputs("DEBUG: Saw EOF!\n", stderr); | |
1015 | saweof = 1; | |
1016 | break; | |
1017 | } | |
1018 | } | |
1019 | } | |
1020 | else | |
1021 | { | |
1022 | /* | |
1023 | * No DSC comments - write any page commands and then the rest of the file... | |
1024 | */ | |
1025 | ||
1026 | if (slowcollate && Copies > 1) | |
1027 | printf("%%%%Pages: %d\n", Copies); | |
1028 | else | |
1029 | puts("%%Pages: 1"); | |
1030 | ||
1031 | if (UseESPsp) | |
1032 | puts("userdict/ESPshowpage/showpage load put\n" | |
1033 | "userdict/showpage{}put"); | |
1034 | ||
1035 | puts("%%BeginProlog"); | |
1036 | WriteLabelProlog(val, PageBottom, PageTop, PageWidth); | |
1037 | do_prolog(ppd); | |
1038 | puts("%%EndProlog"); | |
1039 | ||
1040 | puts("%%BeginSetup"); | |
1041 | do_setup(ppd, Copies, Collate, slowcollate, g, b); | |
1042 | puts("%%EndSetup"); | |
1043 | ||
1044 | if (ppd == NULL || ppd->num_filters == 0) | |
1045 | fprintf(stderr, "PAGE: 1 %d\n", slowcollate ? 1 : Copies); | |
1046 | ||
1047 | ppdEmit(ppd, stdout, PPD_ORDER_PAGE); | |
1048 | ||
1049 | saweof = 1; | |
1050 | ||
1051 | while ((nbytes = fread(line, 1, sizeof(line), fp)) > 0) | |
1052 | { | |
1053 | pswrite(line, nbytes, stdout); | |
1054 | ||
1055 | if (slowcollate) | |
1056 | fwrite(line, 1, nbytes, temp); | |
1057 | } | |
1058 | ||
1059 | if (UseESPsp) | |
1060 | { | |
1061 | WriteLabels(Orientation); | |
1062 | puts("ESPshowpage"); | |
1063 | } | |
1064 | ||
1065 | if (slowcollate) | |
1066 | { | |
1067 | while (Copies > 1) | |
1068 | { | |
1069 | if (ppd == NULL || ppd->num_filters == 0) | |
1070 | fputs("PAGE: 1 1\n", stderr); | |
1071 | ||
1072 | ppdEmit(ppd, stdout, PPD_ORDER_PAGE); | |
1073 | rewind(temp); | |
1074 | copy_bytes(temp, 0); | |
1075 | Copies --; | |
1076 | ||
1077 | if (UseESPsp) | |
1078 | { | |
1079 | WriteLabels(Orientation); | |
1080 | puts("ESPshowpage"); | |
1081 | } | |
1082 | } | |
1083 | } | |
1084 | } | |
1085 | ||
1086 | /* | |
1087 | * Send %%EOF if needed... | |
1088 | */ | |
1089 | ||
1090 | if (!saweof) | |
1091 | puts("%%EOF"); | |
1092 | ||
1093 | /* | |
1094 | * End the job with the appropriate JCL command or CTRL-D otherwise. | |
1095 | */ | |
1096 | ||
1097 | ppdEmitJCLEnd(ppd, stdout); | |
1098 | ||
1099 | /* | |
1100 | * Close files and remove the temporary file if needed... | |
1101 | */ | |
1102 | ||
1103 | if (slowcollate || sloworder) | |
1104 | { | |
1105 | fclose(temp); | |
1106 | unlink(tempfile); | |
1107 | } | |
1108 | ||
1109 | ppdClose(ppd); | |
1110 | ||
1111 | if (fp != stdin) | |
1112 | fclose(fp); | |
1113 | ||
1114 | return (0); | |
1115 | } | |
1116 | ||
1117 | ||
1118 | /* | |
1119 | * 'check_range()' - Check to see if the current page is selected for | |
1120 | * printing. | |
1121 | */ | |
1122 | ||
1123 | static int /* O - 1 if selected, 0 otherwise */ | |
1124 | check_range(int page) /* I - Page number */ | |
1125 | { | |
1126 | const char *range; /* Pointer into range string */ | |
1127 | int lower, upper; /* Lower and upper page numbers */ | |
1128 | ||
1129 | ||
1130 | if (PageSet != NULL) | |
1131 | { | |
1132 | /* | |
1133 | * See if we only print even or odd pages... | |
1134 | */ | |
1135 | ||
1136 | if (!strcasecmp(PageSet, "even") && ((page - 1) % (NUp << 1)) < NUp) | |
1137 | return (0); | |
1138 | if (!strcasecmp(PageSet, "odd") && ((page - 1) % (NUp << 1)) >= NUp) | |
1139 | return (0); | |
1140 | } | |
1141 | ||
1142 | if (PageRanges == NULL) | |
1143 | return (1); /* No range, print all pages... */ | |
1144 | ||
1145 | for (range = PageRanges; *range != '\0';) | |
1146 | { | |
1147 | if (*range == '-') | |
1148 | { | |
1149 | lower = 1; | |
1150 | range ++; | |
1151 | upper = strtol(range, (char **)&range, 10); | |
1152 | } | |
1153 | else | |
1154 | { | |
1155 | lower = strtol(range, (char **)&range, 10); | |
1156 | ||
1157 | if (*range == '-') | |
1158 | { | |
1159 | range ++; | |
1160 | if (!isdigit(*range & 255)) | |
1161 | upper = 65535; | |
1162 | else | |
1163 | upper = strtol(range, (char **)&range, 10); | |
1164 | } | |
1165 | else | |
1166 | upper = lower; | |
1167 | } | |
1168 | ||
1169 | if (page >= lower && page <= upper) | |
1170 | return (1); | |
1171 | ||
1172 | if (*range == ',') | |
1173 | range ++; | |
1174 | else | |
1175 | break; | |
1176 | } | |
1177 | ||
1178 | return (0); | |
1179 | } | |
1180 | ||
1181 | ||
1182 | /* | |
1183 | * 'copy_bytes()' - Copy bytes from the input file to stdout... | |
1184 | */ | |
1185 | ||
1186 | static void | |
1187 | copy_bytes(FILE *fp, /* I - File to read from */ | |
1188 | size_t length) /* I - Length of page data */ | |
1189 | { | |
1190 | char buffer[8192]; /* Data buffer */ | |
1191 | size_t nbytes, /* Number of bytes read */ | |
1192 | nleft; /* Number of bytes left/remaining */ | |
1193 | ||
1194 | ||
1195 | nleft = length; | |
1196 | ||
1197 | while (nleft > 0 || length == 0) | |
1198 | { | |
1199 | if (nleft > sizeof(buffer) || length == 0) | |
1200 | nbytes = sizeof(buffer); | |
1201 | else | |
1202 | nbytes = nleft; | |
1203 | ||
1204 | if ((nbytes = fread(buffer, 1, nbytes, fp)) < 1) | |
1205 | return; | |
1206 | ||
1207 | nleft -= nbytes; | |
1208 | ||
1209 | pswrite(buffer, nbytes, stdout); | |
1210 | } | |
1211 | } | |
1212 | ||
1213 | ||
1214 | /* | |
1215 | * 'do_prolog()' - Send the necessary document prolog commands... | |
1216 | */ | |
1217 | ||
1218 | static void | |
1219 | do_prolog(ppd_file_t *ppd) /* I - PPD file */ | |
1220 | { | |
1221 | /* | |
1222 | * Send the document prolog commands... | |
1223 | */ | |
1224 | ||
1225 | if (ppd != NULL && ppd->patches != NULL) | |
1226 | { | |
1227 | puts("%%BeginFeature: *JobPatchFile 1"); | |
1228 | puts(ppd->patches); | |
1229 | puts("%%EndFeature"); | |
1230 | } | |
1231 | ||
1232 | ppdEmit(ppd, stdout, PPD_ORDER_PROLOG); | |
1233 | } | |
1234 | ||
1235 | ||
1236 | /* | |
1237 | * 'do_setup()' - Send the necessary document setup commands... | |
1238 | */ | |
1239 | ||
1240 | static void | |
1241 | do_setup(ppd_file_t *ppd, /* I - PPD file */ | |
1242 | int copies, /* I - Number of copies */ | |
1243 | int collate, /* I - Collate output? */ | |
1244 | int slowcollate, /* I - Slow collate */ | |
1245 | float g, /* I - Gamma value */ | |
1246 | float b) /* I - Brightness value */ | |
1247 | { | |
1248 | /* | |
1249 | * Send all the printer-specific setup commands... | |
1250 | */ | |
1251 | ||
1252 | ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT); | |
1253 | ppdEmit(ppd, stdout, PPD_ORDER_ANY); | |
1254 | ||
1255 | /* | |
1256 | * Set the number of copies for the job... | |
1257 | */ | |
1258 | ||
1259 | if (copies != 1 && (!collate || !slowcollate)) | |
1260 | { | |
1261 | printf("%%RBIBeginNonPPDFeature: *NumCopies %d\n", copies); | |
1262 | printf("%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse{1 dict begin" | |
1263 | "/NumCopies exch def currentdict end " | |
1264 | "setpagedevice}{userdict/#copies 3 -1 roll put}ifelse\n", copies); | |
1265 | printf("%%RBIEndNonPPDFeature\n"); | |
1266 | } | |
1267 | ||
1268 | /* | |
1269 | * If we are doing N-up printing, disable setpagedevice... | |
1270 | */ | |
1271 | ||
1272 | if (NUp > 1) | |
1273 | puts("userdict/setpagedevice{pop}bind put"); | |
1274 | ||
1275 | /* | |
1276 | * Changes to the transfer function must be made AFTER any | |
1277 | * setpagedevice code... | |
1278 | */ | |
1279 | ||
1280 | if (g != 1.0 || b != 1.0) | |
1281 | printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } " | |
1282 | "ifelse %.3f mul } bind settransfer\n", g, b); | |
1283 | ||
1284 | /* | |
1285 | * Make sure we have rectclip and rectstroke procedures of some sort... | |
1286 | */ | |
1287 | ||
1288 | WriteCommon(); | |
1289 | } | |
1290 | ||
1291 | ||
1292 | /* | |
1293 | * 'end_nup()' - End processing for N-up printing... | |
1294 | */ | |
1295 | ||
1296 | static void | |
1297 | end_nup(int number) /* I - Page number */ | |
1298 | { | |
1299 | puts(""); | |
1300 | ||
1301 | if (Flip || Orientation || NUp > 1) | |
1302 | puts("userdict /ESPsave get restore"); | |
1303 | ||
1304 | switch (NUp) | |
1305 | { | |
1306 | case 1 : | |
1307 | if (UseESPsp) | |
1308 | { | |
1309 | WriteLabels(Orientation); | |
1310 | puts("ESPshowpage"); | |
1311 | } | |
1312 | break; | |
1313 | ||
1314 | case 2 : | |
1315 | case 6 : | |
1316 | if (is_last_page(number) && UseESPsp) | |
1317 | { | |
1318 | if (Orientation & 1) | |
1319 | { | |
1320 | /* | |
1321 | * Rotate the labels back to portrait... | |
1322 | */ | |
1323 | ||
1324 | WriteLabels(Orientation - 1); | |
1325 | } | |
1326 | else if (Orientation == 0) | |
1327 | { | |
1328 | /* | |
1329 | * Rotate the labels to landscape... | |
1330 | */ | |
1331 | ||
1332 | WriteLabels(NormalLandscape ? 1 : 3); | |
1333 | } | |
1334 | else | |
1335 | { | |
1336 | /* | |
1337 | * Rotate the labels to landscape... | |
1338 | */ | |
1339 | ||
1340 | WriteLabels(NormalLandscape ? 3 : 1); | |
1341 | } | |
1342 | ||
1343 | puts("ESPshowpage"); | |
1344 | } | |
1345 | break; | |
1346 | ||
1347 | default : | |
1348 | if (is_last_page(number) && UseESPsp) | |
1349 | { | |
1350 | WriteLabels(Orientation); | |
1351 | puts("ESPshowpage"); | |
1352 | } | |
1353 | break; | |
1354 | } | |
1355 | ||
1356 | fflush(stdout); | |
1357 | } | |
1358 | ||
1359 | ||
1360 | /* | |
1361 | * 'include_feature()' - Include a printer option/feature command. | |
1362 | */ | |
1363 | ||
1364 | static void | |
1365 | include_feature(ppd_file_t *ppd, /* I - PPD file */ | |
1366 | const char *line, /* I - DSC line */ | |
1367 | FILE *out) /* I - Output file */ | |
1368 | { | |
1369 | char name[255], /* Option name */ | |
1370 | value[255]; /* Option value */ | |
1371 | ppd_option_t *option; /* Option in file */ | |
1372 | ppd_choice_t *choice; /* Choice */ | |
1373 | ||
1374 | ||
1375 | /* | |
1376 | * Get the "%%IncludeFeature: *Keyword OptionKeyword" values... | |
1377 | */ | |
1378 | ||
1379 | if (sscanf(line + 17, "%254s%254s", name, value) != 2) | |
1380 | { | |
1381 | fprintf(stderr, "ERROR: Bad line: \"%s\"!\n", line); | |
1382 | return; | |
1383 | } | |
1384 | ||
1385 | /* | |
1386 | * Find the option and choice... | |
1387 | */ | |
1388 | ||
1389 | if ((option = ppdFindOption(ppd, name + 1)) == NULL) | |
1390 | { | |
1391 | fprintf(stderr, "WARNING: Unknown option \"%s\"!\n", name + 1); | |
1392 | return; | |
1393 | } | |
1394 | ||
1395 | if (option->section == PPD_ORDER_EXIT || | |
1396 | option->section == PPD_ORDER_JCL) | |
1397 | { | |
1398 | fprintf(stderr, "WARNING: Option \"%s\" cannot be included via IncludeFeature!\n", | |
1399 | name + 1); | |
1400 | return; | |
1401 | } | |
1402 | ||
1403 | if ((choice = ppdFindChoice(option, value)) == NULL) | |
1404 | { | |
1405 | fprintf(stderr, "WARNING: Unknown choice \"%s\" for option \"%s\"!\n", | |
1406 | value, name + 1); | |
1407 | return; | |
1408 | } | |
1409 | ||
1410 | /* | |
1411 | * Emit the option... | |
1412 | */ | |
1413 | ||
1414 | fputs("[{\n", out); | |
1415 | fprintf(out, "%%%%BeginFeature: %s %s\n", name, value); | |
1416 | if (choice->code && choice->code[0]) | |
1417 | { | |
1418 | fputs(choice->code, out); | |
1419 | ||
1420 | if (choice->code[strlen(choice->code) - 1] != '\n') | |
1421 | putc('\n', out); | |
1422 | } | |
1423 | fputs("%%EndFeature\n", out); | |
1424 | fputs("} stopped cleartomark\n", out); | |
1425 | } | |
1426 | ||
1427 | ||
1428 | /* | |
1429 | * 'psbcp()' - Enable the binary communications protocol on the printer. | |
1430 | */ | |
1431 | ||
1432 | static void | |
1433 | psbcp(ppd_file_t *ppd) /* I - PPD file */ | |
1434 | { | |
1435 | if (ppd->jcl_begin) | |
1436 | fputs(ppd->jcl_begin, stdout); | |
1437 | if (ppd->jcl_ps) | |
1438 | fputs(ppd->jcl_ps, stdout); | |
1439 | ||
1440 | if (ppd->language_level == 1) | |
1441 | { | |
1442 | /* | |
1443 | * Use setsoftwareiomode for BCP mode... | |
1444 | */ | |
1445 | ||
1446 | fputs("%!PS-Adobe-3.0 ExitServer\n", stdout); | |
1447 | fputs("%%Title: (BCP - Level 1)\n", stdout); | |
1448 | fputs("%%EndComments\n", stdout); | |
1449 | fputs("%%BeginExitServer: 0\n", stdout); | |
1450 | fputs("serverdict begin 0 exitserver\n", stdout); | |
1451 | fputs("%%EndExitServer\n", stdout); | |
1452 | fputs("statusdict begin\n", stdout); | |
1453 | fputs("/setsoftwareiomode known {100 setsoftwareiomode}\n", stdout); | |
1454 | fputs("end\n", stdout); | |
1455 | fputs("%EOF\n", stdout); | |
1456 | } | |
1457 | else | |
1458 | { | |
1459 | /* | |
1460 | * Use setdevparams for BCP mode... | |
1461 | */ | |
1462 | ||
1463 | fputs("%!PS-Adobe-3.0\n", stdout); | |
1464 | fputs("%%Title: (BCP - Level 2)\n", stdout); | |
1465 | fputs("%%EndComments\n", stdout); | |
1466 | fputs("currentsysparams\n", stdout); | |
1467 | fputs("/CurInputDevice 2 copy known {\n", stdout); | |
1468 | fputs("get\n", stdout); | |
1469 | fputs("<</Protocol /Binary>> setdevparams\n", stdout); | |
1470 | fputs("}{\n", stdout); | |
1471 | fputs("pop pop\n", stdout); | |
1472 | fputs("} ifelse\n", stdout); | |
1473 | fputs("%EOF\n", stdout); | |
1474 | } | |
1475 | ||
1476 | if (ppd->jcl_end) | |
1477 | fputs(ppd->jcl_end, stdout); | |
1478 | else if (ppd->num_filters == 0) | |
1479 | putchar(0x04); | |
1480 | } | |
1481 | ||
1482 | ||
1483 | /* | |
1484 | * 'psgets()' - Get a line from a file. | |
1485 | * | |
1486 | * Note: | |
1487 | * | |
1488 | * This function differs from the gets() function in that it | |
1489 | * handles any combination of CR, LF, or CR LF to end input | |
1490 | * lines. | |
1491 | */ | |
1492 | ||
1493 | static char * /* O - String or NULL if EOF */ | |
1494 | psgets(char *buf, /* I - Buffer to read into */ | |
1495 | size_t *bytes, /* IO - Length of buffer */ | |
1496 | FILE *fp) /* I - File to read from */ | |
1497 | { | |
1498 | char *bufptr; /* Pointer into buffer */ | |
1499 | int ch; /* Character from file */ | |
1500 | size_t len; /* Max length of string */ | |
1501 | ||
1502 | ||
1503 | len = *bytes - 1; | |
1504 | bufptr = buf; | |
1505 | ch = EOF; | |
1506 | ||
1507 | while ((bufptr - buf) < len) | |
1508 | { | |
1509 | if ((ch = getc(fp)) == EOF) | |
1510 | break; | |
1511 | ||
1512 | if (ch == '\r') | |
1513 | { | |
1514 | /* | |
1515 | * Got a CR; see if there is a LF as well... | |
1516 | */ | |
1517 | ||
1518 | ch = getc(fp); | |
1519 | ||
1520 | if (ch != EOF && ch != '\n') | |
1521 | { | |
1522 | ungetc(ch, fp); /* Nope, save it for later... */ | |
1523 | ch = '\r'; | |
1524 | } | |
1525 | else | |
1526 | *bufptr++ = '\r'; | |
1527 | break; | |
1528 | } | |
1529 | else if (ch == '\n') | |
1530 | break; | |
1531 | else | |
1532 | *bufptr++ = ch; | |
1533 | } | |
1534 | ||
1535 | /* | |
1536 | * Add a trailing newline if it is there... | |
1537 | */ | |
1538 | ||
1539 | if (ch == '\n' || ch == '\r') | |
1540 | { | |
1541 | if ((bufptr - buf) < len) | |
1542 | *bufptr++ = ch; | |
1543 | else | |
1544 | ungetc(ch, fp); | |
1545 | } | |
1546 | ||
1547 | /* | |
1548 | * Nul-terminate the string and return it (or NULL for EOF). | |
1549 | */ | |
1550 | ||
1551 | *bufptr = '\0'; | |
1552 | *bytes = bufptr - buf; | |
1553 | ||
1554 | if (ch == EOF && bufptr == buf) | |
1555 | return (NULL); | |
1556 | else | |
1557 | return (buf); | |
1558 | } | |
1559 | ||
1560 | ||
1561 | /* | |
1562 | * 'pswrite()' - Write data from a file. | |
1563 | */ | |
1564 | ||
1565 | static size_t /* O - Number of bytes written */ | |
1566 | pswrite(const char *buf, /* I - Buffer to write */ | |
1567 | size_t bytes, /* I - Bytes to write */ | |
1568 | FILE *fp) /* I - File to write to */ | |
1569 | { | |
1570 | size_t count; /* Remaining bytes */ | |
1571 | ||
1572 | ||
1573 | switch (Protocol) | |
1574 | { | |
1575 | case PROT_STANDARD : | |
1576 | return (fwrite(buf, 1, bytes, fp)); | |
1577 | ||
1578 | case PROT_BCP : | |
1579 | for (count = bytes; count > 0; count --, buf ++) | |
1580 | switch (*buf) | |
1581 | { | |
1582 | case 0x01 : /* CTRL-A */ | |
1583 | case 0x03 : /* CTRL-C */ | |
1584 | case 0x04 : /* CTRL-D */ | |
1585 | case 0x05 : /* CTRL-E */ | |
1586 | case 0x11 : /* CTRL-Q */ | |
1587 | case 0x13 : /* CTRL-S */ | |
1588 | case 0x14 : /* CTRL-T */ | |
1589 | case 0x1c : /* CTRL-\ */ | |
1590 | putchar(0x01); | |
1591 | putchar(*buf ^ 0x40); | |
1592 | break; | |
1593 | ||
1594 | default : | |
1595 | putchar(*buf); | |
1596 | break; | |
1597 | } | |
1598 | return (bytes); | |
1599 | ||
1600 | case PROT_TBCP : | |
1601 | for (count = bytes; count > 0; count --, buf ++) | |
1602 | switch (*buf) | |
1603 | { | |
1604 | case 0x01 : /* CTRL-A */ | |
1605 | case 0x03 : /* CTRL-C */ | |
1606 | case 0x04 : /* CTRL-D */ | |
1607 | case 0x05 : /* CTRL-E */ | |
1608 | case 0x11 : /* CTRL-Q */ | |
1609 | case 0x13 : /* CTRL-S */ | |
1610 | case 0x14 : /* CTRL-T */ | |
1611 | case 0x1b : /* CTRL-[ (aka ESC) */ | |
1612 | case 0x1c : /* CTRL-\ */ | |
1613 | putchar(0x01); | |
1614 | putchar(*buf ^ 0x40); | |
1615 | break; | |
1616 | ||
1617 | default : | |
1618 | putchar(*buf); | |
1619 | break; | |
1620 | } | |
1621 | return (bytes); | |
1622 | } | |
1623 | ||
1624 | return (fwrite(buf, 1, bytes, fp)); | |
1625 | } | |
1626 | ||
1627 | ||
1628 | /* | |
1629 | * 'start_nup()' - Start processing for N-up printing... | |
1630 | */ | |
1631 | ||
1632 | static void | |
1633 | start_nup(int number, /* I - Page number */ | |
1634 | int show_border) /* I - Show the page border? */ | |
1635 | { | |
1636 | int pos; /* Position on page */ | |
1637 | int x, y; /* Relative position of subpage */ | |
1638 | float w, l, /* Width and length of subpage */ | |
1639 | tx, ty; /* Translation values for subpage */ | |
1640 | float pw, pl; /* Printable width and length of full page */ | |
1641 | ||
1642 | ||
1643 | if (Flip || Orientation || NUp > 1) | |
1644 | puts("userdict/ESPsave save put"); | |
1645 | ||
1646 | if (Flip) | |
1647 | printf("%.1f 0.0 translate -1 1 scale\n", PageWidth); | |
1648 | ||
1649 | pos = number % NUp; | |
1650 | pw = PageRight - PageLeft; | |
1651 | pl = PageTop - PageBottom; | |
1652 | ||
1653 | fprintf(stderr, "DEBUG: pw = %.1f, pl = %.1f\n", pw, pl); | |
1654 | fprintf(stderr, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n", PageLeft, PageRight); | |
1655 | fprintf(stderr, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n", PageTop, PageBottom); | |
1656 | fprintf(stderr, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n", PageWidth, PageLength); | |
1657 | ||
1658 | switch (Orientation) | |
1659 | { | |
1660 | case 1 : /* Landscape */ | |
1661 | printf("%.1f 0.0 translate 90 rotate\n", PageLength); | |
1662 | break; | |
1663 | case 2 : /* Reverse Portrait */ | |
1664 | printf("%.1f %.1f translate 180 rotate\n", PageWidth, PageLength); | |
1665 | break; | |
1666 | case 3 : /* Reverse Landscape */ | |
1667 | printf("0.0 %.1f translate -90 rotate\n", PageWidth); | |
1668 | break; | |
1669 | } | |
1670 | ||
1671 | if (Duplex && NUp > 1 && ((number / NUp) & 1)) | |
1672 | printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom); | |
1673 | else if (NUp > 1) | |
1674 | printf("%.1f %.1f translate\n", PageLeft, PageBottom); | |
1675 | ||
1676 | switch (NUp) | |
1677 | { | |
1678 | default : | |
1679 | w = PageWidth; | |
1680 | l = PageLength; | |
1681 | break; | |
1682 | ||
1683 | case 2 : | |
1684 | if (Orientation & 1) | |
1685 | { | |
1686 | x = pos & 1; | |
1687 | ||
1688 | if (Layout & LAYOUT_NEGATEY) | |
1689 | x = 1 - x; | |
1690 | ||
1691 | w = pl; | |
1692 | l = w * PageLength / PageWidth; | |
1693 | ||
1694 | if (l > (pw * 0.5)) | |
1695 | { | |
1696 | l = pw * 0.5; | |
1697 | w = l * PageWidth / PageLength; | |
1698 | } | |
1699 | ||
1700 | tx = 0.5 * (pw * 0.5 - l); | |
1701 | ty = 0.5 * (pl - w); | |
1702 | ||
1703 | if (NormalLandscape) | |
1704 | printf("0.0 %.1f translate -90 rotate\n", pl); | |
1705 | else | |
1706 | printf("%.1f 0.0 translate 90 rotate\n", pw); | |
1707 | ||
1708 | printf("%.1f %.1f translate %.3f %.3f scale\n", | |
1709 | ty, tx + l * x, w / PageWidth, l / PageLength); | |
1710 | } | |
1711 | else | |
1712 | { | |
1713 | x = pos & 1; | |
1714 | ||
1715 | if (Layout & LAYOUT_NEGATEX) | |
1716 | x = 1 - x; | |
1717 | ||
1718 | l = pw; | |
1719 | w = l * PageWidth / PageLength; | |
1720 | ||
1721 | if (w > (pl * 0.5)) | |
1722 | { | |
1723 | w = pl * 0.5; | |
1724 | l = w * PageLength / PageWidth; | |
1725 | } | |
1726 | ||
1727 | tx = 0.5 * (pl * 0.5 - w); | |
1728 | ty = 0.5 * (pw - l); | |
1729 | ||
1730 | if (NormalLandscape) | |
1731 | printf("%.1f 0.0 translate 90 rotate\n", pw); | |
1732 | else | |
1733 | printf("0.0 %.1f translate -90 rotate\n", pl); | |
1734 | ||
1735 | printf("%.1f %.1f translate %.3f %.3f scale\n", | |
1736 | tx + w * x, ty, w / PageWidth, l / PageLength); | |
1737 | } | |
1738 | break; | |
1739 | ||
1740 | case 4 : | |
1741 | if (Layout & LAYOUT_VERTICAL) | |
1742 | { | |
1743 | x = (pos / 2) & 1; | |
1744 | y = pos & 1; | |
1745 | } | |
1746 | else | |
1747 | { | |
1748 | x = pos & 1; | |
1749 | y = (pos / 2) & 1; | |
1750 | } | |
1751 | ||
1752 | if (Layout & LAYOUT_NEGATEX) | |
1753 | x = 1 - x; | |
1754 | ||
1755 | if (Layout & LAYOUT_NEGATEY) | |
1756 | y = 1 - y; | |
1757 | ||
1758 | w = pw * 0.5; | |
1759 | l = w * PageLength / PageWidth; | |
1760 | ||
1761 | if (l > (pl * 0.5)) | |
1762 | { | |
1763 | l = pl * 0.5; | |
1764 | w = l * PageWidth / PageLength; | |
1765 | } | |
1766 | ||
1767 | tx = 0.5 * (pw * 0.5 - w); | |
1768 | ty = 0.5 * (pl * 0.5 - l); | |
1769 | ||
1770 | printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l, | |
1771 | w / PageWidth, l / PageLength); | |
1772 | break; | |
1773 | ||
1774 | case 6 : | |
1775 | if (Orientation & 1) | |
1776 | { | |
1777 | if (Layout & LAYOUT_VERTICAL) | |
1778 | { | |
1779 | x = pos / 3; | |
1780 | y = pos % 3; | |
1781 | ||
1782 | if (Layout & LAYOUT_NEGATEX) | |
1783 | x = 1 - x; | |
1784 | ||
1785 | if (Layout & LAYOUT_NEGATEY) | |
1786 | y = 2 - y; | |
1787 | } | |
1788 | else | |
1789 | { | |
1790 | x = pos & 1; | |
1791 | y = pos / 2; | |
1792 | ||
1793 | if (Layout & LAYOUT_NEGATEX) | |
1794 | x = 1 - x; | |
1795 | ||
1796 | if (Layout & LAYOUT_NEGATEY) | |
1797 | y = 2 - y; | |
1798 | } | |
1799 | ||
1800 | w = pl * 0.5; | |
1801 | l = w * PageLength / PageWidth; | |
1802 | ||
1803 | if (l > (pw * 0.333)) | |
1804 | { | |
1805 | l = pw * 0.333; | |
1806 | w = l * PageWidth / PageLength; | |
1807 | } | |
1808 | ||
1809 | tx = 0.5 * (pl - 2 * w); | |
1810 | ty = 0.5 * (pw - 3 * l); | |
1811 | ||
1812 | if (NormalLandscape) | |
1813 | printf("0.0 %.1f translate -90 rotate\n", pl); | |
1814 | else | |
1815 | printf("%.1f 0.0 translate 90 rotate\n", pw); | |
1816 | ||
1817 | printf("%.1f %.1f translate %.3f %.3f scale\n", | |
1818 | tx + x * w, ty + y * l, w / PageWidth, l / PageLength); | |
1819 | } | |
1820 | else | |
1821 | { | |
1822 | if (Layout & LAYOUT_VERTICAL) | |
1823 | { | |
1824 | x = pos / 2; | |
1825 | y = pos & 1; | |
1826 | ||
1827 | if (Layout & LAYOUT_NEGATEX) | |
1828 | x = 2 - x; | |
1829 | ||
1830 | if (Layout & LAYOUT_NEGATEY) | |
1831 | y = 1 - y; | |
1832 | } | |
1833 | else | |
1834 | { | |
1835 | x = pos % 3; | |
1836 | y = pos / 3; | |
1837 | ||
1838 | if (Layout & LAYOUT_NEGATEX) | |
1839 | x = 2 - x; | |
1840 | ||
1841 | if (Layout & LAYOUT_NEGATEY) | |
1842 | y = 1 - y; | |
1843 | } | |
1844 | ||
1845 | l = pw * 0.5; | |
1846 | w = l * PageWidth / PageLength; | |
1847 | ||
1848 | if (w > (pl * 0.333)) | |
1849 | { | |
1850 | w = pl * 0.333; | |
1851 | l = w * PageLength / PageWidth; | |
1852 | } | |
1853 | ||
1854 | tx = 0.5 * (pl - 3 * w); | |
1855 | ty = 0.5 * (pw - 2 * l); | |
1856 | ||
1857 | if (NormalLandscape) | |
1858 | printf("%.1f 0.0 translate 90 rotate\n", pw); | |
1859 | else | |
1860 | printf("0.0 %.1f translate -90 rotate\n", pl); | |
1861 | ||
1862 | printf("%.1f %.1f translate %.3f %.3f scale\n", | |
1863 | tx + w * x, ty + l * y, w / PageWidth, l / PageLength); | |
1864 | } | |
1865 | break; | |
1866 | ||
1867 | case 9 : | |
1868 | if (Layout & LAYOUT_VERTICAL) | |
1869 | { | |
1870 | x = (pos / 3) % 3; | |
1871 | y = pos % 3; | |
1872 | } | |
1873 | else | |
1874 | { | |
1875 | x = pos % 3; | |
1876 | y = (pos / 3) % 3; | |
1877 | } | |
1878 | ||
1879 | if (Layout & LAYOUT_NEGATEX) | |
1880 | x = 2 - x; | |
1881 | ||
1882 | if (Layout & LAYOUT_NEGATEY) | |
1883 | y = 2 - y; | |
1884 | ||
1885 | w = pw * 0.333; | |
1886 | l = w * PageLength / PageWidth; | |
1887 | ||
1888 | if (l > (pl * 0.333)) | |
1889 | { | |
1890 | l = pl * 0.333; | |
1891 | w = l * PageWidth / PageLength; | |
1892 | } | |
1893 | ||
1894 | tx = 0.5 * (pw * 0.333 - w); | |
1895 | ty = 0.5 * (pl * 0.333 - l); | |
1896 | ||
1897 | printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l, | |
1898 | w / PageWidth, l / PageLength); | |
1899 | break; | |
1900 | ||
1901 | case 16 : | |
1902 | if (Layout & LAYOUT_VERTICAL) | |
1903 | { | |
1904 | x = (pos / 4) & 3; | |
1905 | y = pos & 3; | |
1906 | } | |
1907 | else | |
1908 | { | |
1909 | x = pos & 3; | |
1910 | y = (pos / 4) & 3; | |
1911 | } | |
1912 | ||
1913 | if (Layout & LAYOUT_NEGATEX) | |
1914 | x = 3 - x; | |
1915 | ||
1916 | if (Layout & LAYOUT_NEGATEY) | |
1917 | y = 3 - y; | |
1918 | ||
1919 | w = pw * 0.25; | |
1920 | l = w * PageLength / PageWidth; | |
1921 | ||
1922 | if (l > (pl * 0.25)) | |
1923 | { | |
1924 | l = pl * 0.25; | |
1925 | w = l * PageWidth / PageLength; | |
1926 | } | |
1927 | ||
1928 | tx = 0.5 * (pw * 0.25 - w); | |
1929 | ty = 0.5 * (pl * 0.25 - l); | |
1930 | ||
1931 | printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l, | |
1932 | w / PageWidth, l / PageLength); | |
1933 | break; | |
1934 | } | |
1935 | ||
1936 | /* | |
1937 | * Draw borders as necessary... | |
1938 | */ | |
1939 | ||
1940 | if (Border && show_border) | |
1941 | { | |
1942 | int rects; /* Number of border rectangles */ | |
1943 | float fscale, /* Scaling value for points */ | |
1944 | margin; /* Current margin for borders */ | |
1945 | ||
1946 | ||
1947 | rects = (Border & BORDER_DOUBLE) ? 2 : 1; | |
1948 | fscale = PageWidth / w; | |
1949 | margin = 2.25 * fscale; | |
1950 | ||
1951 | /* | |
1952 | * Set the line width and color... | |
1953 | */ | |
1954 | ||
1955 | puts("gsave"); | |
1956 | printf("%.3f setlinewidth 0 setgray newpath\n", | |
1957 | (Border & BORDER_THICK) ? 0.5 * fscale : 0.24 * fscale); | |
1958 | ||
1959 | /* | |
1960 | * Draw border boxes... | |
1961 | */ | |
1962 | ||
1963 | for (; rects > 0; rects --, margin += 2 * fscale) | |
1964 | if (NUp > 1) | |
1965 | printf("%.1f %.1f %.1f %.1f ESPrs\n", | |
1966 | margin, | |
1967 | margin, | |
1968 | PageWidth - 2 * margin, | |
1969 | PageLength - 2 * margin); | |
1970 | else | |
1971 | printf("%.1f %.1f %.1f %.1f ESPrs\n", | |
1972 | PageLeft + margin, | |
1973 | PageBottom + margin, | |
1974 | PageRight - PageLeft - 2 * margin, | |
1975 | PageTop - PageBottom - 2 * margin); | |
1976 | ||
1977 | /* | |
1978 | * Restore pen settings... | |
1979 | */ | |
1980 | ||
1981 | puts("grestore"); | |
1982 | } | |
1983 | ||
1984 | if (NUp > 1) | |
1985 | { | |
1986 | /* | |
1987 | * Clip the page that follows to the bounding box of the page... | |
1988 | */ | |
1989 | ||
1990 | printf("0 0 %.1f %.1f ESPrc\n", PageWidth, PageLength); | |
1991 | } | |
1992 | } | |
1993 | ||
1994 | ||
1995 | /* | |
1996 | * End of "$Id: pstops.c 4672 2005-09-18 04:25:46Z mike $". | |
1997 | */ |