PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/epstool-3.08/src/cdoc.c

#
C | 1073 lines | 881 code | 94 blank | 98 comment | 257 complexity | 28b9f76f86936dcd7893f4916686b256 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* Copyright (C) 2001-2005 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 licence and may not be copied,
  5. modified or distributed except as expressly authorised under the terms
  6. of the licence contained in the file LICENCE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd,
  9. 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA,
  10. Fax +61 3 9886 6616.
  11. */
  12. /* $Id: cdoc.c,v 1.19 2005/06/10 08:45:36 ghostgum Exp $ */
  13. /* Common routines for Doc object */
  14. #include "common.h"
  15. #include "dscparse.h"
  16. #include "capp.h"
  17. #define DEFINE_CDOC
  18. #include "cdoc.h"
  19. #include "cres.h"
  20. typedef enum PclType_e {
  21. PCLTYPE_UNKNOWN,
  22. PCLTYPE_PCL,
  23. PCLTYPE_PXL,
  24. PCLTYPE_POSTSCRIPT
  25. } PclType;
  26. /* private */
  27. static int doc_scan(Doc *doc); /* look for DSC comments */
  28. static int doc_init(Doc *doc);
  29. static int doc_gunzip(Doc *doc);
  30. static int doc_bunzip2(Doc *doc);
  31. static int doc_msg_len(void *handle, const char *str, int len);
  32. static PclType doc_pl_parse(const char *str, int len, unsigned int *resolution);
  33. static int doc_pl_readline(const char *str, int len);
  34. static PclType doc_pjl_parse(const char *str, int len, unsigned int *resolution);
  35. /* prototypes */
  36. void doc_message(void *caller_data, const char *str);
  37. int show_dsc_error(void *caller_data, CDSC *dsc,
  38. unsigned int explanation, const char *line, unsigned int line_len);
  39. /* Create a new document object */
  40. Doc *
  41. doc_new(GSview *a)
  42. {
  43. Doc *d = (Doc *)malloc(sizeof(Doc));
  44. if (d == NULL) {
  45. app_msg(a, "Out of memory\n");
  46. return_error(NULL);
  47. }
  48. app_lock(a);
  49. doc_init(d);
  50. d->app = a;
  51. app_ref(a); /* doc has reference to app */
  52. doc_ref(d); /* caller has reference to doc */
  53. app_unlock(a);
  54. return d;
  55. }
  56. /* Add document to application list of documents */
  57. int
  58. doc_add(Doc *d, GSview *a)
  59. {
  60. Doc *dn;
  61. app_lock(a);
  62. dn = *app_docs(a);
  63. while (dn && dn->next)
  64. dn = dn->next;
  65. if (dn == NULL)
  66. *app_docs(a) = d;
  67. else
  68. dn->next = d;
  69. doc_ref(d); /* app has reference to doc */
  70. app_unlock(a);
  71. return 0;
  72. }
  73. /* Remove document from application list */
  74. int
  75. doc_remove(Doc *d)
  76. {
  77. GSview *a = d->app;
  78. int code = 0;
  79. Doc *dn;
  80. app_lock(a);
  81. dn = *app_docs(a);
  82. if (dn == NULL) {
  83. /* not in list */
  84. char str[] = "App has no Doc\n";
  85. /* Doc has already locked app */
  86. app_msg_len_nolock(a, str, (int)strlen(str));
  87. code = -1;
  88. }
  89. else if (dn == d) {
  90. *app_docs(a) = d->next;
  91. doc_unref(d); /* app loses reference to doc */
  92. }
  93. else {
  94. while (dn && dn->next != d)
  95. dn = dn->next;
  96. if (dn && dn->next == d) {
  97. dn->next = d->next;
  98. doc_unref(d); /* app loses reference to doc */
  99. }
  100. else {
  101. char str[] = "Doc not found\n";
  102. /* Doc has already locked app */
  103. app_msg_len_nolock(a, str, (int)strlen(str));
  104. code = -1;
  105. }
  106. }
  107. app_unlock(a);
  108. return code;
  109. }
  110. /* Increment reference count of Doc */
  111. /* A View will increment refcount when it attaches to Doc */
  112. /* Assumes we own the lock */
  113. int
  114. doc_ref(Doc *d)
  115. {
  116. int refcount = ++(d->refcount);
  117. if (debug & DEBUG_DEV) {
  118. char buf[MAXSTR];
  119. snprintf(buf, sizeof(buf), "doc refcount=%d\n", refcount);
  120. buf[sizeof(buf)-1]='\0';
  121. app_msg_len_nolock(d->app, buf, (int)strlen(buf));
  122. }
  123. return refcount;
  124. }
  125. /* Release reference to Doc. */
  126. /* When reference count reaches zero, Doc is freed. */
  127. /* Assumes we own the lock */
  128. int
  129. doc_unref(Doc *d)
  130. {
  131. int refcount;
  132. GSview *a = d->app;
  133. if (d->refcount > 0)
  134. d->refcount--;
  135. refcount = d->refcount;
  136. if (debug & DEBUG_DEV) {
  137. char buf[MAXSTR];
  138. snprintf(buf, sizeof(buf), "doc refcount=%d\n", refcount);
  139. buf[sizeof(buf)-1]='\0';
  140. app_msg_len_nolock(d->app, buf, (int)strlen(buf));
  141. }
  142. if (d->refcount == 0) {
  143. doc_close(d);
  144. d->app = NULL;
  145. app_unref(a); /* doc loses reference to app */
  146. memset(d, 0, sizeof(Doc));
  147. free(d);
  148. }
  149. return refcount;
  150. }
  151. GSview *
  152. doc_app(Doc *doc)
  153. {
  154. return doc->app;
  155. }
  156. static int
  157. doc_init(Doc *doc)
  158. {
  159. memset(doc, 0, sizeof(Doc));
  160. doc->handle = NULL;
  161. doc->app = NULL;
  162. doc->next = NULL;
  163. doc->viewlist = NULL;
  164. doc->doctype = DOC_UNKNOWN;
  165. doc->page_count = -1;
  166. doc->ignore_dsc = FALSE;
  167. doc->dsc_warn = CDSC_ERROR_WARN;
  168. doc->verbose = TRUE;
  169. return 0;
  170. }
  171. int
  172. doc_close(Doc *doc)
  173. {
  174. #ifdef NOTUSED
  175. /* index of extracted text */
  176. free_text_index(doc);
  177. if (doc->text_name[0])
  178. wunlink(doc->text_name);
  179. memset(doc->text_name, 0, sizeof(doc->text_name));
  180. #endif
  181. /* temporary uncompressed file */
  182. if (doc->tname[0])
  183. csunlink(doc->tname);
  184. memset(doc->name, 0, sizeof(doc->name));
  185. memset(doc->tname, 0, sizeof(doc->tname));
  186. doc->doctype = DOC_UNKNOWN;
  187. doc->gzip = FALSE;
  188. doc->bzip2 = FALSE;
  189. doc->page_count = 0;
  190. doc->length1 = 0;
  191. doc->length2 = 0;
  192. doc->time1 = 0;
  193. doc->time2 = 0;
  194. if (doc->dsc)
  195. dsc_unref(doc->dsc);
  196. doc->dsc = NULL;
  197. #ifdef NOTUSED
  198. doc->ignore_special = FALSE;
  199. #endif
  200. doc->ctrld = FALSE;
  201. doc->pjl = FALSE;
  202. if (doc->pdfscan)
  203. pdf_scan_close(doc->pdfscan);
  204. doc->pdfscan = NULL;
  205. return 0;
  206. }
  207. /* Open a new document.
  208. * +ve = non DSC
  209. * 0 = DSC
  210. * -ve = error
  211. */
  212. int
  213. doc_open(Doc *doc, LPCTSTR filename)
  214. {
  215. int code;
  216. doc_close(doc);
  217. csncpy(doc->name, filename, sizeof(doc->name)/sizeof(TCHAR)-1);
  218. code = doc_scan(doc);
  219. if (code < 0)
  220. doc_close(doc);
  221. return code;
  222. }
  223. DocType
  224. doc_type(Doc *doc)
  225. {
  226. return doc->doctype;
  227. }
  228. BOOL
  229. doc_is_open(Doc *doc)
  230. {
  231. return (doc->name[0] != '\0');
  232. }
  233. void
  234. doc_ignore_dsc(Doc *doc, BOOL flag)
  235. {
  236. doc->ignore_dsc = flag;
  237. }
  238. void
  239. doc_dsc_warn(Doc *doc, int level)
  240. {
  241. doc->dsc_warn = level;
  242. }
  243. void
  244. doc_verbose(Doc *doc, BOOL verbose)
  245. {
  246. doc->verbose = verbose;
  247. }
  248. void
  249. doc_message(void *caller_data, const char *str)
  250. {
  251. app_msg(((Doc *)caller_data)->app, str);
  252. }
  253. /* Debug for DSC comments */
  254. void
  255. doc_dump(Doc *doc)
  256. {
  257. app_csmsgf(doc->app, TEXT("DSC dump for %.200s\n"), doc->name);
  258. dsc_display(doc->dsc, doc_message);
  259. app_csmsgf(doc->app, TEXT("End of DSC dump\n"));
  260. }
  261. int
  262. show_dsc_error(void *caller_data, CDSC *dsc,
  263. unsigned int explanation, const char *line, unsigned int line_len)
  264. {
  265. Doc *doc = (Doc *)caller_data;
  266. int response = CDSC_RESPONSE_CANCEL;
  267. int severity;
  268. char buf[MAXSTR];
  269. int len;
  270. TCHAR title[MAXSTR];
  271. TCHAR linefmt[MAXSTR];
  272. int i;
  273. TCHAR *p;
  274. if (explanation > dsc->max_error)
  275. return CDSC_RESPONSE_OK;
  276. severity = dsc->severity[explanation];
  277. /* If debug function provided, copy messages there */
  278. /* These are always in English */
  279. if (dsc->debug_print_fn) {
  280. switch (severity) {
  281. case CDSC_ERROR_INFORM:
  282. dsc_debug_print(dsc, "\nDSC Information");
  283. break;
  284. case CDSC_ERROR_WARN:
  285. dsc_debug_print(dsc, "\nDSC Warning");
  286. break;
  287. case CDSC_ERROR_ERROR:
  288. dsc_debug_print(dsc, "\nDSC Error");
  289. break;
  290. }
  291. dsc_debug_print(dsc, "\n");
  292. if (explanation <= dsc->max_error) {
  293. if (line && line_len) {
  294. int length = min(line_len, sizeof(buf)-1);
  295. snprintf(buf, sizeof(buf), "At line %d:\n", dsc->line_count);
  296. buf[sizeof(buf)-1]='\0';
  297. dsc_debug_print(dsc, buf);
  298. strncpy(buf, line, length);
  299. buf[length]='\0';
  300. dsc_debug_print(dsc, " ");
  301. dsc_debug_print(dsc, buf);
  302. }
  303. dsc_debug_print(dsc, dsc_message[explanation]);
  304. }
  305. }
  306. /* Here you could prompt user for OK, Cancel, Ignore ALL DSC */
  307. if (severity <= doc->dsc_warn)
  308. return response;
  309. switch (severity) {
  310. case CDSC_ERROR_INFORM:
  311. i = IDS_DSC_INFO;
  312. break;
  313. case CDSC_ERROR_WARN:
  314. i = IDS_DSC_WARN;
  315. break;
  316. case CDSC_ERROR_ERROR:
  317. i = IDS_DSC_ERROR;
  318. break;
  319. default:
  320. i = -1;
  321. }
  322. if (i != -1)
  323. load_string(doc->app, i, title, sizeof(title)/sizeof(TCHAR));
  324. else
  325. title[0] = '\0';
  326. /* build up string */
  327. #define MLEN 4096
  328. p = (TCHAR *)malloc(MLEN*sizeof(TCHAR));
  329. memset(p, 0, MLEN*sizeof(TCHAR));
  330. if (p == (TCHAR *)NULL)
  331. return response;
  332. if (line) {
  333. int len;
  334. int wlen;
  335. load_string(doc->app, IDS_DSC_LINEFMT, linefmt, sizeof(linefmt)/sizeof(TCHAR));
  336. csnprintf(p, MLEN, linefmt, title, dsc->line_count);
  337. csncat(p, TEXT("\n "), MLEN-1-cslen(p));
  338. len = (int)cslen(p);
  339. if (line_len > 256)
  340. line_len = 256; /* this is the maximum DSC line length */
  341. wlen = narrow_to_cs(NULL, 0, line, line_len);
  342. narrow_to_cs(p+len, MLEN-1-len, line, line_len);
  343. p[len+wlen] = '\0';
  344. }
  345. else {
  346. csncpy(p, title, MLEN-1);
  347. csncat(p, TEXT("\n"), MLEN-1-cslen(p));
  348. }
  349. len = (int)cslen(p);
  350. load_string(doc->app, CDSC_RESOURCE_BASE+(explanation*2),
  351. p+len, MLEN-len);
  352. len = (int)cslen(p);
  353. load_string(doc->app, CDSC_RESOURCE_BASE+(explanation*2)+1,
  354. p+len, MLEN-len);
  355. response = get_dsc_response(doc->app, p);
  356. free(p);
  357. if (dsc->debug_print_fn) {
  358. switch (response) {
  359. case CDSC_RESPONSE_OK:
  360. dsc_debug_print(dsc, "Response = OK\n");
  361. break;
  362. case CDSC_RESPONSE_CANCEL:
  363. dsc_debug_print(dsc, "Response = Cancel\n");
  364. break;
  365. case CDSC_RESPONSE_IGNORE_ALL:
  366. dsc_debug_print(dsc, "Response = Ignore All DSC\n");
  367. break;
  368. }
  369. }
  370. return response;
  371. }
  372. LPCTSTR
  373. doc_name(Doc *doc)
  374. {
  375. /* If original file was compressed, give name of uncompressed file */
  376. if ((doc->tname[0]!='\0') && ((doc->gzip) || doc->bzip2))
  377. return doc->tname;
  378. /* otherwise return original file name */
  379. return doc->name;
  380. }
  381. /* gunzip to temporary file */
  382. static int
  383. doc_gunzip(Doc *doc)
  384. {
  385. GFile *outfile;
  386. int code;
  387. char name[MAXSTR+MAXSTR];
  388. if ((outfile = app_temp_gfile(doc->app, doc->tname,
  389. sizeof(doc->tname)/sizeof(TCHAR)-1))
  390. == (GFile *)NULL) {
  391. TCHAR buf[MAXSTR];
  392. load_string(doc->app, IDS_NOTEMP, buf, sizeof(buf)/sizeof(TCHAR));
  393. app_csmsg(doc->app, buf);
  394. return_error(-1);
  395. }
  396. cs_to_narrow(name, sizeof(name)-1, doc->name, (int)cslen(doc->name)+1);
  397. app_msg(doc->app, "Uncompressing ");
  398. app_msg(doc->app, name);
  399. app_msg(doc->app, " to ");
  400. app_csmsg(doc->app, doc->tname);
  401. app_msg(doc->app, "\n");
  402. code = zlib_uncompress(doc->app, outfile, name);
  403. gfile_close(outfile);
  404. if (code != 0) {
  405. csunlink(doc->tname);
  406. doc->tname[0] = '\0';
  407. return_error(-1);
  408. }
  409. return 0;
  410. }
  411. /* Uncompress bzip2 to temporary file */
  412. static int
  413. doc_bunzip2(Doc *doc)
  414. {
  415. GFile *outfile;
  416. int code;
  417. char name[MAXSTR+MAXSTR];
  418. if ((outfile = app_temp_gfile(doc->app, doc->tname,
  419. sizeof(doc->tname)/sizeof(TCHAR)-1))
  420. == (GFile *)NULL) {
  421. TCHAR buf[MAXSTR];
  422. load_string(doc->app, IDS_NOTEMP, buf, sizeof(buf)/sizeof(TCHAR));
  423. app_csmsg(doc->app, buf);
  424. return_error(-1);
  425. }
  426. cs_to_narrow(name, sizeof(name)-1, doc->name, (int)cslen(doc->name)+1);
  427. app_msg(doc->app, "Uncompressing ");
  428. app_msg(doc->app, name);
  429. app_msg(doc->app, " to ");
  430. app_csmsg(doc->app, doc->tname);
  431. app_msg(doc->app, "\n");
  432. code = bzip2_uncompress(doc->app, outfile, name);
  433. gfile_close(outfile);
  434. if (code != 0) {
  435. csunlink(doc->tname);
  436. doc->tname[0] = '\0';
  437. return_error(-1);
  438. }
  439. return 0;
  440. }
  441. /* Try to recognise PCL files.
  442. * PJL starts with
  443. * ESC %-12345X
  444. * PCL commonly starts with
  445. * ESC %, ESC E, ESC *, ESC &
  446. * PCLXL commonly starts with
  447. * ) HP-PCL XL
  448. * If the resolution is not specified, set it to 0.
  449. */
  450. static PclType doc_pl_parse(const char *str, int len, unsigned int *resolution)
  451. {
  452. PclType type;
  453. *resolution = 0;
  454. if ((len >= 9) && (memcmp(str, "\033%-12345X", 9) == 0))
  455. type = doc_pjl_parse(str, len, resolution);
  456. else if ((len >= 11) && (memcmp(str, ") HP-PCL XL", 11) == 0))
  457. type = PCLTYPE_PXL;
  458. else if ((len >= 2) && (str[0] == '\033') &&
  459. ((str[1]=='%') || (str[1]=='E') || (str[1]=='*') || (str[1] == '&')))
  460. type = PCLTYPE_PCL;
  461. else
  462. type = PCLTYPE_UNKNOWN;
  463. return type;
  464. }
  465. /* Get length of line in buffer.
  466. */
  467. static int doc_pl_readline(const char *str, int len)
  468. {
  469. int i = 0;
  470. /* skip until EOL */
  471. while ((i<len) && (str[i] != '\r') && (str[i] != '\n'))
  472. i++;
  473. /* skip over EOL */
  474. while ((i<len) && ((str[i] == '\r') || (str[i] == '\n')))
  475. i++;
  476. return i;
  477. }
  478. /* PJL starts with \033%-12345X
  479. * and finishes with a line that does not start with @.
  480. * We are interested in the following lines:
  481. * @PJL SET RESOLUTION=600
  482. * @PJL ENTER LANGUAGE=PCL
  483. * @PJL ENTER LANGUAGE=PCLXL
  484. * @PJL ENTER LANGUAGE=POSTSCRIPT
  485. * If the language type is not specified but PJL is used,
  486. * assume PCL.
  487. */
  488. static PclType doc_pjl_parse(const char *str, int len, unsigned int *resolution)
  489. {
  490. PclType type = PCLTYPE_PCL;
  491. const char *p;
  492. int idx = 0;
  493. int count;
  494. int i;
  495. char buf[16];
  496. int bufcnt;
  497. if ((len < 9) || (memcmp(str, "\033%-12345X", 9) != 0))
  498. return PCLTYPE_UNKNOWN;
  499. idx = 9;
  500. while ((count = doc_pl_readline(str+idx, len-idx)) != 0) {
  501. p = str+idx;
  502. if ((count >= 9) && (memcmp(p, "\033%-12345X", 9) == 0)) {
  503. count -= 9;
  504. p += 9;
  505. idx += 9;
  506. if (count == 0)
  507. break;
  508. }
  509. if (*p != '@')
  510. break; /* Not PJL */
  511. if ((count >= 19) &&
  512. (memcmp(p, "@PJL SET RESOLUTION", 19) == 0)) {
  513. i = 19;
  514. while ((i<count) && (p[i] == ' '))
  515. i++;
  516. if ((i<count) && (p[i] == '=')) {
  517. i++;
  518. while ((i<count) && (p[i] == ' '))
  519. i++;
  520. /* now read number */
  521. bufcnt = min(count-i, (int)sizeof(buf)-1);
  522. memcpy(buf, p+i, bufcnt);
  523. buf[bufcnt] = '\0';
  524. *resolution = atoi(buf);
  525. }
  526. }
  527. else if ((count >= 19) &&
  528. (memcmp(p, "@PJL ENTER LANGUAGE", 19) == 0)) {
  529. i = 19;
  530. while ((i<count) && (p[i] == ' '))
  531. i++;
  532. if ((i<count) && (p[i] == '=')) {
  533. i++;
  534. while ((i<count) && (p[i] == ' '))
  535. i++;
  536. /* now read language */
  537. if ((count-i >= 10) &&
  538. (memcmp(p+i, "POSTSCRIPT", 10) == 0))
  539. type = PCLTYPE_POSTSCRIPT;
  540. else if ((count-i >= 5) &&
  541. (memcmp(p+i, "PCLXL", 5) == 0))
  542. type = PCLTYPE_PXL;
  543. else if ((count-i >= 3) &&
  544. (memcmp(p+i, "PCL", 3) == 0))
  545. type = PCLTYPE_PCL;
  546. }
  547. }
  548. idx += count;
  549. }
  550. return type;
  551. }
  552. /* scan file for PostScript Document Structuring Conventions */
  553. /* return -ve if error */
  554. /* return +ve if not DSC */
  555. /* On return, doc->dsc is non-zero if DSC */
  556. int
  557. doc_scan(Doc *doc)
  558. {
  559. char line[4096];
  560. FILE_POS file_length;
  561. GFile *f;
  562. CDSC *dsc;
  563. PclType pcltype = PCLTYPE_UNKNOWN;
  564. if ( (f = gfile_open(doc->name, gfile_modeRead)) == (GFile *)NULL ) {
  565. app_msg(doc->app, "File \042");
  566. app_csmsg(doc->app, doc_name(doc));
  567. app_msg(doc->app, "\042 does not exist\n");
  568. return_error(-1);
  569. }
  570. if (doc->dsc)
  571. dsc_unref(doc->dsc);
  572. doc->dsc = NULL;
  573. /* get first line to look for magic numbers */
  574. memset(line, 0, sizeof(line));
  575. gfile_read(f, line, sizeof(line)-1);
  576. gfile_seek(f, 0, gfile_begin);
  577. /* check for gzip */
  578. doc->gzip = FALSE;
  579. doc->bzip2 = FALSE;
  580. if ( (line[0]=='\037') && (line[1]=='\213') ) { /* 1F 8B */
  581. doc->gzip = TRUE;
  582. gfile_close(f);
  583. if (doc_gunzip(doc) != 0) {
  584. app_msg(doc->app, "Failed to gunzip file\n");
  585. return_error(-1);
  586. }
  587. if ((f = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) {
  588. app_msg(doc->app, "File '");
  589. app_csmsg(doc->app, doc_name(doc));
  590. app_msg(doc->app, "' does not exist\n");
  591. return_error(-1);
  592. }
  593. gfile_read(f, line, sizeof(line)-1);
  594. gfile_seek(f, 0, gfile_begin);
  595. }
  596. /* check for bzip2 */
  597. if ( (line[0]=='B') && (line[1]=='Z') && (line[2]=='h')) { /* "BZh */
  598. doc->bzip2 = TRUE;
  599. gfile_close(f);
  600. if (doc_bunzip2(doc) != 0) {
  601. app_msg(doc->app, "Failed to uncompress bzip2 file\n");
  602. return_error(-1);
  603. }
  604. if ((f = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) {
  605. app_msg(doc->app, "File '");
  606. app_csmsg(doc->app, doc_name(doc));
  607. app_msg(doc->app, "' does not exist\n");
  608. return_error(-1);
  609. }
  610. gfile_read(f, line, sizeof(line)-1);
  611. gfile_seek(f, 0, gfile_begin);
  612. }
  613. file_length = gfile_get_length(f);
  614. /* save file date and length */
  615. doc_savestat(doc);
  616. doc->doctype = DOC_UNKNOWN;
  617. doc->dpi = 0;
  618. /* check for PDF */
  619. if ( strncmp("%PDF-", line, 5) == 0 ) {
  620. gfile_close(f);
  621. doc->doctype = DOC_PDF;
  622. doc->page_count = 0;
  623. if (doc->pdfscan)
  624. pdf_scan_close(doc->pdfscan);
  625. doc->pdfscan = NULL;
  626. doc->pdfscan = pdf_scan_open(doc_name(doc), doc->app, doc_msg_len);
  627. doc->page_count = pdf_scan_page_count(doc->pdfscan);
  628. if (debug & DEBUG_GENERAL)
  629. app_msgf(doc->app, "PDF page count %d\n", doc->page_count);
  630. return 0;
  631. }
  632. /* check for PCL */
  633. #ifdef NOTUSED
  634. if ((line[0]=='\033') && (line[1]=='E') && (line[2]=='\033')) {
  635. TCHAR buf[MAXSTR];
  636. doc->doctype = DOC_PCL;
  637. load_string(doc->app, IDS_PROBABLY_PCL, buf, sizeof(buf)/sizeof(TCHAR));
  638. app_msgf(doc->app, "%s\n", buf);
  639. if (app_msg_box(doc->app, buf, MB_ICONEXCLAMATION | MB_YESNO)
  640. != IDYES) {
  641. gfile_close(f);
  642. return_error(-1);
  643. }
  644. }
  645. #else
  646. pcltype = doc_pl_parse(line, (int)strlen(line), &doc->dpi);
  647. if ((pcltype == PCLTYPE_PCL) || (pcltype == PCLTYPE_PXL)) {
  648. doc->doctype = DOC_PCL;
  649. if (debug & DEBUG_GENERAL)
  650. app_msgf(doc->app, "Document is PCL or PXL\n");
  651. gfile_close(f);
  652. return 0;
  653. }
  654. #endif
  655. /* check for Windows BMP or NETPBM */
  656. if ( ((line[0]=='B') && (line[1]=='M')) ||
  657. ((line[0]=='P') && (line[1]>='1') && (line[1]<='6')) ||
  658. (((unsigned char)line[0]==0x89) && (line[1]=='P') &&
  659. (line[2]=='N') && (line[3]=='G'))
  660. ) {
  661. doc->doctype = DOC_BITMAP;
  662. doc->page_count = 1;
  663. gfile_close(f);
  664. return 0;
  665. }
  666. /* Otherwise, assume it is PostScript */
  667. doc->doctype = DOC_PS;
  668. /* check for documents that start with Ctrl-D */
  669. doc->ctrld = (line[0] == '\004');
  670. /* check for HP LaserJet prologue */
  671. doc->pjl = FALSE;
  672. if (strncmp("\033%-12345X", line, 9) == 0)
  673. doc->pjl = TRUE;
  674. if (doc->ignore_dsc)
  675. doc->dsc = (CDSC *)NULL;
  676. else {
  677. int code = 0;
  678. int count;
  679. char *d;
  680. doc->dsc = NULL;
  681. if ( (d = (char *) malloc(COPY_BUF_SIZE)) == NULL)
  682. return_error(-1);
  683. doc->dsc = dsc_new(doc);
  684. if (doc->verbose)
  685. dsc_set_debug_function(doc->dsc, doc_message);
  686. dsc_set_error_function(doc->dsc, show_dsc_error);
  687. dsc_set_length(doc->dsc, file_length);
  688. while ((count = (int)gfile_read(f, d, COPY_BUF_SIZE))!=0) {
  689. code = dsc_scan_data(doc->dsc, d, count);
  690. if ((code == CDSC_ERROR) || (code == CDSC_NOTDSC)) {
  691. /* not DSC or an error */
  692. break;
  693. }
  694. }
  695. if ((code == CDSC_ERROR) || (code == CDSC_NOTDSC)) {
  696. dsc_unref(doc->dsc);
  697. doc->dsc = NULL;
  698. }
  699. else {
  700. dsc_fixup(doc->dsc);
  701. }
  702. free(d);
  703. }
  704. gfile_close(f);
  705. /* check for DSC comments */
  706. dsc = doc->dsc;
  707. if (dsc == (CDSC *)NULL)
  708. return 1; /* OK, but not DSC */
  709. if (dsc->doseps) {
  710. BOOL bad_header = FALSE;
  711. /* check for errors in header */
  712. if (dsc->doseps->ps_begin > file_length)
  713. bad_header = TRUE;
  714. if (dsc->doseps->ps_begin + dsc->doseps->ps_length > file_length)
  715. bad_header = TRUE;
  716. if (dsc->doseps->wmf_begin > file_length)
  717. bad_header = TRUE;
  718. if (dsc->doseps->wmf_begin + dsc->doseps->wmf_length > file_length)
  719. bad_header = TRUE;
  720. if (dsc->doseps->tiff_begin > file_length)
  721. bad_header = TRUE;
  722. if (dsc->doseps->tiff_begin + dsc->doseps->tiff_length > file_length)
  723. bad_header = TRUE;
  724. if (bad_header) {
  725. TCHAR buf[MAXSTR];
  726. load_string(doc->app, IDS_BAD_DOSEPS_HEADER,
  727. buf, sizeof(buf)/sizeof(TCHAR));
  728. app_csmsgf(doc->app, TEXT("%s\n"), buf);
  729. app_msg_box(doc->app, buf, 0);
  730. /* Ignore the bad information */
  731. dsc_unref(doc->dsc);
  732. doc->dsc = NULL;
  733. return_error(-1);
  734. }
  735. }
  736. if (debug & DEBUG_GENERAL)
  737. doc_dump(doc);
  738. return 0;
  739. }
  740. /* reverse zero based page number if needed */
  741. int
  742. doc_map_page(Doc *doc, int page)
  743. {
  744. if (doc->dsc != (CDSC *)NULL)
  745. if (doc->dsc->page_order == CDSC_DESCEND)
  746. return (doc->dsc->page_count - 1) - page;
  747. return page;
  748. }
  749. int
  750. doc_page_limit(Doc *doc, int page)
  751. {
  752. if (doc == NULL)
  753. return 0;
  754. if (doc->doctype == DOC_PS) {
  755. if (doc->dsc) {
  756. if (page >= (int)doc->dsc->page_count)
  757. page = doc->dsc->page_count - 1;
  758. if (page < 0)
  759. page = 0;
  760. }
  761. else if (doc->page_count) {
  762. if (page >= (int)doc->page_count)
  763. page = doc->page_count - 1;
  764. }
  765. }
  766. else if (doc->doctype == DOC_PDF) {
  767. if (page >= (int)doc->page_count)
  768. page = doc->page_count - 1;
  769. if (page < 0)
  770. page = 0;
  771. }
  772. else if (doc->doctype == DOC_BITMAP)
  773. page = 0;
  774. return page;
  775. }
  776. View **
  777. doc_views(Doc *doc)
  778. {
  779. return &doc->viewlist;
  780. }
  781. /* append to a string in a buffer of length len */
  782. static TCHAR *
  783. csappend(LPTSTR dest, LPCTSTR src, int len)
  784. {
  785. return csncat(dest, src, len - (int)cslen(dest)/sizeof(TCHAR) - 1);
  786. }
  787. /* Information about a document, suitable for showing in a dialog */
  788. void
  789. doc_info(Doc *doc, DocInfo *info)
  790. {
  791. TCHAR buf[MAXSTR];
  792. CDSC *dsc = doc->dsc;
  793. int typelen;
  794. memset(info, 0, sizeof(DocInfo));
  795. if (cslen(doc->name))
  796. csncpy(info->name, doc->name, sizeof(info->name)/sizeof(TCHAR));
  797. else
  798. load_string(doc->app, IDS_NOFILE, info->name,
  799. sizeof(info->name)/sizeof(TCHAR));
  800. typelen = sizeof(info->type)/sizeof(TCHAR);
  801. if (doc->gzip)
  802. csappend(info->type, TEXT("gzip "), typelen);
  803. if (doc->bzip2)
  804. csappend(info->type, TEXT("bzip2 "), typelen);
  805. if (dsc) {
  806. load_string(doc->app, IDS_CTRLD, buf, sizeof(buf)/sizeof(TCHAR));
  807. if (doc->ctrld)
  808. csappend(info->type, buf, typelen);
  809. load_string(doc->app, IDS_PJL, buf, sizeof(buf)/sizeof(TCHAR));
  810. if (doc->pjl)
  811. csappend(info->type, buf, typelen);
  812. load_string(doc->app, IDS_DCS2, buf, sizeof(buf)/sizeof(TCHAR));
  813. if (dsc->dcs2)
  814. csappend(info->type, buf, typelen);
  815. if (dsc->epsf) {
  816. switch(dsc->preview) {
  817. default:
  818. case CDSC_NOPREVIEW:
  819. buf[0] = '\0';
  820. break;
  821. case CDSC_EPSI:
  822. load_string(doc->app, IDS_EPSI,
  823. buf, sizeof(buf)/sizeof(TCHAR));
  824. break;
  825. case CDSC_TIFF:
  826. load_string(doc->app, IDS_EPST,
  827. buf, sizeof(buf)/sizeof(TCHAR));
  828. break;
  829. case CDSC_WMF:
  830. load_string(doc->app, IDS_EPSW,
  831. buf, sizeof(buf)/sizeof(TCHAR));
  832. break;
  833. }
  834. csappend(info->type, buf, typelen);
  835. }
  836. else {
  837. load_string(doc->app, IDS_DSC, buf, sizeof(buf)/sizeof(TCHAR));
  838. csappend(info->type, buf, typelen);
  839. }
  840. if (dsc->dsc_title)
  841. narrow_to_cs(info->title, sizeof(info->title)/sizeof(TCHAR)-1,
  842. dsc->dsc_title, (int)strlen(dsc->dsc_title)+1);
  843. if (dsc->dsc_date)
  844. narrow_to_cs(info->date, sizeof(info->date)/sizeof(TCHAR)-1,
  845. dsc->dsc_date, (int)strlen(dsc->dsc_date)+1);
  846. if (dsc->bbox) {
  847. csnprintf(buf, sizeof(buf)/sizeof(TCHAR),
  848. TEXT("%d %d %d %d"), dsc->bbox->llx, dsc->bbox->lly,
  849. dsc->bbox->urx, dsc->bbox->ury);
  850. buf[sizeof(buf)-1]='\0';
  851. csncpy(info->bbox, buf, sizeof(info->bbox)/sizeof(TCHAR));
  852. }
  853. if (dsc->hires_bbox) {
  854. csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("%g %g %g %g"),
  855. dsc->hires_bbox->fllx, dsc->hires_bbox->flly,
  856. dsc->hires_bbox->furx, dsc->hires_bbox->fury);
  857. buf[sizeof(buf)-1]='\0';
  858. csncpy(info->hiresbbox, buf,
  859. sizeof(info->hiresbbox)/sizeof(TCHAR));
  860. }
  861. switch (dsc->page_orientation) {
  862. case CDSC_PORTRAIT:
  863. load_string(doc->app, IDS_PORTRAIT, info->orientation,
  864. sizeof(info->orientation)/sizeof(TCHAR));
  865. break;
  866. case CDSC_LANDSCAPE:
  867. load_string(doc->app, IDS_LANDSCAPE, info->orientation,
  868. sizeof(info->orientation)/sizeof(TCHAR));
  869. break;
  870. }
  871. switch (dsc->page_order) {
  872. case CDSC_ASCEND:
  873. load_string(doc->app, IDS_ASCEND, info->pageorder,
  874. sizeof(info->pageorder)/sizeof(TCHAR));
  875. break;
  876. case CDSC_DESCEND:
  877. load_string(doc->app, IDS_LANDSCAPE, info->pageorder,
  878. sizeof(info->pageorder)/sizeof(TCHAR));
  879. break;
  880. case CDSC_SPECIAL:
  881. load_string(doc->app, IDS_SPECIAL, info->pageorder,
  882. sizeof(info->pageorder)/sizeof(TCHAR));
  883. break;
  884. }
  885. if (dsc->page_media && dsc->page_media->name) {
  886. int wlen = narrow_to_cs(buf, (int)sizeof(buf)/sizeof(TCHAR),
  887. dsc->page_media->name, (int)strlen(dsc->page_media->name)+1);
  888. csnprintf(buf+wlen, sizeof(buf)/sizeof(TCHAR)-wlen, TEXT(" %g %g"),
  889. dsc->page_media->width, dsc->page_media->height);
  890. buf[sizeof(buf)-1]='\0';
  891. }
  892. else {
  893. buf[0] = '\0';
  894. }
  895. csncpy(info->pagemedia, buf, sizeof(info->pages)/sizeof(TCHAR));
  896. csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("%d"), dsc->page_count);
  897. buf[sizeof(buf)-1]='\0';
  898. csncpy(info->pages, buf, sizeof(info->pages)/sizeof(TCHAR));
  899. }
  900. else if (doc->doctype == DOC_PDF) {
  901. load_string(doc->app, IDS_PDF, buf, sizeof(buf)/sizeof(TCHAR));
  902. csappend(info->type, buf, typelen);
  903. csnprintf(buf, sizeof(buf)/sizeof(TCHAR),
  904. TEXT("%d"), doc->page_count);
  905. buf[sizeof(buf)-1]='\0';
  906. csncpy(info->pages, buf, sizeof(info->pages)/sizeof(TCHAR));
  907. }
  908. }
  909. /* Generate string for page list box, as either
  910. * ordinal
  911. * ordinal "label"
  912. */
  913. void
  914. doc_ordlabel(Doc *doc, char *buf, int buflen, int page_number)
  915. {
  916. if (doc->doctype == DOC_PDF) {
  917. snprintf(buf, buflen, "%d", page_number+1);
  918. }
  919. else if (doc->dsc) {
  920. const char *label;
  921. int ordinal;
  922. label = doc->dsc->page[doc_map_page(doc, page_number)].label;
  923. ordinal = doc->dsc->page[doc_map_page(doc, page_number)].ordinal;
  924. snprintf(buf, buflen, "%d", ordinal);
  925. if (strcmp(buf, label) != 0) {
  926. /* label and ordinal don't match, so use composite */
  927. snprintf(buf, buflen, "%d \042%s\042", ordinal, label);
  928. }
  929. }
  930. }
  931. static int
  932. doc_msg_len(void *handle, const char *str, int len)
  933. {
  934. return app_msg_len((GSview *)handle, str, len);
  935. }
  936. /* Copy document unmodified */
  937. int
  938. doc_copyfile(Doc *doc, LPCTSTR filename)
  939. {
  940. GFile *infile, *outfile;
  941. int code = 0;
  942. char *buf;
  943. int count = 0;
  944. buf = (char *)malloc(COPY_BUF_SIZE);
  945. if (buf == (char *)NULL)
  946. return -1;
  947. if ((infile = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL){
  948. app_msg(doc->app, "File \042");
  949. app_csmsg(doc->app, doc_name(doc));
  950. app_msg(doc->app, "\042 does not exist\n");
  951. free(buf);
  952. return_error(-1);
  953. }
  954. if ((outfile = gfile_open(filename, gfile_modeWrite | gfile_modeCreate))
  955. == (GFile *)NULL) {
  956. app_msg(doc->app, "File \042");
  957. app_csmsg(doc->app, filename);
  958. app_msg(doc->app, "\042 can not be opened for writing\n");
  959. free(buf);
  960. gfile_close(infile);
  961. return_error(-1);
  962. }
  963. while (((count = (int)gfile_read(infile, buf, COPY_BUF_SIZE)) > 0))
  964. if ((int)gfile_write(outfile, buf, count) != count)
  965. break;
  966. free(buf);
  967. if (gfile_error(infile)!=0)
  968. code = -1;
  969. if (gfile_error(outfile)!=0)
  970. code = -1;
  971. gfile_close(outfile);
  972. gfile_close(infile);
  973. if (code && !(debug & DEBUG_GENERAL))
  974. csunlink(filename);
  975. return code;
  976. }