PageRenderTime 74ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/sys/src/cmd/gs/src/dscparse.c

https://bitbucket.org/rminnich/sysfromiso
C | 4492 lines | 3658 code | 306 blank | 528 comment | 1327 complexity | d6530e093d91893fb8be1ff6b7da5bd2 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-3.0, MPL-2.0-no-copyleft-exception, Unlicense

Large files files are truncated, but you can click here to view the full file

  1. /* Copyright (C) 2000-2003, Ghostgum Software Pty Ltd. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: dscparse.c,v 1.14 2003/09/13 02:04:15 ghostgum Exp $ */
  14. /*
  15. * This is a DSC parser, based on the DSC 3.0 spec,
  16. * with a few DSC 2.1 additions for page size.
  17. *
  18. * Current limitations:
  19. * %%+ may be used after any comment in the comment or trailer,
  20. * but is currently only supported by
  21. * %%DocumentMedia
  22. *
  23. * DSC 2.1 additions (discontinued in DSC 3.0):
  24. * %%DocumentPaperColors:
  25. * %%DocumentPaperForms:
  26. * %%DocumentPaperSizes:
  27. * %%DocumentPaperWeights:
  28. * %%PaperColor: (ignored)
  29. * %%PaperForm: (ignored)
  30. * %%PaperSize:
  31. * %%PaperWeight: (ignored)
  32. *
  33. * Other additions for defaults or page section
  34. % %%ViewingOrientation: xx xy yx yy
  35. */
  36. #include <stdio.h> /* for sprintf(), not file I/O */
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40. #define MAXSTR 256
  41. #include "dscparse.h"
  42. /* Macros for comparing string literals
  43. * For maximum speed, the length of the second macro argument is
  44. * computed at compile time.
  45. * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL.
  46. */
  47. #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
  48. #define IS_DSC(line, str) (COMPARE((line), (str)))
  49. /* Macros for comparing the first one or two characters */
  50. #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
  51. #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
  52. #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
  53. #define IS_BLANK(str) (IS_EOL(str[0]))
  54. #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
  55. /* Macros for document offset to start and end of line */
  56. #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
  57. #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)
  58. /* dsc_scan_SECTION() functions return one of
  59. * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
  60. * or one of the following
  61. */
  62. /* The line should be passed on to the next section parser. */
  63. #define CDSC_PROPAGATE 10
  64. /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
  65. #define CDSC_NEEDMORE 11
  66. /* local prototypes */
  67. dsc_private void * dsc_memalloc(CDSC *dsc, size_t size);
  68. dsc_private void dsc_memfree(CDSC*dsc, void *ptr);
  69. dsc_private CDSC * dsc_init2(CDSC *dsc);
  70. dsc_private void dsc_reset(CDSC *dsc);
  71. dsc_private void dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast);
  72. dsc_private int dsc_read_line(CDSC *dsc);
  73. dsc_private int dsc_read_doseps(CDSC *dsc);
  74. dsc_private int dsc_read_macbin(CDSC *dsc);
  75. dsc_private int dsc_read_applesingle(CDSC *dsc);
  76. dsc_private char * dsc_alloc_string(CDSC *dsc, const char *str, int len);
  77. dsc_private char * dsc_add_line(CDSC *dsc, const char *line, unsigned int len);
  78. dsc_private char * dsc_copy_string(char *str, unsigned int slen,
  79. char *line, unsigned int len, unsigned int *offset);
  80. dsc_private GSDWORD dsc_get_dword(const unsigned char *buf);
  81. dsc_private GSWORD dsc_get_word(const unsigned char *buf);
  82. dsc_private GSDWORD dsc_get_bigendian_dword(const unsigned char *buf);
  83. dsc_private GSWORD dsc_get_bigendian_word(const unsigned char *buf);
  84. dsc_private int dsc_get_int(const char *line, unsigned int len, unsigned int *offset);
  85. dsc_private float dsc_get_real(const char *line, unsigned int len,
  86. unsigned int *offset);
  87. dsc_private void dsc_unknown(CDSC *dsc);
  88. dsc_private GSBOOL dsc_is_section(char *line);
  89. dsc_private int dsc_parse_pages(CDSC *dsc);
  90. dsc_private int dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset);
  91. dsc_private int dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pfbbox, int offset);
  92. dsc_private int dsc_parse_orientation(CDSC *dsc, unsigned int *porientation,
  93. int offset);
  94. dsc_private int dsc_parse_order(CDSC *dsc);
  95. dsc_private int dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media);
  96. dsc_private int dsc_parse_document_media(CDSC *dsc);
  97. dsc_private int dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm);
  98. dsc_private int dsc_parse_page(CDSC *dsc);
  99. dsc_private void dsc_save_line(CDSC *dsc);
  100. dsc_private int dsc_scan_type(CDSC *dsc);
  101. dsc_private int dsc_scan_comments(CDSC *dsc);
  102. dsc_private int dsc_scan_preview(CDSC *dsc);
  103. dsc_private int dsc_scan_defaults(CDSC *dsc);
  104. dsc_private int dsc_scan_prolog(CDSC *dsc);
  105. dsc_private int dsc_scan_setup(CDSC *dsc);
  106. dsc_private int dsc_scan_page(CDSC *dsc);
  107. dsc_private int dsc_scan_trailer(CDSC *dsc);
  108. dsc_private int dsc_error(CDSC *dsc, unsigned int explanation,
  109. char *line, unsigned int line_len);
  110. dsc_private int dsc_dcs2_fixup(CDSC *dsc);
  111. dsc_private int dsc_parse_platefile(CDSC *dsc);
  112. dsc_private int dsc_parse_dcs1plate(CDSC *dsc);
  113. dsc_private CDSCCOLOUR * dsc_find_colour(CDSC *dsc, const char *colourname);
  114. dsc_private int dsc_parse_process_colours(CDSC *dsc);
  115. dsc_private int dsc_parse_custom_colours(CDSC *dsc);
  116. dsc_private int dsc_parse_cmyk_custom_colour(CDSC *dsc);
  117. dsc_private int dsc_parse_rgb_custom_colour(CDSC *dsc);
  118. /* DSC error reporting */
  119. dsc_private const int dsc_severity[] = {
  120. CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */
  121. CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */
  122. CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */
  123. CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */
  124. CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */
  125. CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */
  126. CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */
  127. CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */
  128. CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */
  129. CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */
  130. CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */
  131. CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */
  132. CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */
  133. CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */
  134. CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */
  135. CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */
  136. 0
  137. };
  138. #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
  139. const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = {
  140. /* These sizes taken from Ghostscript gs_statd.ps */
  141. {"11x17", 792, 1224, 0, NULL, NULL},
  142. {"A3", 842, 1190, 0, NULL, NULL},
  143. {"A4", 595, 842, 0, NULL, NULL},
  144. {"A5", 421, 595, 0, NULL, NULL},
  145. {"B4", 709, 1002, 0, NULL, NULL}, /* ISO, but not Adobe standard */
  146. {"B5", 501, 709, 0, NULL, NULL}, /* ISO, but not Adobe standard */
  147. {"Ledger", 1224, 792, 0, NULL, NULL},
  148. {"Legal", 612, 1008, 0, NULL, NULL},
  149. {"Letter", 612, 792, 0, NULL, NULL},
  150. {"Note", 612, 792, 0, NULL, NULL},
  151. {NULL, 0, 0, 0, NULL, NULL}
  152. };
  153. /* parser state */
  154. enum CDSC_SCAN_SECTION {
  155. scan_none = 0,
  156. scan_comments = 1,
  157. scan_pre_preview = 2,
  158. scan_preview = 3,
  159. scan_pre_defaults = 4,
  160. scan_defaults = 5,
  161. scan_pre_prolog = 6,
  162. scan_prolog = 7,
  163. scan_pre_setup = 8,
  164. scan_setup = 9,
  165. scan_pre_pages = 10,
  166. scan_pages = 11,
  167. scan_pre_trailer = 12,
  168. scan_trailer = 13,
  169. scan_eof = 14
  170. };
  171. static const char * const dsc_scan_section_name[15] = {
  172. "Type", "Comments",
  173. "pre-Preview", "Preview",
  174. "pre-Defaults", "Defaults",
  175. "pre-Prolog", "Prolog",
  176. "pre-Setup", "Setup",
  177. "pre-Page", "Page",
  178. "pre-Trailer", "Trailer",
  179. "EOF"
  180. };
  181. /******************************************************************/
  182. /* Public functions */
  183. /******************************************************************/
  184. /* constructor */
  185. CDSC *
  186. dsc_init(void *caller_data)
  187. {
  188. CDSC *dsc = (CDSC *)malloc(sizeof(CDSC));
  189. if (dsc == NULL)
  190. return NULL;
  191. memset(dsc, 0, sizeof(CDSC));
  192. dsc->caller_data = caller_data;
  193. dsc->ref_count = 0;
  194. dsc_ref(dsc);
  195. return dsc_init2(dsc);
  196. }
  197. /* constructor, with caller supplied memalloc */
  198. CDSC *
  199. dsc_init_with_alloc(
  200. void *caller_data,
  201. void *(*memalloc)(size_t size, void *closure_data),
  202. void (*memfree)(void *ptr, void *closure_data),
  203. void *closure_data)
  204. {
  205. CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data);
  206. if (dsc == NULL)
  207. return NULL;
  208. memset(dsc, 0, sizeof(CDSC));
  209. dsc->caller_data = caller_data;
  210. dsc->memalloc = memalloc;
  211. dsc->memfree = memfree;
  212. dsc->mem_closure_data = closure_data;
  213. dsc->ref_count = 0;
  214. dsc_ref(dsc);
  215. return dsc_init2(dsc);
  216. }
  217. /* destructor */
  218. void
  219. dsc_free(CDSC *dsc)
  220. {
  221. if (dsc == NULL)
  222. return;
  223. dsc_reset(dsc);
  224. dsc_memfree(dsc, dsc);
  225. }
  226. CDSC *
  227. dsc_new(void *caller_data)
  228. {
  229. return dsc_init(caller_data);
  230. }
  231. int
  232. dsc_ref(CDSC *dsc)
  233. {
  234. return ++(dsc->ref_count);
  235. }
  236. int
  237. dsc_unref(CDSC *dsc)
  238. {
  239. if (dsc->ref_count <= 0)
  240. return -1;
  241. dsc->ref_count--;
  242. if (dsc->ref_count == 0) {
  243. dsc_free(dsc);
  244. return 0;
  245. }
  246. return dsc->ref_count;
  247. }
  248. /* Tell DSC parser how long document will be, to allow ignoring
  249. * of early %%Trailer and %%EOF. This is optional.
  250. */
  251. void
  252. dsc_set_length(CDSC *dsc, DSC_OFFSET len)
  253. {
  254. dsc->file_length = len;
  255. }
  256. /* Process a buffer containing DSC comments and PostScript */
  257. /* Return value is < 0 for error, >=0 for OK.
  258. * CDSC_ERROR
  259. * CDSC_OK
  260. * CDSC_NOTDSC (DSC will be ignored)
  261. * other values indicate the last DSC comment read
  262. */
  263. int
  264. dsc_scan_data(CDSC *dsc, const char *data, int length)
  265. {
  266. int bytes_read;
  267. int code = 0;
  268. if (dsc == NULL)
  269. return CDSC_ERROR;
  270. if (dsc->id == CDSC_NOTDSC)
  271. return CDSC_NOTDSC;
  272. dsc->id = CDSC_OK;
  273. if (dsc->eof)
  274. return CDSC_OK; /* ignore */
  275. if (length == 0) {
  276. /* EOF, so process what remains */
  277. dsc->eof = TRUE;
  278. }
  279. do {
  280. if (dsc->id == CDSC_NOTDSC)
  281. break;
  282. if (length != 0) {
  283. /* move existing data if needed */
  284. if (dsc->data_length > CDSC_DATA_LENGTH/2) {
  285. memmove(dsc->data, dsc->data + dsc->data_index,
  286. dsc->data_length - dsc->data_index);
  287. dsc->data_offset += dsc->data_index;
  288. dsc->data_length -= dsc->data_index;
  289. dsc->data_index = 0;
  290. }
  291. /* append to buffer */
  292. bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length));
  293. memcpy(dsc->data + dsc->data_length, data, bytes_read);
  294. dsc->data_length += bytes_read;
  295. data += bytes_read;
  296. length -= bytes_read;
  297. }
  298. if (dsc->scan_section == scan_none) {
  299. code = dsc_scan_type(dsc);
  300. if (code == CDSC_NEEDMORE) {
  301. /* need more characters before we can identify type */
  302. code = CDSC_OK;
  303. break;
  304. }
  305. dsc->id = code;
  306. }
  307. if (code == CDSC_NOTDSC) {
  308. dsc->id = CDSC_NOTDSC;
  309. break;
  310. }
  311. while ((code = dsc_read_line(dsc)) > 0) {
  312. if (dsc->id == CDSC_NOTDSC)
  313. break;
  314. if (dsc->file_length &&
  315. (dsc->data_offset + dsc->data_index > dsc->file_length)) {
  316. /* have read past end of where we need to parse. */
  317. return CDSC_OK; /* ignore */
  318. }
  319. if (dsc->doseps_end &&
  320. (dsc->data_offset + dsc->data_index > dsc->doseps_end)) {
  321. /* have read past end of DOS EPS or Mac Binary
  322. * PostScript section
  323. */
  324. return CDSC_OK; /* ignore */
  325. }
  326. if (dsc->eof)
  327. return CDSC_OK;
  328. if (dsc->skip_document)
  329. continue; /* embedded document */
  330. if (dsc->skip_lines)
  331. continue; /* embedded lines */
  332. if (IS_DSC(dsc->line, "%%BeginData:"))
  333. continue;
  334. if (IS_DSC(dsc->line, "%%BeginBinary:"))
  335. continue;
  336. if (IS_DSC(dsc->line, "%%EndDocument"))
  337. continue;
  338. if (IS_DSC(dsc->line, "%%EndData"))
  339. continue;
  340. if (IS_DSC(dsc->line, "%%EndBinary"))
  341. continue;
  342. do {
  343. switch (dsc->scan_section) {
  344. case scan_comments:
  345. code = dsc_scan_comments(dsc);
  346. break;
  347. case scan_pre_preview:
  348. case scan_preview:
  349. code = dsc_scan_preview(dsc);
  350. break;
  351. case scan_pre_defaults:
  352. case scan_defaults:
  353. code = dsc_scan_defaults(dsc);
  354. break;
  355. case scan_pre_prolog:
  356. case scan_prolog:
  357. code = dsc_scan_prolog(dsc);
  358. break;
  359. case scan_pre_setup:
  360. case scan_setup:
  361. code = dsc_scan_setup(dsc);
  362. break;
  363. case scan_pre_pages:
  364. case scan_pages:
  365. code = dsc_scan_page(dsc);
  366. break;
  367. case scan_pre_trailer:
  368. case scan_trailer:
  369. code = dsc_scan_trailer(dsc);
  370. break;
  371. case scan_eof:
  372. code = CDSC_OK;
  373. break;
  374. default:
  375. /* invalid state */
  376. code = CDSC_ERROR;
  377. }
  378. /* repeat if line is start of next section */
  379. } while (code == CDSC_PROPAGATE);
  380. /* if DOS EPS header not complete, ask for more */
  381. if (code == CDSC_NEEDMORE) {
  382. code = CDSC_OK;
  383. break;
  384. }
  385. if (code == CDSC_NOTDSC) {
  386. dsc->id = CDSC_NOTDSC;
  387. break;
  388. }
  389. }
  390. } while (length != 0);
  391. return (code < 0) ? code : dsc->id;
  392. }
  393. /* Tidy up from incorrect DSC comments */
  394. int
  395. dsc_fixup(CDSC *dsc)
  396. {
  397. unsigned int i;
  398. char buf[32];
  399. DSC_OFFSET *last;
  400. if (dsc->id == CDSC_NOTDSC)
  401. return 0;
  402. /* flush last partial line */
  403. dsc_scan_data(dsc, NULL, 0);
  404. /* Fix DSC error: EOF before end of %%BeginData */
  405. if (dsc->eof &&
  406. (dsc->skip_lines || dsc->skip_bytes || dsc->skip_document)) {
  407. switch (dsc->scan_section) {
  408. case scan_comments:
  409. dsc->endcomments = DSC_END(dsc);
  410. break;
  411. case scan_preview:
  412. dsc->endpreview = DSC_END(dsc);
  413. break;
  414. case scan_defaults:
  415. dsc->enddefaults = DSC_END(dsc);
  416. break;
  417. case scan_prolog:
  418. dsc->endprolog = DSC_END(dsc);
  419. break;
  420. case scan_setup:
  421. dsc->endsetup = DSC_END(dsc);
  422. break;
  423. case scan_pages:
  424. if (dsc->page_count)
  425. dsc->page[dsc->page_count-1].end = DSC_END(dsc);
  426. break;
  427. case scan_trailer:
  428. case scan_eof:
  429. dsc->endtrailer = DSC_END(dsc);
  430. break;
  431. }
  432. }
  433. /* Fix DSC error: code between %%EndSetup and %%Page */
  434. if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup)
  435. && (dsc->endsetup != dsc->beginsetup)) {
  436. dsc->endsetup = dsc->page[0].begin;
  437. dsc_debug_print(dsc, "Warning: code included between setup and first page\n");
  438. }
  439. /* Last page contained a false trailer, */
  440. /* so extend last page to start of trailer */
  441. if (dsc->page_count && (dsc->begintrailer != 0) &&
  442. (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) {
  443. dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n");
  444. dsc_debug_print(dsc, "and extending last page to start of trailer\n");
  445. dsc->page[dsc->page_count-1].end = dsc->begintrailer;
  446. }
  447. /*
  448. * Join up all sections.
  449. * There might be extra code between them, or we might have
  450. * missed including the \n which followed \r.
  451. */
  452. last = &dsc->endcomments;
  453. dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last);
  454. dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last);
  455. dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last);
  456. dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last);
  457. for (i=0; i<dsc->page_count; i++)
  458. dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last);
  459. if (dsc->begintrailer)
  460. *last = dsc->begintrailer;
  461. if ((dsc->page_pages == 0) && (dsc->page_count == 1)) {
  462. /* don't flag an error if %%Pages absent but one %%Page found */
  463. /* adjust incorrect page count */
  464. dsc->page_pages = dsc->page_count;
  465. }
  466. /* Warnings and Errors that we can now identify */
  467. if ((dsc->page_count != dsc->page_pages)) {
  468. int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0);
  469. switch (rc) {
  470. case CDSC_RESPONSE_OK:
  471. /* adjust incorrect page count */
  472. dsc->page_pages = dsc->page_count;
  473. break;
  474. case CDSC_RESPONSE_CANCEL:
  475. break;;
  476. case CDSC_RESPONSE_IGNORE_ALL:
  477. return CDSC_NOTDSC;
  478. }
  479. }
  480. if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) {
  481. /* EPS files MUST include a BoundingBox */
  482. int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0);
  483. switch (rc) {
  484. case CDSC_RESPONSE_OK:
  485. /* Assume that it is EPS */
  486. break;
  487. case CDSC_RESPONSE_CANCEL:
  488. /* Is NOT an EPS file */
  489. dsc->epsf = FALSE;
  490. case CDSC_RESPONSE_IGNORE_ALL:
  491. return CDSC_NOTDSC;
  492. }
  493. }
  494. if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) {
  495. int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0);
  496. switch (rc) {
  497. case CDSC_RESPONSE_OK:
  498. /* Is an EPS file */
  499. break;
  500. case CDSC_RESPONSE_CANCEL:
  501. /* Is NOT an EPS file */
  502. dsc->epsf = FALSE;
  503. break;
  504. case CDSC_RESPONSE_IGNORE_ALL:
  505. return CDSC_NOTDSC;
  506. }
  507. }
  508. /* convert single file DSC 2.0 into multiple pages */
  509. dsc_dcs2_fixup(dsc);
  510. if ((dsc->media_count == 1) && (dsc->page_media == NULL)) {
  511. /* if one only media was specified, and default page media */
  512. /* was not specified, assume that default is the only media. */
  513. dsc->page_media = dsc->media[0];
  514. }
  515. if ((dsc->media_count != 0) && (dsc->page_media == NULL)) {
  516. int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0);
  517. switch (rc) {
  518. case CDSC_RESPONSE_OK:
  519. /* default media is first listed */
  520. dsc->page_media = dsc->media[0];
  521. break;
  522. case CDSC_RESPONSE_CANCEL:
  523. /* No default media */
  524. break;
  525. case CDSC_RESPONSE_IGNORE_ALL:
  526. return CDSC_NOTDSC;
  527. }
  528. }
  529. /* make sure all pages have a label */
  530. for (i=0; i<dsc->page_count; i++) {
  531. if (strlen(dsc->page[i].label) == 0) {
  532. sprintf(buf, "%d", i+1);
  533. if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, (int)strlen(buf)))
  534. == (char *)NULL)
  535. return CDSC_ERROR; /* no memory */
  536. }
  537. }
  538. return CDSC_OK;
  539. }
  540. /* Install a function to be used for displaying messages about
  541. * DSC errors and warnings, and to request advice from user.
  542. * Installing an error function is optional.
  543. */
  544. void
  545. dsc_set_error_function(CDSC *dsc,
  546. int (*fn)(void *caller_data, CDSC *dsc,
  547. unsigned int explanation, const char *line, unsigned int line_len))
  548. {
  549. dsc->dsc_error_fn = fn;
  550. }
  551. /* Install a function for printing debug messages */
  552. /* This is optional */
  553. void
  554. dsc_set_debug_function(CDSC *dsc,
  555. void (*debug_fn)(void *caller_data, const char *str))
  556. {
  557. dsc->debug_print_fn = debug_fn;
  558. }
  559. /* Doesn't need to be public for PostScript documents */
  560. /* Made public so GSview can add pages when processing PDF files */
  561. int
  562. dsc_add_page(CDSC *dsc, int ordinal, char *label)
  563. {
  564. dsc->page[dsc->page_count].ordinal = ordinal;
  565. dsc->page[dsc->page_count].label =
  566. dsc_alloc_string(dsc, label, (int)strlen(label)+1);
  567. dsc->page[dsc->page_count].begin = 0;
  568. dsc->page[dsc->page_count].end = 0;
  569. dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN;
  570. dsc->page[dsc->page_count].media = NULL;
  571. dsc->page[dsc->page_count].bbox = NULL;
  572. dsc->page[dsc->page_count].viewing_orientation = NULL;
  573. dsc->page[dsc->page_count].crop_box = NULL;
  574. dsc->page_count++;
  575. if (dsc->page_count >= dsc->page_chunk_length) {
  576. CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc,
  577. (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE));
  578. if (new_page == NULL)
  579. return CDSC_ERROR; /* out of memory */
  580. memcpy(new_page, dsc->page,
  581. dsc->page_count * sizeof(CDSCPAGE));
  582. dsc_memfree(dsc, dsc->page);
  583. dsc->page= new_page;
  584. dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count;
  585. }
  586. return CDSC_OK;
  587. }
  588. /* Doesn't need to be public for PostScript documents */
  589. /* Made public so GSview can store PDF MediaBox */
  590. int
  591. dsc_add_media(CDSC *dsc, CDSCMEDIA *media)
  592. {
  593. CDSCMEDIA **newmedia_array;
  594. CDSCMEDIA *newmedia;
  595. /* extend media array */
  596. newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc,
  597. (dsc->media_count + 1) * sizeof(CDSCMEDIA *));
  598. if (newmedia_array == NULL)
  599. return CDSC_ERROR; /* out of memory */
  600. if (dsc->media != NULL) {
  601. memcpy(newmedia_array, dsc->media,
  602. dsc->media_count * sizeof(CDSCMEDIA *));
  603. dsc_memfree(dsc, dsc->media);
  604. }
  605. dsc->media = newmedia_array;
  606. /* allocate new media */
  607. newmedia = dsc->media[dsc->media_count] =
  608. (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA));
  609. if (newmedia == NULL)
  610. return CDSC_ERROR; /* out of memory */
  611. newmedia->name = NULL;
  612. newmedia->width = 595.0;
  613. newmedia->height = 842.0;
  614. newmedia->weight = 80.0;
  615. newmedia->colour = NULL;
  616. newmedia->type = NULL;
  617. newmedia->mediabox = NULL;
  618. dsc->media_count++;
  619. if (media->name) {
  620. newmedia->name = dsc_alloc_string(dsc, media->name,
  621. (int)strlen(media->name));
  622. if (newmedia->name == NULL)
  623. return CDSC_ERROR; /* no memory */
  624. }
  625. newmedia->width = media->width;
  626. newmedia->height = media->height;
  627. newmedia->weight = media->weight;
  628. if (media->colour) {
  629. newmedia->colour = dsc_alloc_string(dsc, media->colour,
  630. (int)strlen(media->colour));
  631. if (newmedia->colour == NULL)
  632. return CDSC_ERROR; /* no memory */
  633. }
  634. if (media->type) {
  635. newmedia->type = dsc_alloc_string(dsc, media->type,
  636. (int)strlen(media->type));
  637. if (newmedia->type == NULL)
  638. return CDSC_ERROR; /* no memory */
  639. }
  640. newmedia->mediabox = NULL;
  641. if (media->mediabox) {
  642. newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
  643. if (newmedia->mediabox == NULL)
  644. return CDSC_ERROR; /* no memory */
  645. *newmedia->mediabox = *media->mediabox;
  646. }
  647. return CDSC_OK;
  648. }
  649. /* Doesn't need to be public for PostScript documents */
  650. /* Made public so GSview can store PDF CropBox */
  651. int
  652. dsc_set_page_bbox(CDSC *dsc, unsigned int page_number,
  653. int llx, int lly, int urx, int ury)
  654. {
  655. CDSCBBOX *bbox;
  656. if (page_number >= dsc->page_count)
  657. return CDSC_ERROR;
  658. bbox = dsc->page[page_number].bbox;
  659. if (bbox == NULL)
  660. dsc->page[page_number].bbox = bbox =
  661. (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
  662. if (bbox == NULL)
  663. return CDSC_ERROR;
  664. bbox->llx = llx;
  665. bbox->lly = lly;
  666. bbox->urx = urx;
  667. bbox->ury = ury;
  668. return CDSC_OK;
  669. }
  670. /******************************************************************/
  671. /* Private functions below here. */
  672. /******************************************************************/
  673. dsc_private void *
  674. dsc_memalloc(CDSC *dsc, size_t size)
  675. {
  676. if (dsc->memalloc)
  677. return dsc->memalloc(size, dsc->mem_closure_data);
  678. return malloc(size);
  679. }
  680. dsc_private void
  681. dsc_memfree(CDSC*dsc, void *ptr)
  682. {
  683. if (dsc->memfree)
  684. dsc->memfree(ptr, dsc->mem_closure_data);
  685. else
  686. free(ptr);
  687. }
  688. /* private constructor */
  689. dsc_private CDSC *
  690. dsc_init2(CDSC *dsc)
  691. {
  692. dsc_reset(dsc);
  693. dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
  694. if (dsc->string_head == NULL) {
  695. dsc_free(dsc);
  696. return NULL; /* no memory */
  697. }
  698. dsc->string = dsc->string_head;
  699. dsc->string->next = NULL;
  700. dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
  701. if (dsc->string->data == NULL) {
  702. dsc_free(dsc);
  703. return NULL; /* no memory */
  704. }
  705. dsc->string->index = 0;
  706. dsc->string->length = CDSC_STRING_CHUNK;
  707. dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE));
  708. if (dsc->page == NULL) {
  709. dsc_free(dsc);
  710. return NULL; /* no memory */
  711. }
  712. dsc->page_chunk_length = CDSC_PAGE_CHUNK;
  713. dsc->page_count = 0;
  714. dsc->line = NULL;
  715. dsc->data_length = 0;
  716. dsc->data_index = dsc->data_length;
  717. return dsc;
  718. }
  719. dsc_private void
  720. dsc_reset(CDSC *dsc)
  721. {
  722. unsigned int i;
  723. /* Clear public members */
  724. dsc->dsc = FALSE;
  725. dsc->ctrld = FALSE;
  726. dsc->pjl = FALSE;
  727. dsc->epsf = FALSE;
  728. dsc->pdf = FALSE;
  729. dsc->epsf = FALSE;
  730. dsc->preview = CDSC_NOPREVIEW;
  731. dsc->dsc_version = NULL; /* stored in dsc->string */
  732. dsc->language_level = 0;
  733. dsc->document_data = CDSC_DATA_UNKNOWN;
  734. dsc->begincomments = 0;
  735. dsc->endcomments = 0;
  736. dsc->beginpreview = 0;
  737. dsc->endpreview = 0;
  738. dsc->begindefaults = 0;
  739. dsc->enddefaults = 0;
  740. dsc->beginprolog = 0;
  741. dsc->endprolog = 0;
  742. dsc->beginsetup = 0;
  743. dsc->endsetup = 0;
  744. dsc->begintrailer = 0;
  745. dsc->endtrailer = 0;
  746. for (i=0; i<dsc->page_count; i++) {
  747. /* page media is pointer to an element of media or dsc_known_media */
  748. /* do not free it. */
  749. if (dsc->page[i].bbox)
  750. dsc_memfree(dsc, dsc->page[i].bbox);
  751. if (dsc->page[i].viewing_orientation)
  752. dsc_memfree(dsc, dsc->page[i].viewing_orientation);
  753. if (dsc->page[i].crop_box)
  754. dsc_memfree(dsc, dsc->page[i].crop_box);
  755. }
  756. if (dsc->page)
  757. dsc_memfree(dsc, dsc->page);
  758. dsc->page = NULL;
  759. dsc->page_count = 0;
  760. dsc->page_pages = 0;
  761. dsc->page_order = CDSC_ORDER_UNKNOWN;
  762. dsc->page_orientation = CDSC_ORIENT_UNKNOWN;
  763. if (dsc->viewing_orientation)
  764. dsc_memfree(dsc, dsc->viewing_orientation);
  765. dsc->viewing_orientation = NULL;
  766. if (dsc->media) {
  767. for (i=0; i<dsc->media_count; i++) {
  768. if (dsc->media[i]) {
  769. if (dsc->media[i]->mediabox)
  770. dsc_memfree(dsc, dsc->media[i]->mediabox);
  771. dsc_memfree(dsc, dsc->media[i]);
  772. }
  773. }
  774. dsc_memfree(dsc, dsc->media);
  775. }
  776. dsc->media_count = 0;
  777. dsc->media = NULL;
  778. /* page_media is pointer to an element of media or dsc_known_media */
  779. /* do not free it. */
  780. dsc->page_media = NULL;
  781. if (dsc->bbox)
  782. dsc_memfree(dsc, dsc->bbox);
  783. dsc->bbox = NULL;
  784. if (dsc->page_bbox)
  785. dsc_memfree(dsc, dsc->page_bbox);
  786. dsc->page_bbox = NULL;
  787. if (dsc->doseps)
  788. dsc_memfree(dsc, dsc->doseps);
  789. dsc->doseps = NULL;
  790. dsc->dsc_title = NULL;
  791. dsc->dsc_creator = NULL;
  792. dsc->dsc_date = NULL;
  793. dsc->dsc_for = NULL;
  794. dsc->max_error = DSC_MAX_ERROR;
  795. dsc->severity = dsc_severity;
  796. /* Clear private members */
  797. /* Don't touch dsc->caller_data */
  798. dsc->id = CDSC_OK;
  799. dsc->scan_section = scan_none;
  800. dsc->doseps_end = 0;
  801. dsc->page_chunk_length = 0;
  802. dsc->file_length = 0;
  803. dsc->skip_document = 0;
  804. dsc->skip_bytes = 0;
  805. dsc->skip_lines = 0;
  806. dsc->skip_pjl = 0;
  807. dsc->begin_font_count = 0;
  808. dsc->begin_feature_count = 0;
  809. dsc->begin_resource_count = 0;
  810. dsc->begin_procset_count = 0;
  811. dsc->data_length = 0;
  812. dsc->data_index = 0;
  813. dsc->data_offset = 0;
  814. dsc->eof = 0;
  815. dsc->line = 0;
  816. dsc->line_length = 0;
  817. dsc->eol = 0;
  818. dsc->last_cr = FALSE;
  819. dsc->line_count = 1;
  820. dsc->long_line = FALSE;
  821. memset(dsc->last_line, 0, sizeof(dsc->last_line));
  822. dsc->string = dsc->string_head;
  823. while (dsc->string != (CDSCSTRING *)NULL) {
  824. if (dsc->string->data)
  825. dsc_memfree(dsc, dsc->string->data);
  826. dsc->string_head = dsc->string;
  827. dsc->string = dsc->string->next;
  828. dsc_memfree(dsc, dsc->string_head);
  829. }
  830. dsc->string_head = NULL;
  831. dsc->string = NULL;
  832. /* don't touch caller functions */
  833. /* public data */
  834. if (dsc->hires_bbox)
  835. dsc_memfree(dsc, dsc->hires_bbox);
  836. dsc->hires_bbox = NULL;
  837. if (dsc->crop_box)
  838. dsc_memfree(dsc, dsc->crop_box);
  839. dsc->crop_box = NULL;
  840. if (dsc->dcs2) {
  841. CDCS2 *this_dcs, *next_dcs;
  842. this_dcs = dsc->dcs2;
  843. while (this_dcs) {
  844. next_dcs = this_dcs->next;
  845. /* strings have already been freed */
  846. dsc_memfree(dsc, this_dcs);
  847. this_dcs = next_dcs;
  848. }
  849. dsc->dcs2 = NULL;
  850. }
  851. if (dsc->colours) {
  852. CDSCCOLOUR *this_colour, *next_colour;
  853. this_colour = dsc->colours;
  854. while (this_colour) {
  855. next_colour = this_colour->next;
  856. /* strings have already been freed */
  857. dsc_memfree(dsc, this_colour);
  858. this_colour = next_colour;
  859. }
  860. dsc->colours = NULL;
  861. }
  862. if (dsc->macbin)
  863. dsc_memfree(dsc, dsc->macbin);
  864. dsc->macbin = NULL;
  865. }
  866. /*
  867. * Join up all sections.
  868. * There might be extra code between them, or we might have
  869. * missed including the \n which followed \r.
  870. * begin is the start of this section
  871. * pend is a pointer to the end of this section
  872. * pplast is a pointer to a pointer of the end of the previous section
  873. */
  874. dsc_private void
  875. dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast)
  876. {
  877. if (begin)
  878. **pplast = begin;
  879. if (*pend > begin)
  880. *pplast = pend;
  881. }
  882. /* return value is 0 if no line available, or length of line */
  883. dsc_private int
  884. dsc_read_line(CDSC *dsc)
  885. {
  886. char *p, *last;
  887. dsc->line = NULL;
  888. if (dsc->eof) {
  889. /* return all that remains, even if line incomplete */
  890. dsc->line = dsc->data + dsc->data_index;
  891. dsc->line_length = dsc->data_length - dsc->data_index;
  892. dsc->data_index = dsc->data_length;
  893. return dsc->line_length;
  894. }
  895. if (dsc->file_length &&
  896. (dsc->data_offset + dsc->data_index >= dsc->file_length)) {
  897. /* Have read past where we need to parse. */
  898. /* Ignore all that remains. */
  899. dsc->line = dsc->data + dsc->data_index;
  900. dsc->line_length = dsc->data_length - dsc->data_index;
  901. dsc->data_index = dsc->data_length;
  902. return dsc->line_length;
  903. }
  904. if (dsc->doseps_end &&
  905. (dsc->data_offset + dsc->data_index >= dsc->doseps_end)) {
  906. /* Have read past end of DOS EPS PostScript section. */
  907. /* Ignore all that remains. */
  908. dsc->line = dsc->data + dsc->data_index;
  909. dsc->line_length = dsc->data_length - dsc->data_index;
  910. dsc->data_index = dsc->data_length;
  911. return dsc->line_length;
  912. }
  913. /* ignore embedded bytes */
  914. if (dsc->skip_bytes) {
  915. int cnt = min(dsc->skip_bytes,
  916. (int)(dsc->data_length - dsc->data_index));
  917. dsc->skip_bytes -= cnt;
  918. dsc->data_index += cnt;
  919. if (dsc->skip_bytes != 0)
  920. return 0;
  921. }
  922. do {
  923. dsc->line = dsc->data + dsc->data_index;
  924. last = dsc->data + dsc->data_length;
  925. if (dsc->data_index == dsc->data_length) {
  926. dsc->line_length = 0;
  927. return 0;
  928. }
  929. if (dsc->eol) {
  930. /* if previous line was complete, increment line count */
  931. dsc->line_count++;
  932. if (dsc->skip_lines)
  933. dsc->skip_lines--;
  934. }
  935. /* skip over \n which followed \r */
  936. if (dsc->last_cr && dsc->line[0] == '\n') {
  937. dsc->data_index++;
  938. dsc->line++;
  939. }
  940. dsc->last_cr = FALSE;
  941. /* look for EOL */
  942. dsc->eol = FALSE;
  943. for (p = dsc->line; p < last; p++) {
  944. if (*p == '\r') {
  945. p++;
  946. if ((p<last) && (*p == '\n'))
  947. p++; /* include line feed also */
  948. else
  949. dsc->last_cr = TRUE; /* we might need to skip \n */
  950. dsc->eol = TRUE; /* dsc->line is a complete line */
  951. break;
  952. }
  953. if (*p == '\n') {
  954. p++;
  955. dsc->eol = TRUE; /* dsc->line is a complete line */
  956. break;
  957. }
  958. if (*p == '\032') { /* MS-DOS Ctrl+Z */
  959. dsc->eol = TRUE;
  960. }
  961. }
  962. if (dsc->eol == FALSE) {
  963. /* we haven't got a complete line yet */
  964. if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) {
  965. /* buffer is less than half full, ask for some more */
  966. dsc->line_length = 0;
  967. return 0;
  968. }
  969. }
  970. dsc->data_index += dsc->line_length = (int)(p - dsc->line);
  971. } while (dsc->skip_lines && dsc->line_length);
  972. if (dsc->line_length == 0)
  973. return 0;
  974. if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) {
  975. /* handle recursive %%BeginDocument */
  976. if ((dsc->skip_document) && dsc->line_length &&
  977. COMPARE(dsc->line, "%%EndDocument")) {
  978. dsc->skip_document--;
  979. }
  980. /* handle embedded lines or binary data */
  981. if (COMPARE(dsc->line, "%%BeginData:")) {
  982. /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ]
  983. * <numberof> ::= <uint> (Lines or physical bytes)
  984. * <type> ::= Hex | Binary | ASCII (Type of data)
  985. * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines)
  986. */
  987. char begindata[MAXSTR+1];
  988. int cnt;
  989. const char *numberof, *bytesorlines;
  990. cnt = dsc->line_length;
  991. if (dsc->line_length > sizeof(begindata)-1)
  992. cnt = sizeof(begindata)-1;
  993. memcpy(begindata, dsc->line, cnt);
  994. begindata[cnt] = '\0';
  995. numberof = strtok(begindata+12, " \r\n");
  996. strtok(NULL, " \r\n"); /* dump type */
  997. bytesorlines = strtok(NULL, " \r\n");
  998. if (bytesorlines == NULL)
  999. bytesorlines = "Bytes";
  1000. if ( (numberof == NULL) || (bytesorlines == NULL) ) {
  1001. /* invalid usage of %%BeginData */
  1002. /* ignore that we ever saw it */
  1003. int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE,
  1004. dsc->line, dsc->line_length);
  1005. switch (rc) {
  1006. case CDSC_RESPONSE_OK:
  1007. case CDSC_RESPONSE_CANCEL:
  1008. break;
  1009. case CDSC_RESPONSE_IGNORE_ALL:
  1010. return 0;
  1011. }
  1012. }
  1013. else {
  1014. cnt = atoi(numberof);
  1015. if (cnt) {
  1016. if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) {
  1017. /* skip cnt lines */
  1018. if (dsc->skip_lines == 0) {
  1019. /* we are not already skipping lines */
  1020. dsc->skip_lines = cnt+1;
  1021. }
  1022. }
  1023. else {
  1024. /* byte count doesn't includes \n or \r\n */
  1025. /* or \r of %%BeginData: */
  1026. /* skip cnt bytes */
  1027. if (dsc->skip_bytes == 0) {
  1028. /* we are not already skipping lines */
  1029. dsc->skip_bytes = cnt;
  1030. }
  1031. }
  1032. }
  1033. }
  1034. }
  1035. else if (COMPARE(dsc->line, "%%BeginBinary:")) {
  1036. /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/
  1037. int cnt = dsc_get_int(dsc->line + 14,
  1038. dsc->line_length - 14, NULL);
  1039. if (dsc->skip_bytes == 0) {
  1040. /* we are not already skipping lines */
  1041. dsc->skip_bytes = cnt;
  1042. }
  1043. }
  1044. }
  1045. if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
  1046. COMPARE(dsc->line, "%%BeginDocument:") ) {
  1047. /* Skip over embedded document, recursively */
  1048. dsc->skip_document++;
  1049. }
  1050. if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) {
  1051. dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length);
  1052. dsc->long_line = TRUE;
  1053. }
  1054. return dsc->line_length;
  1055. }
  1056. /* Save last DSC line, for use with %%+ */
  1057. dsc_private void
  1058. dsc_save_line(CDSC *dsc)
  1059. {
  1060. int len = min(sizeof(dsc->last_line), dsc->line_length);
  1061. memcpy(dsc->last_line, dsc->line, len);
  1062. }
  1063. /* display unknown DSC line */
  1064. dsc_private void
  1065. dsc_unknown(CDSC *dsc)
  1066. {
  1067. if (dsc->debug_print_fn) {
  1068. char line[DSC_LINE_LENGTH];
  1069. unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length);
  1070. sprintf(line, "Unknown in %s section at line %d:\n ",
  1071. dsc_scan_section_name[dsc->scan_section], dsc->line_count);
  1072. dsc_debug_print(dsc, line);
  1073. strncpy(line, dsc->line, length);
  1074. line[length] = '\0';
  1075. dsc_debug_print(dsc, line);
  1076. dsc_debug_print(dsc, "\n");
  1077. }
  1078. }
  1079. dsc_private GSBOOL
  1080. dsc_is_section(char *line)
  1081. {
  1082. if ( !((line[0]=='%') && (line[1]=='%')) )
  1083. return FALSE;
  1084. if (IS_DSC(line, "%%BeginPreview"))
  1085. return TRUE;
  1086. if (IS_DSC(line, "%%BeginDefaults"))
  1087. return TRUE;
  1088. if (IS_DSC(line, "%%BeginProlog"))
  1089. return TRUE;
  1090. if (IS_DSC(line, "%%BeginSetup"))
  1091. return TRUE;
  1092. if (IS_DSC(line, "%%Page:"))
  1093. return TRUE;
  1094. if (IS_DSC(line, "%%Trailer"))
  1095. return TRUE;
  1096. if (IS_DSC(line, "%%EOF"))
  1097. return TRUE;
  1098. return FALSE;
  1099. }
  1100. /* Get little-endian DWORD, used for DOS EPS files */
  1101. dsc_private GSDWORD
  1102. dsc_get_dword(const unsigned char *buf)
  1103. {
  1104. GSDWORD dw;
  1105. dw = (GSDWORD)buf[0];
  1106. dw += ((GSDWORD)buf[1])<<8;
  1107. dw += ((GSDWORD)buf[2])<<16;
  1108. dw += ((GSDWORD)buf[3])<<24;
  1109. return dw;
  1110. }
  1111. dsc_private GSWORD
  1112. dsc_get_word(const unsigned char *buf)
  1113. {
  1114. GSWORD w;
  1115. w = (GSWORD)buf[0];
  1116. w |= (GSWORD)(buf[1]<<8);
  1117. return w;
  1118. }
  1119. /* Get big-endian DWORD, used for Mac Binary files */
  1120. dsc_private GSDWORD
  1121. dsc_get_bigendian_dword(const unsigned char *buf)
  1122. {
  1123. GSDWORD dw;
  1124. dw = (GSDWORD)buf[3];
  1125. dw += ((GSDWORD)buf[2])<<8;
  1126. dw += ((GSDWORD)buf[1])<<16;
  1127. dw += ((GSDWORD)buf[0])<<24;
  1128. return dw;
  1129. }
  1130. dsc_private GSWORD
  1131. dsc_get_bigendian_word(const unsigned char *buf)
  1132. {
  1133. GSWORD w;
  1134. w = (GSWORD)buf[1];
  1135. w |= (GSWORD)(buf[0]<<8);
  1136. return w;
  1137. }
  1138. dsc_private int
  1139. dsc_read_doseps(CDSC *dsc)
  1140. {
  1141. unsigned char *line = (unsigned char *)dsc->line;
  1142. if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL)
  1143. return CDSC_ERROR; /* no memory */
  1144. dsc->doseps->ps_begin = dsc_get_dword(line+4);
  1145. dsc->doseps->ps_length = dsc_get_dword(line+8);
  1146. dsc->doseps->wmf_begin = dsc_get_dword(line+12);
  1147. dsc->doseps->wmf_length = dsc_get_dword(line+16);
  1148. dsc->doseps->tiff_begin = dsc_get_dword(line+20);
  1149. dsc->doseps->tiff_length = dsc_get_dword(line+24);
  1150. dsc->doseps->checksum = dsc_get_word(line+28);
  1151. if (dsc->file_length &&
  1152. (dsc->doseps->ps_begin + dsc->doseps->ps_length > dsc->file_length)) {
  1153. /* Error in DOS EPS header.
  1154. * Some files have been seen with a fixed large value as
  1155. * the length of the PostScript section.
  1156. * Correct for these erroneous files.
  1157. */
  1158. dsc->doseps->ps_length =
  1159. (GSDWORD)(dsc->file_length - dsc->doseps->ps_begin);
  1160. }
  1161. dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length;
  1162. /* move data_index backwards to byte after doseps header */
  1163. dsc->data_index -= dsc->line_length - 30;
  1164. /* we haven't read a line of PostScript code yet */
  1165. dsc->line_count = 0;
  1166. /* skip from current position to start of PostScript section */
  1167. dsc->skip_bytes = dsc->doseps->ps_begin - 30;
  1168. if (dsc->doseps->tiff_begin)
  1169. dsc->preview = CDSC_TIFF;
  1170. if (dsc->doseps->wmf_begin)
  1171. dsc->preview = CDSC_WMF;
  1172. return CDSC_OK;
  1173. }
  1174. dsc_private int
  1175. dsc_read_macbin(CDSC *dsc)
  1176. {
  1177. unsigned char *line = (unsigned char *)dsc->line;
  1178. if ((dsc->macbin =
  1179. (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
  1180. return CDSC_ERROR; /* no memory */
  1181. dsc->macbin->data_begin = 128;
  1182. dsc->macbin->data_length = dsc_get_bigendian_dword(line+83);
  1183. dsc->macbin->resource_begin =
  1184. (dsc->macbin->data_begin + dsc->macbin->data_length + 127 ) & ~127;
  1185. dsc->macbin->resource_length = dsc_get_bigendian_dword(line+87);
  1186. if (dsc->file_length &&
  1187. (((dsc->macbin->resource_begin + dsc->macbin->resource_length
  1188. + 127) & ~127) > dsc->file_length)) {
  1189. return CDSC_ERROR;
  1190. }
  1191. dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
  1192. /* move data_index to byte after Mac Binary header */
  1193. dsc->data_index -= dsc->line_length - 128;
  1194. /* we haven't read a line of PostScript code yet */
  1195. dsc->line_count = 0;
  1196. dsc->preview = CDSC_PICT;
  1197. return CDSC_OK;
  1198. }
  1199. dsc_private int
  1200. dsc_read_applesingle(CDSC *dsc)
  1201. {
  1202. GSDWORD EntryID;
  1203. GSDWORD Offset;
  1204. GSDWORD Length;
  1205. GSWORD entries;
  1206. int index;
  1207. int header;
  1208. int i;
  1209. unsigned char *line = (unsigned char *)dsc->line;
  1210. if ((dsc->macbin =
  1211. (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
  1212. return CDSC_ERROR; /* no memory */
  1213. entries = dsc_get_bigendian_word(line+24);
  1214. for (i=0; i<(int)entries; i++) {
  1215. index = 26 + i * 12;
  1216. EntryID = dsc_get_bigendian_dword(line+index);
  1217. Offset = dsc_get_bigendian_dword(line+index+4);
  1218. Length = dsc_get_bigendian_dword(line+index+8);
  1219. if (EntryID == 1) {
  1220. /* data fork */
  1221. dsc->macbin->data_begin = Offset;
  1222. dsc->macbin->data_length = Length;
  1223. }
  1224. else if (EntryID == 2) {
  1225. /* resource fork */
  1226. dsc->macbin->resource_begin = Offset;
  1227. dsc->macbin->resource_length = Length;
  1228. }
  1229. }
  1230. if (dsc->file_length &&
  1231. (dsc->macbin->resource_begin + dsc->macbin->resource_length
  1232. > dsc->file_length)) {
  1233. return CDSC_ERROR;
  1234. }
  1235. if (dsc->file_length &&
  1236. (dsc->macbin->data_begin + dsc->macbin->data_length
  1237. > dsc->file_length)) {
  1238. return CDSC_ERROR;
  1239. }
  1240. dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
  1241. header = 26 + entries * 12;
  1242. /* move data_index to byte after AppleSingle/AppleDouble header */
  1243. dsc->data_index -= dsc->line_length - header;
  1244. /* we haven't read a line of PostScript code yet */
  1245. dsc->line_count = 0;
  1246. /* skip from current position to start of PostScript section */
  1247. dsc->skip_bytes = dsc->macbin->data_begin - header;
  1248. dsc->preview = CDSC_PICT;
  1249. return CDSC_OK;
  1250. }
  1251. dsc_private int
  1252. dsc_parse_pages(CDSC *dsc)
  1253. {
  1254. int ip, io;
  1255. unsigned int i;
  1256. char *p;
  1257. int n;
  1258. if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) {
  1259. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
  1260. dsc->line_length);
  1261. switch (rc) {
  1262. case CDSC_RESPONSE_OK:
  1263. case CDSC_RESPONSE_CANCEL:
  1264. return CDSC_OK; /* ignore duplicate comments in header */
  1265. case CDSC_RESPONSE_IGNORE_ALL:
  1266. return CDSC_NOTDSC;
  1267. }
  1268. }
  1269. if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) {
  1270. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
  1271. dsc->line_length);
  1272. switch (rc) {
  1273. case CDSC_RESPONSE_OK:
  1274. case CDSC_RESPONSE_CANCEL:
  1275. break; /* use duplicate comments in header */
  1276. case CDSC_RESPONSE_IGNORE_ALL:
  1277. return CDSC_NOTDSC;
  1278. }
  1279. }
  1280. n = IS_DSC(dsc->line, "%%+") ? 3 : 8;
  1281. while (IS_WHITE(dsc->line[n]))
  1282. n++;
  1283. p = dsc->line + n;
  1284. if (COMPARE(p, "atend")) {
  1285. if (dsc->scan_section != scan_comments)
  1286. dsc_unknown(dsc);
  1287. else {
  1288. int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
  1289. dsc->line, dsc->line_length);
  1290. switch (rc) {
  1291. case CDSC_RESPONSE_OK:
  1292. /* assume (atend) */
  1293. /* we should mark it as deferred */
  1294. break;
  1295. case CDSC_RESPONSE_CANCEL:
  1296. /* ignore it */
  1297. break;
  1298. case CDSC_RESPONSE_IGNORE_ALL:
  1299. return CDSC_NOTDSC;
  1300. }
  1301. }
  1302. }
  1303. else if (COMPARE(p, "(atend)")) {
  1304. if (dsc->scan_section != scan_comments)
  1305. dsc_unknown(dsc);
  1306. /* do nothing */
  1307. /* we should mark it as deferred */
  1308. }
  1309. else {
  1310. ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
  1311. if (i) {
  1312. n+=i;
  1313. dsc->page_pages = ip;
  1314. io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
  1315. if (i) {
  1316. /* DSC 2 uses extra integer to indicate page order */
  1317. /* DSC 3 uses %%PageOrder: */
  1318. if (dsc->page_order == CDSC_ORDER_UNKNOWN)
  1319. switch (io) {
  1320. case -1:
  1321. dsc->page_order = CDSC_DESCEND;
  1322. break;
  1323. case 0:
  1324. dsc->page_order = CDSC_SPECIAL;
  1325. break;
  1326. case 1:
  1327. dsc->page_order = CDSC_ASCEND;
  1328. break;
  1329. }
  1330. }
  1331. }
  1332. else {
  1333. int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line,
  1334. dsc->line_length);
  1335. switch (rc) {
  1336. case CDSC_RESPONSE_OK:
  1337. case CDSC_RESPONSE_CANCEL:
  1338. /* ignore it */
  1339. break;
  1340. case CDSC_RESPONSE_IGNORE_ALL:
  1341. return CDSC_NOTDSC;
  1342. }
  1343. }
  1344. }
  1345. return CDSC_OK;
  1346. }
  1347. dsc_private int
  1348. dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
  1349. {
  1350. unsigned int i, n;
  1351. int llx, lly, urx, ury;
  1352. float fllx, flly, furx, fury;
  1353. char *p;
  1354. /* Process first %%BoundingBox: in comments, and last in trailer */
  1355. if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
  1356. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
  1357. dsc->line_length);
  1358. switch (rc) {
  1359. case CDSC_RESPONSE_OK:
  1360. case CDSC_RESPONSE_CANCEL:
  1361. return CDSC_OK; /* ignore duplicate comments in header */
  1362. case CDSC_RESPONSE_IGNORE_ALL:
  1363. return CDSC_NOTDSC;
  1364. }
  1365. }
  1366. if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
  1367. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
  1368. dsc->line_length);
  1369. switch (rc) {
  1370. case CDSC_RESPONSE_OK:
  1371. case CDSC_RESPONSE_CANCEL:
  1372. return CDSC_OK; /* ignore duplicate comments in header */
  1373. case CDSC_RESPONSE_IGNORE_ALL:
  1374. return CDSC_NOTDSC;
  1375. }
  1376. }
  1377. if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
  1378. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
  1379. dsc->line_length);
  1380. switch (rc) {
  1381. case CDSC_RESPONSE_OK:
  1382. case CDSC_RESPONSE_CANCEL:
  1383. break; /* use duplicate comments in trailer */
  1384. case CDSC_RESPONSE_IGNORE_ALL:
  1385. return CDSC_NOTDSC;
  1386. }
  1387. }
  1388. if (*pbbox != NULL) {
  1389. dsc_memfree(dsc, *pbbox);
  1390. *pbbox = NULL;
  1391. }
  1392. /* should only process first %%BoundingBox: */
  1393. while (IS_WHITE(dsc->line[offset]))
  1394. offset++;
  1395. p = dsc->line + offset;
  1396. if (COMPARE(p, "atend")) {
  1397. if (dsc->scan_section == scan_trailer)
  1398. dsc_unknown(dsc);
  1399. else {
  1400. int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
  1401. dsc->line_length);
  1402. switch (rc) {
  1403. case CDSC_RESPONSE_OK:
  1404. /* assume (atend) */
  1405. /* we should mark it as deferred */
  1406. break;
  1407. case CDSC_RESPONSE_CANCEL:
  1408. /* ignore it */
  1409. break;
  1410. case CDSC_RESPONSE_IGNORE_ALL:
  1411. return CDSC_NOTDSC;
  1412. }
  1413. }
  1414. }
  1415. else if (COMPARE(p, "(atend)")) {
  1416. if (dsc->scan_section == scan_trailer)
  1417. dsc_unknown(dsc);
  1418. /* do nothing */
  1419. /* we should mark it as deferred */
  1420. }
  1421. else {
  1422. /* llx = */ lly = urx = ury = 0;
  1423. n = offset;
  1424. llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
  1425. n += i;
  1426. if (i)
  1427. lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
  1428. n += i;
  1429. if (i)
  1430. urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
  1431. n += i;
  1432. if (i)
  1433. ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
  1434. if (i) {
  1435. *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
  1436. if (*pbbox == NULL)
  1437. return CDSC_ERROR; /* no memory */
  1438. (*pbbox)->llx = llx;
  1439. (*pbbox)->lly = lly;
  1440. (*pbbox)->urx = urx;
  1441. (*pbbox)->ury = ury;
  1442. }
  1443. else {
  1444. int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line,
  1445. dsc->line_length);
  1446. switch (rc) {
  1447. case CDSC_RESPONSE_OK:
  1448. /* fllx = */ flly = furx = fury = 0.0;
  1449. n = offset;
  1450. n += i;
  1451. fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1452. n += i;
  1453. if (i)
  1454. flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1455. n += i;
  1456. if (i)
  1457. furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1458. n += i;
  1459. if (i)
  1460. fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1461. if (i) {
  1462. *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
  1463. if (*pbbox == NULL)
  1464. return CDSC_ERROR; /* no memory */
  1465. (*pbbox)->llx = (int)fllx;
  1466. (*pbbox)->lly = (int)flly;
  1467. (*pbbox)->urx = (int)(furx+0.999);
  1468. (*pbbox)->ury = (int)(fury+0.999);
  1469. }
  1470. return CDSC_OK;
  1471. case CDSC_RESPONSE_CANCEL:
  1472. return CDSC_OK;
  1473. case CDSC_RESPONSE_IGNORE_ALL:
  1474. return CDSC_NOTDSC;
  1475. }
  1476. }
  1477. }
  1478. return CDSC_OK;
  1479. }
  1480. dsc_private int
  1481. dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
  1482. {
  1483. unsigned int i, n;
  1484. float fllx, flly, furx, fury;
  1485. char *p;
  1486. /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
  1487. * and last in trailer.
  1488. */
  1489. if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
  1490. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
  1491. dsc->line_length);
  1492. switch (rc) {
  1493. case CDSC_RESPONSE_OK:
  1494. case CDSC_RESPONSE_CANCEL:
  1495. return CDSC_OK; /* ignore duplicate comments in header */
  1496. case CDSC_RESPONSE_IGNORE_ALL:
  1497. return CDSC_NOTDSC;
  1498. }
  1499. }
  1500. if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
  1501. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
  1502. dsc->line_length);
  1503. switch (rc) {
  1504. case CDSC_RESPONSE_OK:
  1505. case CDSC_RESPONSE_CANCEL:
  1506. return CDSC_OK; /* ignore duplicate comments in header */
  1507. case CDSC_RESPONSE_IGNORE_ALL:
  1508. return CDSC_NOTDSC;
  1509. }
  1510. }
  1511. if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
  1512. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
  1513. dsc->line_length);
  1514. switch (rc) {
  1515. case CDSC_RESPONSE_OK:
  1516. case CDSC_RESPONSE_CANCEL:
  1517. break; /* use duplicate comments in trailer */
  1518. case CDSC_RESPONSE_IGNORE_ALL:
  1519. return CDSC_NOTDSC;
  1520. }
  1521. }
  1522. if (*pbbox != NULL) {
  1523. dsc_memfree(dsc, *pbbox);
  1524. *pbbox = NULL;
  1525. }
  1526. /* should only process first %%BoundingBox: */
  1527. while (IS_WHITE(dsc->line[offset]))
  1528. offset++;
  1529. p = dsc->line + offset;
  1530. if (COMPARE(p, "atend")) {
  1531. if (dsc->scan_section == scan_trailer)
  1532. dsc_unknown(dsc);
  1533. else {
  1534. int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
  1535. dsc->line_length);
  1536. switch (rc) {
  1537. case CDSC_RESPONSE_OK:
  1538. /* assume (atend) */
  1539. /* we should mark it as deferred */
  1540. break;
  1541. case CDSC_RESPONSE_CANCEL:
  1542. /* ignore it */
  1543. break;
  1544. case CDSC_RESPONSE_IGNORE_ALL:
  1545. return CDSC_NOTDSC;
  1546. }
  1547. }
  1548. }
  1549. else if (COMPARE(p, "(atend)")) {
  1550. if (dsc->scan_section == scan_trailer)
  1551. dsc_unknown(dsc);
  1552. /* do nothing */
  1553. /* we should mark it as deferred */
  1554. }
  1555. else {
  1556. /* fllx = */ flly = furx = fury = 0.0;
  1557. n = offset;
  1558. fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1559. n += i;
  1560. if (i)
  1561. flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1562. n += i;
  1563. if (i)
  1564. furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1565. n += i;
  1566. if (i)
  1567. fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
  1568. if (i) {
  1569. *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
  1570. if (*pbbox == NULL)
  1571. return CDSC_ERROR; /* no memory */
  1572. (*pbbox)->fllx = fllx;
  1573. (*pbbox)->flly = flly;
  1574. (*pbbox)->furx = furx;
  1575. (*pbbox)->fury = fury;
  1576. }
  1577. }
  1578. return CDSC_OK;
  1579. }
  1580. dsc_private int
  1581. dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset)
  1582. {
  1583. char *p;
  1584. if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
  1585. (dsc->scan_section == scan_comments)) {
  1586. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
  1587. dsc->line_length);
  1588. switch (rc) {
  1589. case CDSC_RESPONSE_OK:
  1590. case CDSC_RESPONSE_CANCEL:
  1591. return CDSC_OK; /* ignore duplicate comments in header */
  1592. case CDSC_RESPONSE_IGNORE_ALL:
  1593. return CDSC_NOTDSC;
  1594. }
  1595. }
  1596. if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
  1597. (dsc->scan_section == scan_trailer)) {
  1598. int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
  1599. dsc->line_length);
  1600. switch (rc) {
  1601. case CDSC_RESPONSE_OK:
  1602. case CDSC_RESPONSE_CANCEL:
  1603. break; /* use duplicate comments in header; */
  1604. case CDSC_RESPONSE_IGNORE_ALL:
  1605. return CDSC_NOTDSC;
  1606. }
  1607. }
  1608. p = dsc->line + offset;
  1609. while (IS_WHITE(*p))
  1610. p++;
  1611. if (COMPARE(p, "atend")) {
  1612. if (dsc->scan_section == scan_trailer)
  1613. dsc_unknown(dsc);
  1614. else {
  1615. int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
  1616. dsc->line, dsc->line_length);
  1617. switch (rc) {
  1618. case CDSC_RESPONSE_OK:
  1619. /* assume (atend) */
  1620. /* we should mark it as deferred */
  1621. break;
  1622. case CDSC_RESPONSE_CANCEL:
  1623. /* ignore it */
  1624. break;
  1625. case CDSC_RESPONSE_IGNORE_ALL:
  1626. return CDSC_NOTDSC;
  1627. }
  1628. }
  1629. }
  1630. else if (COMPARE(p, "(atend)")) {
  1631. if (dsc->scan_section == scan_trailer)
  1632. dsc_unknown(dsc);
  1633. /* do nothing */
  1634. /* we should mark it as deferred */
  1635. }
  1636. else if (COMPARE(p, "Portrait")) {
  1637. *porientation = CDSC_PORTRAIT;
  1638. }
  1639. else if (COMPARE(p, "Landscape")) {
  1640. *porientation = CDSC_LANDSCAPE;
  1641. }
  1642. else {
  1643. dsc_unknown(dsc);
  1644. }
  1645. return CDSC_O

Large files files are truncated, but you can click here to view the full file