"Fossies" - the Fresh Open Source Software Archive

Member "epstool-3.08/src/cps.c" (10 Jun 2005, 12277 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) 1993-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: cps.c,v 1.7 2005/06/10 09:39:24 ghostgum Exp $ */
   17 /* Copying PostScript files */
   18 
   19 #include "common.h"
   20 #include "dscparse.h"
   21 #include "capp.h"
   22 #define DEFINE_CDOC
   23 #include "cdoc.h"
   24 
   25 int ps_extract(Doc *doc, LPCTSTR filename, PAGELIST *pagelist, int copies);
   26 int ps_copy(GFile *outfile, GFile *infile, FILE_OFFSET begin, FILE_OFFSET end);
   27 int ps_fgets(char *s, int n, GFile *f);
   28 
   29 static int ps_writestring(GFile *f, const char *str)
   30 {
   31     return gfile_write(f, str, (int)strlen(str));
   32 }
   33 
   34 /* Like fgets, but allows any combination of EOL characters
   35  * and returns the count of bytes, not the string pointer.
   36  * This reads one byte at a time, so is pretty slow.
   37  * Use it for copying a header or trailer, but not for
   38  * copying the whole document.
   39  */
   40 int ps_fgets(char *s, int n, GFile *f)
   41 {
   42     char ch = '\0';
   43     int not_eof = 0;
   44     char *p = s;
   45     int count = 0;  /* bytes written to buffer */
   46     /* copy until first EOL character */
   47     while ( (count < n) &&  ((not_eof = (int)gfile_read(f, &ch, 1)) != 0)
   48     && (ch != '\r') && (ch != '\n') ) {
   49     *p++ = (char)ch;
   50     count++;
   51     }
   52 
   53     if ((count < n) && not_eof) {
   54         /* check for extra EOL characters */
   55     if (ch == '\r') {
   56         *p++ = (char)ch;
   57         count++;
   58         /* check if MS-DOS \r\n is being used */
   59         if ((count < n) && ((not_eof = (int)gfile_read(f, &ch, 1)) != 0)) {
   60         if (ch == '\n') {
   61             /* Yes, MS-DOS */
   62             *p++ = (char)ch;
   63             count++;
   64         }
   65         else {
   66             /* No, Macintosh */
   67             gfile_seek(f, -1, gfile_current);
   68         }
   69         }
   70     }
   71     else {
   72         /* must have been '\n' */
   73         *p++ = (char)ch;
   74         count++;
   75     }
   76     }
   77     if (count < n)
   78     *p = '\0';
   79 
   80     if ( (!not_eof) && (p == s) )
   81     return 0;
   82     return count;
   83 }
   84 
   85 
   86 
   87 static void 
   88 ps_num_copies(GFile *f, int copies)
   89 {
   90    char buf[MAXSTR];
   91    if (copies >= 1) {
   92       snprintf(buf, sizeof(buf)-1,  
   93     "[{\n%%%%BeginFeature: *NumCopies %d\n", copies);
   94       ps_writestring(f, buf);
   95       snprintf(buf, sizeof(buf)-1,  
   96     "<< /NumCopies %d >> setpagedevice\n", copies);
   97       ps_writestring(f, buf);
   98       ps_writestring(f, "%%%%EndFeature\n} stopped cleartomark\n");
   99    }
  100 }
  101 
  102 /* Copy DSC until a particular comment is found */
  103 /* Do not copy the comment */
  104 /* Stop if file offset exceeds end */
  105 /* return TRUE if comment found, FALSE if not found */
  106 static BOOL 
  107 ps_copy_find(GFile *outfile, GFile *infile, FILE_OFFSET end,
  108         char *s, int n, const char *comment)
  109 {
  110     int count;
  111     int remain;
  112     while (((remain = (FILE_POS)end - gfile_get_position(infile)) > 0) &&
  113         ((count = ps_fgets(s, min(n-1, remain), infile))!=0)) {
  114         s[n-1] = '\0';
  115         if (strncmp(s, comment, strlen(comment)) == 0)
  116             return TRUE;
  117         gfile_write(outfile, s, count);
  118     }
  119     return FALSE;
  120 }
  121 
  122 int 
  123 ps_copy(GFile *outfile, GFile *infile, FILE_OFFSET begin, FILE_OFFSET end)
  124 {
  125     char *buf;
  126     int count = 0;
  127     buf = (char *)malloc(COPY_BUF_SIZE);
  128     if (buf == (char *)NULL)
  129     return -1;
  130     if (begin >= 0)
  131         gfile_seek(infile, begin, gfile_begin); /* seek to section to extract */
  132     begin = gfile_get_position(infile);
  133     while (begin < end) {
  134         count = (int)(min(end-begin, COPY_BUF_SIZE));
  135     if ((count = (int)gfile_read(infile, buf, count)) > 0) {
  136         gfile_write(outfile, buf, count);
  137         begin += count;
  138     }
  139     else
  140         begin = end;    /* EOF or error */
  141     }
  142     free(buf);
  143     return count;
  144 }
  145 
  146 static int
  147 ps_copy_setup(GFile *outfile, GFile *infile, 
  148     FILE_OFFSET begin, FILE_OFFSET end, int copies)
  149 {
  150     char line[DSC_LINE_LENGTH+1];
  151     BOOL found;
  152     int code = 0;
  153     if (copies > 1) {
  154         if (begin != end) {
  155             gfile_seek(infile, begin, gfile_begin);
  156             /* copy up to, but not including %%EndSetup */
  157             found = ps_copy_find(outfile, infile, end,
  158                 line, sizeof(line)-1, "%%EndSetup");
  159             /* insert code for multiple copies */
  160             ps_num_copies(outfile, copies);
  161             /* copy rest of setup section, including %%EndSetup */
  162             if (found)
  163             ps_writestring(outfile, line);
  164             code = ps_copy(outfile, infile, -1, end);
  165         }
  166         else {
  167             /* setup section was missing - add our own. */
  168         ps_writestring(outfile, "%%BeginSetup\n");
  169             ps_num_copies(outfile, copies);
  170         ps_writestring(outfile, "%%EndSetup\n");
  171         }
  172     }
  173     else
  174         code = ps_copy(outfile, infile, begin, end);
  175     return code;
  176 }
  177 
  178 
  179 /* Extract pages from a PostScript file */
  180 /* The pages are in v->pagelist */
  181 static int
  182 ps_extract_pages(Doc *doc, GFile *infile, GFile *outfile, 
  183     PAGELIST *pagelist, int copies)
  184 {
  185     int i;
  186     int pages = 0;
  187     int neworder;
  188     BOOL reverse;
  189     DSC_OFFSET position;
  190     char line[DSC_LINE_LENGTH+1];
  191     char buf[MAXSTR];
  192     BOOL end_header;
  193     BOOL line_written;
  194     BOOL pages_written = FALSE;
  195     BOOL pageorder_written = FALSE;
  196     CDSC *dsc = doc->dsc;
  197     int page;
  198     int count;
  199 
  200     if (dsc == NULL)
  201     return_error(-1);
  202     if ((pagelist->page_count == 0) || (pagelist->select == NULL))
  203     return_error(-1);   /* can't do */
  204     if (pagelist->page_count != (int)dsc->page_count)
  205     return_error(-1);
  206     for (i=0; i<pagelist->page_count; i++) {
  207     if (pagelist->select[i]) 
  208         pages++;
  209     }
  210 
  211     /* neworder = page order of the extracted document */
  212     /* reverse = reverse the current page order */
  213     neworder = dsc->page_order;
  214     reverse = FALSE;
  215     if (neworder == CDSC_ORDER_UNKNOWN) /* No page order so assume ASCEND */
  216     neworder = CDSC_ASCEND;
  217     /* Don't touch SPECIAL pageorder */
  218     if (pagelist->reverse) {
  219         /* New page order to be DESCEND */
  220     if (neworder == CDSC_ASCEND)
  221         neworder = CDSC_DESCEND;
  222     else if (neworder == CDSC_DESCEND) {
  223         /* neworder = DESCEND;*/    /* unchanged */
  224         reverse = FALSE;    /* already reversed, don't do it again */
  225     }
  226     }
  227     else {
  228     if (neworder == CDSC_DESCEND) {
  229         neworder = CDSC_ASCEND;
  230         reverse = TRUE; /* reverse it to become ascending */
  231     }
  232     }
  233 
  234     /* copy header, fixing up %%Pages: and %%PageOrder:
  235      * Write a DSC 3.0 %%Pages: or %%PageOrder: in header,
  236      * even if document was DSC 2.x.
  237      */
  238     position = gfile_seek(infile, dsc->begincomments, gfile_begin);
  239     while ( position < dsc->endcomments ) {
  240     if (ps_fgets(line, min(sizeof(line), dsc->endcomments - position), 
  241         infile) == 0)
  242         return FALSE;
  243     position = gfile_get_position(infile);
  244     end_header = (strncmp(line, "%%EndComments", 13) == 0);
  245     if ((line[0] != '%') && (line[0] != ' ') && (line[0] != '+')
  246      && (line[0] != '\t') && (line[0] != '\r') && (line[0] != '\n'))
  247         end_header = TRUE;
  248     line_written = FALSE;
  249     if (end_header || strncmp(line, "%%Pages:", 8) == 0) {
  250         if (!pages_written) {
  251         snprintf(buf, sizeof(buf)-1, "%%%%Pages: %d\r\n", pages);
  252             ps_writestring(outfile, buf);
  253         pages_written = TRUE;
  254         }
  255         line_written = !end_header;
  256     }
  257     if (end_header || strncmp(line, "%%PageOrder:", 12) == 0) {
  258         if (!pageorder_written) {
  259         if (neworder == CDSC_ASCEND)
  260             ps_writestring(outfile, "%%PageOrder: Ascend\r\n");
  261         else if (neworder == CDSC_DESCEND)
  262             ps_writestring(outfile, "%%PageOrder: Descend\r\n");
  263         else 
  264             ps_writestring(outfile, "%%PageOrder: Special\r\n");
  265         pageorder_written = TRUE;
  266         }
  267         line_written = !end_header;
  268     }
  269     if (!line_written)
  270         ps_writestring(outfile, line);  
  271     }
  272 
  273     if (dsc->begincomments != dsc->endcomments) {
  274     if (!pages_written) {
  275         snprintf(buf, sizeof(buf)-1, "%%%%Pages: %d\r\n", pages);
  276         ps_writestring(outfile, buf);   
  277         /* pages_written = TRUE; */
  278     }
  279     if (!pageorder_written) {
  280         if (neworder == CDSC_ASCEND)
  281         ps_writestring(outfile, "%%PageOrder: Ascend\r\n");
  282         else if (neworder == CDSC_DESCEND)
  283         ps_writestring(outfile, "%%PageOrder: Descend\r\n");
  284         else 
  285         ps_writestring(outfile, "%%PageOrder: Special\r\n");
  286         /* pageorder_written = TRUE; */
  287     }
  288     }
  289 
  290     ps_copy(outfile, infile, dsc->beginpreview, dsc->endpreview);
  291     ps_copy(outfile, infile, dsc->begindefaults, dsc->enddefaults);
  292     ps_copy(outfile, infile, dsc->beginprolog, dsc->endprolog);
  293     ps_copy_setup(outfile, infile, dsc->beginsetup, dsc->endsetup, copies);
  294 
  295     /* Copy each page */
  296     page = 1;
  297     i = reverse ? dsc->page_count - 1 : 0;
  298     while ( reverse ? (i >= 0)  : (i < (int)dsc->page_count) ) {
  299     if (pagelist->select[doc_map_page(doc,i)])  {
  300         gfile_seek(infile, dsc->page[i].begin, gfile_begin);
  301         position = gfile_get_position(infile);
  302         /* Read original %%Page: line */
  303         if ((count = ps_fgets(line, sizeof(line)-1, infile)) == 0)
  304             return -1;
  305         /* Write new %%Page: line with new ordinal */
  306         if (dsc->page[i].label)
  307         snprintf(buf, sizeof(buf)-1,  "%%%%Page: %s %d\r\n", 
  308             dsc->page[i].label, page);
  309         else
  310         snprintf(buf, sizeof(buf)-1,  
  311             "%%%%Page: %d %d\r\n", page, page);
  312         ps_writestring(outfile, buf);
  313         page++;
  314         if (strncmp(line, "%%Page:", 7) != 0)
  315         gfile_write(outfile, line, count);
  316         ps_copy(outfile, infile, -1, dsc->page[i].end);
  317     }
  318         i += reverse ? -1 : 1;
  319     }
  320 
  321     /* copy trailer, removing %%Pages: and %%PageOrder: */
  322     gfile_seek(infile, dsc->begintrailer, gfile_begin);
  323     position = gfile_get_position(infile);
  324     while ( position < dsc->endtrailer ) {
  325     if (ps_fgets(line, min(sizeof(line), dsc->endtrailer - position), 
  326         infile) == 0)
  327         return -1;
  328     position = gfile_get_position(infile);
  329     if (strncmp(line, "%%Pages:", 8) == 0) {
  330         continue;   /* has already been written in header */
  331     }
  332     else if (strncmp(line, "%%PageOrder:", 12) == 0) {
  333         continue;   /* has already been written in header */
  334     }
  335     else {
  336         ps_writestring(outfile, line);  
  337     }
  338     }
  339     return 0;
  340 }
  341 
  342 
  343 
  344 /* Extract pages from a PostScript file.
  345  * If copies > 1, insert PostScript code to request printing 
  346  * copies of each page.
  347  * Used for saving a page that is being displayed,
  348  * or in preparation for printing.
  349  * Returns 0 if OK, -ve if error.
  350  */
  351 int
  352 ps_extract(Doc *doc, LPCTSTR filename, PAGELIST *pagelist, int copies)
  353 {
  354     GFile *infile, *outfile;
  355     CDSC *dsc;
  356     int code;
  357 
  358     if (doc_type(doc) == DOC_PDF)
  359     return -1;
  360     if ((infile = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) {
  361     app_msg(doc->app, "File \042");
  362     app_csmsg(doc->app, doc_name(doc));
  363     app_msg(doc->app, "\042 does not exist\n");
  364     return_error(-1);
  365     }
  366     if ( (outfile = gfile_open(filename, gfile_modeWrite | gfile_modeCreate)) 
  367     == (GFile *)NULL ) {
  368     app_msg(doc->app, "File \042");
  369     app_csmsg(doc->app, filename);
  370     app_msg(doc->app, "\042 can not be opened for writing\n");
  371     gfile_close(infile);
  372     return_error(-1);
  373     }
  374 
  375     if (pagelist == NULL) {
  376     /* Save file without changes */
  377     code = ps_copy(outfile, infile, 0, gfile_get_length(infile));
  378     }
  379     else if (doc->dsc && doc->dsc->page_count &&
  380     pagelist->page_count && (pagelist->select != NULL)) {
  381     /* DSC with pages */
  382     code = ps_extract_pages(doc, infile, outfile, pagelist, copies);
  383     }
  384     else if (doc->dsc) {
  385     /* DSC without pages */
  386     dsc = doc->dsc;
  387     code = ps_copy(outfile, infile, dsc->begincomments, dsc->endcomments);
  388     if (!code)
  389       code = ps_copy(outfile, infile, dsc->begindefaults, dsc->enddefaults);
  390     if (!code)
  391       code = ps_copy(outfile, infile, dsc->beginprolog, dsc->endprolog);
  392     if (!code)
  393       code = ps_copy_setup(outfile, infile, dsc->beginsetup, dsc->endsetup,
  394         copies);
  395     if (!code)
  396       code = ps_copy(outfile, infile, dsc->begintrailer, dsc->endtrailer);
  397     }
  398     else {
  399     /* Not DSC */
  400     if (copies > 1)
  401         ps_num_copies(outfile, copies);
  402     code = ps_copy(outfile, infile, 0, gfile_get_length(infile));
  403     }
  404 
  405     gfile_close(outfile);
  406     gfile_close(infile);
  407     if (code && !(debug & DEBUG_GENERAL))
  408     csunlink(filename);
  409     return code;
  410 }
  411 
  412