Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/gs/src/dscparse.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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