"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* Copyright (C) 2000-2005, Ghostgum Software Pty Ltd. All rights reserved.
2
3 This file is part of GSview.
4
5 This program is distributed with NO WARRANTY OF ANY KIND. No author
6 or distributor accepts any responsibility for the consequences of using it,
7 or for whether it serves any particular purpose or works at all, unless he
8 or she says so in writing. Refer to the GSview Licence (the "Licence")
9 for full details.
10
11 Every copy of GSview must include a copy of the Licence, normally in a
12 plain ASCII text file named LICENCE. The Licence grants you the right
13 to copy, modify and redistribute GSview, but only under certain conditions
14 described in the Licence. Among other things, the Licence requires that
15 the copyright notice and this notice be preserved on all copies.
16 */
17
18 /* $Id: dscparse.c,v 1.36 2005/01/20 11:19:00 ghostgum Exp $ */
19
20 /*
21 * This is a DSC parser, based on the DSC 3.0 spec,
22 * with a few DSC 2.1 additions for page size.
23 *
24 * Current limitations:
25 * %%+ may be used after any comment in the comment or trailer,
26 * but is currently only supported by
27 * %%DocumentMedia
28 *
29 * DSC 2.1 additions (discontinued in DSC 3.0):
30 * %%DocumentPaperColors:
31 * %%DocumentPaperForms:
32 * %%DocumentPaperSizes:
33 * %%DocumentPaperWeights:
34 * %%PaperColor: (ignored)
35 * %%PaperForm: (ignored)
36 * %%PaperSize:
37 * %%PaperWeight: (ignored)
38 *
39 * Other additions for defaults or page section
40 % %%ViewingOrientation: xx xy yx yy
41 */
42
43 #include <stdio.h> /* for sprintf(), not file I/O */
44 #include <stdlib.h>
45 #include <string.h>
46 #include <ctype.h>
47
48 #define MAXSTR 256
49
50 #include "dscparse.h"
51
52 /* Macros for comparing string literals
53 * For maximum speed, the length of the second macro argument is
54 * computed at compile time.
55 * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL.
56 */
57 #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
58 #define IS_DSC(line, str) (COMPARE((line), (str)))
59
60 /* Macros for comparing the first one or two characters */
61 #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
62 #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
63 #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
64 #define IS_BLANK(str) (IS_EOL(str[0]))
65 #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
66
67 /* Macros for document offset to start and end of line */
68 #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
69 #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)
70
71 /* dsc_scan_SECTION() functions return one of
72 * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
73 * or one of the following
74 */
75 /* The line should be passed on to the next section parser. */
76 #define CDSC_PROPAGATE 10
77
78 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
79 #define CDSC_NEEDMORE 11
80
81 /* local prototypes */
82 dsc_private void * dsc_memalloc(CDSC *dsc, size_t size);
83 dsc_private void dsc_memfree(CDSC*dsc, void *ptr);
84 dsc_private CDSC * dsc_init2(CDSC *dsc);
85 dsc_private void dsc_reset(CDSC *dsc);
86 dsc_private void dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast);
87 dsc_private int dsc_read_line(CDSC *dsc);
88 dsc_private int dsc_read_doseps(CDSC *dsc);
89 dsc_private int dsc_read_macbin(CDSC *dsc);
90 dsc_private int dsc_read_applesingle(CDSC *dsc);
91 dsc_private char * dsc_alloc_string(CDSC *dsc, const char *str, int len);
92 dsc_private char * dsc_add_line(CDSC *dsc, const char *line, unsigned int len);
93 dsc_private char * dsc_copy_string(char *str, unsigned int slen,
94 char *line, unsigned int len, unsigned int *offset);
95 dsc_private GSDWORD dsc_get_dword(const unsigned char *buf);
96 dsc_private GSWORD dsc_get_word(const unsigned char *buf);
97 dsc_private GSDWORD dsc_get_bigendian_dword(const unsigned char *buf);
98 dsc_private GSWORD dsc_get_bigendian_word(const unsigned char *buf);
99 dsc_private int dsc_get_int(const char *line, unsigned int len, unsigned int *offset);
100 dsc_private float dsc_get_real(const char *line, unsigned int len,
101 unsigned int *offset);
102 dsc_private void dsc_unknown(CDSC *dsc);
103 dsc_private GSBOOL dsc_is_section(char *line);
104 dsc_private int dsc_parse_pages(CDSC *dsc);
105 dsc_private int dsc_parse_feature(CDSC *dsc);
106 dsc_private int dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset);
107 dsc_private int dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pfbbox, int offset);
108 dsc_private int dsc_parse_orientation(CDSC *dsc, unsigned int *porientation,
109 int offset);
110 dsc_private int dsc_parse_order(CDSC *dsc);
111 dsc_private int dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media);
112 dsc_private int dsc_parse_document_media(CDSC *dsc);
113 dsc_private int dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm);
114 dsc_private int dsc_parse_page(CDSC *dsc);
115 dsc_private void dsc_save_line(CDSC *dsc);
116 dsc_private int dsc_scan_type(CDSC *dsc);
117 dsc_private int dsc_scan_comments(CDSC *dsc);
118 dsc_private int dsc_scan_preview(CDSC *dsc);
119 dsc_private int dsc_scan_defaults(CDSC *dsc);
120 dsc_private int dsc_scan_prolog(CDSC *dsc);
121 dsc_private int dsc_scan_setup(CDSC *dsc);
122 dsc_private int dsc_scan_page(CDSC *dsc);
123 dsc_private int dsc_scan_trailer(CDSC *dsc);
124 dsc_private int dsc_error(CDSC *dsc, unsigned int explanation,
125 char *line, unsigned int line_len);
126 dsc_private int dsc_dcs2_fixup(CDSC *dsc);
127 dsc_private int dsc_parse_platefile(CDSC *dsc);
128 dsc_private int dsc_parse_dcs1plate(CDSC *dsc);
129 dsc_private CDSCCOLOUR * dsc_find_colour(CDSC *dsc, const char *colourname);
130 dsc_private int dsc_parse_process_colours(CDSC *dsc);
131 dsc_private int dsc_parse_custom_colours(CDSC *dsc);
132 dsc_private int dsc_parse_cmyk_custom_colour(CDSC *dsc);
133 dsc_private int dsc_parse_rgb_custom_colour(CDSC *dsc);
134
135 /* DSC error reporting */
136 dsc_private const int dsc_severity[] = {
137 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */
138 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */
139 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */
140 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */
141 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */
142 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */
143 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */
144 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */
145 CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */
146 CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */
147 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */
148 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */
149 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */
150 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */
151 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */
152 CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */
153 0
154 };
155
156 #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
157
158 const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = {
159 /* These sizes taken from Ghostscript gs_statd.ps */
160 {"11x17", 792, 1224, 0, NULL, NULL, NULL},
161 {"A3", 842, 1190, 0, NULL, NULL, NULL},
162 {"A4", 595, 842, 0, NULL, NULL, NULL},
163 {"A5", 421, 595, 0, NULL, NULL, NULL},
164 {"B4", 709, 1002, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */
165 {"B5", 501, 709, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */
166 {"Ledger", 1224, 792, 0, NULL, NULL, NULL},
167 {"Legal", 612, 1008, 0, NULL, NULL, NULL},
168 {"Letter", 612, 792, 0, NULL, NULL, NULL},
169 {"Note", 612, 792, 0, NULL, NULL, NULL},
170 /* Other standard sizes */
171 {"A0", 2384, 3370, 0, NULL, NULL, NULL},
172 {"A1", 1684, 2384, 0, NULL, NULL, NULL},
173 {"A2", 1190, 1684, 0, NULL, NULL, NULL},
174 /* Other non-standard sizes */
175 {"AnsiA", 612, 792, 0, NULL, NULL, NULL}, /* 8.5 x 11" */
176 {"AnsiB", 792, 1224, 0, NULL, NULL, NULL}, /* 11 x 17" */
177 {"AnsiC", 1224, 1584, 0, NULL, NULL, NULL}, /* 17 x 22" */
178 {"AnsiD", 1584, 2448, 0, NULL, NULL, NULL}, /* 22 x 34" */
179 {"AnsiE", 2448, 3168, 0, NULL, NULL, NULL}, /* 34 x 44" */
180 {"ArchA", 648, 864, 0, NULL, NULL, NULL}, /* 9 x 12" */
181 {"ArchB", 864, 1296, 0, NULL, NULL, NULL}, /* 12 x 18" */
182 {"ArchC", 1296, 1728, 0, NULL, NULL, NULL}, /* 18 x 24" */
183 {"ArchD", 1728, 2592, 0, NULL, NULL, NULL}, /* 24 x 36" */
184 {"ArchE", 2592, 3456, 0, NULL, NULL, NULL}, /* 36 x 48" */
185 {"ArchF", 2160, 3024, 0, NULL, NULL, NULL}, /* 30 x 42" */
186 {NULL, 0, 0, 0, NULL, NULL, NULL}
187 };
188
189 /* parser state */
190 enum CDSC_SCAN_SECTION {
191 scan_none = 0,
192 scan_comments = 1,
193 scan_pre_preview = 2,
194 scan_preview = 3,
195 scan_pre_defaults = 4,
196 scan_defaults = 5,
197 scan_pre_prolog = 6,
198 scan_prolog = 7,
199 scan_pre_setup = 8,
200 scan_setup = 9,
201 scan_pre_pages = 10,
202 scan_pages = 11,
203 scan_pre_trailer = 12,
204 scan_trailer = 13,
205 scan_eof = 14
206 };
207
208 static const char * const dsc_scan_section_name[15] = {
209 "Type", "Comments",
210 "pre-Preview", "Preview",
211 "pre-Defaults", "Defaults",
212 "pre-Prolog", "Prolog",
213 "pre-Setup", "Setup",
214 "pre-Page", "Page",
215 "pre-Trailer", "Trailer",
216 "EOF"
217 };
218
219
220 /******************************************************************/
221 /* Public functions */
222 /******************************************************************/
223
224 /* constructor */
225 CDSC *
226 dsc_init(void *caller_data)
227 {
228 CDSC *dsc = (CDSC *)malloc(sizeof(CDSC));
229 if (dsc == NULL)
230 return NULL;
231 memset(dsc, 0, sizeof(CDSC));
232 dsc->caller_data = caller_data;
233 dsc->ref_count = 0;
234 dsc_ref(dsc);
235
236 return dsc_init2(dsc);
237 }
238
239 /* constructor, with caller supplied memalloc */
240 CDSC *
241 dsc_init_with_alloc(
242 void *caller_data,
243 void *(*memalloc)(size_t size, void *closure_data),
244 void (*memfree)(void *ptr, void *closure_data),
245 void *closure_data)
246 {
247 CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data);
248 if (dsc == NULL)
249 return NULL;
250 memset(dsc, 0, sizeof(CDSC));
251 dsc->caller_data = caller_data;
252
253 dsc->memalloc = memalloc;
254 dsc->memfree = memfree;
255 dsc->mem_closure_data = closure_data;
256 dsc->ref_count = 0;
257 dsc_ref(dsc);
258
259 return dsc_init2(dsc);
260 }
261
262
263
264 /* destructor */
265 void
266 dsc_free(CDSC *dsc)
267 {
268 if (dsc == NULL)
269 return;
270 dsc_reset(dsc);
271 dsc_memfree(dsc, dsc);
272 }
273
274
275 CDSC *
276 dsc_new(void *caller_data)
277 {
278 return dsc_init(caller_data);
279 }
280
281 int
282 dsc_ref(CDSC *dsc)
283 {
284 return ++(dsc->ref_count);
285 }
286
287 int
288 dsc_unref(CDSC *dsc)
289 {
290 if (dsc->ref_count <= 0)
291 return -1;
292 dsc->ref_count--;
293 if (dsc->ref_count == 0) {
294 dsc_free(dsc);
295 return 0;
296 }
297 return dsc->ref_count;
298 }
299
300
301 /* Tell DSC parser how long document will be, to allow ignoring
302 * of early %%Trailer and %%EOF. This is optional.
303 */
304 void
305 dsc_set_length(CDSC *dsc, DSC_OFFSET len)
306 {
307 dsc->file_length = len;
308 }
309
310 /* Process a buffer containing DSC comments and PostScript */
311 /* Return value is < 0 for error, >=0 for OK.
312 * CDSC_ERROR
313 * CDSC_OK
314 * CDSC_NOTDSC (DSC will be ignored)
315 * other values indicate the last DSC comment read
316 */
317 int
318 dsc_scan_data(CDSC *dsc, const char *data, int length)
319 {
320 int bytes_read;
321 int code = 0;
322
323 if (dsc == NULL)
324 return CDSC_ERROR;
325
326 if (dsc->id == CDSC_NOTDSC)
327 return CDSC_NOTDSC;
328 dsc->id = CDSC_OK;
329 if (dsc->eof)
330 return CDSC_OK; /* ignore */
331
332 if (length == 0) {
333 /* EOF, so process what remains */
334 dsc->eof = TRUE;
335 }
336
337 do {
338 if (dsc->id == CDSC_NOTDSC)
339 break;
340
341 if (length != 0) {
342 /* move existing data if needed */
343 if (dsc->data_length > CDSC_DATA_LENGTH/2) {
344 memmove(dsc->data, dsc->data + dsc->data_index,
345 dsc->data_length - dsc->data_index);
346 dsc->data_offset += dsc->data_index;
347 dsc->data_length -= dsc->data_index;
348 dsc->data_index = 0;
349 }
350 /* append to buffer */
351 bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length));
352 memcpy(dsc->data + dsc->data_length, data, bytes_read);
353 dsc->data_length += bytes_read;
354 data += bytes_read;
355 length -= bytes_read;
356 }
357 if (dsc->scan_section == scan_none) {
358 code = dsc_scan_type(dsc);
359 if (code == CDSC_NEEDMORE) {
360 /* need more characters before we can identify type */
361 code = CDSC_OK;
362 break;
363 }
364 dsc->id = code;
365 }
366
367 if (code == CDSC_NOTDSC) {
368 dsc->id = CDSC_NOTDSC;
369 break;
370 }
371
372 while ((code = dsc_read_line(dsc)) > 0) {
373 if (dsc->id == CDSC_NOTDSC)
374 break;
375 if (dsc->file_length &&
376 (dsc->data_offset + dsc->data_index > dsc->file_length)) {
377 /* have read past end of where we need to parse. */
378 return CDSC_OK; /* ignore */
379 }
380 if (dsc->doseps_end &&
381 (dsc->data_offset + dsc->data_index > dsc->doseps_end)) {
382 /* have read past end of DOS EPS or Mac Binary
383 * PostScript section
384 */
385 return CDSC_OK; /* ignore */
386 }
387 if (dsc->eof)
388 return CDSC_OK;
389 if (dsc->skip_document)
390 continue; /* embedded document */
391 if (dsc->skip_lines)
392 continue; /* embedded lines */
393 if (IS_DSC(dsc->line, "%%BeginData:"))
394 continue;
395 if (IS_DSC(dsc->line, "%%BeginBinary:"))
396 continue;
397 if (IS_DSC(dsc->line, "%%EndDocument"))
398 continue;
399 if (IS_DSC(dsc->line, "%%EndData"))
400 continue;
401 if (IS_DSC(dsc->line, "%%EndBinary"))
402 continue;
403
404 do {
405 switch (dsc->scan_section) {
406 case scan_comments:
407 code = dsc_scan_comments(dsc);
408 break;
409 case scan_pre_preview:
410 case scan_preview:
411 code = dsc_scan_preview(dsc);
412 break;
413 case scan_pre_defaults:
414 case scan_defaults:
415 code = dsc_scan_defaults(dsc);
416 break;
417 case scan_pre_prolog:
418 case scan_prolog:
419 code = dsc_scan_prolog(dsc);
420 break;
421 case scan_pre_setup:
422 case scan_setup:
423 code = dsc_scan_setup(dsc);
424 break;
425 case scan_pre_pages:
426 case scan_pages:
427 code = dsc_scan_page(dsc);
428 break;
429 case scan_pre_trailer:
430 case scan_trailer:
431 code = dsc_scan_trailer(dsc);
432 break;
433 case scan_eof:
434 code = CDSC_OK;
435 break;
436 default:
437 /* invalid state */
438 code = CDSC_ERROR;
439 }
440 /* repeat if line is start of next section */
441 } while (code == CDSC_PROPAGATE);
442
443 /* if DOS EPS header not complete, ask for more */
444 if (code == CDSC_NEEDMORE) {
445 code = CDSC_OK;
446 break;
447 }
448 if (code == CDSC_NOTDSC) {
449 dsc->id = CDSC_NOTDSC;
450 break;
451 }
452 }
453 } while (length != 0);
454
455 return (code < 0) ? code : dsc->id;
456 }
457
458 /* Tidy up from incorrect DSC comments */
459 int
460 dsc_fixup(CDSC *dsc)
461 {
462 unsigned int i;
463 char buf[32];
464 DSC_OFFSET *last;
465
466 if (dsc->id == CDSC_NOTDSC)
467 return 0;
468
469 /* flush last partial line */
470 dsc_scan_data(dsc, NULL, 0);
471
472
473 /* Fix DSC error: EOF before end of %%BeginData */
474 if (dsc->eof &&
475 (dsc->skip_lines || dsc->skip_bytes || dsc->skip_document)) {
476 switch (dsc->scan_section) {
477 case scan_comments:
478 dsc->endcomments = DSC_END(dsc);
479 break;
480 case scan_preview:
481 dsc->endpreview = DSC_END(dsc);
482 break;
483 case scan_defaults:
484 dsc->enddefaults = DSC_END(dsc);
485 break;
486 case scan_prolog:
487 dsc->endprolog = DSC_END(dsc);
488 break;
489 case scan_setup:
490 dsc->endsetup = DSC_END(dsc);
491 break;
492 case scan_pages:
493 if (dsc->page_count)
494 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
495 break;
496 case scan_trailer:
497 case scan_eof:
498 dsc->endtrailer = DSC_END(dsc);
499 break;
500 }
501 }
502
503 /* Fix DSC error: code between %%EndSetup and %%Page */
504 if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup)
505 && (dsc->endsetup != dsc->beginsetup)) {
506 dsc->endsetup = dsc->page[0].begin;
507 dsc_debug_print(dsc, "Warning: code included between setup and first page\n");
508 }
509
510 /* Last page contained a false trailer, */
511 /* so extend last page to start of trailer */
512 if (dsc->page_count && (dsc->begintrailer != 0) &&
513 (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) {
514 dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n");
515 dsc_debug_print(dsc, "and extending last page to start of trailer\n");
516 dsc->page[dsc->page_count-1].end = dsc->begintrailer;
517 }
518
519 /*
520 * Join up all sections.
521 * There might be extra code between them, or we might have
522 * missed including the \n which followed \r.
523 */
524 last = &dsc->endcomments;
525 dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last);
526 dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last);
527 dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last);
528 dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last);
529 for (i=0; i<dsc->page_count; i++)
530 dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last);
531 if (dsc->begintrailer)
532 *last = dsc->begintrailer;
533
534 if ((dsc->page_pages == 0) && (dsc->page_count == 1)) {
535 /* don't flag an error if %%Pages absent but one %%Page found */
536 /* adjust incorrect page count */
537 dsc->page_pages = dsc->page_count;
538 }
539
540 /* Warnings and Errors that we can now identify */
541 if ((dsc->page_count != dsc->page_pages)) {
542 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0);
543 switch (rc) {
544 case CDSC_RESPONSE_OK:
545 /* adjust incorrect page count */
546 dsc->page_pages = dsc->page_count;
547 break;
548 case CDSC_RESPONSE_CANCEL:
549 break;;
550 case CDSC_RESPONSE_IGNORE_ALL:
551 return CDSC_NOTDSC;
552 }
553 }
554
555 if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) {
556 /* EPS files MUST include a BoundingBox */
557 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0);
558 switch (rc) {
559 case CDSC_RESPONSE_OK:
560 /* Assume that it is EPS */
561 break;
562 case CDSC_RESPONSE_CANCEL:
563 /* Is NOT an EPS file */
564 dsc->epsf = FALSE;
565 case CDSC_RESPONSE_IGNORE_ALL:
566 return CDSC_NOTDSC;
567 }
568 }
569
570 if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) {
571 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0);
572 switch (rc) {
573 case CDSC_RESPONSE_OK:
574 /* Is an EPS file */
575 break;
576 case CDSC_RESPONSE_CANCEL:
577 /* Is NOT an EPS file */
578 dsc->epsf = FALSE;
579 break;
580 case CDSC_RESPONSE_IGNORE_ALL:
581 return CDSC_NOTDSC;
582 }
583 }
584
585 /* convert single file DSC 2.0 into multiple pages */
586 dsc_dcs2_fixup(dsc);
587
588 if ((dsc->media_count == 1) && (dsc->page_media == NULL)) {
589 /* if one only media was specified, and default page media */
590 /* was not specified, assume that default is the only media. */
591 dsc->page_media = dsc->media[0];
592 }
593
594 if ((dsc->media_count != 0) && (dsc->page_media == NULL)) {
595 int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0);
596 switch (rc) {
597 case CDSC_RESPONSE_OK:
598 /* default media is first listed */
599 dsc->page_media = dsc->media[0];
600 break;
601 case CDSC_RESPONSE_CANCEL:
602 /* No default media */
603 break;
604 case CDSC_RESPONSE_IGNORE_ALL:
605 return CDSC_NOTDSC;
606 }
607 }
608
609 /* make sure all pages have a label */
610 for (i=0; i<dsc->page_count; i++) {
611 if (strlen(dsc->page[i].label) == 0) {
612 sprintf(buf, "%d", i+1);
613 if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, (int)strlen(buf)))
614 == (char *)NULL)
615 return CDSC_ERROR; /* no memory */
616 }
617 }
618 return CDSC_OK;
619 }
620
621 /* Install a function to be used for displaying messages about
622 * DSC errors and warnings, and to request advice from user.
623 * Installing an error function is optional.
624 */
625 void
626 dsc_set_error_function(CDSC *dsc,
627 int (*fn)(void *caller_data, CDSC *dsc,
628 unsigned int explanation, const char *line, unsigned int line_len))
629 {
630 dsc->dsc_error_fn = fn;
631 }
632
633
634 /* Install a function for printing debug messages */
635 /* This is optional */
636 void
637 dsc_set_debug_function(CDSC *dsc,
638 void (*debug_fn)(void *caller_data, const char *str))
639 {
640 dsc->debug_print_fn = debug_fn;
641 }
642
643 /* Doesn't need to be public for PostScript documents */
644 /* Made public so GSview can add pages when processing PDF files */
645 int
646 dsc_add_page(CDSC *dsc, int ordinal, char *label)
647 {
648 dsc->page[dsc->page_count].ordinal = ordinal;
649 dsc->page[dsc->page_count].label =
650 dsc_alloc_string(dsc, label, (int)strlen(label)+1);
651 dsc->page[dsc->page_count].begin = 0;
652 dsc->page[dsc->page_count].end = 0;
653 dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN;
654 dsc->page[dsc->page_count].media = NULL;
655 dsc->page[dsc->page_count].bbox = NULL;
656 dsc->page[dsc->page_count].viewing_orientation = NULL;
657 dsc->page[dsc->page_count].crop_box = NULL;
658
659 dsc->page_count++;
660 if (dsc->page_count >= dsc->page_chunk_length) {
661 CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc,
662 (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE));
663 if (new_page == NULL)
664 return CDSC_ERROR; /* out of memory */
665 memcpy(new_page, dsc->page,
666 dsc->page_count * sizeof(CDSCPAGE));
667 dsc_memfree(dsc, dsc->page);
668 dsc->page= new_page;
669 dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count;
670 }
671 return CDSC_OK;
672 }
673
674 /* Doesn't need to be public for PostScript documents */
675 /* Made public so GSview can store PDF MediaBox */
676 int
677 dsc_add_media(CDSC *dsc, CDSCMEDIA *media)
678 {
679 CDSCMEDIA **newmedia_array;
680 CDSCMEDIA *newmedia;
681
682 /* extend media array */
683 newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc,
684 (dsc->media_count + 1) * sizeof(CDSCMEDIA *));
685 if (newmedia_array == NULL)
686 return CDSC_ERROR; /* out of memory */
687 if (dsc->media != NULL) {
688 memcpy(newmedia_array, dsc->media,
689 dsc->media_count * sizeof(CDSCMEDIA *));
690 dsc_memfree(dsc, dsc->media);
691 }
692 dsc->media = newmedia_array;
693
694 /* allocate new media */
695 newmedia = dsc->media[dsc->media_count] =
696 (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA));
697 if (newmedia == NULL)
698 return CDSC_ERROR; /* out of memory */
699 newmedia->name = NULL;
700 newmedia->width = 595.0;
701 newmedia->height = 842.0;
702 newmedia->weight = 80.0;
703 newmedia->colour = NULL;
704 newmedia->type = NULL;
705 newmedia->mediabox = NULL;
706
707 dsc->media_count++;
708
709 if (media->name) {
710 newmedia->name = dsc_alloc_string(dsc, media->name,
711 (int)strlen(media->name));
712 if (newmedia->name == NULL)
713 return CDSC_ERROR; /* no memory */
714 }
715 newmedia->width = media->width;
716 newmedia->height = media->height;
717 newmedia->weight = media->weight;
718 if (media->colour) {
719 newmedia->colour = dsc_alloc_string(dsc, media->colour,
720 (int)strlen(media->colour));
721 if (newmedia->colour == NULL)
722 return CDSC_ERROR; /* no memory */
723 }
724 if (media->type) {
725 newmedia->type = dsc_alloc_string(dsc, media->type,
726 (int)strlen(media->type));
727 if (newmedia->type == NULL)
728 return CDSC_ERROR; /* no memory */
729 }
730 newmedia->mediabox = NULL;
731
732 if (media->mediabox) {
733 newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
734 if (newmedia->mediabox == NULL)
735 return CDSC_ERROR; /* no memory */
736 *newmedia->mediabox = *media->mediabox;
737 }
738 return CDSC_OK;
739 }
740
741 /* Doesn't need to be public for PostScript documents */
742 /* Made public so GSview can store PDF CropBox */
743 int
744 dsc_set_page_bbox(CDSC *dsc, unsigned int page_number,
745 int llx, int lly, int urx, int ury)
746 {
747 CDSCBBOX *bbox;
748 if (page_number >= dsc->page_count)
749 return CDSC_ERROR;
750 bbox = dsc->page[page_number].bbox;
751 if (bbox == NULL)
752 dsc->page[page_number].bbox = bbox =
753 (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
754 if (bbox == NULL)
755 return CDSC_ERROR;
756 bbox->llx = llx;
757 bbox->lly = lly;
758 bbox->urx = urx;
759 bbox->ury = ury;
760 return CDSC_OK;
761 }
762
763
764 /******************************************************************/
765 /* Private functions below here. */
766 /******************************************************************/
767
768 dsc_private void *
769 dsc_memalloc(CDSC *dsc, size_t size)
770 {
771 if (dsc->memalloc)
772 return dsc->memalloc(size, dsc->mem_closure_data);
773 return malloc(size);
774 }
775
776 dsc_private void
777 dsc_memfree(CDSC*dsc, void *ptr)
778 {
779 if (dsc->memfree)
780 dsc->memfree(ptr, dsc->mem_closure_data);
781 else
782 free(ptr);
783 }
784
785 /* private constructor */
786 dsc_private CDSC *
787 dsc_init2(CDSC *dsc)
788 {
789 dsc_reset(dsc);
790
791 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
792 if (dsc->string_head == NULL) {
793 dsc_free(dsc);
794 return NULL; /* no memory */
795 }
796 dsc->string = dsc->string_head;
797 dsc->string->next = NULL;
798 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
799 if (dsc->string->data == NULL) {
800 dsc_free(dsc);
801 return NULL; /* no memory */
802 }
803 dsc->string->index = 0;
804 dsc->string->length = CDSC_STRING_CHUNK;
805
806 dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE));
807 if (dsc->page == NULL) {
808 dsc_free(dsc);
809 return NULL; /* no memory */
810 }
811 dsc->page_chunk_length = CDSC_PAGE_CHUNK;
812 dsc->page_count = 0;
813
814 dsc->line = NULL;
815 dsc->data_length = 0;
816 dsc->data_index = dsc->data_length;
817
818 return dsc;
819 }
820
821
822 dsc_private void
823 dsc_reset(CDSC *dsc)
824 {
825 unsigned int i;
826 /* Clear public members */
827 dsc->dsc = FALSE;
828 dsc->ctrld = FALSE;
829 dsc->pjl = FALSE;
830 dsc->epsf = FALSE;
831 dsc->pdf = FALSE;
832 dsc->epsf = FALSE;
833 dsc->preview = CDSC_NOPREVIEW;
834 dsc->dsc_version = NULL; /* stored in dsc->string */
835 dsc->language_level = 0;
836 dsc->document_data = CDSC_DATA_UNKNOWN;
837 dsc->begincomments = 0;
838 dsc->endcomments = 0;
839 dsc->beginpreview = 0;
840 dsc->endpreview = 0;
841 dsc->begindefaults = 0;
842 dsc->enddefaults = 0;
843 dsc->beginprolog = 0;
844 dsc->endprolog = 0;
845 dsc->beginsetup = 0;
846 dsc->endsetup = 0;
847 dsc->begintrailer = 0;
848 dsc->endtrailer = 0;
849
850 for (i=0; i<dsc->page_count; i++) {
851 /* page media is pointer to an element of media or dsc_known_media */
852 /* do not free it. */
853
854 if (dsc->page[i].bbox)
855 dsc_memfree(dsc, dsc->page[i].bbox);
856 if (dsc->page[i].viewing_orientation)
857 dsc_memfree(dsc, dsc->page[i].viewing_orientation);
858 if (dsc->page[i].crop_box)
859 dsc_memfree(dsc, dsc->page[i].crop_box);
860 }
861 if (dsc->page)
862 dsc_memfree(dsc, dsc->page);
863 dsc->page = NULL;
864
865 dsc->page_count = 0;
866 dsc->page_pages = 0;
867 dsc->page_order = CDSC_ORDER_UNKNOWN;
868 dsc->page_orientation = CDSC_ORIENT_UNKNOWN;
869 if (dsc->viewing_orientation)
870 dsc_memfree(dsc, dsc->viewing_orientation);
871 dsc->viewing_orientation = NULL;
872
873 if (dsc->media) {
874 for (i=0; i<dsc->media_count; i++) {
875 if (dsc->media[i]) {
876 if (dsc->media[i]->mediabox)
877 dsc_memfree(dsc, dsc->media[i]->mediabox);
878 dsc_memfree(dsc, dsc->media[i]);
879 }
880 }
881 dsc_memfree(dsc, dsc->media);
882 }
883 dsc->media_count = 0;
884 dsc->media = NULL;
885
886 /* page_media is pointer to an element of media or dsc_known_media */
887 /* do not free it. */
888 dsc->page_media = NULL;
889
890 if (dsc->bbox)
891 dsc_memfree(dsc, dsc->bbox);
892 dsc->bbox = NULL;
893 if (dsc->page_bbox)
894 dsc_memfree(dsc, dsc->page_bbox);
895 dsc->page_bbox = NULL;
896 if (dsc->doseps)
897 dsc_memfree(dsc, dsc->doseps);
898 dsc->doseps = NULL;
899
900 dsc->dsc_title = NULL;
901 dsc->dsc_creator = NULL;
902 dsc->dsc_date = NULL;
903 dsc->dsc_for = NULL;
904
905
906 dsc->max_error = DSC_MAX_ERROR;
907 dsc->severity = dsc_severity;
908
909 /* Clear private members */
910 /* Don't touch dsc->caller_data */
911 dsc->id = CDSC_OK;
912 dsc->scan_section = scan_none;
913 dsc->doseps_end = 0;
914 dsc->page_chunk_length = 0;
915 dsc->file_length = 0;
916 dsc->skip_document = 0;
917 dsc->skip_bytes = 0;
918 dsc->skip_lines = 0;
919 dsc->skip_pjl = 0;
920 dsc->begin_font_count = 0;
921 dsc->begin_feature_count = 0;
922 dsc->begin_resource_count = 0;
923 dsc->begin_procset_count = 0;
924
925 dsc->data_length = 0;
926 dsc->data_index = 0;
927 dsc->data_offset = 0;
928
929 dsc->eof = 0;
930
931 dsc->line = 0;
932 dsc->line_length = 0;
933 dsc->eol = 0;
934 dsc->last_cr = FALSE;
935 dsc->line_count = 1;
936 dsc->long_line = FALSE;
937 memset(dsc->last_line, 0, sizeof(dsc->last_line));
938
939 dsc->string = dsc->string_head;
940 while (dsc->string != (CDSCSTRING *)NULL) {
941 if (dsc->string->data)
942 dsc_memfree(dsc, dsc->string->data);
943 dsc->string_head = dsc->string;
944 dsc->string = dsc->string->next;
945 dsc_memfree(dsc, dsc->string_head);
946 }
947 dsc->string_head = NULL;
948 dsc->string = NULL;
949
950 /* don't touch caller functions */
951
952 /* public data */
953 if (dsc->hires_bbox)
954 dsc_memfree(dsc, dsc->hires_bbox);
955 dsc->hires_bbox = NULL;
956 if (dsc->crop_box)
957 dsc_memfree(dsc, dsc->crop_box);
958 dsc->crop_box = NULL;
959
960 if (dsc->dcs2) {
961 CDCS2 *this_dcs, *next_dcs;
962 this_dcs = dsc->dcs2;
963 while (this_dcs) {
964 next_dcs = this_dcs->next;
965 /* strings have already been freed */
966 dsc_memfree(dsc, this_dcs);
967 this_dcs = next_dcs;
968 }
969 dsc->dcs2 = NULL;
970 }
971 if (dsc->colours) {
972 CDSCCOLOUR *this_colour, *next_colour;
973 this_colour = dsc->colours;
974 while (this_colour) {
975 next_colour = this_colour->next;
976 /* strings have already been freed */
977 dsc_memfree(dsc, this_colour);
978 this_colour = next_colour;
979 }
980 dsc->colours = NULL;
981 }
982
983 if (dsc->macbin)
984 dsc_memfree(dsc, dsc->macbin);
985 dsc->macbin = NULL;
986
987 dsc->worst_error = CDSC_ERROR_NONE;
988 }
989
990 /*
991 * Join up all sections.
992 * There might be extra code between them, or we might have
993 * missed including the \n which followed \r.
994 * begin is the start of this section
995 * pend is a pointer to the end of this section
996 * pplast is a pointer to a pointer of the end of the previous section
997 */
998 dsc_private void
999 dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast)
1000 {
1001 if (begin)
1002 **pplast = begin;
1003 if (*pend > begin)
1004 *pplast = pend;
1005 }
1006
1007
1008 /* return value is 0 if no line available, or length of line */
1009 dsc_private int
1010 dsc_read_line(CDSC *dsc)
1011 {
1012 char *p, *last;
1013 dsc->line = NULL;
1014
1015 if (dsc->eof) {
1016 /* return all that remains, even if line incomplete */
1017 dsc->line = dsc->data + dsc->data_index;
1018 dsc->line_length = dsc->data_length - dsc->data_index;
1019 dsc->data_index = dsc->data_length;
1020 return dsc->line_length;
1021 }
1022
1023 if (dsc->file_length &&
1024 (dsc->data_offset + dsc->data_index >= dsc->file_length)) {
1025 /* Have read past where we need to parse. */
1026 /* Ignore all that remains. */
1027 dsc->line = dsc->data + dsc->data_index;
1028 dsc->line_length = dsc->data_length - dsc->data_index;
1029 dsc->data_index = dsc->data_length;
1030 return dsc->line_length;
1031
1032 }
1033 if (dsc->doseps_end &&
1034 (dsc->data_offset + dsc->data_index >= dsc->doseps_end)) {
1035 /* Have read past end of DOS EPS PostScript section. */
1036 /* Ignore all that remains. */
1037 dsc->line = dsc->data + dsc->data_index;
1038 dsc->line_length = dsc->data_length - dsc->data_index;
1039 dsc->data_index = dsc->data_length;
1040 return dsc->line_length;
1041 }
1042
1043 /* ignore embedded bytes */
1044 if (dsc->skip_bytes) {
1045 int cnt = min(dsc->skip_bytes,
1046 (int)(dsc->data_length - dsc->data_index));
1047 dsc->skip_bytes -= cnt;
1048 dsc->data_index += cnt;
1049 if (dsc->skip_bytes != 0)
1050 return 0;
1051 }
1052
1053 do {
1054 dsc->line = dsc->data + dsc->data_index;
1055 last = dsc->data + dsc->data_length;
1056 if (dsc->data_index == dsc->data_length) {
1057 dsc->line_length = 0;
1058 return 0;
1059 }
1060 if (dsc->eol) {
1061 /* if previous line was complete, increment line count */
1062 dsc->line_count++;
1063 if (dsc->skip_lines)
1064 dsc->skip_lines--;
1065 }
1066
1067 /* skip over \n which followed \r */
1068 if (dsc->last_cr && dsc->line[0] == '\n') {
1069 dsc->data_index++;
1070 dsc->line++;
1071 }
1072 dsc->last_cr = FALSE;
1073
1074 /* look for EOL */
1075 dsc->eol = FALSE;
1076 for (p = dsc->line; p < last; p++) {
1077 if (*p == '\r') {
1078 p++;
1079 if ((p<last) && (*p == '\n'))
1080 p++; /* include line feed also */
1081 else
1082 dsc->last_cr = TRUE; /* we might need to skip \n */
1083 dsc->eol = TRUE; /* dsc->line is a complete line */
1084 break;
1085 }
1086 if (*p == '\n') {
1087 p++;
1088 dsc->eol = TRUE; /* dsc->line is a complete line */
1089 break;
1090 }
1091 if (*p == '\032') { /* MS-DOS Ctrl+Z */
1092 dsc->eol = TRUE;
1093 }
1094 }
1095 if (dsc->eol == FALSE) {
1096 /* we haven't got a complete line yet */
1097 if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) {
1098 /* buffer is less than half full, ask for some more */
1099 dsc->line_length = 0;
1100 return 0;
1101 }
1102 }
1103 dsc->data_index += dsc->line_length = (int)(p - dsc->line);
1104 } while (dsc->skip_lines && dsc->line_length);
1105
1106 if (dsc->line_length == 0)
1107 return 0;
1108
1109 if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) {
1110 /* handle recursive %%BeginDocument */
1111 if ((dsc->skip_document) && dsc->line_length &&
1112 COMPARE(dsc->line, "%%EndDocument")) {
1113 dsc->skip_document--;
1114 }
1115
1116 /* handle embedded lines or binary data */
1117 if (COMPARE(dsc->line, "%%BeginData:")) {
1118 /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ]
1119 * <numberof> ::= <uint> (Lines or physical bytes)
1120 * <type> ::= Hex | Binary | ASCII (Type of data)
1121 * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines)
1122 */
1123 char begindata[MAXSTR+1];
1124 int cnt;
1125 const char *numberof, *bytesorlines;
1126 cnt = dsc->line_length;
1127 if (dsc->line_length > sizeof(begindata)-1)
1128 cnt = sizeof(begindata)-1;
1129 memcpy(begindata, dsc->line, cnt);
1130 begindata[cnt] = '\0';
1131 numberof = strtok(begindata+12, " \r\n");
1132 strtok(NULL, " \r\n"); /* dump type */
1133 bytesorlines = strtok(NULL, " \r\n");
1134 if (bytesorlines == NULL)
1135 bytesorlines = "Bytes";
1136
1137 if ( (numberof == NULL) || (bytesorlines == NULL) ) {
1138 /* invalid usage of %%BeginData */
1139 /* ignore that we ever saw it */
1140 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE,
1141 dsc->line, dsc->line_length);
1142 switch (rc) {
1143 case CDSC_RESPONSE_OK:
1144 case CDSC_RESPONSE_CANCEL:
1145 break;
1146 case CDSC_RESPONSE_IGNORE_ALL:
1147 return 0;
1148 }
1149 }
1150 else {
1151 cnt = atoi(numberof);
1152 if (cnt) {
1153 if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) {
1154 /* skip cnt lines */
1155 if (dsc->skip_lines == 0) {
1156 /* we are not already skipping lines */
1157 dsc->skip_lines = cnt+1;
1158 }
1159 }
1160 else {
1161 /* byte count doesn't includes \n or \r\n */
1162 /* or \r of %%BeginData: */
1163 /* skip cnt bytes */
1164 if (dsc->skip_bytes == 0) {
1165 /* we are not already skipping lines */
1166 dsc->skip_bytes = cnt;
1167 }
1168
1169 }
1170 }
1171 }
1172 }
1173 else if (COMPARE(dsc->line, "%%BeginBinary:")) {
1174 /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/
1175 int cnt = dsc_get_int(dsc->line + 14,
1176 dsc->line_length - 14, NULL);
1177 if (dsc->skip_bytes == 0) {
1178 /* we are not already skipping lines */
1179 dsc->skip_bytes = cnt;
1180 }
1181 }
1182 }
1183
1184 if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
1185 COMPARE(dsc->line, "%%BeginDocument:") ) {
1186 /* Skip over embedded document, recursively */
1187 dsc->skip_document++;
1188 }
1189
1190 if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) {
1191 dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length);
1192 dsc->long_line = TRUE;
1193 }
1194
1195 return dsc->line_length;
1196 }
1197
1198
1199 /* Save last DSC line, for use with %%+ */
1200 dsc_private void
1201 dsc_save_line(CDSC *dsc)
1202 {
1203 int len = min(sizeof(dsc->last_line), dsc->line_length);
1204 memcpy(dsc->last_line, dsc->line, len);
1205 }
1206
1207 /* display unknown DSC line */
1208 dsc_private void
1209 dsc_unknown(CDSC *dsc)
1210 {
1211 if (dsc->debug_print_fn) {
1212 char line[DSC_LINE_LENGTH];
1213 unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length);
1214 sprintf(line, "Unknown in %s section at line %d:\n ",
1215 dsc_scan_section_name[dsc->scan_section], dsc->line_count);
1216 dsc_debug_print(dsc, line);
1217 strncpy(line, dsc->line, length);
1218 line[length] = '\0';
1219 dsc_debug_print(dsc, line);
1220 dsc_debug_print(dsc, "\n");
1221 }
1222 }
1223
1224
1225 dsc_private GSBOOL
1226 dsc_is_section(char *line)
1227 {
1228 if ( !((line[0]=='%') && (line[1]=='%')) )
1229 return FALSE;
1230 if (IS_DSC(line, "%%BeginPreview"))
1231 return TRUE;
1232 if (IS_DSC(line, "%%BeginDefaults"))
1233 return TRUE;
1234 if (IS_DSC(line, "%%BeginProlog"))
1235 return TRUE;
1236 if (IS_DSC(line, "%%BeginSetup"))
1237 return TRUE;
1238 if (IS_DSC(line, "%%Page:"))
1239 return TRUE;
1240 if (IS_DSC(line, "%%Trailer"))
1241 return TRUE;
1242 if (IS_DSC(line, "%%EOF"))
1243 return TRUE;
1244 return FALSE;
1245 }
1246
1247 /* Get little-endian DWORD, used for DOS EPS files */
1248 dsc_private GSDWORD
1249 dsc_get_dword(const unsigned char *buf)
1250 {
1251 GSDWORD dw;
1252 dw = (GSDWORD)buf[0];
1253 dw += ((GSDWORD)buf[1])<<8;
1254 dw += ((GSDWORD)buf[2])<<16;
1255 dw += ((GSDWORD)buf[3])<<24;
1256 return dw;
1257 }
1258
1259 dsc_private GSWORD
1260 dsc_get_word(const unsigned char *buf)
1261 {
1262 GSWORD w;
1263 w = (GSWORD)buf[0];
1264 w |= (GSWORD)(buf[1]<<8);
1265 return w;
1266 }
1267
1268 /* Get big-endian DWORD, used for Mac Binary files */
1269 dsc_private GSDWORD
1270 dsc_get_bigendian_dword(const unsigned char *buf)
1271 {
1272 GSDWORD dw;
1273 dw = (GSDWORD)buf[3];
1274 dw += ((GSDWORD)buf[2])<<8;
1275 dw += ((GSDWORD)buf[1])<<16;
1276 dw += ((GSDWORD)buf[0])<<24;
1277 return dw;
1278 }
1279
1280 dsc_private GSWORD
1281 dsc_get_bigendian_word(const unsigned char *buf)
1282 {
1283 GSWORD w;
1284 w = (GSWORD)buf[1];
1285 w |= (GSWORD)(buf[0]<<8);
1286 return w;
1287 }
1288
1289 dsc_private int
1290 dsc_read_doseps(CDSC *dsc)
1291 {
1292 unsigned char *line = (unsigned char *)dsc->line;
1293 if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL)
1294 return CDSC_ERROR; /* no memory */
1295
1296 dsc->doseps->ps_begin = dsc_get_dword(line+4);
1297 dsc->doseps->ps_length = dsc_get_dword(line+8);
1298 dsc->doseps->wmf_begin = dsc_get_dword(line+12);
1299 dsc->doseps->wmf_length = dsc_get_dword(line+16);
1300 dsc->doseps->tiff_begin = dsc_get_dword(line+20);
1301 dsc->doseps->tiff_length = dsc_get_dword(line+24);
1302 dsc->doseps->checksum = dsc_get_word(line+28);
1303
1304 if (dsc->file_length &&
1305 (dsc->doseps->ps_begin + dsc->doseps->ps_length > dsc->file_length)) {
1306 /* Error in DOS EPS header.
1307 * Some files have been seen with a fixed large value as
1308 * the length of the PostScript section.
1309 * Correct for these erroneous files.
1310 */
1311 dsc->doseps->ps_length =
1312 (GSDWORD)(dsc->file_length - dsc->doseps->ps_begin);
1313 }
1314
1315 dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length;
1316
1317 /* move data_index backwards to byte after doseps header */
1318 dsc->data_index -= dsc->line_length - 30;
1319 /* we haven't read a line of PostScript code yet */
1320 dsc->line_count = 0;
1321 /* skip from current position to start of PostScript section */
1322 dsc->skip_bytes = dsc->doseps->ps_begin - 30;
1323
1324 if (dsc->doseps->tiff_begin)
1325 dsc->preview = CDSC_TIFF;
1326 if (dsc->doseps->wmf_begin)
1327 dsc->preview = CDSC_WMF;
1328
1329 return CDSC_OK;
1330 }
1331
1332
1333 dsc_private int
1334 dsc_read_macbin(CDSC *dsc)
1335 {
1336 unsigned char *line = (unsigned char *)dsc->line;
1337 if ((dsc->macbin =
1338 (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
1339 return CDSC_ERROR; /* no memory */
1340
1341 dsc->macbin->data_begin = 128;
1342 dsc->macbin->data_length = dsc_get_bigendian_dword(line+83);
1343 dsc->macbin->resource_begin =
1344 (dsc->macbin->data_begin + dsc->macbin->data_length + 127 ) & ~127;
1345 dsc->macbin->resource_length = dsc_get_bigendian_dword(line+87);
1346
1347 /* A MacBinary file has been seen that doesn't have the resource
1348 * fork padded out to 128 bytes. Just make sure that the resource
1349 * doesn't extend beyond EOF.
1350 */
1351 if (dsc->file_length &&
1352 (((dsc->macbin->resource_begin + dsc->macbin->resource_length
1353 /* + 127 */ ) /* & ~127 */ ) > dsc->file_length)) {
1354 return CDSC_ERROR;
1355 }
1356
1357 dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
1358
1359 /* move data_index to byte after Mac Binary header */
1360 dsc->data_index -= dsc->line_length - 128;
1361 /* we haven't read a line of PostScript code yet */
1362 dsc->line_count = 0;
1363
1364 dsc->preview = CDSC_PICT;
1365
1366 return CDSC_OK;
1367 }
1368
1369
1370 dsc_private int
1371 dsc_read_applesingle(CDSC *dsc)
1372 {
1373 GSDWORD EntryID;
1374 GSDWORD Offset;
1375 GSDWORD Length;
1376 GSWORD entries;
1377 int index;
1378 int header;
1379 int i;
1380
1381 unsigned char *line = (unsigned char *)dsc->line;
1382 if ((dsc->macbin =
1383 (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
1384 return CDSC_ERROR; /* no memory */
1385 entries = dsc_get_bigendian_word(line+24);
1386 for (i=0; i<(int)entries; i++) {
1387 index = 26 + i * 12;
1388 EntryID = dsc_get_bigendian_dword(line+index);
1389 Offset = dsc_get_bigendian_dword(line+index+4);
1390 Length = dsc_get_bigendian_dword(line+index+8);
1391 if (EntryID == 1) {
1392 /* data fork */
1393 dsc->macbin->data_begin = Offset;
1394 dsc->macbin->data_length = Length;
1395 }
1396 else if (EntryID == 2) {
1397 /* resource fork */
1398 dsc->macbin->resource_begin = Offset;
1399 dsc->macbin->resource_length = Length;
1400 }
1401 }
1402
1403 if (dsc->file_length &&
1404 (dsc->macbin->resource_begin + dsc->macbin->resource_length
1405 > dsc->file_length)) {
1406 return CDSC_ERROR;
1407 }
1408 if (dsc->file_length &&
1409 (dsc->macbin->data_begin + dsc->macbin->data_length
1410 > dsc->file_length)) {
1411 return CDSC_ERROR;
1412 }
1413
1414 dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
1415
1416 header = 26 + entries * 12;
1417 /* move data_index to byte after AppleSingle/AppleDouble header */
1418 dsc->data_index -= dsc->line_length - header;
1419 /* we haven't read a line of PostScript code yet */
1420 dsc->line_count = 0;
1421 /* skip from current position to start of PostScript section */
1422 dsc->skip_bytes = dsc->macbin->data_begin - header;
1423
1424 dsc->preview = CDSC_PICT;
1425
1426 return CDSC_OK;
1427 }
1428
1429 dsc_private int
1430 dsc_parse_pages(CDSC *dsc)
1431 {
1432 int ip, io;
1433 unsigned int i;
1434 char *p;
1435 int n;
1436 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) {
1437 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1438 dsc->line_length);
1439 switch (rc) {
1440 case CDSC_RESPONSE_OK:
1441 case CDSC_RESPONSE_CANCEL:
1442 return CDSC_OK; /* ignore duplicate comments in header */
1443 case CDSC_RESPONSE_IGNORE_ALL:
1444 return CDSC_NOTDSC;
1445 }
1446 }
1447 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) {
1448 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1449 dsc->line_length);
1450 switch (rc) {
1451 case CDSC_RESPONSE_OK:
1452 case CDSC_RESPONSE_CANCEL:
1453 break; /* use duplicate comments in header */
1454 case CDSC_RESPONSE_IGNORE_ALL:
1455 return CDSC_NOTDSC;
1456 }
1457 }
1458
1459 n = IS_DSC(dsc->line, "%%+") ? 3 : 8;
1460 while (IS_WHITE(dsc->line[n]))
1461 n++;
1462 p = dsc->line + n;
1463 if (COMPARE(p, "atend")) {
1464 if (dsc->scan_section != scan_comments)
1465 dsc_unknown(dsc);
1466 else {
1467 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
1468 dsc->line, dsc->line_length);
1469 switch (rc) {
1470 case CDSC_RESPONSE_OK:
1471 /* assume (atend) */
1472 /* we should mark it as deferred */
1473 break;
1474 case CDSC_RESPONSE_CANCEL:
1475 /* ignore it */
1476 break;
1477 case CDSC_RESPONSE_IGNORE_ALL:
1478 return CDSC_NOTDSC;
1479 }
1480 }
1481 }
1482 else if (COMPARE(p, "(atend)")) {
1483 if (dsc->scan_section != scan_comments)
1484 dsc_unknown(dsc);
1485 /* do nothing */
1486 /* we should mark it as deferred */
1487 }
1488 else {
1489 ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1490 if (i) {
1491 n+=i;
1492 dsc->page_pages = ip;
1493 io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1494 if (i) {
1495 /* DSC 2 uses extra integer to indicate page order */
1496 /* DSC 3 uses %%PageOrder: */
1497 if (dsc->page_order == CDSC_ORDER_UNKNOWN)
1498 switch (io) {
1499 case -1:
1500 dsc->page_order = CDSC_DESCEND;
1501 break;
1502 case 0:
1503 dsc->page_order = CDSC_SPECIAL;
1504 break;
1505 case 1:
1506 dsc->page_order = CDSC_ASCEND;
1507 break;
1508 }
1509 }
1510 }
1511 else {
1512 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line,
1513 dsc->line_length);
1514 switch (rc) {
1515 case CDSC_RESPONSE_OK:
1516 case CDSC_RESPONSE_CANCEL:
1517 /* ignore it */
1518 break;
1519 case CDSC_RESPONSE_IGNORE_ALL:
1520 return CDSC_NOTDSC;
1521 }
1522 }
1523 }
1524 return CDSC_OK;
1525 }
1526
1527 dsc_private int
1528 dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
1529 {
1530 unsigned int i, n;
1531 int llx, lly, urx, ury;
1532 float fllx, flly, furx, fury;
1533 char *p;
1534 /* Process first %%BoundingBox: in comments, and last in trailer */
1535 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1536 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1537 dsc->line_length);
1538 switch (rc) {
1539 case CDSC_RESPONSE_OK:
1540 case CDSC_RESPONSE_CANCEL:
1541 return CDSC_OK; /* ignore duplicate comments in header */
1542 case CDSC_RESPONSE_IGNORE_ALL:
1543 return CDSC_NOTDSC;
1544 }
1545 }
1546 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1547 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1548 dsc->line_length);
1549 switch (rc) {
1550 case CDSC_RESPONSE_OK:
1551 case CDSC_RESPONSE_CANCEL:
1552 return CDSC_OK; /* ignore duplicate comments in header */
1553 case CDSC_RESPONSE_IGNORE_ALL:
1554 return CDSC_NOTDSC;
1555 }
1556 }
1557 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1558 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1559 dsc->line_length);
1560 switch (rc) {
1561 case CDSC_RESPONSE_OK:
1562 case CDSC_RESPONSE_CANCEL:
1563 break; /* use duplicate comments in trailer */
1564 case CDSC_RESPONSE_IGNORE_ALL:
1565 return CDSC_NOTDSC;
1566 }
1567 }
1568 if (*pbbox != NULL) {
1569 dsc_memfree(dsc, *pbbox);
1570 *pbbox = NULL;
1571 }
1572
1573 /* should only process first %%BoundingBox: */
1574
1575 while (IS_WHITE(dsc->line[offset]))
1576 offset++;
1577 p = dsc->line + offset;
1578
1579 if (COMPARE(p, "atend")) {
1580 if (dsc->scan_section == scan_trailer)
1581 dsc_unknown(dsc);
1582 else {
1583 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1584 dsc->line_length);
1585 switch (rc) {
1586 case CDSC_RESPONSE_OK:
1587 /* assume (atend) */
1588 /* we should mark it as deferred */
1589 break;
1590 case CDSC_RESPONSE_CANCEL:
1591 /* ignore it */
1592 break;
1593 case CDSC_RESPONSE_IGNORE_ALL:
1594 return CDSC_NOTDSC;
1595 }
1596 }
1597 }
1598 else if (COMPARE(p, "(atend)")) {
1599 if (dsc->scan_section == scan_trailer)
1600 dsc_unknown(dsc);
1601 /* do nothing */
1602 /* we should mark it as deferred */
1603 }
1604 else {
1605 /* llx = */ lly = urx = ury = 0;
1606 n = offset;
1607 llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1608 n += i;
1609 if (i)
1610 lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1611 n += i;
1612 if (i)
1613 urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1614 n += i;
1615 if (i)
1616 ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1617 if (i) {
1618 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1619 if (*pbbox == NULL)
1620 return CDSC_ERROR; /* no memory */
1621 (*pbbox)->llx = llx;
1622 (*pbbox)->lly = lly;
1623 (*pbbox)->urx = urx;
1624 (*pbbox)->ury = ury;
1625 }
1626 else {
1627 int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line,
1628 dsc->line_length);
1629 switch (rc) {
1630 case CDSC_RESPONSE_OK:
1631 /* fllx = */ flly = furx = fury = 0.0;
1632 n = offset;
1633 n += i;
1634 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1635 n += i;
1636 if (i)
1637 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1638 n += i;
1639 if (i)
1640 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1641 n += i;
1642 if (i)
1643 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1644 if (i) {
1645 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1646 if (*pbbox == NULL)
1647 return CDSC_ERROR; /* no memory */
1648 (*pbbox)->llx = (int)fllx;
1649 (*pbbox)->lly = (int)flly;
1650 (*pbbox)->urx = (int)(furx+0.999);
1651 (*pbbox)->ury = (int)(fury+0.999);
1652 }
1653 return CDSC_OK;
1654 case CDSC_RESPONSE_CANCEL:
1655 return CDSC_OK;
1656 case CDSC_RESPONSE_IGNORE_ALL:
1657 return CDSC_NOTDSC;
1658 }
1659 }
1660 }
1661 return CDSC_OK;
1662 }
1663
1664 dsc_private int
1665 dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
1666 {
1667 unsigned int i, n;
1668 float fllx, flly, furx, fury;
1669 char *p;
1670 /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
1671 * and last in trailer.
1672 */
1673 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1674 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1675 dsc->line_length);
1676 switch (rc) {
1677 case CDSC_RESPONSE_OK:
1678 case CDSC_RESPONSE_CANCEL:
1679 return CDSC_OK; /* ignore duplicate comments in header */
1680 case CDSC_RESPONSE_IGNORE_ALL:
1681 return CDSC_NOTDSC;
1682 }
1683 }
1684 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1685 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1686 dsc->line_length);
1687 switch (rc) {
1688 case CDSC_RESPONSE_OK:
1689 case CDSC_RESPONSE_CANCEL:
1690 return CDSC_OK; /* ignore duplicate comments in header */
1691 case CDSC_RESPONSE_IGNORE_ALL:
1692 return CDSC_NOTDSC;
1693 }
1694 }
1695 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1696 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1697 dsc->line_length);
1698 switch (rc) {
1699 case CDSC_RESPONSE_OK:
1700 case CDSC_RESPONSE_CANCEL:
1701 break; /* use duplicate comments in trailer */
1702 case CDSC_RESPONSE_IGNORE_ALL:
1703 return CDSC_NOTDSC;
1704 }
1705 }
1706 if (*pbbox != NULL) {
1707 dsc_memfree(dsc, *pbbox);
1708 *pbbox = NULL;
1709 }
1710
1711 /* should only process first %%BoundingBox: */
1712
1713 while (IS_WHITE(dsc->line[offset]))
1714 offset++;
1715 p = dsc->line + offset;
1716
1717 if (COMPARE(p, "atend")) {
1718 if (dsc->scan_section == scan_trailer)
1719 dsc_unknown(dsc);
1720 else {
1721 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1722 dsc->line_length);
1723 switch (rc) {
1724 case CDSC_RESPONSE_OK:
1725 /* assume (atend) */
1726 /* we should mark it as deferred */
1727 break;
1728 case CDSC_RESPONSE_CANCEL:
1729 /* ignore it */
1730 break;
1731 case CDSC_RESPONSE_IGNORE_ALL:
1732 return CDSC_NOTDSC;
1733 }
1734 }
1735 }
1736 else if (COMPARE(p, "(atend)")) {
1737 if (dsc->scan_section == scan_trailer)
1738 dsc_unknown(dsc);
1739 /* do nothing */
1740 /* we should mark it as deferred */
1741 }
1742 else {
1743 /* fllx = */ flly = furx = fury = 0.0;
1744 n = offset;
1745 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1746 n += i;
1747 if (i)
1748 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1749 n += i;
1750 if (i)
1751 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1752 n += i;
1753 if (i)
1754 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1755 if (i) {
1756 *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
1757 if (*pbbox == NULL)
1758 return CDSC_ERROR; /* no memory */
1759 (*pbbox)->fllx = fllx;
1760 (*pbbox)->flly = flly;
1761 (*pbbox)->furx = furx;
1762 (*pbbox)->fury = fury;
1763 }
1764 }
1765 return CDSC_OK;
1766 }
1767
1768 dsc_private int
1769 dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset)
1770 {
1771 char *p;
1772 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1773 (dsc->scan_section == scan_comments)) {
1774 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1775 dsc->line_length);
1776 switch (rc) {
1777 case CDSC_RESPONSE_OK:
1778 case CDSC_RESPONSE_CANCEL:
1779 return CDSC_OK; /* ignore duplicate comments in header */
1780 case CDSC_RESPONSE_IGNORE_ALL:
1781 return CDSC_NOTDSC;
1782 }
1783 }
1784 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1785 (dsc->scan_section == scan_trailer)) {
1786 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1787 dsc->line_length);
1788 switch (rc) {
1789 case CDSC_RESPONSE_OK:
1790 case CDSC_RESPONSE_CANCEL:
1791 break; /* use duplicate comments in header; */
1792 case CDSC_RESPONSE_IGNORE_ALL:
1793 return CDSC_NOTDSC;
1794 }
1795 }
1796 p = dsc->line + offset;
1797 while (IS_WHITE(*p))
1798 p++;
1799 if (COMPARE(p, "atend")) {
1800 if (dsc->scan_section == scan_trailer)
1801 dsc_unknown(dsc);
1802 else {
1803 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
1804 dsc->line, dsc->line_length);
1805 switch (rc) {
1806 case CDSC_RESPONSE_OK:
1807 /* assume (atend) */
1808 /* we should mark it as deferred */
1809 break;
1810 case CDSC_RESPONSE_CANCEL:
1811 /* ignore it */
1812 break;
1813 case CDSC_RESPONSE_IGNORE_ALL:
1814 return CDSC_NOTDSC;
1815 }
1816 }
1817 }
1818 else if (COMPARE(p, "(atend)")) {
1819 if (dsc->scan_section == scan_trailer)
1820 dsc_unknown(dsc);
1821 /* do nothing */
1822 /* we should mark it as deferred */
1823 }
1824 else if (COMPARE(p, "Portrait")) {
1825 *porientation = CDSC_PORTRAIT;
1826 }
1827 else if (COMPARE(p, "Landscape")) {
1828 *porientation = CDSC_LANDSCAPE;
1829 }
1830 else {
1831 dsc_unknown(dsc);
1832 }
1833 return CDSC_OK;
1834 }
1835
1836 dsc_private int
1837 dsc_parse_order(CDSC *dsc)
1838 {
1839 char *p;
1840 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1841 (dsc->scan_section == scan_comments)) {
1842 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1843 dsc->line_length);
1844 switch (rc) {
1845 case CDSC_RESPONSE_OK:
1846 case CDSC_RESPONSE_CANCEL:
1847 return CDSC_OK; /* ignore duplicate comments in header */
1848 case CDSC_RESPONSE_IGNORE_ALL:
1849 return CDSC_NOTDSC;
1850 }
1851 }
1852 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1853 (dsc->scan_section == scan_trailer)) {
1854 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1855 dsc->line_length);
1856 switch (rc) {
1857 case CDSC_RESPONSE_OK:
1858 case CDSC_RESPONSE_CANCEL:
1859 break; /* use duplicate comments in trailer */
1860 case CDSC_RESPONSE_IGNORE_ALL:
1861 return CDSC_NOTDSC;
1862 }
1863 }
1864
1865 p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13);
1866 while (IS_WHITE(*p))
1867 p++;
1868 if (COMPARE(p, "atend")) {
1869 if (dsc->scan_section == scan_trailer)
1870 dsc_unknown(dsc);
1871 else {
1872 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1873 dsc->line_length);
1874 switch (rc) {
1875 case CDSC_RESPONSE_OK:
1876 /* assume (atend) */
1877 /* we should mark it as deferred */
1878 break;
1879 case CDSC_RESPONSE_CANCEL:
1880 /* ignore it */
1881 break;
1882 case CDSC_RESPONSE_IGNORE_ALL:
1883 return CDSC_NOTDSC;
1884 }
1885 }
1886 }
1887 else if (COMPARE(p, "(atend)")) {
1888 if (dsc->scan_section == scan_trailer)
1889 dsc_unknown(dsc);
1890 /* do nothing */
1891 /* we should mark it as deferred */
1892 }
1893 else if (COMPARE(p, "Ascend")) {
1894 dsc->page_order = CDSC_ASCEND;
1895 }
1896 else if (COMPARE(p, "Descend")) {
1897 dsc->page_order = CDSC_DESCEND;
1898 }
1899 else if (COMPARE(p, "Special")) {
1900 dsc->page_order = CDSC_SPECIAL;
1901 }
1902 else {
1903 dsc_unknown(dsc);
1904 }
1905 return CDSC_OK;
1906 }
1907
1908
1909 dsc_private int
1910 dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media)
1911 {
1912 char media_name[MAXSTR];
1913 int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */
1914 unsigned int i;
1915
1916 if (dsc_copy_string(media_name, sizeof(media_name)-1,
1917 dsc->line+n, dsc->line_length-n, NULL)) {
1918 for (i=0; i<dsc->media_count; i++) {
1919 if (dsc->media[i]->name &&
1920 (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) {
1921 *page_media = dsc->media[i];
1922 return CDSC_OK;
1923 }
1924 }
1925 }
1926 dsc_unknown(dsc);
1927
1928 return CDSC_OK;
1929 }
1930
1931
1932 dsc_private int
1933 dsc_parse_document_media(CDSC *dsc)
1934 {
1935 unsigned int i, n;
1936 CDSCMEDIA lmedia;
1937 GSBOOL blank_line;
1938
1939 if (IS_DSC(dsc->line, "%%DocumentMedia:"))
1940 n = 16;
1941 else if (IS_DSC(dsc->line, "%%+"))
1942 n = 3;
1943 else
1944 return CDSC_ERROR; /* error */
1945
1946 /* check for blank remainder of line */
1947 blank_line = TRUE;
1948 for (i=n; i<dsc->line_length; i++) {
1949 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
1950 blank_line = FALSE;
1951 break;
1952 }
1953 }
1954
1955 if (!blank_line) {
1956 char name[MAXSTR];
1957 char colour[MAXSTR];
1958 char type[MAXSTR];
1959 lmedia.name = lmedia.colour = lmedia.type = (char *)NULL;
1960 lmedia.width = lmedia.height = lmedia.weight = 0;
1961 lmedia.mediabox = (CDSCBBOX *)NULL;
1962 lmedia.name = dsc_copy_string(name, sizeof(name),
1963 dsc->line+n, dsc->line_length-n, &i);
1964 n+=i;
1965 if (i)
1966 lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1967 n+=i;
1968 if (i)
1969 lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1970 n+=i;
1971 if (i)
1972 lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1973 n+=i;
1974 if (i)
1975 lmedia.colour = dsc_copy_string(colour, sizeof(colour),
1976 dsc->line+n, dsc->line_length-n, &i);
1977 n+=i;
1978 if (i)
1979 lmedia.type = dsc_copy_string(type, sizeof(type),
1980 dsc->line+n, dsc->line_length-n, &i);
1981
1982 if (i==0)
1983 dsc_unknown(dsc); /* we didn't get all fields */
1984 else {
1985 if (dsc_add_media(dsc, &lmedia))
1986 return CDSC_ERROR; /* out of memory */
1987 }
1988 }
1989 return CDSC_OK;
1990 }
1991
1992 /* viewing orientation is believed to be the first four elements of
1993 * a CTM matrix
1994 */
1995 dsc_private int
1996 dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm)
1997 {
1998 CDSCCTM ctm;
1999 unsigned int i, n;
2000
2001 if (*pctm != NULL) {
2002 dsc_memfree(dsc, *pctm);
2003 *pctm = NULL;
2004 }
2005
2006 n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */
2007 while (IS_WHITE(dsc->line[n]))
2008 n++;
2009
2010 /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0;
2011 ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2012 n += i;
2013 if (i)
2014 ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2015 n += i;
2016 if (i)
2017 ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2018 n += i;
2019 if (i)
2020 ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2021 if (i==0) {
2022 dsc_unknown(dsc); /* we didn't get all fields */
2023 }
2024 else {
2025 *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM));
2026 if (*pctm == NULL)
2027 return CDSC_ERROR; /* no memory */
2028 **pctm = ctm;
2029 }
2030 return CDSC_OK;
2031 }
2032
2033
2034 /* This is called before dsc_read_line(), since we may
2035 * need to skip a binary header which contains a new line
2036 * character
2037 */
2038 dsc_private int
2039 dsc_scan_type(CDSC *dsc)
2040 {
2041 unsigned char *p;
2042 unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index);
2043 int length = dsc->data_length - dsc->data_index;
2044
2045 /* Types that should be known:
2046 * DSC
2047 * EPSF
2048 * PJL + any of above
2049 * ^D + any of above
2050 * DOS EPS
2051 * PDF
2052 * non-DSC
2053 */
2054
2055 /* First process any non PostScript headers */
2056 /* At this stage we do not have a complete line */
2057
2058 if (length == 0)
2059 return CDSC_NEEDMORE;
2060
2061 /* If we have already found a DOS EPS header, */
2062 /* ignore all until the PostScript section */
2063 if (dsc->skip_bytes) {
2064 int cnt = min(dsc->skip_bytes,
2065 (int)(dsc->data_length - dsc->data_index));
2066 dsc->skip_bytes -= cnt;
2067 dsc->data_index += cnt;
2068 length -= cnt;
2069 line += cnt;
2070 if (dsc->skip_bytes != 0)
2071 return CDSC_NEEDMORE;
2072 }
2073
2074 if (dsc->skip_pjl) {
2075 /* skip until first PostScript comment */
2076 while (length >= 2) {
2077 while (length && !IS_EOL(line[0])) {
2078 /* skip until EOL character */
2079 line++;
2080 dsc->data_index++;
2081 length--;
2082 }
2083 while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) {
2084 /* skip until EOL followed by non-EOL */
2085 line++;
2086 dsc->data_index++;
2087 length--;
2088 }
2089 if (length < 2)
2090 return CDSC_NEEDMORE;
2091
2092 if (IS_EOL(line[0]) && line[1]=='%') {
2093 line++;
2094 dsc->data_index++;
2095 length--;
2096 dsc->skip_pjl = FALSE;
2097 break;
2098 }
2099 else {
2100 line++;
2101 dsc->data_index++;
2102 length--;
2103 }
2104 }
2105 if (dsc->skip_pjl)
2106 return CDSC_NEEDMORE;
2107 }
2108
2109 if (length == 0)
2110 return CDSC_NEEDMORE;
2111
2112 if (line[0] == '\004') {
2113 line++;
2114 dsc->data_index++;
2115 length--;
2116 dsc->ctrld = TRUE;
2117 }
2118
2119 if (line[0] == '\033') {
2120 /* possibly PJL */
2121 if (length < 9)
2122 return CDSC_NEEDMORE;
2123 if (COMPARE(line, "\033%-12345X")) {
2124 dsc->skip_pjl = TRUE; /* skip until first PostScript comment */
2125 dsc->pjl = TRUE;
2126 dsc->data_index += 9;
2127 return dsc_scan_type(dsc);
2128 }
2129 }
2130
2131 if ((line[0]==0x0) && (length < 2))
2132 return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2133 if ((line[0]==0x0) && (line[1] >= 1) && (line[1] <= 63) && (length < 128))
2134 return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2135 if ((line[0]==0x0) && (line[1] == 0x5) && (length < 4))
2136 return CDSC_NEEDMORE; /* Could be Mac AppleSingle/AppleDouble */
2137 if ((line[0]==0xc5) && (length < 4))
2138 return CDSC_NEEDMORE; /* Could be DOS EPS */
2139
2140 if ((line[0]==0xc5) && (line[1]==0xd0) &&
2141 (line[2]==0xd3) && (line[3]==0xc6) ) {
2142 /* id is "EPSF" with bit 7 set */
2143 /* read DOS EPS header, then ignore all bytes until the PS section */
2144 if (length < 30)
2145 return CDSC_NEEDMORE;
2146 dsc->line = (char *)line;
2147 if (dsc_read_doseps(dsc))
2148 return CDSC_ERROR;
2149 }
2150 else if ((line[0]==0x0) && (line[1]==0x05) &&
2151 (line[2]==0x16) && ((line[3]==0x0) || (line[3] == 0x07))) {
2152 /* Mac AppleSingle or AppleDouble */
2153 GSDWORD version;
2154 GSWORD entries;
2155 if (length < 26)
2156 return CDSC_NEEDMORE;
2157 version = dsc_get_bigendian_dword(line+4);
2158 entries = dsc_get_bigendian_word(line+24);
2159 if ((version == 0x00010000) || (version == 0x00020000)) {
2160 if (length < (int)(26 + entries * 12))
2161 return CDSC_NEEDMORE;
2162 dsc->line = (char *)line;
2163 if (dsc_read_applesingle(dsc))
2164 return CDSC_ERROR;
2165 }
2166 }
2167 else if ((line[0]==0x0) &&
2168 (line[1] >= 1) && (line[1] <= 63) &&
2169 (line[74]==0x0) &&
2170 (line[65]=='E') && (line[66]=='P') &&
2171 (line[67]=='S') && (line[68]=='F')) {
2172 /* Mac Binary EPSF */
2173 dsc->line = (char *)line;
2174 if (dsc_read_macbin(dsc))
2175 return CDSC_ERROR;
2176 }
2177 else {
2178 if (length < 2)
2179 return CDSC_NEEDMORE;
2180 if ((line[0] == '%') && (line[1] == 'P')) {
2181 if (length < 5)
2182 return CDSC_NEEDMORE;
2183 if (COMPARE(line, "%PDF-")) {
2184 dsc->pdf = TRUE;
2185 dsc->scan_section = scan_comments;
2186 return CDSC_OK;
2187 }
2188 }
2189 }
2190
2191 /* Finally process PostScript headers */
2192
2193 if (dsc_read_line(dsc) <= 0)
2194 return CDSC_NEEDMORE;
2195
2196 dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
2197 if (COMPARE(dsc->line, "%!PS-Adobe")) {
2198 dsc->dsc = TRUE;
2199 dsc->begincomments = DSC_START(dsc);
2200 if (dsc->dsc_version == NULL)
2201 return CDSC_ERROR; /* no memory */
2202 p = (unsigned char *)dsc->line + 14;
2203 while (IS_WHITE(*p))
2204 p++;
2205 if (COMPARE(p, "EPSF-"))
2206 dsc->epsf = TRUE;
2207 dsc->scan_section = scan_comments;
2208 return CDSC_PSADOBE;
2209 }
2210 if (COMPARE(dsc->line, "%!")) {
2211 dsc->scan_section = scan_comments;
2212 return CDSC_NOTDSC;
2213 }
2214
2215 dsc->scan_section = scan_comments;
2216 return CDSC_NOTDSC; /* unrecognised */
2217 }
2218
2219
2220
2221 dsc_private int
2222 dsc_scan_comments(CDSC *dsc)
2223 {
2224 /* Comments section ends at */
2225 /* %%EndComments */
2226 /* another section */
2227 /* line that does not start with %% */
2228 /* Save a few important lines */
2229
2230 char *line = dsc->line;
2231 GSBOOL continued = FALSE;
2232 dsc->id = CDSC_OK;
2233 if (IS_DSC(line, "%%EndComments")) {
2234 dsc->id = CDSC_ENDCOMMENTS;
2235 dsc->endcomments = DSC_END(dsc);
2236 dsc->scan_section = scan_pre_preview;
2237 return CDSC_OK;
2238 }
2239 else if (IS_DSC(line, "%%BeginComments")) {
2240 /* ignore because we are in this section */
2241 dsc->id = CDSC_BEGINCOMMENTS;
2242 }
2243 else if (dsc_is_section(line)) {
2244 dsc->endcomments = DSC_START(dsc);
2245 dsc->scan_section = scan_pre_preview;
2246 return CDSC_PROPAGATE;
2247 }
2248 else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) {
2249 dsc->endcomments = DSC_START(dsc);
2250 dsc->scan_section = scan_pre_preview;
2251 return CDSC_PROPAGATE;
2252 }
2253 else if (line[0] != '%') {
2254 dsc->id = CDSC_OK;
2255 dsc->endcomments = DSC_START(dsc);
2256 dsc->scan_section = scan_pre_preview;
2257 return CDSC_PROPAGATE;
2258 }
2259 else if (IS_DSC(line, "%%Begin")) {
2260 dsc->endcomments = DSC_START(dsc);
2261 dsc->scan_section = scan_pre_preview;
2262 return CDSC_PROPAGATE;
2263 }
2264
2265 /* Handle continuation lines.
2266 * To simply processing, we assume that contination lines
2267 * will only occur if repeat parameters are allowed and that
2268 * a complete set of these parameters appears on each line.
2269 * This is more restrictive than the DSC specification, but
2270 * is valid for the DSC comments understood by this parser
2271 * for all documents that we have seen.
2272 */
2273 if (IS_DSC(line, "%%+")) {
2274 line = dsc->last_line;
2275 continued = TRUE;
2276 }
2277 else
2278 dsc_save_line(dsc);
2279
2280 if (IS_DSC(line, "%%Pages:")) {
2281 dsc->id = CDSC_PAGES;
2282 if (dsc_parse_pages(dsc) != 0)
2283 return CDSC_ERROR;
2284 }
2285 else if (IS_DSC(line, "%%Creator:")) {
2286 dsc->id = CDSC_CREATOR;
2287 dsc->dsc_creator = dsc_add_line(dsc, dsc->line+10, dsc->line_length-10);
2288 if (dsc->dsc_creator==NULL)
2289 return CDSC_ERROR;
2290 }
2291 else if (IS_DSC(line, "%%CreationDate:")) {
2292 dsc->id = CDSC_CREATIONDATE;
2293 dsc->dsc_date = dsc_add_line(dsc, dsc->line+15, dsc->line_length-15);
2294 if (dsc->dsc_date==NULL)
2295 return CDSC_ERROR;
2296 }
2297 else if (IS_DSC(line, "%%Title:")) {
2298 dsc->id = CDSC_TITLE;
2299 dsc->dsc_title = dsc_add_line(dsc, dsc->line+8, dsc->line_length-8);
2300 if (dsc->dsc_title==NULL)
2301 return CDSC_ERROR;
2302 }
2303 else if (IS_DSC(line, "%%For:")) {
2304 dsc->id = CDSC_FOR;
2305 dsc->dsc_for = dsc_add_line(dsc, dsc->line+6, dsc->line_length-6);
2306 if (dsc->dsc_for==NULL)
2307 return CDSC_ERROR;
2308 }
2309 else if (IS_DSC(line, "%%LanguageLevel:")) {
2310 unsigned int n = continued ? 3 : 16;
2311 unsigned int i;
2312 int ll;
2313 dsc->id = CDSC_LANGUAGELEVEL;
2314 ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
2315 if (i) {
2316 if ( (ll==1) || (ll==2) || (ll==3) )
2317 dsc->language_level = ll;
2318 else {
2319 dsc_unknown(dsc);
2320 }
2321 }
2322 else
2323 dsc_unknown(dsc);
2324 }
2325 else if (IS_DSC(line, "%%BoundingBox:")) {
2326 dsc->id = CDSC_BOUNDINGBOX;
2327 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
2328 return CDSC_ERROR;
2329 }
2330 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
2331 dsc->id = CDSC_HIRESBOUNDINGBOX;
2332 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
2333 continued ? 3 : 19))
2334 return CDSC_ERROR;
2335 }
2336 else if (IS_DSC(line, "%%CropBox:")) {
2337 dsc->id = CDSC_CROPBOX;
2338 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
2339 continued ? 3 : 10))
2340 return CDSC_ERROR;
2341 }
2342 else if (IS_DSC(line, "%%Orientation:")) {
2343 dsc->id = CDSC_ORIENTATION;
2344 if (dsc_parse_orientation(dsc, &(dsc->page_orientation),
2345 continued ? 3 : 14))
2346 return CDSC_ERROR;
2347 }
2348 else if (IS_DSC(line, "%%PageOrder:")) {
2349 dsc->id = CDSC_PAGEORDER;
2350 if (dsc_parse_order(dsc))
2351 return CDSC_ERROR;
2352 }
2353 else if (IS_DSC(line, "%%DocumentMedia:")) {
2354 dsc->id = CDSC_DOCUMENTMEDIA;
2355 if (dsc_parse_document_media(dsc))
2356 return CDSC_ERROR;
2357 }
2358 else if (IS_DSC(line, "%%DocumentPaperSizes:")) {
2359 /* DSC 2.1 */
2360 unsigned int n = continued ? 3 : 21;
2361 unsigned int count = 0;
2362 unsigned int i = 1;
2363 char name[MAXSTR];
2364 char *p;
2365 dsc->id = CDSC_DOCUMENTPAPERSIZES;
2366 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2367 p = dsc_copy_string(name, sizeof(name)-1,
2368 dsc->line+n, dsc->line_length-n, &i);
2369 if (i && p) {
2370 const CDSCMEDIA *m = dsc_known_media;
2371 if (count >= dsc->media_count) {
2372 /* set some default values */
2373 CDSCMEDIA lmedia;
2374 lmedia.name = p;
2375 lmedia.width = 595.0;
2376 lmedia.height = 842.0;
2377 lmedia.weight = 80.0;
2378 lmedia.colour = NULL;
2379 lmedia.type = NULL;
2380 lmedia.mediabox = NULL;
2381 if (dsc_add_media(dsc, &lmedia))
2382 return CDSC_ERROR;
2383 }
2384 else
2385 dsc->media[count]->name =
2386 dsc_alloc_string(dsc, p, (int)strlen(p));
2387 /* find in list of known media */
2388 while (m && m->name) {
2389 if (dsc_stricmp(p, m->name)==0) {
2390 dsc->media[count]->width = m->width;
2391 dsc->media[count]->height = m->height;
2392 break;
2393 }
2394 m++;
2395 }
2396 }
2397 n+=i;
2398 count++;
2399 }
2400 }
2401 else if (IS_DSC(line, "%%DocumentPaperForms:")) {
2402 /* DSC 2.1 */
2403 unsigned int n = continued ? 3 : 21;
2404 unsigned int count = 0;
2405 unsigned int i = 1;
2406 char type[MAXSTR];
2407 char *p;
2408 dsc->id = CDSC_DOCUMENTPAPERFORMS;
2409 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2410 p = dsc_copy_string(type, sizeof(type)-1,
2411 dsc->line+n, dsc->line_length-n, &i);
2412 if (i && p) {
2413 if (count >= dsc->media_count) {
2414 /* set some default values */
2415 CDSCMEDIA lmedia;
2416 lmedia.name = NULL;
2417 lmedia.width = 595.0;
2418 lmedia.height = 842.0;
2419 lmedia.weight = 80.0;
2420 lmedia.colour = NULL;
2421 lmedia.type = p;
2422 lmedia.mediabox = NULL;
2423 if (dsc_add_media(dsc, &lmedia))
2424 return CDSC_ERROR;
2425 }
2426 else
2427 dsc->media[count]->type =
2428 dsc_alloc_string(dsc, p, (int)strlen(p));
2429 }
2430 n+=i;
2431 count++;
2432 }
2433 }
2434 else if (IS_DSC(line, "%%DocumentPaperColors:")) {
2435 /* DSC 2.1 */
2436 unsigned int n = continued ? 3 : 22;
2437 unsigned int count = 0;
2438 unsigned int i = 1;
2439 char colour[MAXSTR];
2440 char *p;
2441 dsc->id = CDSC_DOCUMENTPAPERCOLORS;
2442 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2443 p = dsc_copy_string(colour, sizeof(colour)-1,
2444 dsc->line+n, dsc->line_length-n, &i);
2445 if (i && p) {
2446 if (count >= dsc->media_count) {
2447 /* set some default values */
2448 CDSCMEDIA lmedia;
2449 lmedia.name = NULL;
2450 lmedia.width = 595.0;
2451 lmedia.height = 842.0;
2452 lmedia.weight = 80.0;
2453 lmedia.colour = p;
2454 lmedia.type = NULL;
2455 lmedia.mediabox = NULL;
2456 if (dsc_add_media(dsc, &lmedia))
2457 return CDSC_ERROR;
2458 }
2459 else
2460 dsc->media[count]->colour =
2461 dsc_alloc_string(dsc, p, (int)strlen(p));
2462 }
2463 n+=i;
2464 count++;
2465 }
2466 }
2467 else if (IS_DSC(line, "%%DocumentPaperWeights:")) {
2468 /* DSC 2.1 */
2469 unsigned int n = continued ? 3 : 23;
2470 unsigned int count = 0;
2471 unsigned int i = 1;
2472 float w;
2473 dsc->id = CDSC_DOCUMENTPAPERWEIGHTS;
2474 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2475 w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2476 if (i) {
2477 if (count >= dsc->media_count) {
2478 /* set some default values */
2479 CDSCMEDIA lmedia;
2480 lmedia.name = NULL;
2481 lmedia.width = 595.0;
2482 lmedia.height = 842.0;
2483 lmedia.weight = w;
2484 lmedia.colour = NULL;
2485 lmedia.type = NULL;
2486 lmedia.mediabox = NULL;
2487 if (dsc_add_media(dsc, &lmedia))
2488 return CDSC_ERROR;
2489 }
2490 else
2491 dsc->media[count]->weight = w;
2492 }
2493 n+=i;
2494 count++;
2495 }
2496 }
2497 else if (IS_DSC(line, "%%DocumentData:")) {
2498 unsigned int n = continued ? 3 : 15;
2499 char *p = dsc->line + n;
2500 while (IS_WHITE(*p))
2501 p++;
2502 dsc->id = CDSC_DOCUMENTDATA;
2503 if (COMPARE(p, "Clean7Bit"))
2504 dsc->document_data = CDSC_CLEAN7BIT;
2505 else if (COMPARE(p, "Clean8Bit"))
2506 dsc->document_data = CDSC_CLEAN8BIT;
2507 else if (COMPARE(p, "Binary"))
2508 dsc->document_data = CDSC_BINARY;
2509 else
2510 dsc_unknown(dsc);
2511 }
2512 else if (IS_DSC(line, "%%Requirements:")) {
2513 dsc->id = CDSC_REQUIREMENTS;
2514 /* ignore */
2515 }
2516 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
2517 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
2518 /* ignore */
2519 }
2520 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
2521 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
2522 /* ignore */
2523 }
2524 else if (IS_DSC(line, "%%PlateFile:")) {
2525 dsc->id = CDSC_PLATEFILE;
2526 if (dsc_parse_platefile(dsc) != CDSC_OK)
2527 dsc->id = CDSC_UNKNOWNDSC;
2528 }
2529 else if (IS_DSC(line, "%%CyanPlate:") ||
2530 IS_DSC(line, "%%MagentaPlate:") ||
2531 IS_DSC(line, "%%YellowPlate:") ||
2532 IS_DSC(line, "%%BlackPlate:")) {
2533 dsc->id = CDSC_PLATEFILE;
2534 if (dsc_parse_dcs1plate(dsc) != CDSC_OK)
2535 dsc->id = CDSC_UNKNOWNDSC;
2536 }
2537 else if (IS_DSC(line, "%%DocumentProcessColors:")) {
2538 dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
2539 if (dsc_parse_process_colours(dsc) != CDSC_OK)
2540 dsc->id = CDSC_UNKNOWNDSC;
2541 }
2542 else if (IS_DSC(line, "%%DocumentCustomColors:")) {
2543 dsc->id = CDSC_DOCUMENTCUSTOMCOLORS;
2544 if (dsc_parse_custom_colours(dsc) != CDSC_OK)
2545 dsc->id = CDSC_UNKNOWNDSC;
2546 }
2547 else if (IS_DSC(line, "%%CMYKCustomColor:")) {
2548 dsc->id = CDSC_CMYKCUSTOMCOLOR;
2549 if (dsc_parse_cmyk_custom_colour(dsc) != CDSC_OK)
2550 dsc->id = CDSC_UNKNOWNDSC;
2551 }
2552 else if (IS_DSC(line, "%%RGBCustomColor:")) {
2553 dsc->id = CDSC_RGBCUSTOMCOLOR;
2554 if (dsc_parse_rgb_custom_colour(dsc) != CDSC_OK)
2555 dsc->id = CDSC_UNKNOWNDSC;
2556 }
2557 else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) {
2558 dsc->id = CDSC_OK;
2559 /* ignore */
2560 }
2561 else {
2562 dsc->id = CDSC_UNKNOWNDSC;
2563 dsc_unknown(dsc);
2564 }
2565
2566 dsc->endcomments = DSC_END(dsc);
2567 return CDSC_OK;
2568 }
2569
2570
2571 dsc_private int
2572 dsc_scan_preview(CDSC *dsc)
2573 {
2574 /* Preview section ends at */
2575 /* %%EndPreview */
2576 /* another section */
2577 /* Preview section must start with %%BeginPreview */
2578 char *line = dsc->line;
2579 dsc->id = CDSC_OK;
2580
2581 if (dsc->scan_section == scan_pre_preview) {
2582 if (IS_BLANK(line))
2583 return CDSC_OK; /* ignore blank lines before preview */
2584 else if (IS_DSC(line, "%%BeginPreview")) {
2585 dsc->id = CDSC_BEGINPREVIEW;
2586 dsc->beginpreview = DSC_START(dsc);
2587 dsc->endpreview = DSC_END(dsc);
2588 dsc->scan_section = scan_preview;
2589 /* Don't mark the preview as EPSI if a DOS EPS header is present */
2590 if (dsc->preview == CDSC_NOPREVIEW)
2591 dsc->preview = CDSC_EPSI;
2592 return CDSC_OK;
2593 }
2594 else {
2595 dsc->scan_section = scan_pre_defaults;
2596 return CDSC_PROPAGATE;
2597 }
2598 }
2599
2600 if (IS_DSC(line, "%%BeginPreview")) {
2601 /* ignore because we are in this section */
2602 }
2603 else if (dsc_is_section(line)) {
2604 dsc->endpreview = DSC_START(dsc);
2605 dsc->scan_section = scan_pre_defaults;
2606 return CDSC_PROPAGATE;
2607 }
2608 else if (IS_DSC(line, "%%EndPreview")) {
2609 dsc->id = CDSC_ENDPREVIEW;
2610 dsc->endpreview = DSC_END(dsc);
2611 dsc->scan_section = scan_pre_defaults;
2612 return CDSC_OK;
2613 }
2614 else if (line[0] == '%' && line[1] != '%') {
2615 /* Ordinary comments are OK */
2616 }
2617 else {
2618 dsc->id = CDSC_UNKNOWNDSC;
2619 /* DSC comments should not occur in preview */
2620 dsc_unknown(dsc);
2621 }
2622
2623 dsc->endpreview = DSC_END(dsc);
2624 return CDSC_OK;
2625 }
2626
2627 dsc_private int
2628 dsc_scan_defaults(CDSC *dsc)
2629 {
2630 /* Defaults section ends at */
2631 /* %%EndDefaults */
2632 /* another section */
2633 /* Defaults section must start with %%BeginDefaults */
2634 char *line = dsc->line;
2635 dsc->id = CDSC_OK;
2636
2637 if (dsc->scan_section == scan_pre_defaults) {
2638 if (IS_BLANK(line))
2639 return CDSC_OK; /* ignore blank lines before defaults */
2640 else if (IS_DSC(line, "%%BeginDefaults")) {
2641 dsc->id = CDSC_BEGINDEFAULTS;
2642 dsc->begindefaults = DSC_START(dsc);
2643 dsc->enddefaults = DSC_END(dsc);
2644 dsc->scan_section = scan_defaults;
2645 return CDSC_OK;
2646 }
2647 else {
2648 dsc->scan_section = scan_pre_prolog;
2649 return CDSC_PROPAGATE;
2650 }
2651 }
2652
2653 if (NOT_DSC_LINE(line)) {
2654 /* ignore */
2655 }
2656 else if (IS_DSC(line, "%%BeginPreview")) {
2657 /* ignore because we have already processed this section */
2658 }
2659 else if (IS_DSC(line, "%%BeginDefaults")) {
2660 /* ignore because we are in this section */
2661 }
2662 else if (dsc_is_section(line)) {
2663 dsc->enddefaults = DSC_START(dsc);
2664 dsc->scan_section = scan_pre_prolog;
2665 return CDSC_PROPAGATE;
2666 }
2667 else if (IS_DSC(line, "%%EndDefaults")) {
2668 dsc->id = CDSC_ENDDEFAULTS;
2669 dsc->enddefaults = DSC_END(dsc);
2670 dsc->scan_section = scan_pre_prolog;
2671 return CDSC_OK;
2672 }
2673 else if (IS_DSC(line, "%%PageMedia:")) {
2674 dsc->id = CDSC_PAGEMEDIA;
2675 dsc_parse_media(dsc, &dsc->page_media);
2676 }
2677 else if (IS_DSC(line, "%%PageOrientation:")) {
2678 dsc->id = CDSC_PAGEORIENTATION;
2679 /* This can override %%Orientation: */
2680 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18))
2681 return CDSC_ERROR;
2682 }
2683 else if (IS_DSC(line, "%%PageBoundingBox:")) {
2684 dsc->id = CDSC_PAGEBOUNDINGBOX;
2685 if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18))
2686 return CDSC_ERROR;
2687 }
2688 else if (IS_DSC(line, "%%ViewingOrientation:")) {
2689 dsc->id = CDSC_VIEWINGORIENTATION;
2690 if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation))
2691 return CDSC_ERROR;
2692 }
2693 else if (IS_DSC(line, "%%PageCropBox:")) {
2694 dsc->id = CDSC_PAGECROPBOX;
2695 if (dsc_parse_float_bounding_box(dsc, &dsc->crop_box, 14))
2696 return CDSC_ERROR;
2697 }
2698 else {
2699 dsc->id = CDSC_UNKNOWNDSC;
2700 /* All other DSC comments are unknown, but not an error */
2701 dsc_unknown(dsc);
2702 }
2703 dsc->enddefaults = DSC_END(dsc);
2704 return CDSC_OK;
2705 }
2706
2707 /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the
2708 * mismatch (default) */
2709 dsc_private int
2710 dsc_check_match_prompt(CDSC *dsc, const char *str, int count)
2711 {
2712 if (count != 0) {
2713 char buf[MAXSTR+MAXSTR];
2714 if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1)) {
2715 strncpy(buf, dsc->line, dsc->line_length);
2716 buf[dsc->line_length] = '\0';
2717 }
2718 sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
2719 return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, (int)strlen(buf));
2720 }
2721 return CDSC_RESPONSE_CANCEL;
2722 }
2723
2724 dsc_private int
2725 dsc_check_match_type(CDSC *dsc, const char *str, int count)
2726 {
2727 if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL)
2728 return CDSC_NOTDSC;
2729 return CDSC_OK;
2730 }
2731
2732 /* complain if Begin/End blocks didn't match */
2733 /* return non-zero if we should ignore all DSC */
2734 dsc_private int
2735 dsc_check_match(CDSC *dsc)
2736 {
2737 int rc = 0;
2738 const char *font = "Font";
2739 const char *feature = "Feature";
2740 const char *resource = "Resource";
2741 const char *procset = "ProcSet";
2742
2743 if (!rc)
2744 rc = dsc_check_match_type(dsc, font, dsc->begin_font_count);
2745 if (!rc)
2746 rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count);
2747 if (!rc)
2748 rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count);
2749 if (!rc)
2750 rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count);
2751
2752 dsc->begin_font_count = 0;
2753 dsc->begin_feature_count = 0;
2754 dsc->begin_resource_count = 0;
2755 dsc->begin_procset_count = 0;
2756 return rc;
2757 }
2758
2759
2760 dsc_private int
2761 dsc_scan_prolog(CDSC *dsc)
2762 {
2763 /* Prolog section ends at */
2764 /* %%EndProlog */
2765 /* another section */
2766 /* Prolog section may start with %%BeginProlog or non-dsc line */
2767 char *line = dsc->line;
2768 dsc->id = CDSC_OK;
2769
2770 if (dsc->scan_section == scan_pre_prolog) {
2771 if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) {
2772 dsc->scan_section = scan_pre_setup;
2773 return CDSC_PROPAGATE;
2774 }
2775 dsc->id = CDSC_BEGINPROLOG;
2776 dsc->beginprolog = DSC_START(dsc);
2777 dsc->endprolog = DSC_END(dsc);
2778 dsc->scan_section = scan_prolog;
2779 if (IS_DSC(line, "%%BeginProlog"))
2780 return CDSC_OK;
2781 }
2782
2783 if (NOT_DSC_LINE(line)) {
2784 /* ignore */
2785 }
2786 else if (IS_DSC(line, "%%BeginPreview")) {
2787 /* ignore because we have already processed this section */
2788 }
2789 else if (IS_DSC(line, "%%BeginDefaults")) {
2790 /* ignore because we have already processed this section */
2791 }
2792 else if (IS_DSC(line, "%%BeginProlog")) {
2793 /* ignore because we are in this section */
2794 }
2795 else if (dsc_is_section(line)) {
2796 dsc->endprolog = DSC_START(dsc);
2797 dsc->scan_section = scan_pre_setup;
2798 if (dsc_check_match(dsc))
2799 return CDSC_NOTDSC;
2800 return CDSC_PROPAGATE;
2801 }
2802 else if (IS_DSC(line, "%%EndProlog")) {
2803 dsc->id = CDSC_ENDPROLOG;
2804 dsc->endprolog = DSC_END(dsc);
2805 dsc->scan_section = scan_pre_setup;
2806 if (dsc_check_match(dsc))
2807 return CDSC_NOTDSC;
2808 return CDSC_OK;
2809 }
2810 else if (IS_DSC(line, "%%BeginFont:")) {
2811 dsc->id = CDSC_BEGINFONT;
2812 /* ignore Begin/EndFont, apart form making sure */
2813 /* that they are matched. */
2814 dsc->begin_font_count++;
2815 }
2816 else if (IS_DSC(line, "%%EndFont")) {
2817 dsc->id = CDSC_ENDFONT;
2818 dsc->begin_font_count--;
2819 }
2820 else if (IS_DSC(line, "%%BeginFeature:")) {
2821 dsc->id = CDSC_BEGINFEATURE;
2822 /* ignore Begin/EndFeature, apart form making sure */
2823 /* that they are matched. */
2824 dsc->begin_feature_count++;
2825 }
2826 else if (IS_DSC(line, "%%EndFeature")) {
2827 dsc->id = CDSC_ENDFEATURE;
2828 dsc->begin_feature_count--;
2829 }
2830 else if (IS_DSC(line, "%%BeginResource:")) {
2831 dsc->id = CDSC_BEGINRESOURCE;
2832 /* ignore Begin/EndResource, apart form making sure */
2833 /* that they are matched. */
2834 dsc->begin_resource_count++;
2835 }
2836 else if (IS_DSC(line, "%%EndResource")) {
2837 dsc->id = CDSC_ENDRESOURCE;
2838 dsc->begin_resource_count--;
2839 }
2840 else if (IS_DSC(line, "%%BeginProcSet:")) {
2841 dsc->id = CDSC_BEGINPROCSET;
2842 /* ignore Begin/EndProcSet, apart form making sure */
2843 /* that they are matched. */
2844 dsc->begin_procset_count++;
2845 }
2846 else if (IS_DSC(line, "%%EndProcSet")) {
2847 dsc->id = CDSC_ENDPROCSET;
2848 dsc->begin_procset_count--;
2849 }
2850 else {
2851 /* All other DSC comments are unknown, but not an error */
2852 dsc->id = CDSC_UNKNOWNDSC;
2853 dsc_unknown(dsc);
2854 }
2855
2856 dsc->endprolog = DSC_END(dsc);
2857 return CDSC_OK;
2858 }
2859
2860 dsc_private int
2861 dsc_scan_setup(CDSC *dsc)
2862 {
2863 /* Setup section ends at */
2864 /* %%EndSetup */
2865 /* another section */
2866 /* Setup section must start with %%BeginSetup */
2867
2868 char *line = dsc->line;
2869 dsc->id = CDSC_OK;
2870
2871 if (dsc->scan_section == scan_pre_setup) {
2872 if (IS_BLANK(line))
2873 return CDSC_OK; /* ignore blank lines before setup */
2874 else if (IS_DSC(line, "%%BeginSetup")) {
2875 dsc->id = CDSC_BEGINSETUP;
2876 dsc->beginsetup = DSC_START(dsc);
2877 dsc->endsetup = DSC_END(dsc);
2878 dsc->scan_section = scan_setup;
2879 return CDSC_OK;
2880 }
2881 else {
2882 dsc->scan_section = scan_pre_pages;
2883 return CDSC_PROPAGATE;
2884 }
2885 }
2886
2887 if (NOT_DSC_LINE(line)) {
2888 /* ignore */
2889 }
2890 else if (IS_DSC(line, "%%BeginPreview")) {
2891 /* ignore because we have already processed this section */
2892 }
2893 else if (IS_DSC(line, "%%BeginDefaults")) {
2894 /* ignore because we have already processed this section */
2895 }
2896 else if (IS_DSC(line, "%%BeginProlog")) {
2897 /* ignore because we have already processed this section */
2898 }
2899 else if (IS_DSC(line, "%%BeginSetup")) {
2900 /* ignore because we are in this section */
2901 }
2902 else if (dsc_is_section(line)) {
2903 dsc->endsetup = DSC_START(dsc);
2904 dsc->scan_section = scan_pre_pages;
2905 if (dsc_check_match(dsc))
2906 return CDSC_NOTDSC;
2907 return CDSC_PROPAGATE;
2908 }
2909 else if (IS_DSC(line, "%%EndSetup")) {
2910 dsc->id = CDSC_ENDSETUP;
2911 dsc->endsetup = DSC_END(dsc);
2912 dsc->scan_section = scan_pre_pages;
2913 if (dsc_check_match(dsc))
2914 return CDSC_NOTDSC;
2915 return CDSC_OK;
2916 }
2917 else if (IS_DSC(line, "%%BeginFeature:")) {
2918 dsc->id = CDSC_BEGINFEATURE;
2919 /* ignore Begin/EndFeature, apart form making sure */
2920 /* that they are matched. */
2921 dsc->begin_feature_count++;
2922 /* Look for "*PageSize name" where name is known */
2923 if (dsc_parse_feature(dsc))
2924 return CDSC_ERROR;
2925 }
2926 else if (IS_DSC(line, "%%EndFeature")) {
2927 dsc->id = CDSC_ENDFEATURE;
2928 dsc->begin_feature_count--;
2929 }
2930 else if (IS_DSC(line, "%%Feature:")) {
2931 dsc->id = CDSC_FEATURE;
2932 /* ignore */
2933 }
2934 else if (IS_DSC(line, "%%BeginResource:")) {
2935 dsc->id = CDSC_BEGINRESOURCE;
2936 /* ignore Begin/EndResource, apart form making sure */
2937 /* that they are matched. */
2938 dsc->begin_resource_count++;
2939 }
2940 else if (IS_DSC(line, "%%EndResource")) {
2941 dsc->id = CDSC_ENDRESOURCE;
2942 dsc->begin_resource_count--;
2943 }
2944 else if (IS_DSC(line, "%%PaperColor:")) {
2945 dsc->id = CDSC_PAPERCOLOR;
2946 /* ignore */
2947 }
2948 else if (IS_DSC(line, "%%PaperForm:")) {
2949 dsc->id = CDSC_PAPERFORM;
2950 /* ignore */
2951 }
2952 else if (IS_DSC(line, "%%PaperWeight:")) {
2953 dsc->id = CDSC_PAPERWEIGHT;
2954 /* ignore */
2955 }
2956 else if (IS_DSC(line, "%%PaperSize:")) {
2957 /* DSC 2.1 */
2958 GSBOOL found_media = FALSE;
2959 int i;
2960 int n = 12;
2961 char buf[MAXSTR];
2962 buf[0] = '\0';
2963 dsc->id = CDSC_PAPERSIZE;
2964 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n,
2965 NULL);
2966 for (i=0; i<(int)dsc->media_count; i++) {
2967 if (dsc->media[i] && dsc->media[i]->name &&
2968 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
2969 dsc->page_media = dsc->media[i];
2970 found_media = TRUE;
2971 break;
2972 }
2973 }
2974 if (!found_media) {
2975 /* It didn't match %%DocumentPaperSizes: */
2976 /* Try our known media */
2977 const CDSCMEDIA *m = dsc_known_media;
2978 while (m->name) {
2979 if (dsc_stricmp(buf, m->name)==0) {
2980 dsc->page_media = m;
2981 break;
2982 }
2983 m++;
2984 }
2985 if (m->name == NULL)
2986 dsc_unknown(dsc);
2987 }
2988 }
2989 else {
2990 /* All other DSC comments are unknown, but not an error */
2991 dsc->id = CDSC_UNKNOWNDSC;
2992 dsc_unknown(dsc);
2993 }
2994
2995 dsc->endsetup = DSC_END(dsc);
2996 return CDSC_OK;
2997 }
2998
2999 dsc_private int
3000 dsc_scan_page(CDSC *dsc)
3001 {
3002 /* Page section ends at */
3003 /* %%Page */
3004 /* %%Trailer */
3005 /* %%EOF */
3006 char *line = dsc->line;
3007 dsc->id = CDSC_OK;
3008
3009 if (dsc->scan_section == scan_pre_pages) {
3010 if (IS_DSC(line, "%%Page:")) {
3011 dsc->scan_section = scan_pages;
3012 /* fall through */
3013 }
3014 else {
3015 /* %%Page: didn't follow %%EndSetup
3016 * Keep reading until reach %%Page or %%Trailer
3017 * and add it to previous section.
3018 */
3019 DSC_OFFSET *last;
3020 if (dsc->endsetup != 0)
3021 last = &dsc->endsetup;
3022 else if (dsc->endprolog != 0)
3023 last = &dsc->endprolog;
3024 else if (dsc->enddefaults != 0)
3025 last = &dsc->enddefaults;
3026 else if (dsc->endpreview != 0)
3027 last = &dsc->endpreview;
3028 else if (dsc->endcomments != 0)
3029 last = &dsc->endcomments;
3030 else
3031 last = &dsc->begincomments;
3032 *last = DSC_START(dsc);
3033 if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) {
3034 dsc->scan_section = scan_pre_trailer;
3035 return CDSC_PROPAGATE;
3036 }
3037 *last = DSC_END(dsc);
3038 return CDSC_OK;
3039 }
3040 }
3041
3042 if (NOT_DSC_LINE(line)) {
3043 /* ignore */
3044 }
3045 else if (IS_DSC(line, "%%Page:")) {
3046 int code;
3047 dsc->id = CDSC_PAGE;
3048 if (dsc->page_count) {
3049 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3050 if (dsc_check_match(dsc))
3051 return CDSC_NOTDSC;
3052 }
3053
3054 if ( (code = dsc_parse_page(dsc)) != CDSC_OK)
3055 return code;
3056 if (dsc->page_count == 0)
3057 dsc->scan_section = scan_pre_pages;
3058 }
3059 else if (IS_DSC(line, "%%BeginPreview")) {
3060 /* ignore because we have already processed this section */
3061 }
3062 else if (IS_DSC(line, "%%BeginDefaults")) {
3063 /* ignore because we have already processed this section */
3064 }
3065 else if (IS_DSC(line, "%%BeginProlog")) {
3066 /* ignore because we have already processed this section */
3067 }
3068 else if (IS_DSC(line, "%%BeginSetup")) {
3069 /* ignore because we have already processed this section */
3070 }
3071 else if (dsc_is_section(line)) {
3072 if (IS_DSC(line, "%%Trailer")) {
3073 if (dsc->page_count)
3074 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3075 if (dsc->file_length) {
3076 if ((!dsc->doseps_end &&
3077 ((DSC_END(dsc) + 32768) < dsc->file_length)) ||
3078 ((dsc->doseps_end) &&
3079 ((DSC_END(dsc) + 32768) < dsc->doseps_end))) {
3080 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER,
3081 dsc->line, dsc->line_length);
3082 switch (rc) {
3083 case CDSC_RESPONSE_OK:
3084 /* ignore early trailer */
3085 break;
3086 case CDSC_RESPONSE_CANCEL:
3087 /* this is the trailer */
3088 dsc->scan_section = scan_pre_trailer;
3089 if (dsc_check_match(dsc))
3090 return CDSC_NOTDSC;
3091 return CDSC_PROPAGATE;
3092 case CDSC_RESPONSE_IGNORE_ALL:
3093 return CDSC_NOTDSC;
3094 }
3095 }
3096 else {
3097 dsc->scan_section = scan_pre_trailer;
3098 if (dsc_check_match(dsc))
3099 return CDSC_NOTDSC;
3100 return CDSC_PROPAGATE;
3101 }
3102 }
3103 else {
3104 dsc->scan_section = scan_pre_trailer;
3105 if (dsc_check_match(dsc))
3106 return CDSC_NOTDSC;
3107 return CDSC_PROPAGATE;
3108 }
3109 }
3110 else if (IS_DSC(line, "%%EOF")) {
3111 if (dsc->page_count)
3112 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3113 if (dsc->file_length) {
3114 if ((!dsc->doseps_end &&
3115 ((DSC_END(dsc) + 100) < dsc->file_length)) ||
3116 ((dsc->doseps_end) &&
3117 ((DSC_END(dsc) + 100) < dsc->doseps_end))) {
3118 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF,
3119 dsc->line, dsc->line_length);
3120 switch (rc) {
3121 case CDSC_RESPONSE_OK:
3122 /* %%EOF is wrong, ignore it */
3123 break;
3124 case CDSC_RESPONSE_CANCEL:
3125 /* %%EOF is correct */
3126 dsc->scan_section = scan_eof;
3127 dsc->eof = TRUE;
3128 if (dsc_check_match(dsc))
3129 return CDSC_NOTDSC;
3130 return CDSC_PROPAGATE;
3131 case CDSC_RESPONSE_IGNORE_ALL:
3132 return CDSC_NOTDSC;
3133 }
3134 }
3135 }
3136 else {
3137 /* ignore it */
3138 if (dsc_check_match(dsc))
3139 return CDSC_NOTDSC;
3140 return CDSC_OK;
3141 }
3142 }
3143 else {
3144 /* Section comment, probably from a badly */
3145 /* encapsulated EPS file. */
3146 int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION,
3147 dsc->line, dsc->line_length);
3148 if (rc == CDSC_RESPONSE_IGNORE_ALL)
3149 return CDSC_NOTDSC;
3150 }
3151 }
3152 else if (IS_DSC(line, "%%PageTrailer")) {
3153 dsc->id = CDSC_PAGETRAILER;
3154 /* ignore */
3155 }
3156 else if (IS_DSC(line, "%%BeginPageSetup")) {
3157 dsc->id = CDSC_BEGINPAGESETUP;
3158 /* ignore */
3159 }
3160 else if (IS_DSC(line, "%%EndPageSetup")) {
3161 dsc->id = CDSC_ENDPAGESETUP;
3162 /* ignore */
3163 }
3164 else if (IS_DSC(line, "%%PageMedia:")) {
3165 dsc->id = CDSC_PAGEMEDIA;
3166 if (dsc->page_count)
3167 dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media));
3168 }
3169 else if (IS_DSC(line, "%%PaperColor:")) {
3170 dsc->id = CDSC_PAPERCOLOR;
3171 /* ignore */
3172 }
3173 else if (IS_DSC(line, "%%PaperForm:")) {
3174 dsc->id = CDSC_PAPERFORM;
3175 /* ignore */
3176 }
3177 else if (IS_DSC(line, "%%PaperWeight:")) {
3178 dsc->id = CDSC_PAPERWEIGHT;
3179 /* ignore */
3180 }
3181 else if (IS_DSC(line, "%%PaperSize:")) {
3182 /* DSC 2.1 */
3183 GSBOOL found_media = FALSE;
3184 int i;
3185 int n = 12;
3186 char buf[MAXSTR];
3187 buf[0] = '\0';
3188 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n,
3189 dsc->line_length-n, NULL);
3190 for (i=0; i<(int)dsc->media_count; i++) {
3191 if (dsc->media[i] && dsc->media[i]->name &&
3192 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
3193 if (dsc->page_count)
3194 dsc->page[dsc->page_count-1].media = dsc->media[i];
3195 found_media = TRUE;
3196 break;
3197 }
3198 }
3199 if (!found_media) {
3200 /* It didn't match %%DocumentPaperSizes: */
3201 /* Try our known media */
3202 const CDSCMEDIA *m = dsc_known_media;
3203 while (m->name) {
3204 if (dsc_stricmp(buf, m->name)==0) {
3205 if (dsc->page_count)
3206 dsc->page[dsc->page_count-1].media = m;
3207 break;
3208 }
3209 m++;
3210 }
3211 if (m->name == NULL)
3212 dsc_unknown(dsc);
3213 }
3214 }
3215 else if (IS_DSC(line, "%%PageOrientation:")) {
3216 if (dsc->page_count) {
3217 dsc->id = CDSC_PAGEORIENTATION;
3218 if (dsc_parse_orientation(dsc,
3219 &(dsc->page[dsc->page_count-1].orientation) ,18))
3220 return CDSC_NOTDSC;
3221 }
3222 }
3223 else if (IS_DSC(line, "%%PageBoundingBox:")) {
3224 if (dsc->page_count) {
3225 dsc->id = CDSC_PAGEBOUNDINGBOX;
3226 if (dsc_parse_bounding_box(dsc,
3227 &dsc->page[dsc->page_count-1].bbox, 18))
3228 return CDSC_NOTDSC;
3229 }
3230 }
3231 else if (IS_DSC(line, "%%ViewingOrientation:")) {
3232 if (dsc->page_count) {
3233 dsc->id = CDSC_VIEWINGORIENTATION;
3234 if (dsc_parse_viewing_orientation(dsc,
3235 &dsc->page[dsc->page_count-1].viewing_orientation))
3236 return CDSC_ERROR;
3237 }
3238 }
3239 else if (IS_DSC(line, "%%PageCropBox:")) {
3240 if (dsc->page_count) {
3241 dsc->id = CDSC_PAGECROPBOX;
3242 if (dsc_parse_float_bounding_box(dsc,
3243 &(dsc->page[dsc->page_count-1].crop_box), 14))
3244 return CDSC_ERROR;
3245 }
3246 }
3247 else if (IS_DSC(line, "%%BeginFont:")) {
3248 dsc->id = CDSC_BEGINFONT;
3249 /* ignore Begin/EndFont, apart form making sure */
3250 /* that they are matched. */
3251 dsc->begin_font_count++;
3252 }
3253 else if (IS_DSC(line, "%%EndFont")) {
3254 dsc->id = CDSC_BEGINFONT;
3255 dsc->begin_font_count--;
3256 }
3257 else if (IS_DSC(line, "%%BeginFeature:")) {
3258 dsc->id = CDSC_BEGINFEATURE;
3259 /* ignore Begin/EndFeature, apart form making sure */
3260 /* that they are matched. */
3261 dsc->begin_feature_count++;
3262 }
3263 else if (IS_DSC(line, "%%EndFeature")) {
3264 dsc->id = CDSC_ENDFEATURE;
3265 dsc->begin_feature_count--;
3266 }
3267 else if (IS_DSC(line, "%%BeginResource:")) {
3268 dsc->id = CDSC_BEGINRESOURCE;
3269 /* ignore Begin/EndResource, apart form making sure */
3270 /* that they are matched. */
3271 dsc->begin_resource_count++;
3272 }
3273 else if (IS_DSC(line, "%%EndResource")) {
3274 dsc->id = CDSC_ENDRESOURCE;
3275 dsc->begin_resource_count--;
3276 }
3277 else if (IS_DSC(line, "%%BeginProcSet:")) {
3278 dsc->id = CDSC_BEGINPROCSET;
3279 /* ignore Begin/EndProcSet, apart form making sure */
3280 /* that they are matched. */
3281 dsc->begin_procset_count++;
3282 }
3283 else if (IS_DSC(line, "%%EndProcSet")) {
3284 dsc->id = CDSC_ENDPROCSET;
3285 dsc->begin_procset_count--;
3286 }
3287 else if (IS_DSC(line, "%%IncludeFont:")) {
3288 dsc->id = CDSC_INCLUDEFONT;
3289 /* ignore */
3290 }
3291 else {
3292 /* All other DSC comments are unknown, but not an error */
3293 dsc->id = CDSC_UNKNOWNDSC;
3294 dsc_unknown(dsc);
3295 }
3296
3297 if (dsc->page_count)
3298 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
3299 return CDSC_OK;
3300 }
3301
3302 /* Valid Trailer comments are
3303 * %%Trailer
3304 * %%EOF
3305 * or the following deferred with (atend)
3306 * %%BoundingBox:
3307 * %%DocumentCustomColors:
3308 * %%DocumentFiles:
3309 * %%DocumentFonts:
3310 * %%DocumentNeededFiles:
3311 * %%DocumentNeededFonts:
3312 * %%DocumentNeededProcSets:
3313 * %%DocumentNeededResources:
3314 * %%DocumentProcSets:
3315 * %%DocumentProcessColors:
3316 * %%DocumentSuppliedFiles:
3317 * %%DocumentSuppliedFonts:
3318 * %%DocumentSuppliedProcSets:
3319 * %%DocumentSuppliedResources:
3320 * %%Orientation:
3321 * %%Pages:
3322 * %%PageOrder:
3323 *
3324 * Our supported subset is
3325 * %%Trailer
3326 * %%EOF
3327 * %%BoundingBox:
3328 * %%CropBox:
3329 * %%HiResBoundingBox:
3330 * %%DocumentCustomColors:
3331 * %%DocumentProcessColors:
3332 * %%Orientation:
3333 * %%Pages:
3334 * %%PageOrder:
3335 * In addition to these, we support
3336 * %%DocumentMedia:
3337 *
3338 * A %%PageTrailer can have the following:
3339 * %%PageBoundingBox:
3340 * %%PageCustomColors:
3341 * %%PageFiles:
3342 * %%PageFonts:
3343 * %%PageOrientation:
3344 * %%PageProcessColors:
3345 * %%PageResources:
3346 */
3347
3348 dsc_private int
3349 dsc_scan_trailer(CDSC *dsc)
3350 {
3351 /* Trailer section start at */
3352 /* %%Trailer */
3353 /* and ends at */
3354 /* %%EOF */
3355 char *line = dsc->line;
3356 GSBOOL continued = FALSE;
3357 dsc->id = CDSC_OK;
3358
3359 if (dsc->scan_section == scan_pre_trailer) {
3360 if (IS_DSC(line, "%%Trailer")) {
3361 dsc->id = CDSC_TRAILER;
3362 dsc->begintrailer = DSC_START(dsc);
3363 dsc->endtrailer = DSC_END(dsc);
3364 dsc->scan_section = scan_trailer;
3365 return CDSC_OK;
3366 }
3367 else if (IS_DSC(line, "%%EOF")) {
3368 dsc->id = CDSC_EOF;
3369 dsc->begintrailer = DSC_START(dsc);
3370 dsc->endtrailer = DSC_END(dsc);
3371 dsc->scan_section = scan_trailer;
3372 /* Continue, in case we found %%EOF in an embedded document */
3373 return CDSC_OK;
3374 }
3375 else {
3376 /* %%Page: didn't follow %%EndSetup
3377 * Keep reading until reach %%Page or %%Trailer
3378 * and add it to setup section
3379 */
3380 /* append to previous section */
3381 if (dsc->beginsetup)
3382 dsc->endsetup = DSC_END(dsc);
3383 else if (dsc->beginprolog)
3384 dsc->endprolog = DSC_END(dsc);
3385 else {
3386 /* horribly confused */
3387 }
3388 return CDSC_OK;
3389 }
3390 }
3391
3392 /* Handle continuation lines.
3393 * See comment above about our restrictive processing of
3394 * continuation lines
3395 */
3396 if (IS_DSC(line, "%%+")) {
3397 line = dsc->last_line;
3398 continued = TRUE;
3399 }
3400 else
3401 dsc_save_line(dsc);
3402
3403 if (NOT_DSC_LINE(line)) {
3404 /* ignore */
3405 }
3406 else if (IS_DSC(dsc->line, "%%EOF")) {
3407 /* Keep scanning, in case we have a false trailer */
3408 dsc->id = CDSC_EOF;
3409 }
3410 else if (IS_DSC(dsc->line, "%%Trailer")) {
3411 /* Cope with no pages with code after setup and before trailer. */
3412 /* Last trailer is the correct one. */
3413 dsc->id = CDSC_TRAILER;
3414 dsc->begintrailer = DSC_START(dsc);
3415 }
3416 else if (IS_DSC(line, "%%Pages:")) {
3417 dsc->id = CDSC_PAGES;
3418 if (dsc_parse_pages(dsc) != 0)
3419 return CDSC_ERROR;
3420 }
3421 else if (IS_DSC(line, "%%BoundingBox:")) {
3422 dsc->id = CDSC_BOUNDINGBOX;
3423 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
3424 return CDSC_ERROR;
3425 }
3426 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
3427 dsc->id = CDSC_HIRESBOUNDINGBOX;
3428 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
3429 continued ? 3 : 19))
3430 return CDSC_ERROR;
3431 }
3432 else if (IS_DSC(line, "%%CropBox:")) {
3433 dsc->id = CDSC_CROPBOX;
3434 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
3435 continued ? 3 : 10))
3436 return CDSC_ERROR;
3437 }
3438 else if (IS_DSC(line, "%%Orientation:")) {
3439 dsc->id = CDSC_ORIENTATION;
3440 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14))
3441 return CDSC_ERROR;
3442 }
3443 else if (IS_DSC(line, "%%PageOrder:")) {
3444 dsc->id = CDSC_PAGEORDER;
3445 if (dsc_parse_order(dsc))
3446 return CDSC_ERROR;
3447 }
3448 else if (IS_DSC(line, "%%DocumentMedia:")) {
3449 dsc->id = CDSC_DOCUMENTMEDIA;
3450 if (dsc_parse_document_media(dsc))
3451 return CDSC_ERROR;
3452 }
3453 else if (IS_DSC(dsc->line, "%%Page:")) {
3454 /* This should not occur in the trailer, but we might see
3455 * this if a document has been incorrectly embedded.
3456 */
3457 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER,
3458 dsc->line, dsc->line_length);
3459 switch (rc) {
3460 case CDSC_RESPONSE_OK:
3461 /* Assume that we are really in the previous */
3462 /* page, not the trailer */
3463 dsc->scan_section = scan_pre_pages;
3464 if (dsc->page_count)
3465 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3466 return CDSC_PROPAGATE; /* try again */
3467 case CDSC_RESPONSE_CANCEL:
3468 /* ignore pages in trailer */
3469 break;
3470 case CDSC_RESPONSE_IGNORE_ALL:
3471 return CDSC_NOTDSC;
3472 }
3473 }
3474 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
3475 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
3476 /* ignore */
3477 }
3478 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
3479 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
3480 /* ignore */
3481 }
3482 else if (IS_DSC(line, "%%DocumentProcessColors:")) {
3483 dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
3484 if (dsc_parse_process_colours(dsc) != CDSC_OK)
3485 dsc->id = CDSC_UNKNOWNDSC;
3486 }
3487 else if (IS_DSC(line, "%%DocumentCustomColors:")) {
3488 dsc->id = CDSC_DOCUMENTCUSTOMCOLORS;
3489 if (dsc_parse_custom_colours(dsc) != CDSC_OK)
3490 dsc->id = CDSC_UNKNOWNDSC;
3491 }
3492 else {
3493 /* All other DSC comments are unknown, but not an error */
3494 dsc->id = CDSC_UNKNOWNDSC;
3495 dsc_unknown(dsc);
3496 }
3497
3498 dsc->endtrailer = DSC_END(dsc);
3499 return CDSC_OK;
3500 }
3501
3502
3503 dsc_private char *
3504 dsc_alloc_string(CDSC *dsc, const char *str, int len)
3505 {
3506 char *p;
3507 if (dsc->string_head == NULL) {
3508 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3509 if (dsc->string_head == NULL)
3510 return NULL; /* no memory */
3511 dsc->string = dsc->string_head;
3512 dsc->string->next = NULL;
3513 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3514 if (dsc->string->data == NULL) {
3515 dsc_reset(dsc);
3516 return NULL; /* no memory */
3517 }
3518 dsc->string->index = 0;
3519 dsc->string->length = CDSC_STRING_CHUNK;
3520 }
3521 if ( dsc->string->index + len + 1 > dsc->string->length) {
3522 /* allocate another string block */
3523 CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3524 if (newstring == NULL) {
3525 dsc_debug_print(dsc, "Out of memory\n");
3526 return NULL;
3527 }
3528 newstring->next = NULL;
3529 newstring->length = 0;
3530 newstring->index = 0;
3531 newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3532 if (newstring->data == NULL) {
3533 dsc_memfree(dsc, newstring);
3534 dsc_debug_print(dsc, "Out of memory\n");
3535 return NULL; /* no memory */
3536 }
3537 newstring->length = CDSC_STRING_CHUNK;
3538 dsc->string->next = newstring;
3539 dsc->string = newstring;
3540 }
3541 if ( dsc->string->index + len + 1 > dsc->string->length)
3542 return NULL; /* failed */
3543 p = dsc->string->data + dsc->string->index;
3544 memcpy(p, str, len);
3545 *(p+len) = '\0';
3546 dsc->string->index += len + 1;
3547 return p;
3548 }
3549
3550 /* store line, ignoring leading spaces */
3551 dsc_private char *
3552 dsc_add_line(CDSC *dsc, const char *line, unsigned int len)
3553 {
3554 char *newline;
3555 unsigned int i;
3556 while (len && (IS_WHITE(*line))) {
3557 len--;
3558 line++;
3559 }
3560 newline = dsc_alloc_string(dsc, line, len);
3561 if (newline == NULL)
3562 return NULL;
3563
3564 for (i=0; i<len; i++) {
3565 if (newline[i] == '\r') {
3566 newline[i]='\0';
3567 break;
3568 }
3569 if (newline[i] == '\n') {
3570 newline[i]='\0';
3571 break;
3572 }
3573 }
3574 return newline;
3575 }
3576
3577
3578 /* Copy string on line to new allocated string str */
3579 /* String is always null terminated */
3580 /* String is no longer than len */
3581 /* Return pointer to string */
3582 /* Store number of used characters from line */
3583 /* Don't copy enclosing () */
3584 dsc_private char *
3585 dsc_copy_string(char *str, unsigned int slen, char *line,
3586 unsigned int len, unsigned int *offset)
3587 {
3588 int quoted = FALSE;
3589 int instring=0;
3590 unsigned int newlength = 0;
3591 unsigned int i = 0;
3592 unsigned char ch;
3593 if (len > slen)
3594 len = slen-1;
3595 while ( (i<len) && IS_WHITE(line[i]))
3596 i++; /* skip leading spaces */
3597 if ((i < len) && (line[i]=='(')) {
3598 quoted = TRUE;
3599 instring++;
3600 i++; /* don't copy outside () */
3601 }
3602 while (i < len) {
3603 str[newlength] = ch = line[i];
3604 i++;
3605 if (quoted) {
3606 if (ch == '(')
3607 instring++;
3608 if (ch == ')')
3609 instring--;
3610 if (instring==0)
3611 break;
3612 }
3613 else if (ch == ' ')
3614 break;
3615
3616 if (ch == '\r')
3617 break;
3618 if (ch == '\n')
3619 break;
3620 else if ( (ch == '\\') && (i+1 < len) ) {
3621 ch = line[i];
3622 if ((ch >= '0') && (ch <= '9')) {
3623 /* octal coded character */
3624 int j = 3;
3625 ch = 0;
3626 while (j && (i < len) && line[i]>='0' && line[i]<='7') {
3627 ch = (unsigned char)((ch<<3) + (line[i]-'0'));
3628 i++;
3629 j--;
3630 }
3631 str[newlength] = ch;
3632 }
3633 else if (ch == '(') {
3634 str[newlength] = ch;
3635 i++;
3636 }
3637 else if (ch == ')') {
3638 str[newlength] = ch;
3639 i++;
3640 }
3641 else if (ch == 'b') {
3642 str[newlength] = '\b';
3643 i++;
3644 }
3645 else if (ch == 'f') {
3646 str[newlength] = '\b';
3647 i++;
3648 }
3649 else if (ch == 'n') {
3650 str[newlength] = '\n';
3651 i++;
3652 }
3653 else if (ch == 'r') {
3654 str[newlength] = '\r';
3655 i++;
3656 }
3657 else if (ch == 't') {
3658 str[newlength] = '\t';
3659 i++;
3660 }
3661 else if (ch == '\\') {
3662 str[newlength] = '\\';
3663 i++;
3664 }
3665 }
3666 newlength++;
3667 }
3668 str[newlength] = '\0';
3669 if (offset != (unsigned int *)NULL)
3670 *offset = i;
3671 return str;
3672 }
3673
3674 dsc_private int
3675 dsc_get_int(const char *line, unsigned int len, unsigned int *offset)
3676 {
3677 char newline[MAXSTR];
3678 int newlength = 0;
3679 unsigned int i = 0;
3680 unsigned char ch;
3681
3682 len = min(len, sizeof(newline)-1);
3683 while ((i<len) && IS_WHITE(line[i]))
3684 i++; /* skip leading spaces */
3685 while (i < len) {
3686 newline[newlength] = ch = line[i];
3687 if (!(isdigit(ch) || (ch=='-') || (ch=='+')))
3688 break; /* not part of an integer number */
3689 i++;
3690 newlength++;
3691 }
3692 while ((i<len) && IS_WHITE(line[i]))
3693 i++; /* skip trailing spaces */
3694 newline[newlength] = '\0';
3695 if (offset != (unsigned int *)NULL)
3696 *offset = i;
3697 return atoi(newline);
3698 }
3699
3700 dsc_private float
3701 dsc_get_real(const char *line, unsigned int len, unsigned int *offset)
3702 {
3703 char newline[MAXSTR];
3704 int newlength = 0;
3705 unsigned int i = 0;
3706 unsigned char ch;
3707
3708 len = min(len, sizeof(newline)-1);
3709 while ((i<len) && IS_WHITE(line[i]))
3710 i++; /* skip leading spaces */
3711 while (i < len) {
3712 newline[newlength] = ch = line[i];
3713 if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+')
3714 || (ch=='e') || (ch=='E')))
3715 break; /* not part of a real number */
3716 i++;
3717 newlength++;
3718 }
3719 while ((i<len) && IS_WHITE(line[i]))
3720 i++; /* skip trailing spaces */
3721
3722 newline[newlength] = '\0';
3723
3724 if (offset != (unsigned int *)NULL)
3725 *offset = i;
3726 return (float)atof(newline);
3727 }
3728
3729 int
3730 dsc_stricmp(const char *s, const char *t)
3731 {
3732 while (toupper(*s) == toupper(*t)) {
3733 if (*s == '\0')
3734 return 0;
3735 s++;
3736 t++;
3737 }
3738 return (toupper(*s) - toupper(*t));
3739 }
3740
3741
3742 dsc_private int
3743 dsc_parse_page(CDSC *dsc)
3744 {
3745 char *p;
3746 unsigned int i;
3747 char page_label[MAXSTR];
3748 char *pl;
3749 int page_ordinal;
3750 int page_number;
3751
3752 p = dsc->line + 7;
3753 pl = dsc_copy_string(page_label, sizeof(page_label), p, dsc->line_length-7, &i);
3754 if (pl == NULL)
3755 return CDSC_ERROR;
3756 p += i;
3757 if (dsc->line_length - 7 - i == 0) {
3758 /* Ordinal missing, or parentheses not matched in label */
3759 /* Try to find ordinal at end of line */
3760 while (i > 0) {
3761 if (!IS_WHITE_OR_EOL(p[-1]))
3762 break;
3763 p--;
3764 i--;
3765 }
3766 while (i > 0) {
3767 if (!isdigit((int)p[-1]))
3768 break;
3769 p--;
3770 i--;
3771 }
3772 }
3773 page_ordinal = dsc_get_int(p, dsc->line_length - 7 - i, NULL);
3774
3775 if ( (page_ordinal == 0) || (strlen(page_label) == 0) ||
3776 ((dsc->page_count == 0) && (page_ordinal != 1)) ||
3777 (dsc->page_count &&
3778 (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) {
3779 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line,
3780 dsc->line_length);
3781 switch (rc) {
3782 case CDSC_RESPONSE_OK:
3783 /* ignore this page */
3784 return CDSC_OK;
3785 case CDSC_RESPONSE_CANCEL:
3786 /* accept the page */
3787 break;
3788 case CDSC_RESPONSE_IGNORE_ALL:
3789 return CDSC_NOTDSC;
3790 }
3791 }
3792
3793 page_number = dsc->page_count;
3794 dsc_add_page(dsc, page_ordinal, page_label);
3795 dsc->page[page_number].begin = DSC_START(dsc);
3796 dsc->page[page_number].end = DSC_START(dsc);
3797
3798 if (dsc->page[page_number].label == NULL)
3799 return CDSC_ERROR; /* no memory */
3800
3801 return CDSC_OK;
3802 }
3803
3804
3805 dsc_private int
3806 dsc_parse_feature(CDSC *dsc)
3807 {
3808 char *p;
3809 unsigned int i;
3810 char feature_name[MAXSTR];
3811 char feature_value[MAXSTR];
3812 char *fn;
3813 char *fv;
3814
3815 feature_name[0] = '\0';
3816 feature_value[0] = '\0';
3817 p = dsc->line + 15; /* %%BeginFeature: */
3818 fn = dsc_copy_string(feature_name, sizeof(feature_name),
3819 p, dsc->line_length-15, &i);
3820 if (fn == NULL)
3821 return CDSC_ERROR;
3822 p += i;
3823 fv = dsc_copy_string(feature_value, sizeof(feature_value),
3824 p, dsc->line_length-15-i, &i);
3825
3826 if ((dsc_stricmp(feature_name, "*PageSize") == 0) &&
3827 (fv != NULL) &&
3828 (dsc->scan_section == scan_setup)) {
3829 /* If this media was not specified in the header and the name
3830 * is known to us, add it to the media list
3831 */
3832 int found = 0;
3833 int media_index = -1;
3834 for (i=0; i<dsc->media_count; i++) {
3835 if (dsc->media[i]->name &&
3836 (dsc_stricmp(feature_value, dsc->media[i]->name) == 0))
3837 found = 1; /* don't add it again */
3838 }
3839 for (i=0; dsc_known_media[i].name; i++) {
3840 if (dsc_stricmp(feature_value, dsc_known_media[i].name)==0) {
3841 media_index = i; /* we know this paper size */
3842 break;
3843 }
3844 }
3845
3846 if (!found && (media_index >= 0)) {
3847 /* This media type was not included in the header where
3848 * it should have been. Add it to the media list now.
3849 */
3850 CDSCMEDIA lmedia;
3851 lmedia.name = feature_value;
3852 lmedia.width = dsc_known_media[i].width;
3853 lmedia.height = dsc_known_media[i].height;
3854 lmedia.weight = 80.0;
3855 lmedia.colour = NULL;
3856 lmedia.type = NULL;
3857 lmedia.mediabox = NULL;
3858 if (dsc_add_media(dsc, &lmedia))
3859 return CDSC_ERROR; /* out of memory */
3860 }
3861 }
3862
3863 return CDSC_OK;
3864 }
3865
3866
3867 /* DSC error reporting */
3868
3869 void
3870 dsc_debug_print(CDSC *dsc, const char *str)
3871 {
3872 if (dsc->debug_print_fn)
3873 dsc->debug_print_fn(dsc->caller_data, str);
3874 }
3875
3876
3877 /* Display a message about a problem with the DSC comments.
3878 *
3879 * explanation = an index to to a multiline explanation in dsc_message[]
3880 * line = pointer to the offending DSC line (if any)
3881 * return code =
3882 * CDSC_RESPONSE_OK DSC was wrong, make a guess about what
3883 * was really meant.
3884 * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it
3885 * is misplaced.
3886 * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC.
3887 */
3888 /* Silent operation. Don't display errors. */
3889 dsc_private int
3890 dsc_error(CDSC *dsc, unsigned int explanation,
3891 char *line, unsigned int line_len)
3892 {
3893 if (explanation > DSC_MAX_ERROR)
3894 return CDSC_RESPONSE_CANCEL;
3895 if ((int)dsc->worst_error < (int)dsc_severity[explanation])
3896 dsc->worst_error = dsc_severity[explanation];
3897 /* if error function provided, use it */
3898 if (dsc->dsc_error_fn)
3899 return dsc->dsc_error_fn(dsc->caller_data, dsc,
3900 explanation, line, line_len);
3901
3902 /* treat DSC as being correct */
3903 return CDSC_RESPONSE_CANCEL;
3904 }
3905
3906
3907 /* Fixup if DCS 2.0 was used */
3908 dsc_private int
3909 dsc_dcs2_fixup(CDSC *dsc)
3910 {
3911 char composite[] = "Composite";
3912 /* If DCS 2.0 single file format found, expose the separations
3913 * as multiple pages. Treat the initial EPS file as a single
3914 * page without comments, prolog or trailer.
3915 */
3916 if (dsc->dcs2) {
3917 int code = CDSC_OK;
3918 int page_number;
3919 DSC_OFFSET *pbegin;
3920 DSC_OFFSET *pend;
3921 DSC_OFFSET end;
3922 CDCS2 *pdcs = dsc->dcs2;
3923 /* Now treat the initial EPS file as a single page without
3924 * headers or trailer, so page extraction will fetch the
3925 * the correct separation. */
3926 if (dsc->page_count == 0)
3927 code = dsc_add_page(dsc, 1, composite);
3928 else if (dsc->page_count == 1)
3929 dsc->page[0].label =
3930 dsc_alloc_string(dsc, composite, (int)strlen(composite)+1);
3931 if (code != CDSC_OK)
3932 return code;
3933 page_number = dsc->page_count - 1;
3934 pbegin = &dsc->page[page_number].begin;
3935 pend = &dsc->page[page_number].end;
3936 if (*pbegin == *pend) {
3937 /* no page, so force it to conform to the following sections */
3938 *pbegin = 999999999;
3939 *pend = 0;
3940 }
3941
3942 if (dsc->begincomments != dsc->endcomments) {
3943 *pbegin = min(dsc->begincomments, *pbegin);
3944 dsc->begincomments = 0;
3945 *pend = max(dsc->endcomments, *pend);
3946 dsc->endcomments = 0;
3947 }
3948
3949 if (dsc->beginpreview != dsc->endpreview) {
3950 *pbegin = min(dsc->beginpreview, *pbegin);
3951 dsc->beginpreview = 0;
3952 *pend = max(dsc->endpreview, *pend);
3953 dsc->endpreview = 0;
3954 }
3955
3956 if (dsc->begindefaults != dsc->enddefaults) {
3957 *pbegin = min(dsc->begindefaults, *pbegin);
3958 dsc->begindefaults = 0;
3959 *pend = max(dsc->enddefaults, *pend);
3960 dsc->enddefaults = 0;
3961 }
3962
3963 if (dsc->beginprolog != dsc->endprolog) {
3964 *pbegin = min(dsc->beginprolog, *pbegin);
3965 dsc->beginprolog = 0;
3966 *pend = max(dsc->endprolog, *pend);
3967 dsc->endprolog = 0;
3968 }
3969
3970 if (dsc->beginsetup != dsc->endsetup) {
3971 *pbegin = min(dsc->beginsetup, *pbegin);
3972 dsc->beginsetup = 0;
3973 *pend = max(dsc->endsetup, *pend);
3974 dsc->endsetup = 0;
3975 }
3976
3977 if (dsc->begintrailer != dsc->endtrailer) {
3978 *pbegin = min(dsc->begintrailer, *pbegin);
3979 dsc->begintrailer = 0;
3980 *pend = max(dsc->endtrailer, *pend);
3981 dsc->endtrailer = 0;
3982 }
3983
3984 if (*pbegin == 999999999)
3985 *pbegin = *pend;
3986 end = 0; /* end of composite is start of first separation */
3987
3988 while (pdcs) {
3989 page_number = dsc->page_count;
3990 if ((pdcs->begin) && (pdcs->colourname != NULL)) {
3991 /* Single file DCS 2.0 */
3992 code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
3993 if (code)
3994 return code;
3995 dsc->page[page_number].begin = pdcs->begin;
3996 dsc->page[page_number].end = pdcs->end;
3997 if (end != 0)
3998 end = min(end, pdcs->begin);
3999 else
4000 end = pdcs->begin; /* first separation */
4001 }
4002 else {
4003 /* Multiple file DCS 2.0 */
4004 if ((pdcs->location != NULL) &&
4005 (pdcs->filetype != NULL) &&
4006 (pdcs->colourname != NULL) &&
4007 (dsc_stricmp(pdcs->location, "Local") == 0) &&
4008 ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
4009 (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
4010 code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
4011 if (code)
4012 return code;
4013 dsc->page[page_number].begin = 0;
4014 dsc->page[page_number].end = 0;
4015 }
4016 }
4017 pdcs = pdcs->next;
4018 }
4019 /* end of composite is start of first separation */
4020 if (end != 0)
4021 *pend = end;
4022 /* According to the DCS2 specification, the size of the composite
4023 * section can be determined by the smallest #offset.
4024 * Some incorrect DCS2 files don't put the separations inside
4025 * the DOS EPS PostScript section, and have a TIFF separation
4026 * between the composite and the first separation. This
4027 * contravenes the DCS2 specification. If we see one of these
4028 * files, bring the end of the composite back to the end of
4029 * the DOS EPS PostScript section.
4030 */
4031 if (dsc->doseps_end && (*pend > dsc->doseps_end))
4032 *pend = dsc->doseps_end;
4033 }
4034 return 0;
4035 }
4036
4037
4038 dsc_private int
4039 dsc_parse_platefile(CDSC *dsc)
4040 {
4041 unsigned int i, n;
4042 CDCS2 dcs2;
4043 CDCS2 *pdcs2;
4044 char colourname[MAXSTR];
4045 char filetype[MAXSTR];
4046 char location[MAXSTR];
4047 char *filename = NULL;
4048 int filename_length = 0;
4049 GSBOOL blank_line;
4050 GSBOOL single = FALSE;
4051 if (IS_DSC(dsc->line, "%%PlateFile:"))
4052 n = 12;
4053 else if (IS_DSC(dsc->line, "%%+"))
4054 n = 3;
4055 else
4056 return CDSC_ERROR; /* error */
4057
4058 memset(&dcs2, 0, sizeof(dcs2));
4059 memset(&colourname, 0, sizeof(colourname));
4060 memset(&filetype, 0, sizeof(filetype));
4061 memset(&location, 0, sizeof(location));
4062 memset(&filename, 0, sizeof(filename));
4063
4064 /* check for blank remainder of line */
4065 blank_line = TRUE;
4066 for (i=n; i<dsc->line_length; i++) {
4067 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4068 blank_line = FALSE;
4069 break;
4070 }
4071 }
4072
4073 if (!blank_line) {
4074 dsc_copy_string(colourname, sizeof(colourname),
4075 dsc->line+n, dsc->line_length-n, &i);
4076 n+=i;
4077 if (i)
4078 dsc_copy_string(filetype, sizeof(filetype),
4079 dsc->line+n, dsc->line_length-n, &i);
4080 n+=i;
4081 while (IS_WHITE_OR_EOL(dsc->line[n]))
4082 n++;
4083 if (dsc->line[n] == '#') {
4084 /* single file DCS 2.0 */
4085 single = TRUE;
4086 n++;
4087 if (i)
4088 dcs2.begin= dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
4089 n+=i;
4090 if (i)
4091 dcs2.end= dcs2.begin +
4092 dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
4093 }
4094 else {
4095 /* multiple file DCS 2.0 */
4096 if (i)
4097 dsc_copy_string(location, sizeof(location),
4098 dsc->line+n, dsc->line_length-n, &i);
4099 n+=i;
4100 if (i) {
4101 filename = dsc->line+n;
4102 filename_length = dsc->line_length-n;
4103 if (filename[0] == '(') {
4104 /* Filename in parentheses like a PS string */
4105 int j;
4106 for (j=0; j<filename_length; j++)
4107 if (filename[j] == ')')
4108 break;
4109 if (j < filename_length) {
4110 filename++;
4111 filename_length = j-1;
4112 }
4113 }
4114 }
4115 }
4116 if (i==0)
4117 dsc_unknown(dsc); /* we didn't get all fields */
4118 else {
4119 /* Allocate strings */
4120 if (strlen(colourname))
4121 dcs2.colourname = dsc_alloc_string(dsc,
4122 colourname, (int)strlen(colourname));
4123 if (strlen(filetype))
4124 dcs2.filetype = dsc_alloc_string(dsc,
4125 filetype, (int)strlen(filetype));
4126 if (strlen(location))
4127 dcs2.location = dsc_alloc_string(dsc,
4128 location, (int)strlen(location));
4129 if (filename)
4130 dcs2.filename = dsc_add_line(dsc, filename, filename_length);
4131
4132 /* Prevent parser from reading separations */
4133 if (single)
4134 dsc->file_length = min(dsc->file_length, dcs2.begin);
4135 /* Allocate it */
4136 pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4137 if (pdcs2 == NULL)
4138 return CDSC_ERROR; /* out of memory */
4139 memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4140 /* Then add to list of separations */
4141 if (dsc->dcs2 == NULL)
4142 dsc->dcs2 = pdcs2;
4143 else {
4144 CDCS2 *this_dcs2 = dsc->dcs2;
4145 while (this_dcs2->next)
4146 this_dcs2 = this_dcs2->next;
4147 this_dcs2->next = pdcs2;
4148 }
4149 }
4150 }
4151 return CDSC_OK;
4152 }
4153
4154 /* Parse a DCS 1.0 plate comment, storing like a multi file DSC 2.0 */
4155 dsc_private int
4156 dsc_parse_dcs1plate(CDSC *dsc)
4157 {
4158 unsigned int i, n = 0;
4159 CDCS2 dcs2;
4160 CDCS2 *pdcs2;
4161 const char *colourname;
4162 char *filename = NULL;
4163 int filename_length = 0;
4164 GSBOOL blank_line;
4165 GSBOOL continued = FALSE;
4166 char *line = dsc->line;
4167
4168 memset(&dcs2, 0, sizeof(dcs2));
4169 memset(&filename, 0, sizeof(filename));
4170
4171 if (IS_DSC(line, "%%+")) {
4172 n = 3;
4173 line = dsc->last_line;
4174 continued = TRUE;
4175 }
4176
4177 if (IS_DSC(line, "%%CyanPlate:")) {
4178 colourname = "Cyan";
4179 if (!continued)
4180 n = 12;
4181 }
4182 else if (IS_DSC(line, "%%MagentaPlate:")) {
4183 colourname = "Magenta";
4184 if (!continued)
4185 n = 15;
4186 }
4187 else if (IS_DSC(line, "%%YellowPlate:")) {
4188 colourname = "Yellow";
4189 if (!continued)
4190 n = 14;
4191 }
4192 else if (IS_DSC(line, "%%BlackPlate:")) {
4193 colourname = "Black";
4194 if (!continued)
4195 n = 13;
4196 }
4197 else
4198 return CDSC_ERROR; /* error */
4199
4200 /* check for blank remainder of line */
4201 blank_line = TRUE;
4202 for (i=n; i<dsc->line_length; i++) {
4203 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4204 blank_line = FALSE;
4205 break;
4206 }
4207 }
4208
4209 if (!blank_line) {
4210 filename = dsc->line+n;
4211 filename_length = dsc->line_length - n;
4212 if ((filename_length==0) || (strlen(filename) == 0))
4213 dsc_unknown(dsc); /* we didn't get all fields */
4214 else {
4215 /* Allocate strings */
4216 dcs2.colourname = dsc_alloc_string(dsc,
4217 colourname, (int)strlen(colourname));
4218 dcs2.filetype = dsc_alloc_string(dsc, "EPS", 3);
4219 dcs2.location = dsc_alloc_string(dsc, "Local", 5);
4220 dcs2.filename = dsc_add_line(dsc, filename, filename_length);
4221
4222 /* Allocate it */
4223 pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4224 if (pdcs2 == NULL)
4225 return CDSC_ERROR; /* out of memory */
4226 memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4227 /* Then add to list of separations */
4228 if (dsc->dcs2 == NULL)
4229 dsc->dcs2 = pdcs2;
4230 else {
4231 CDCS2 *this_dcs2 = dsc->dcs2;
4232 while (this_dcs2->next)
4233 this_dcs2 = this_dcs2->next;
4234 this_dcs2->next = pdcs2;
4235 }
4236 /* We've set the DCS 2.0 data, but it really is DCS 1.0 */
4237 dsc->dcs1 = TRUE;
4238 }
4239 }
4240 return CDSC_OK;
4241 }
4242
4243
4244 /* Find the filename which corresponds to this separation.
4245 * Used with multiple file DCS 2.0.
4246 * Returns NULL if there is no filename, or not DCS 2.0,
4247 * or single file DCS 2.0.
4248 * Caller will need to obtain the filesize from the file.
4249 */
4250 const char *
4251 dsc_find_platefile(CDSC *dsc, int page)
4252 {
4253 CDCS2 *pdcs = dsc->dcs2;
4254 int i = 1;
4255 while (pdcs) {
4256 if (pdcs->begin != pdcs->end)
4257 return NULL; /* Single file DCS 2.0 */
4258 if (pdcs->location && pdcs->filetype && pdcs->colourname
4259 && (dsc_stricmp(pdcs->location, "Local") == 0)
4260 && ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
4261 (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
4262 if (i == page)
4263 return pdcs->filename;
4264 i++;
4265 }
4266 pdcs = pdcs->next;
4267 }
4268 return NULL;
4269 }
4270
4271
4272 dsc_private CDSCCOLOUR *
4273 dsc_find_colour(CDSC *dsc, const char *colourname)
4274 {
4275 CDSCCOLOUR *colour = dsc->colours;
4276 while (colour) {
4277 if (colour->name && (dsc_stricmp(colour->name, colourname)==0))
4278 return colour;
4279 colour = colour->next;
4280 }
4281 return 0;
4282 }
4283
4284 dsc_private int
4285 dsc_parse_process_colours(CDSC *dsc)
4286 {
4287 unsigned int i, n;
4288 CDSCCOLOUR *pcolour;
4289 char colourname[MAXSTR];
4290 GSBOOL blank_line;
4291 if (IS_DSC(dsc->line, "%%DocumentProcessColors:"))
4292 n = 24;
4293 else if (IS_DSC(dsc->line, "%%+"))
4294 n = 3;
4295 else
4296 return CDSC_ERROR; /* error */
4297
4298 memset(&colourname, 0, sizeof(colourname));
4299
4300 /* check for blank remainder of line */
4301 blank_line = TRUE;
4302 for (i=n; i<dsc->line_length; i++) {
4303 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4304 blank_line = FALSE;
4305 break;
4306 }
4307 }
4308 while (IS_WHITE(dsc->line[n]))
4309 n++;
4310 if (COMPARE(dsc->line+n, "(atend)")) {
4311 if (dsc->scan_section == scan_comments)
4312 blank_line = TRUE;
4313 else {
4314 dsc_unknown(dsc);
4315 return CDSC_NOTDSC;
4316 }
4317 }
4318
4319 if (!blank_line) {
4320 do {
4321 dsc_copy_string(colourname, sizeof(colourname),
4322 dsc->line+n, dsc->line_length-n, &i);
4323 n+=i;
4324 if (i && strlen(colourname)) {
4325 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4326 pcolour = (CDSCCOLOUR *)
4327 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4328 if (pcolour == NULL)
4329 return CDSC_ERROR; /* out of memory */
4330 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4331 pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4332 pcolour->name = dsc_alloc_string(dsc,
4333 colourname, (int)strlen(colourname));
4334 if (dsc->colours == NULL)
4335 dsc->colours = pcolour;
4336 else {
4337 CDSCCOLOUR *this_colour = dsc->colours;
4338 while (this_colour->next)
4339 this_colour = this_colour->next;
4340 this_colour->next = pcolour;
4341 }
4342 }
4343 pcolour->type = CDSC_COLOUR_PROCESS;
4344 if (dsc_stricmp(colourname, "Cyan")==0) {
4345 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4346 pcolour->cyan = 1.0;
4347 pcolour->magenta = pcolour->yellow = pcolour->black = 0.0;
4348 }
4349 else if (dsc_stricmp(colourname, "Magenta")==0) {
4350 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4351 pcolour->magenta = 1.0;
4352 pcolour->cyan = pcolour->yellow = pcolour->black = 0.0;
4353 }
4354 else if (dsc_stricmp(colourname, "Yellow")==0) {
4355 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4356 pcolour->yellow = 1.0;
4357 pcolour->cyan = pcolour->magenta = pcolour->black = 0.0;
4358 }
4359 else if (dsc_stricmp(colourname, "Black")==0) {
4360 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4361 pcolour->black = 1.0;
4362 pcolour->cyan = pcolour->magenta = pcolour->yellow = 0.0;
4363 }
4364 else if (dsc_stricmp(colourname, "Red")==0) {
4365 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4366 pcolour->red = 1.0;
4367 pcolour->green = pcolour->blue = 0.0;
4368 }
4369 else if (dsc_stricmp(colourname, "Green")==0) {
4370 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4371 pcolour->green = 1.0;
4372 pcolour->red = pcolour->blue = 0.0;
4373 }
4374 else if (dsc_stricmp(colourname, "Blue")==0) {
4375 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4376 pcolour->blue = 1.0;
4377 pcolour->red = pcolour->green = 0.0;
4378 }
4379 }
4380 } while (i != 0);
4381 }
4382 return CDSC_OK;
4383 }
4384
4385 dsc_private int
4386 dsc_parse_custom_colours(CDSC *dsc)
4387 {
4388 unsigned int i, n;
4389 CDSCCOLOUR *pcolour;
4390 char colourname[MAXSTR];
4391 GSBOOL blank_line;
4392 if (IS_DSC(dsc->line, "%%DocumentCustomColors:"))
4393 n = 23;
4394 else if (IS_DSC(dsc->line, "%%+"))
4395 n = 3;
4396 else
4397 return CDSC_ERROR; /* error */
4398
4399 memset(&colourname, 0, sizeof(colourname));
4400
4401 /* check for blank remainder of line */
4402 blank_line = TRUE;
4403 for (i=n; i<dsc->line_length; i++) {
4404 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4405 blank_line = FALSE;
4406 break;
4407 }
4408 }
4409 while (IS_WHITE(dsc->line[n]))
4410 n++;
4411 if (COMPARE(dsc->line+n, "(atend)")) {
4412 if (dsc->scan_section == scan_comments)
4413 blank_line = TRUE;
4414 else {
4415 dsc_unknown(dsc);
4416 return CDSC_NOTDSC;
4417 }
4418 }
4419
4420 if (!blank_line) {
4421 do {
4422 dsc_copy_string(colourname, sizeof(colourname),
4423 dsc->line+n, dsc->line_length-n, &i);
4424 n+=i;
4425 if (i && strlen(colourname)) {
4426 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4427 pcolour = (CDSCCOLOUR *)
4428 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4429 if (pcolour == NULL)
4430 return CDSC_ERROR; /* out of memory */
4431 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4432 pcolour->name = dsc_alloc_string(dsc,
4433 colourname, (int)strlen(colourname));
4434 pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4435 if (dsc->colours == NULL)
4436 dsc->colours = pcolour;
4437 else {
4438 CDSCCOLOUR *this_colour = dsc->colours;
4439 while (this_colour->next)
4440 this_colour = this_colour->next;
4441 this_colour->next = pcolour;
4442 }
4443 }
4444 pcolour->type = CDSC_COLOUR_CUSTOM;
4445 }
4446 } while (i != 0);
4447 }
4448 return CDSC_OK;
4449 }
4450
4451
4452 dsc_private int
4453 dsc_parse_cmyk_custom_colour(CDSC *dsc)
4454 {
4455 unsigned int i, n;
4456 CDSCCOLOUR *pcolour;
4457 char colourname[MAXSTR];
4458 float cyan, magenta, yellow, black;
4459 GSBOOL blank_line;
4460 if (IS_DSC(dsc->line, "%%CMYKCustomColor:"))
4461 n = 18;
4462 else if (IS_DSC(dsc->line, "%%+"))
4463 n = 3;
4464 else
4465 return CDSC_ERROR; /* error */
4466
4467 memset(&colourname, 0, sizeof(colourname));
4468
4469 /* check for blank remainder of line */
4470
4471 do {
4472 blank_line = TRUE;
4473 for (i=n; i<dsc->line_length; i++) {
4474 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4475 blank_line = FALSE;
4476 break;
4477 }
4478 }
4479 if (blank_line)
4480 break;
4481 else {
4482 cyan = magenta = yellow = black = 0.0;
4483 cyan = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4484 n += i;
4485 if (i)
4486 magenta = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4487 n += i;
4488 if (i)
4489 yellow = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4490 n += i;
4491 if (i)
4492 black = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4493 n += i;
4494 if (i)
4495 dsc_copy_string(colourname, sizeof(colourname),
4496 dsc->line+n, dsc->line_length-n, &i);
4497 n+=i;
4498 if (i && strlen(colourname)) {
4499 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4500 pcolour = (CDSCCOLOUR *)
4501 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4502 if (pcolour == NULL)
4503 return CDSC_ERROR; /* out of memory */
4504 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4505 pcolour->name = dsc_alloc_string(dsc,
4506 colourname, (int)strlen(colourname));
4507 pcolour->type = CDSC_COLOUR_UNKNOWN;
4508 if (dsc->colours == NULL)
4509 dsc->colours = pcolour;
4510 else {
4511 CDSCCOLOUR *this_colour = dsc->colours;
4512 while (this_colour->next)
4513 this_colour = this_colour->next;
4514 this_colour->next = pcolour;
4515 }
4516 }
4517 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4518 pcolour->cyan = cyan;
4519 pcolour->magenta = magenta;
4520 pcolour->yellow = yellow;
4521 pcolour->black = black;
4522 }
4523 }
4524 } while (i != 0);
4525 return CDSC_OK;
4526 }
4527
4528 dsc_private int
4529 dsc_parse_rgb_custom_colour(CDSC *dsc)
4530 {
4531 unsigned int i, n;
4532 CDSCCOLOUR *pcolour;
4533 char colourname[MAXSTR];
4534 float red, green, blue;
4535 GSBOOL blank_line;
4536 if (IS_DSC(dsc->line, "%%RGBCustomColor:"))
4537 n = 17;
4538 else if (IS_DSC(dsc->line, "%%+"))
4539 n = 3;
4540 else
4541 return CDSC_ERROR; /* error */
4542
4543 memset(&colourname, 0, sizeof(colourname));
4544
4545 /* check for blank remainder of line */
4546
4547 do {
4548 blank_line = TRUE;
4549 for (i=n; i<dsc->line_length; i++) {
4550 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4551 blank_line = FALSE;
4552 break;
4553 }
4554 }
4555 if (blank_line)
4556 break;
4557 else {
4558 red = green = blue = 0.0;
4559 red = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4560 n += i;
4561 if (i)
4562 green = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4563 n += i;
4564 if (i)
4565 blue = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4566 n += i;
4567 if (i)
4568 dsc_copy_string(colourname, sizeof(colourname),
4569 dsc->line+n, dsc->line_length-n, &i);
4570 n+=i;
4571 if (i && strlen(colourname)) {
4572 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4573 pcolour = (CDSCCOLOUR *)
4574 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4575 if (pcolour == NULL)
4576 return CDSC_ERROR; /* out of memory */
4577 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4578 pcolour->name = dsc_alloc_string(dsc,
4579 colourname, (int)strlen(colourname));
4580 pcolour->type = CDSC_COLOUR_UNKNOWN;
4581 if (dsc->colours == NULL)
4582 dsc->colours = pcolour;
4583 else {
4584 CDSCCOLOUR *this_colour = dsc->colours;
4585 while (this_colour->next)
4586 this_colour = this_colour->next;
4587 this_colour->next = pcolour;
4588 }
4589 }
4590 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4591 pcolour->red = red;
4592 pcolour->green = green;
4593 pcolour->blue = blue;
4594 }
4595 }
4596 } while (i != 0);
4597 return CDSC_OK;
4598 }