"Fossies" - the Fresh Open Source Software Archive

Member "epstool-3.08/src/cdoc.c" (10 Jun 2005, 26898 Bytes) of package /linux/misc/old/ghost/ghostgum/epstool-3.08-os2.zip:


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 }