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