"Fossies" - the Fresh Open Source Software Archive

Member "epstool-3.08/src/ceps.c" (10 Jun 2005, 67380 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: ceps.c,v 1.43 2005/06/10 08:45:36 ghostgum Exp $ */
   17 
   18 /* EPS preview manipulation */
   19 
   20 #include "common.h"
   21 #include <time.h>
   22 #include "gdevdsp.h"
   23 #include "dscparse.h"
   24 #include "capp.h"
   25 #include "cbmp.h"
   26 #define DEFINE_CDOC
   27 #include "cdoc.h"
   28 #include "cmac.h"
   29 #include "ceps.h"
   30 #include "cimg.h"
   31 #include "cps.h"
   32 
   33 
   34 #define DOSEPS_HEADER_SIZE 30
   35 
   36 /* Local prototypes */
   37 static void write_doseps_header(CDSCDOSEPS *doseps, GFile *outfile);
   38 static void shift_preview(unsigned char *preview, int bwidth, int offset);
   39 static void validate_devbbox(IMAGE *img, CDSCBBOX *devbbox);
   40 int write_interchange(GFile *f, IMAGE *img, CDSCBBOX devbbox);
   41 static void write_bitmap_info(IMAGE *img, LPBITMAP2 pbmi, GFile *f);
   42 static void make_bmp_info(LPBITMAP2 pbmi, IMAGE *img, float xdpi, float ydpi);
   43 void copy_nobbox(GFile *outfile, GFile *infile, 
   44     FILE_POS begin, FILE_POS end);
   45 void copy_bbox_header(GFile *outfile, 
   46     GFile *infile, FILE_POS begin, FILE_POS end,
   47     CDSCBBOX *bbox, CDSCFBBOX *hiresbbox);
   48 static int without_eol(const char *str, int length);
   49 static FILE_POS write_platefile_comments(Doc *doc, GFile *docfile, 
   50     GFile *epsfile, LPCTSTR epsname,
   51     int offset, FILE_POS file_offset, 
   52     BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
   53     const char *renamed[], BOOL some_renamed);
   54 static FILE_POS write_singlefile_separations(Doc *doc, GFile *docfile, 
   55     GFile *epsfile, 
   56     BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
   57     BOOL some_renamed);
   58 
   59 /* A placeable Windows Metafile header is needed
   60  * when the metafile is in a WMF file, but not
   61  * when it is in memory.
   62  */
   63 typedef struct WINRECT_s {
   64     WORD    left;
   65     WORD    top;
   66     WORD    right;
   67     WORD    bottom;
   68 } WINRECT;
   69 
   70 typedef struct METAFILEHEADER_s {
   71     DWORD   key;
   72     WORD    hmf;
   73     WINRECT     bbox;
   74     WORD    inch;
   75     DWORD   reserved;
   76     WORD    checksum;
   77 } METAFILEHEADER;
   78 
   79 
   80 static void
   81 write_doseps_header(CDSCDOSEPS *doseps, GFile *outfile)
   82 {
   83     unsigned char doseps_id[] = {0xc5, 0xd0, 0xd3, 0xc6};
   84     gfile_write(outfile, doseps_id, 4);
   85     write_dword(doseps->ps_begin, outfile);
   86     write_dword(doseps->ps_length, outfile);
   87     write_dword(doseps->wmf_begin, outfile);
   88     write_dword(doseps->wmf_length, outfile);
   89     write_dword(doseps->tiff_begin, outfile);
   90     write_dword(doseps->tiff_length, outfile);
   91     write_word((WORD)(doseps->checksum), outfile);
   92 }
   93 
   94 /* shift preview by offset bits to the left */
   95 /* width is in bytes */
   96 /* fill exposed bits with 1's */
   97 static void
   98 shift_preview(unsigned char *preview, int bwidth, int offset)
   99 {
  100 int bitoffset;
  101 int byteoffset;
  102 int newwidth;
  103 int shifter;
  104 int i;
  105     if (offset == 0)
  106     return;
  107     byteoffset = offset / 8;
  108     newwidth = bwidth - byteoffset;
  109     /* first remove byte offset */
  110     memmove(preview, preview+byteoffset, newwidth);
  111     memset(preview+newwidth, 0xff, bwidth-newwidth);
  112     /* next remove bit offset */
  113     bitoffset = offset - byteoffset*8;
  114     if (bitoffset==0)
  115     return;
  116     bitoffset = 8 - bitoffset;
  117     for (i=0; i<newwidth; i++) {
  118        shifter = preview[i] << 8;
  119        if (i==newwidth-1)
  120        shifter += 0xff; /* can't access preview[bwidth] */
  121        else
  122        shifter += preview[i+1];  
  123        preview[i] = (unsigned char)(shifter>>bitoffset);
  124     }
  125 }
  126 
  127 
  128 static void
  129 validate_devbbox(IMAGE *img, CDSCBBOX *devbbox)
  130 {
  131     /* make sure the pixel coordinates are valid */
  132     if ((devbbox->llx < 0) || (devbbox->llx >= (int)img->width))
  133     devbbox->llx = 0;
  134     if ((devbbox->urx < 0) || (devbbox->urx >= (int)img->width))
  135     devbbox->urx = img->width;
  136     if ((devbbox->lly < 0) || (devbbox->lly >= (int)img->height))
  137     devbbox->lly = 0;
  138     if ((devbbox->ury < 0) || (devbbox->ury >= (int)img->height))
  139     devbbox->ury = img->height;
  140 
  141     if ((devbbox->llx >= devbbox->urx) || (devbbox->lly >= devbbox->ury)) {
  142     devbbox->llx = devbbox->lly = 0;
  143     devbbox->urx = img->width;
  144     devbbox->ury = img->height;
  145     }
  146 }
  147 
  148 /* Write bitmap info.
  149  * This works even if LPBITMAP2 is not packed.
  150  */
  151 static void
  152 write_bitmap_info(IMAGE *img, LPBITMAP2 pbmi, GFile *f)
  153 {
  154     int i;
  155     unsigned char r, g, b;
  156     unsigned char quad[4];
  157     int palcount = 0;
  158 
  159     /* write bitmap info */
  160     write_dword(BITMAP2_LENGTH, f);
  161     write_dword(pbmi->biWidth, f);
  162     write_dword(pbmi->biHeight, f);
  163     write_word(pbmi->biPlanes, f);
  164     write_word(pbmi->biBitCount, f);
  165     write_dword(pbmi->biCompression, f);
  166     write_dword(pbmi->biSizeImage, f);
  167     write_dword(pbmi->biXPelsPerMeter, f);
  168     write_dword(pbmi->biYPelsPerMeter, f);
  169     write_dword(pbmi->biClrUsed, f);
  170     write_dword(pbmi->biClrImportant, f);
  171   
  172     if (pbmi->biBitCount <= 8)
  173     palcount = 1 << pbmi->biBitCount;
  174     for (i=0; i<palcount; i++) {
  175     image_colour(img->format, i, &r, &g, &b);
  176     quad[0] = b;
  177     quad[1] = g;
  178     quad[2] = r;
  179     quad[3] = '\0';
  180     gfile_write(f, quad, 4);
  181     }
  182 }
  183 
  184 /* Make a BMP header from an IMAGE.
  185  * WARNING: The pbmi structure might not be packed, so it
  186  * should only be used by write_bitmap_info(), and not written
  187  * out directly.
  188  */
  189 static void
  190 make_bmp_info(LPBITMAP2 pbmi, IMAGE *img, float xdpi, float ydpi)
  191 {
  192     int palcount = 0;
  193     int depth = image_depth(img);
  194     if (depth <= 8)
  195     palcount = 1 << depth;
  196 
  197     pbmi->biSize = sizeof(BITMAP2); /* WARNING - MAY NOT BE PACKED */
  198     pbmi->biWidth = img->width;
  199     pbmi->biHeight = img->width;
  200     pbmi->biPlanes = 1;
  201     pbmi->biBitCount = (WORD)image_depth(img);
  202     pbmi->biCompression = 0;
  203     pbmi->biSizeImage = 0;
  204     pbmi->biXPelsPerMeter = (long)(1000 * xdpi / 25.4);
  205     pbmi->biYPelsPerMeter = (long)(1000 * ydpi / 25.4);
  206     pbmi->biClrUsed = palcount;
  207     pbmi->biClrImportant = palcount;
  208 }
  209 
  210 /*********************************************************/
  211 
  212 /* extract EPS or TIFF or WMF file from DOS EPS file */
  213 int 
  214 extract_doseps(Doc *doc, LPCTSTR outname, BOOL preview)
  215 {
  216 unsigned long pos;
  217 unsigned long len;
  218 unsigned int count;
  219 char *buffer;
  220 GFile* epsfile;
  221 BOOL is_meta = TRUE;
  222 GFile *outfile;
  223 CDSC *dsc = doc->dsc;
  224 
  225     if ((dsc == (CDSC *)NULL) || (dsc->doseps == (CDSCDOSEPS *)NULL)) {
  226     app_csmsgf(doc->app, 
  227         TEXT("Document \042%s\042 is not a DOS EPS file\n"),
  228         doc->name);
  229     return -1;
  230     }
  231 
  232     epsfile = gfile_open(doc_name(doc), gfile_modeRead);
  233     pos = dsc->doseps->ps_begin;
  234     len = dsc->doseps->ps_length;
  235     if (preview) {
  236     pos = dsc->doseps->wmf_begin;
  237     len = dsc->doseps->wmf_length;
  238     if (pos == 0L) {
  239         pos = dsc->doseps->tiff_begin;
  240         len = dsc->doseps->tiff_length;
  241         is_meta = FALSE;
  242     }
  243     }
  244     if (pos == 0L) {
  245     gfile_close(epsfile);
  246     app_csmsgf(doc->app, 
  247         TEXT("Document \042%s\042 does not have a %s section\n"),
  248         doc->name, preview ? TEXT("preview") : TEXT("PostScript"));
  249     return -1;
  250     }
  251     gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */
  252 
  253     outfile = gfile_open(outname, gfile_modeWrite | gfile_modeCreate);
  254     if (outfile == (GFile *)NULL) {
  255     app_csmsgf(doc->app, 
  256         TEXT("Failed to open output file \042%s\042\n"), outname);
  257     gfile_close(epsfile);
  258     return -1;
  259     }
  260     
  261     /* create buffer for file copy */
  262     buffer = (char *)malloc(COPY_BUF_SIZE);
  263     if (buffer == (char *)NULL) {
  264     app_csmsgf(doc->app, TEXT("Out of memory in extract_doseps\n"));
  265     gfile_close(epsfile);
  266     if (*outname!='\0')
  267         gfile_close(outfile);
  268     return -1;
  269     }
  270 
  271     if (preview && is_meta) {
  272     /* check if metafile already contains header */
  273     DWORD key;
  274     char keybuf[4];
  275     DWORD wmf_key = 0x9ac6cdd7UL;
  276     gfile_read(epsfile, keybuf, 4);
  277     key = (unsigned int)(keybuf[0]) + 
  278          ((unsigned int)(keybuf[1])<<8) + 
  279          ((unsigned int)(keybuf[2])<<16) + 
  280          ((unsigned int)(keybuf[3])<<24);
  281     gfile_seek(epsfile, pos, gfile_begin);  /* seek to section to extract */
  282     if ( key != wmf_key ) {
  283         /* write placeable Windows Metafile header */
  284         METAFILEHEADER mfh;
  285         int i, temp;
  286         unsigned short *pw;
  287         mfh.key = wmf_key;
  288         mfh.hmf = 0;
  289         /* guess the location - this might be wrong */
  290         mfh.bbox.left = 0;
  291         mfh.bbox.top = 0;
  292         if (dsc->bbox != (CDSCBBOX *)NULL) {
  293         temp = (dsc->bbox->urx - dsc->bbox->llx);
  294         /* double transfer to avoid GCC Solaris bug */
  295         mfh.bbox.right = (WORD)temp;    
  296         mfh.bbox.bottom = (WORD)(dsc->bbox->ury - dsc->bbox->lly);
  297         temp = (dsc->bbox->ury - dsc->bbox->lly);
  298         mfh.bbox.bottom = (WORD)temp;
  299         }
  300         else {
  301         /* bbox missing, assume A4 */
  302         mfh.bbox.right = 595;
  303         mfh.bbox.bottom = 842;
  304         }
  305         mfh.inch = 72;  /* PostScript points */
  306         mfh.reserved = 0L;
  307         mfh.checksum =  0;
  308         pw = (WORD *)&mfh;
  309         temp = 0;
  310         for (i=0; i<10; i++) {
  311         temp ^= *pw++;
  312         }
  313         mfh.checksum = (WORD)temp;
  314         write_dword(mfh.key, outfile);
  315         write_word(mfh.hmf, outfile);
  316         write_word(mfh.bbox.left,   outfile);
  317         write_word(mfh.bbox.top,    outfile);
  318         write_word(mfh.bbox.right,  outfile);
  319         write_word(mfh.bbox.bottom, outfile);
  320         write_word(mfh.inch, outfile);
  321         write_dword(mfh.reserved, outfile);
  322         write_word(mfh.checksum, outfile);
  323     }
  324     }
  325 
  326     while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) {
  327     count = (int)gfile_read(epsfile, buffer, count);
  328     gfile_write(outfile, buffer, count);
  329     if (count == 0)
  330         len = 0;
  331     else
  332         len -= count;
  333     }
  334     free(buffer);
  335     gfile_close(epsfile);
  336     gfile_close(outfile);
  337 
  338     return 0;
  339 }
  340 
  341 /* extract EPS or PICT file from Macintosh EPSF file */
  342 int 
  343 extract_macbin(Doc *doc, LPCTSTR outname, BOOL preview)
  344 {
  345 unsigned long pos;
  346 unsigned long len;
  347 unsigned int count;
  348 char *buffer;
  349 GFile* epsfile;
  350 GFile *outfile;
  351 CDSC *dsc = doc->dsc;
  352 
  353 CMACFILE *mac;
  354 
  355     if ((dsc == (CDSC *)NULL) || (dsc->macbin == (CDSCMACBIN *)NULL)) {
  356     app_csmsgf(doc->app, 
  357     TEXT("Document \042%s\042 is not a Macintosh EPSF file with preview\n"),
  358         doc->name);
  359     return -1;
  360     }
  361 
  362     epsfile = gfile_open(doc_name(doc), gfile_modeRead);
  363     if (epsfile == NULL) {
  364     app_csmsgf(doc->app, 
  365         TEXT("Failed to open \042%s\042\n"), doc_name(doc));
  366     return -1;
  367     }
  368 
  369     if (preview) {
  370     int code = 0;
  371     mac = get_mactype(epsfile);
  372     if (mac == NULL) {
  373         app_csmsgf(doc->app, TEXT("Not a Mac file with resource fork\n"));
  374         code = -1;
  375     }
  376     if (code == 0) {
  377         code = get_pict(epsfile, mac, FALSE);
  378         if (code)
  379             app_csmsgf(doc->app, 
  380             TEXT("Resource fork didn't contain PICT preview\n"));
  381     }
  382     if (code == 0) {
  383         code = extract_mac_pict(epsfile, mac, outname);
  384         if (code)
  385         app_csmsgf(doc->app, 
  386             TEXT("Failed to find PICT preview or write file\n"));
  387     }
  388     gfile_close(epsfile);
  389     return code;
  390     }
  391 
  392     pos = dsc->macbin->data_begin;
  393     len = dsc->macbin->data_length;
  394     if (len == 0) {
  395     app_csmsgf(doc->app, 
  396         TEXT("File has not data section for EPSF\n"));
  397     gfile_close(epsfile);
  398     return -1;
  399     }
  400     gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */
  401 
  402     outfile = gfile_open(outname, gfile_modeWrite | gfile_modeCreate);
  403     if (outfile == (GFile *)NULL) {
  404     app_csmsgf(doc->app, 
  405         TEXT("Failed to open output file \042%s\042\n"), outname);
  406     gfile_close(epsfile);
  407     return -1;
  408     }
  409     
  410     /* create buffer for file copy */
  411     buffer = (char *)malloc(COPY_BUF_SIZE);
  412     if (buffer == (char *)NULL) {
  413     app_csmsgf(doc->app, TEXT("Out of memory in extract_doseps\n"));
  414     gfile_close(epsfile);
  415     if (*outname!='\0')
  416         gfile_close(outfile);
  417     return -1;
  418     }
  419 
  420     while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) {
  421     count = (int)gfile_read(epsfile, buffer, count);
  422     gfile_write(outfile, buffer, count);
  423     if (count == 0)
  424         len = 0;
  425     else
  426         len -= count;
  427     }
  428     free(buffer);
  429     gfile_close(epsfile);
  430     gfile_close(outfile);
  431 
  432     return 0;
  433 }
  434 
  435 /*********************************************************/
  436 
  437 /* FIX: instead of devbbox, perhaps we should use CDSCFBBOX in points,
  438   or simply grab this from doc. */
  439 
  440 /* make a PC EPS file with a TIFF Preview */
  441 /* from a PS file and a bitmap */
  442 int
  443 make_eps_tiff(Doc *doc, IMAGE *img, CDSCBBOX devbbox, 
  444     CDSCBBOX *bbox, CDSCFBBOX *hires_bbox,
  445     float xdpi, float ydpi, BOOL tiff4, BOOL use_packbits, BOOL reverse,
  446     LPCTSTR epsname)
  447 {
  448 GFile *epsfile;
  449 GFile *tiff_file;
  450 TCHAR tiffname[MAXSTR];
  451 CDSCDOSEPS doseps;
  452 int code;
  453 GFile *tpsfile;
  454 TCHAR tpsname[MAXSTR];
  455 char *buffer;
  456 unsigned int count;
  457 CDSC *dsc = doc->dsc;
  458 
  459     if (dsc == NULL)
  460     return -1;
  461 
  462     validate_devbbox(img, &devbbox);
  463 
  464     /* Create TIFF file */
  465     if ((tiff_file = app_temp_gfile(doc->app, tiffname, 
  466     sizeof(tiffname)/sizeof(TCHAR))) == (GFile *)NULL) {
  467     app_csmsgf(doc->app, 
  468         TEXT("Can't open temporary TIFF file \042%s\042\n"),
  469         tiffname);
  470     return -1;
  471     }
  472     code = image_to_tiff(tiff_file, img, 
  473     devbbox.llx, devbbox.lly, devbbox.urx, devbbox.ury, 
  474     xdpi, ydpi, tiff4, use_packbits);
  475     gfile_close(tiff_file);
  476     if (code) {
  477     app_csmsgf(doc->app, 
  478         TEXT("Failed to write temporary TIFF file \042%s\042\n"),
  479         tiffname);
  480     if (!(debug & DEBUG_GENERAL))
  481         csunlink(tiffname);
  482     return code;
  483     }
  484 
  485     /* Create temporary EPS file with updated headers */
  486     tpsfile = NULL;
  487     memset(tpsname, 0, sizeof(tpsname));
  488     if ((tpsfile = app_temp_gfile(doc->app, tpsname, 
  489     sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
  490     app_csmsgf(doc->app, 
  491         TEXT("Can't create temporary EPS file \042%s\042\n"),
  492         tpsname);
  493     csunlink(tiffname);
  494     return -1;
  495     }
  496     gfile_close(tpsfile);
  497 
  498     code = copy_eps(doc, tpsname, bbox, hires_bbox, 
  499     DOSEPS_HEADER_SIZE, FALSE); 
  500     if (code) {
  501     if (!(debug & DEBUG_GENERAL))
  502         csunlink(tiffname);
  503     return -1;
  504     }
  505 
  506 
  507     if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
  508     app_csmsgf(doc->app, 
  509         TEXT("Can't open temporary EPS file \042%s\042\n"),
  510         tpsname);
  511     if (!(debug & DEBUG_GENERAL))
  512         csunlink(tiffname);
  513     return -1;
  514     }
  515 
  516     /* Create DOS EPS output file */
  517     epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
  518     if (epsfile == (GFile *)NULL) {
  519     app_csmsgf(doc->app, 
  520         TEXT("Can't open output EPS file \042%s\042\n"),
  521         epsname);
  522     if (!(debug & DEBUG_GENERAL))
  523         csunlink(tiffname);
  524     gfile_close(tpsfile);
  525     if (!(debug & DEBUG_GENERAL))
  526         csunlink(tpsname);
  527     return -1;
  528     }
  529 
  530     buffer = (char *)malloc(COPY_BUF_SIZE);
  531     if (buffer == (char *)NULL) {
  532     if (epsname[0]) {
  533         gfile_close(epsfile);
  534         if (!(debug & DEBUG_GENERAL))
  535         csunlink(epsname);
  536     }
  537     if (!(debug & DEBUG_GENERAL))
  538         csunlink(tiffname);
  539     gfile_close(tpsfile);
  540     if (!(debug & DEBUG_GENERAL))
  541         csunlink(tpsname);
  542     return -1;
  543     }
  544 
  545     if ((tiff_file = gfile_open(tiffname, gfile_modeRead)) == (GFile *)NULL) {
  546     app_csmsgf(doc->app, 
  547         TEXT("Can't open temporary TIFF file \042%s\042\n"),
  548         tiffname);
  549     free(buffer);
  550     if (!(debug & DEBUG_GENERAL))
  551         csunlink(tiffname);
  552     gfile_close(tpsfile);
  553     if (!(debug & DEBUG_GENERAL))
  554         csunlink(tpsname);
  555     if (epsname[0]) {
  556         gfile_close(epsfile);
  557         if (!(debug & DEBUG_GENERAL))
  558         csunlink(epsname);
  559     }
  560     return -1;
  561     }
  562     doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile);
  563     doseps.wmf_begin = 0;
  564     doseps.wmf_length = 0;
  565     doseps.tiff_length = (GSDWORD)gfile_get_length(tiff_file);
  566     if (reverse) {
  567     doseps.tiff_begin = DOSEPS_HEADER_SIZE;
  568     doseps.ps_begin = doseps.tiff_begin + doseps.tiff_length;
  569     }
  570     else {
  571     doseps.ps_begin = DOSEPS_HEADER_SIZE;
  572     doseps.tiff_begin = doseps.ps_begin + doseps.ps_length;
  573     }
  574     doseps.checksum = 0xffff;
  575     write_doseps_header(&doseps, epsfile);
  576 
  577     gfile_seek(tpsfile, 0, gfile_begin);
  578     if (!reverse) {
  579         /* copy EPS file */
  580     while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
  581         gfile_write(epsfile, buffer, count);
  582     }
  583 
  584     /* copy tiff file */
  585     gfile_seek(tiff_file, 0, gfile_begin);
  586     while ((count = (int)gfile_read(tiff_file, buffer, COPY_BUF_SIZE)) != 0)
  587     gfile_write(epsfile, buffer, count);
  588 
  589     if (reverse) {
  590         /* copy EPS file */
  591     while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
  592         gfile_write(epsfile, buffer, count);
  593     }
  594 
  595     free(buffer);
  596     gfile_close(tiff_file);
  597     if (!(debug & DEBUG_GENERAL))
  598     csunlink(tiffname);
  599     gfile_close(tpsfile);
  600     if (!(debug & DEBUG_GENERAL))
  601     csunlink(tpsname);
  602     gfile_close(epsfile);
  603     return 0;
  604 }
  605 
  606 /*********************************************************/
  607 
  608 static char hex[17] = "0123456789ABCDEF";
  609 
  610 #define MAXHEXWIDTH 70
  611 
  612 /* Write interchange preview to file f */
  613 /* Does not copy the file itself */
  614 int
  615 write_interchange(GFile *f, IMAGE *img, CDSCBBOX devbbox)
  616 {
  617     int i, j;
  618     unsigned char *preview;
  619     char buf[MAXSTR];
  620     const char *eol_str = EOLSTR;
  621     const char *endpreview_str = "%%EndPreview";
  622     BYTE *line;
  623     int preview_width, bwidth;
  624     int lines_per_scan;
  625     int topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
  626     char hexline[MAXHEXWIDTH+6];
  627     int hexcount = 0;
  628     unsigned int value;
  629     unsigned int depth = 8;
  630     
  631     validate_devbbox(img, &devbbox);
  632 
  633     switch (img->format & DISPLAY_COLORS_MASK) {
  634     case DISPLAY_COLORS_NATIVE:
  635     case DISPLAY_COLORS_GRAY:
  636         if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1)
  637         depth = 1;
  638     }
  639 
  640     switch (depth) {
  641     case 1:
  642         /* byte width of interchange preview with 1 bit/pixel */
  643         bwidth = (((devbbox.urx-devbbox.llx) + 7) & ~7) >> 3;
  644         /* byte width of intermediate preview with 1 bit/pixel */
  645         preview_width = ((img->width + 7) & ~7) >> 3;
  646         break;
  647     case 8:
  648         bwidth = devbbox.urx-devbbox.llx;
  649         preview_width = img->width;
  650         break;
  651     default:
  652         return -1;
  653     }
  654 
  655     preview = (unsigned char *) malloc(preview_width);
  656 
  657     lines_per_scan = (bwidth + (MAXHEXWIDTH/2) - 1) / (MAXHEXWIDTH/2);
  658     buf[sizeof(buf)-1] = '\0';
  659     snprintf(buf, MAXSTR-1, "%%%%BeginPreview: %u %u %u %u%s",
  660     (devbbox.urx-devbbox.llx), (devbbox.ury-devbbox.lly), depth,
  661     (devbbox.ury-devbbox.lly)*lines_per_scan, eol_str);
  662     gfile_puts(f, buf);
  663 
  664     if (topfirst) 
  665     line = img->image + img->raster * (img->height - devbbox.ury);
  666     else
  667     line = img->image + img->raster * (devbbox.ury-1);
  668 
  669     /* process each line of bitmap */
  670     for (i = 0; i < (devbbox.ury-devbbox.lly); i++) {
  671     memset(preview,0xff,preview_width);
  672     if (depth == 1) {
  673         image_to_mono(img, preview, line);
  674         if (devbbox.llx)
  675         shift_preview(preview, preview_width, devbbox.llx);
  676     }
  677     else {
  678         image_to_grey(img, preview, line);
  679         if (devbbox.llx)
  680         memmove(preview, preview+devbbox.llx, preview_width);
  681     }
  682     hexcount = 0;
  683     hexline[hexcount++] = '%';
  684     hexline[hexcount++] = ' ';
  685     for (j=0; j<bwidth; j++) {
  686         if (hexcount >= 2 + MAXHEXWIDTH) {
  687         if (strlen(eol_str) <= sizeof(hexline)-hexcount) {
  688             memcpy(hexline+hexcount, eol_str, strlen(eol_str));
  689             hexcount += (int)strlen(eol_str);
  690         }
  691         gfile_write(f, hexline, hexcount);
  692         hexcount = 0;
  693         hexline[hexcount++] = '%';
  694         hexline[hexcount++] = ' ';
  695         }
  696         value = preview[j];
  697         if (depth == 8)
  698         value = 255 - value;
  699         hexline[hexcount++] = hex[(value>>4)&15];
  700         hexline[hexcount++] = hex[value&15];
  701     }
  702     if (hexcount && (strlen(eol_str) <= sizeof(hexline)-hexcount)) {
  703         memcpy(hexline+hexcount, eol_str, strlen(eol_str));
  704         hexcount += (int)strlen(eol_str);
  705     }
  706     if (hexcount)
  707         gfile_write(f, hexline, hexcount);
  708 
  709     if (topfirst)
  710         line += img->raster;
  711     else
  712         line -= img->raster;
  713 
  714     }
  715 
  716     
  717     gfile_puts(f, endpreview_str);
  718     gfile_puts(f, eol_str);
  719     free(preview);
  720 
  721     return 0;
  722 }
  723 
  724 /*********************************************************/
  725 
  726 typedef enum PREVIEW_TYPE_e {
  727     PREVIEW_UNKNOWN = 0,
  728     PREVIEW_TIFF = 1,
  729     PREVIEW_WMF = 2
  730 } PREVIEW_TYPE;
  731 
  732 /* Make a DOS EPS file from a PS file and a user supplied preview.
  733  * Preview may be WMF or TIFF.
  734  * Returns 0 on success.
  735  */
  736 int
  737 make_eps_user(Doc *doc, LPCTSTR preview_name, BOOL reverse, LPCTSTR epsname)
  738 {
  739 GFile *epsfile;
  740 GFile *preview_file;
  741 unsigned long preview_length;
  742 unsigned char id[4];
  743 PREVIEW_TYPE type = PREVIEW_UNKNOWN;
  744 CDSCDOSEPS doseps;
  745 char *buffer;
  746 unsigned int count;
  747 GFile *tpsfile;
  748 TCHAR tpsname[MAXSTR];
  749 
  750     if ((preview_name == NULL) || preview_name[0] == '\0')
  751     return -1;
  752     if (doc->dsc == NULL)
  753     return -1;
  754 
  755     /* open preview, determine length and type */
  756     preview_file = gfile_open(preview_name, gfile_modeRead);
  757     if (preview_file == (GFile *)NULL) {
  758     app_csmsgf(doc->app, TEXT("Can't open preview file \042%s\042\n"),
  759         preview_name);
  760     return -1;
  761     }
  762 
  763     /* Determine type of preview */
  764     gfile_read(preview_file, id, 4);
  765     preview_length = (GSDWORD)gfile_get_length(preview_file);
  766     gfile_seek(preview_file, 0, gfile_begin);
  767 
  768     if ((id[0] == 'I') && (id[1] == 'I'))
  769     type = PREVIEW_TIFF;
  770     if ((id[0] == 'M') && (id[1] == 'M'))
  771     type = PREVIEW_TIFF;
  772     if ((id[0] == 0x01) && (id[1] == 0x00) && 
  773     (id[2] == 0x09) && (id[3] == 0x00))
  774     type = PREVIEW_WMF;
  775     if ((id[0] == 0xd7) && (id[1] == 0xcd) && 
  776     (id[2] == 0xc6) && (id[3] == 0x9a)) {
  777     type = PREVIEW_WMF;
  778     preview_length -= 22;   /* skip over placeable metafile header */
  779         gfile_seek(preview_file, 22, gfile_begin);
  780     }
  781 
  782     if (type == PREVIEW_UNKNOWN) {
  783     app_csmsgf(doc->app, 
  784      TEXT("Preview file \042%s\042 is not TIFF or Windows Metafile\n"),
  785      preview_name);
  786     gfile_close(preview_file);
  787     return -1;
  788     }
  789 
  790     /* Create temporary EPS file containing all that is needed
  791      * including updated header and trailer.
  792      */
  793     tpsfile = NULL;
  794     memset(tpsname, 0, sizeof(tpsname));
  795     if ((tpsfile = app_temp_gfile(doc->app, tpsname, 
  796     sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
  797     app_csmsgf(doc->app, 
  798         TEXT("Can't create temporary EPS file \042%s\042\n"),
  799         tpsname);
  800     gfile_close(preview_file);
  801     return -1;
  802     }
  803     gfile_close(tpsfile);
  804 
  805     if (copy_eps(doc, tpsname, doc->dsc->bbox, doc->dsc->hires_bbox, 
  806     DOSEPS_HEADER_SIZE, FALSE) < 0)
  807     return -1; 
  808 
  809 
  810     if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
  811     app_csmsgf(doc->app, 
  812         TEXT("Can't open temporary EPS file \042%s\042\n"),
  813         tpsname);
  814     gfile_close(preview_file);
  815     return -1;
  816     }
  817 
  818 
  819     /* Create EPS output file */
  820     epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
  821 
  822     if (epsfile == (GFile *)NULL) {
  823     app_csmsgf(doc->app, 
  824         TEXT("Can't open EPS output file \042%s\042\n"),
  825         epsname);
  826     gfile_close(preview_file);
  827     gfile_close(tpsfile);
  828     if (!(debug & DEBUG_GENERAL))
  829         csunlink(tpsname);
  830     return -1;
  831     }
  832 
  833     /* write DOS EPS binary header */
  834     doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile);
  835     if (type == PREVIEW_WMF) {
  836     doseps.wmf_length = preview_length;
  837     doseps.tiff_begin = 0;
  838     doseps.tiff_length = 0;
  839     if (reverse) {
  840         doseps.wmf_begin = DOSEPS_HEADER_SIZE;
  841         doseps.ps_begin = doseps.wmf_begin + doseps.wmf_length;
  842     }
  843     else {
  844         doseps.ps_begin = DOSEPS_HEADER_SIZE;
  845         doseps.wmf_begin = doseps.ps_begin + doseps.ps_length;
  846     }
  847     }
  848     else {
  849     doseps.wmf_begin = 0;
  850     doseps.wmf_length = 0;
  851     doseps.tiff_length = preview_length;
  852     if (reverse) {
  853         doseps.tiff_begin = DOSEPS_HEADER_SIZE;
  854         doseps.ps_begin = doseps.tiff_begin + doseps.tiff_length;
  855     }
  856     else {
  857         doseps.ps_begin = DOSEPS_HEADER_SIZE;
  858         doseps.tiff_begin = doseps.ps_begin + doseps.ps_length;
  859     }
  860     }
  861     doseps.checksum = 0xffff;
  862     write_doseps_header(&doseps, epsfile);
  863 
  864     buffer = (char *)malloc(COPY_BUF_SIZE);
  865     if (buffer == (char *)NULL) {
  866     app_csmsgf(doc->app, TEXT("Out of memory in make_eps_user\n"));
  867     if (epsname[0]) {
  868         gfile_close(epsfile);
  869         if (!(debug & DEBUG_GENERAL))
  870         csunlink(epsname);
  871     }
  872     gfile_close(preview_file);
  873     gfile_close(tpsfile);
  874     if (!(debug & DEBUG_GENERAL))
  875         csunlink(tpsname);
  876     return -1;
  877     }
  878 
  879     gfile_seek(tpsfile, 0, gfile_begin);
  880     if (!reverse) {
  881     /* copy EPS file */
  882     while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
  883         gfile_write(epsfile, buffer, count);
  884     }
  885     
  886     /* copy preview file */
  887     while ((count = (int)gfile_read(preview_file, buffer, COPY_BUF_SIZE)) != 0)
  888     gfile_write(epsfile, buffer, count);
  889 
  890     if (reverse) {
  891     /* copy EPS file */
  892     while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
  893         gfile_write(epsfile, buffer, count);
  894     }
  895 
  896     free(buffer);
  897     gfile_close(tpsfile);
  898     if (!(debug & DEBUG_GENERAL))
  899     csunlink(tpsname);
  900     gfile_close(preview_file);
  901     gfile_close(epsfile);
  902     return 0; /* success */
  903 }
  904 
  905 
  906 /*********************************************************/
  907 
  908 typedef struct tagMFH {
  909     WORD type;
  910     WORD headersize;
  911     WORD version;
  912     DWORD size;
  913     WORD nobj;
  914     DWORD maxrec;
  915     WORD noparam;
  916 } MFH;
  917 
  918 int write_metafile(GFile *f, IMAGE *img, CDSCBBOX devbbox, 
  919     float xdpi, float ydpi, MFH *mf);
  920 static int metafile_init(IMAGE *img, CDSCBBOX *pdevbbox, MFH* mf);
  921 
  922 /* A metafile object must not be larger than 64k */
  923 /* Metafile bitmap object contains metafile header, */
  924 /* bitmap header, palette and bitmap bits */
  925 #define MAX_METAFILE_BITMAP 64000L  /* max size of bitmap bits */
  926 
  927 static int
  928 metafile_init(IMAGE *img, CDSCBBOX *pdevbbox, MFH* mf)
  929 {
  930 int wx, wy;
  931 int ny, nylast;
  932 int complete, partial;
  933 int bytewidth;
  934 int palcount;
  935 unsigned long size;
  936 int depth = image_depth(img);
  937 
  938     switch (depth) {
  939     case 1:
  940     case 4:
  941     case 8:
  942     case 24:
  943         break;
  944     default:
  945         /* unsupported format */
  946         return -1;
  947     }
  948 
  949     validate_devbbox(img, pdevbbox);
  950 
  951     wx = pdevbbox->urx - pdevbbox->llx;
  952     wy = pdevbbox->ury - pdevbbox->lly;
  953     bytewidth = (( wx * depth + 31) & ~31) >> 3;
  954     ny = (int)(MAX_METAFILE_BITMAP / bytewidth);
  955     if (depth == 24)
  956     palcount = 0;
  957     else
  958     palcount = 1<<depth;
  959 
  960     complete = wy / ny;
  961     nylast = wy % ny;
  962     partial = nylast ? 1 : 0;
  963     
  964     mf->type = 1;       /* metafile in file */
  965     mf->headersize = 9;     /* 9 WORDs */
  966     mf->version = 0x300;    /* Windows 3.0 */
  967     mf->size =          /* sizes in WORDs */
  968     9UL +           /* header */
  969     5 +         /* SetWindowOrg */
  970     5;          /* SetWindowExt */
  971     /* complete StretchDIBits */
  972     mf->size += 14*complete;
  973     size = (40L + palcount*4L + (unsigned long)ny*(unsigned long)bytewidth)/2L;
  974     mf->size += size * (unsigned long)complete;
  975     /* partial StretchDIBits */
  976     mf->size += 14*partial;
  977     size = (40L + palcount*4L + (unsigned long)nylast*(unsigned long)bytewidth)/2L;
  978     mf->size += size * (unsigned long)partial;
  979     mf->size += 3;          /* end marker */
  980 
  981     mf->nobj = 0;
  982     size = complete ? 
  983        (40L + palcount*4L + (unsigned long)ny*(unsigned long)bytewidth)/2L
  984      : (40L + palcount*4L + (unsigned long)nylast*(unsigned long)bytewidth)/2L;
  985     mf->maxrec = 14L + size;
  986     mf->noparam = 0;
  987     return 0;
  988 }
  989 
  990 
  991 
  992 /* convert the display bitmap to a metafile picture */
  993 int
  994 write_metafile(GFile *f, IMAGE *img, CDSCBBOX devbbox, 
  995     float xdpi, float ydpi, MFH *mf)
  996 {
  997     int i;
  998     int wx;
  999     int ny, sy, dy, wy;
 1000     BYTE *line;
 1001     BYTE *line2;
 1002     LPBITMAP2 pbmi;
 1003     int bsize;
 1004     int bitoffset;
 1005     int bytewidth, activewidth;
 1006     int palcount;
 1007     unsigned long size;
 1008     int depth = image_depth(img);
 1009     int topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
 1010 
 1011     dy = 0;
 1012     wx = devbbox.urx - devbbox.llx;
 1013     sy = devbbox.lly;
 1014     wy = devbbox.ury - devbbox.lly;
 1015     bitoffset = (devbbox.llx * depth);
 1016     bytewidth = (( wx * depth + 31) & ~31) >> 3;
 1017     activewidth = (( wx * depth + 7) & ~7) >> 3;
 1018     ny = (int)(MAX_METAFILE_BITMAP / bytewidth);
 1019     if (depth == 24)
 1020     palcount = 0;
 1021     else
 1022     palcount = 1<<depth;
 1023 
 1024     /* create and initialize a BITMAPINFO for the <64k bitmap */
 1025     bsize = sizeof(BITMAP2) + palcount * RGB4_LENGTH; 
 1026     pbmi = (LPBITMAP2)malloc(bsize);
 1027     if (pbmi == NULL) {
 1028        return -1;
 1029     }
 1030     memset((char *)pbmi, 0, bsize);
 1031     make_bmp_info(pbmi, img, xdpi, ydpi);
 1032     pbmi->biClrUsed = 0;        /* write out full palette */
 1033     pbmi->biClrImportant = 0;
 1034 
 1035     line2 = (BYTE *)malloc(img->raster);
 1036     if (line2 == (BYTE *)NULL)
 1037        return -1;
 1038     pbmi->biWidth = wx;
 1039 
 1040     if (topfirst) 
 1041     line = img->image + img->raster * (img->height - devbbox.lly - 1);
 1042     else
 1043     line = img->image + img->raster * devbbox.lly;
 1044 
 1045     /* write metafile header */
 1046     write_word(mf->type, f);
 1047     write_word(mf->headersize, f);
 1048     write_word(mf->version, f);
 1049     write_dword(mf->size, f);
 1050     write_word(mf->nobj, f);
 1051     write_dword(mf->maxrec, f);
 1052     write_word(mf->noparam, f);
 1053 
 1054     /* write SetWindowOrg */
 1055     write_dword(5, f);
 1056     write_word(0x20b, f);
 1057     write_word(0, f);
 1058     write_word(0, f);
 1059 
 1060     /* write SetWindowExt */
 1061     write_dword(5, f);
 1062     write_word(0x20c, f);
 1063     write_word((WORD)wy, f);
 1064     write_word((WORD)wx, f);
 1065 
 1066     /* copy in chunks < 64k */
 1067     for ( ; wy > ny; dy += ny, wy -= ny, sy += ny ) {
 1068     pbmi->biHeight = ny;
 1069 
 1070     size = BITMAP2_LENGTH + (palcount * RGB4_LENGTH) 
 1071         + (unsigned long)bytewidth * (unsigned long)ny;
 1072     /* write StretchDIBits header */
 1073     write_dword(14 + size/2L, f);
 1074     write_word(0x0f43, f);
 1075     write_dword(0x00cc0020L, f);    /* SRC_COPY */
 1076     write_word(0, f);           /* DIB_RGB_COLORS */
 1077     write_word((WORD)ny, f);        /* Source cy */
 1078     write_word((WORD)wx, f);        /* Source cx */
 1079     write_word(0, f);           /* Source y */
 1080     write_word(0, f);           /* Source x */
 1081     write_word((WORD)ny, f);        /* Dest   cy */
 1082     write_word((WORD)wx, f);        /* Dest   cx */
 1083     write_word((WORD)(devbbox.ury - devbbox.lly - ny - dy), f); 
 1084                         /* Dest   y */
 1085     write_word(0, f);           /* Dest   x */
 1086 
 1087     /* write bitmap header */
 1088     write_bitmap_info(img, pbmi, f);
 1089 
 1090     /* write bitmap rows */
 1091     for (i=0; i<ny; i++) {
 1092         if (depth == 24)
 1093         image_to_24BGR(img, line2, line);
 1094         else
 1095         memmove(line2, line, img->raster);
 1096         shift_preview(line2, img->raster, bitoffset);
 1097         if (activewidth < bytewidth)
 1098         memset(line2+activewidth, 0xff, bytewidth-activewidth);
 1099         gfile_write(f, line2, bytewidth);
 1100         if (topfirst)
 1101         line -= img->raster;
 1102         else
 1103         line += img->raster;
 1104     }
 1105     
 1106     }
 1107 
 1108     /* write StretchDIBits header */
 1109     pbmi->biHeight = wy;
 1110     size = BITMAP2_LENGTH + (palcount * RGB4_LENGTH) + 
 1111     (unsigned long)bytewidth * (unsigned long)wy;
 1112     write_dword(14 + size/2L, f);
 1113     write_word(0x0f43, f);
 1114     write_dword(0x00cc0020L, f);    /* SRC_COPY */
 1115     write_word(0, f);       /* DIB_RGB_COLORS */
 1116     write_word((WORD)wy, f);    /* Source cy */
 1117     write_word((WORD)wx, f);    /* Source cx */
 1118     write_word(0, f);       /* Source y */
 1119     write_word(0, f);       /* Source x */
 1120     write_word((WORD)wy, f);    /* Dest   cy */
 1121     write_word((WORD)wx, f);    /* Dest   cx */
 1122     write_word((WORD)(devbbox.ury - devbbox.lly - wy - dy), f); /* Dest   y */
 1123     write_word(0, f);       /* Dest   x */
 1124 
 1125     /* write bitmap header */
 1126     write_bitmap_info(img, pbmi, f);
 1127 
 1128     /* copy last chunk */
 1129     for (i=0; i<wy; i++) {
 1130     if (depth == 24)
 1131         image_to_24BGR(img, line2, line);
 1132     else
 1133         memmove(line2, line, img->raster);
 1134     shift_preview(line2, img->raster, bitoffset);
 1135     if (activewidth < bytewidth)
 1136         memset(line2+activewidth, 0xff, bytewidth-activewidth);
 1137     gfile_write(f, line2, bytewidth);
 1138     if (topfirst)
 1139         line -= img->raster;
 1140     else
 1141         line += img->raster;
 1142     }
 1143 
 1144     /* write end marker */
 1145     write_dword(3, f);
 1146     write_word(0, f);
 1147 
 1148     free((char *)pbmi);
 1149     free(line2);
 1150 
 1151     return 0;
 1152 }
 1153 
 1154 
 1155 /*********************************************************/
 1156 
 1157 /* Copy a DSC section, removing existing bounding boxes */
 1158 void
 1159 copy_nobbox(GFile *outfile, GFile *infile, 
 1160     FILE_POS begin, FILE_POS end)
 1161 {
 1162     const char bbox_str[] = "%%BoundingBox:";
 1163     const char hiresbbox_str[] = "%%HiResBoundingBox:";
 1164     char buf[DSC_LINE_LENGTH+1];
 1165     int len;
 1166     gfile_seek(infile, begin, gfile_begin);
 1167     begin = gfile_get_position(infile);
 1168     while (begin < end) {
 1169     len = ps_fgets(buf, min(sizeof(buf)-1, end-begin), infile);
 1170         begin = gfile_get_position(infile);
 1171     if (len == 0) {
 1172         return; /* EOF on input file */
 1173     }
 1174     else if (strncmp(buf, bbox_str, strlen(bbox_str)) == 0) {
 1175         /* skip it */
 1176     }
 1177     else if (strncmp(buf, hiresbbox_str, strlen(hiresbbox_str)) == 0) {
 1178         /* skip it */
 1179     }
 1180     else
 1181         gfile_write(outfile, buf, len);
 1182     }
 1183 }
 1184 
 1185 /* Copy a DSC header, removing existing bounding boxes 
 1186  * and adding new ones.
 1187  */
 1188 void
 1189 copy_bbox_header(GFile *outfile, 
 1190     GFile *infile, FILE_POS begin, FILE_POS end,
 1191     CDSCBBOX *bbox, CDSCFBBOX *hiresbbox)
 1192 {
 1193     char buf[DSC_LINE_LENGTH+1];
 1194     int len;
 1195 
 1196     memset(buf, 0, sizeof(buf)-1);
 1197     gfile_seek(infile, begin, gfile_begin);
 1198     len = ps_fgets(buf, min(sizeof(buf)-1, end-begin), infile);
 1199     if (len)
 1200     gfile_write(outfile, buf, len); /* copy version line */
 1201     /* Add bounding box lines */
 1202     if (bbox) {
 1203     snprintf(buf, sizeof(buf)-1, "%%%%BoundingBox: %d %d %d %d\n",
 1204         bbox->llx, bbox->lly, bbox->urx, bbox->ury);
 1205     gfile_puts(outfile, buf);
 1206     }
 1207     if (hiresbbox) {
 1208     snprintf(buf, sizeof(buf)-1, "%%%%HiResBoundingBox: %.3f %.3f %.3f %.3f\n",
 1209         hiresbbox->fllx, hiresbbox->flly, 
 1210         hiresbbox->furx, hiresbbox->fury);
 1211     gfile_puts(outfile, buf);
 1212     }
 1213 
 1214     begin = gfile_get_position(infile);
 1215     copy_nobbox(outfile, infile, begin, end);
 1216 }
 1217 
 1218 /* return the length of the line less the EOL characters */
 1219 static int
 1220 without_eol(const char *str, int length)
 1221 {
 1222     int j;
 1223     for (j=length-1; j>=0; j--) {
 1224     if (!((str[j] == '\r') || (str[j] == '\n'))) {
 1225         j++;
 1226         break;
 1227     }
 1228     }
 1229     if (j < 0)
 1230     j = 0;
 1231     return j;
 1232 }
 1233 
 1234 static BOOL is_process_colour(const char *name)
 1235 {
 1236     return ( 
 1237     (dsc_stricmp(name, "Cyan")==0) ||
 1238         (dsc_stricmp(name, "Magenta")==0) ||
 1239         (dsc_stricmp(name, "Yellow")==0) ||
 1240         (dsc_stricmp(name, "Black")==0)
 1241     );
 1242 }
 1243 
 1244 static const char process_str[] = "%%DocumentProcessColors:";
 1245 static const char custom_str[] = "%%DocumentCustomColors:";
 1246 static const char cmyk_custom_str[] = "%%CMYKCustomColor:";
 1247 static const char rgb_custom_str[] = "%%RGBCustomColor:";
 1248 static const char eol_str[] = EOLSTR;
 1249 
 1250 static const char *
 1251 separation_name(RENAME_SEPARATION *rs, const char *name)
 1252 {
 1253     RENAME_SEPARATION *s;
 1254     const char *newname = name;
 1255     for (s=rs; s; s=s->next) {
 1256     if (strcmp(s->oldname, name) == 0) {
 1257         newname = s->newname;
 1258         break;
 1259     }
 1260     }
 1261     return newname;
 1262 }
 1263 
 1264 /*
 1265  * Set renamed to the names of the renamed separations.
 1266  * renamed[] must be as long as dsc->page_count.
 1267  * Return 0 on success, or -1 if a separation name appears twice.
 1268  */
 1269 int
 1270 rename_separations(CDSC *dsc, RENAME_SEPARATION *rs, const char *renamed[])
 1271 {
 1272     int duplicated = 0;
 1273     int i, j;
 1274     const char *sepname;
 1275     renamed[0] = dsc->page[0].label;
 1276     for (i=1; i<(int)dsc->page_count; i++) {
 1277     sepname = separation_name(rs, dsc->page[i].label);
 1278     /* Check if this is a duplicate separation, in which case
 1279      * we don't want to rename it twice.
 1280      */
 1281     for (j=1; j<i; j++)
 1282         if (strcmp(dsc->page[j].label, dsc->page[i].label) == 0) {
 1283         sepname = NULL; /* don't do it */
 1284         duplicated = 1;
 1285         }
 1286     /* If the separation name already exists in the renamed
 1287      * list, don't rename it */ 
 1288     if (sepname) {
 1289         for (j=1; j<i; j++) {
 1290             if (strcmp(renamed[j], sepname) == 0) {
 1291             sepname = NULL; /* don't do it */
 1292             duplicated = 1;
 1293             break;
 1294         }
 1295         }
 1296     }
 1297     if (sepname == NULL)
 1298         sepname = dsc->page[i].label;
 1299     renamed[i] = sepname;
 1300     }
 1301     if (duplicated)
 1302     return -1;  /* clash in separation names */
 1303     return 0;
 1304 }
 1305 
 1306 /* Find separation begin and end */
 1307 static int
 1308 dcs2_separation(CDSC *dsc, int pagenum, 
 1309     const char **fname, FILE_POS *pbegin, FILE_POS *pend)
 1310 {
 1311     GFile *f;
 1312     TCHAR wfname[MAXSTR];
 1313     *fname = dsc_find_platefile(dsc, pagenum);
 1314     if (*fname) {
 1315     narrow_to_cs(wfname, (int)sizeof(wfname), *fname, 
 1316         (int)strlen(*fname)+1);
 1317     if ((f = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) {
 1318         *pbegin = 0;
 1319         *pend = gfile_get_length(f);
 1320         gfile_close(f);
 1321     }
 1322     else {
 1323         /* Separation file didn't exist */
 1324         *pbegin = *pend = 0;
 1325         return 1;
 1326     }
 1327     }
 1328     else {
 1329     *pbegin = dsc->page[pagenum].begin;
 1330     *pend = dsc->page[pagenum].end;
 1331     }
 1332     return 0;
 1333 }
 1334 
 1335 
 1336 static int 
 1337 fix_custom(Doc *doc, char *buf, int buflen, const char *renamed[])
 1338 {
 1339     /* Create a new %%DocumentCustomColors:
 1340      * containing only those separations that exist
 1341      */
 1342     CDSC *dsc = doc->dsc;
 1343     int i;
 1344     int missing;
 1345     int n = 0;
 1346     FILE_POS begin, end;
 1347     const char *fname;
 1348     int count = min((int)strlen(buf), buflen);
 1349     if ((dsc == NULL) || !dsc->dcs2)
 1350     return 0;
 1351     for (i=1; i<(int)dsc->page_count; i++) {
 1352     const char *sepname = renamed[i];
 1353     missing = dcs2_separation(dsc, i, &fname, &begin, &end);
 1354     if (!missing && !is_process_colour(sepname)) {
 1355         n++;
 1356         strncpy(buf+count, " (", buflen-count-1);
 1357         count = (int)strlen(buf);
 1358         strncpy(buf+count, sepname, buflen-count-1);
 1359         count = (int)strlen(buf);
 1360         strncpy(buf+count, ")", buflen-count-1);
 1361         count = (int)strlen(buf);
 1362     }
 1363     }
 1364     return n;
 1365 }
 1366 
 1367 static int
 1368 fix_process(Doc *doc, char *buf, int buflen, const char *renamed[])
 1369 {
 1370     /* Create a new %%DocumentProcessColors:
 1371      * containing only those separations that exist
 1372      */
 1373     CDSC *dsc = doc->dsc;
 1374     int i;
 1375     int n = 0;
 1376     int missing;
 1377     FILE_POS begin, end;
 1378     const char *fname;
 1379     int count = min((int)strlen(buf), buflen);
 1380     if ((dsc == NULL) || !dsc->dcs2)
 1381     return 0;
 1382     for (i=1; i<(int)dsc->page_count; i++) {
 1383     const char *sepname = renamed[i];
 1384     missing = dcs2_separation(dsc, i, &fname, &begin, &end);
 1385     if (!missing && is_process_colour(sepname)) {
 1386         n++;
 1387         strncpy(buf+count, " ", buflen-count-1);
 1388         count++;
 1389         strncpy(buf+count, sepname, buflen-count-1);
 1390         count = (int)strlen(buf);
 1391     }
 1392     }
 1393     return n;
 1394 }
 1395 
 1396 /* Write out %%CMYKCustomColor line and extensions.
 1397  * count is the number of lines already written.
 1398  */
 1399 static int 
 1400 write_cmyk_custom(GFile *gf, Doc *doc, const char *renamed[], int count)
 1401 {
 1402     /* Create a new %%CMYKCustomColor:
 1403      * containing only those colours that exist
 1404      */
 1405     CDSC *dsc = doc->dsc;
 1406     CDSCCOLOUR *colour;
 1407     int i;
 1408     int missing;
 1409     int n = count;
 1410     FILE_POS begin, end;
 1411     const char *fname;
 1412     char buf[MAXSTR];
 1413     if ((dsc == NULL) || !dsc->dcs2)
 1414     return 0;
 1415     buf[sizeof(buf)-1] = '\0';
 1416     for (i=1; i<(int)dsc->page_count; i++) {
 1417     const char *sepname = renamed[i];
 1418     missing = dcs2_separation(dsc, i, &fname, &begin, &end);
 1419     if (!missing && !is_process_colour(sepname)) {
 1420         /* find colour values */
 1421         for (colour=dsc->colours; colour; colour=colour->next) {
 1422         if (strcmp(colour->name, dsc->page[i].label)==0)
 1423             break;
 1424         }
 1425         if ((colour != NULL) && 
 1426         (colour->custom == CDSC_CUSTOM_COLOUR_CMYK)) {
 1427         if (n == 0)
 1428             strncpy(buf, cmyk_custom_str, sizeof(buf)-1);
 1429         else
 1430             strncpy(buf, "%%+", sizeof(buf)-1);
 1431         snprintf(buf+strlen(buf), sizeof(buf)-1-strlen(buf), 
 1432             " %g %g %g %g (%s)",
 1433             colour->cyan, colour->magenta, colour->yellow, 
 1434             colour->black, sepname);
 1435         gfile_puts(gf, buf);
 1436         gfile_puts(gf, eol_str);
 1437         n++;
 1438         }
 1439     }
 1440     }
 1441     return n;
 1442 }
 1443 
 1444 /* Write out %%RGBCustomColor line and extensions.
 1445  * count is the number of lines already written.
 1446  */
 1447 static int 
 1448 write_rgb_custom(GFile *gf, Doc *doc, const char *renamed[], int count)
 1449 {
 1450     /* Create a new %%RGBCustomColor:
 1451      * containing only those colours that exist
 1452      */
 1453     CDSC *dsc = doc->dsc;
 1454     CDSCCOLOUR *colour;
 1455     int i;
 1456     int missing;
 1457     int n = count;
 1458     FILE_POS begin, end;
 1459     const char *fname;
 1460     char buf[MAXSTR];
 1461     if ((dsc == NULL) || !dsc->dcs2)
 1462     return 0;
 1463     buf[sizeof(buf)-1] = '\0';
 1464     for (i=1; i<(int)dsc->page_count; i++) {
 1465     const char *sepname = renamed[i];
 1466     missing = dcs2_separation(dsc, i, &fname, &begin, &end);
 1467     if (!missing && !is_process_colour(sepname)) {
 1468         /* find colour values */
 1469         for (colour=dsc->colours; colour; colour=colour->next) {
 1470         if (strcmp(colour->name, dsc->page[i].label)==0)
 1471             break;
 1472         }
 1473         if ((colour != NULL) && 
 1474         (colour->custom == CDSC_CUSTOM_COLOUR_RGB)) {
 1475         if (n == 0)
 1476             strncpy(buf, cmyk_custom_str, sizeof(buf)-1);
 1477         else
 1478             strncpy(buf, "%%+", sizeof(buf)-1);
 1479         snprintf(buf+strlen(buf), sizeof(buf)-1-strlen(buf), 
 1480             " %g %g %g (%s)",
 1481             colour->red, colour->green, colour->blue,
 1482             sepname);
 1483         gfile_puts(gf, buf);
 1484         gfile_puts(gf, eol_str);
 1485         n++;
 1486         }
 1487     }
 1488     }
 1489     return n;
 1490 }
 1491 
 1492 /* Write out DCS2 platefile comments, and any multiple file separations */
 1493 static FILE_POS
 1494 write_platefile_comments(Doc *doc, GFile *docfile, 
 1495     GFile *epsfile, LPCTSTR epsname,
 1496     int offset, FILE_POS file_offset, 
 1497     BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
 1498     const char *renamed[], BOOL some_renamed)
 1499 {
 1500     int i;
 1501     CDSC *dsc = doc->dsc;
 1502     FILE_POS begin, end;
 1503     FILE_POS len;
 1504     char platename[MAXSTR];
 1505     char outbuf[MAXSTR];
 1506     GFile *f;
 1507     FILE_POS offset2 = 0;
 1508 
 1509     /* Now write the platefile comments */
 1510     for (i=1; i<(int)dsc->page_count; i++) {
 1511     /* First find length of separation */
 1512     int missing;
 1513     const char *fname = NULL;
 1514     const char *sepname = renamed[i];
 1515     missing = dcs2_separation(dsc, i, &fname, &begin, &end);
 1516     len = end - begin;
 1517     /* Now write out platefile */
 1518     if (missing && (missing_separations || some_renamed)) {
 1519         if (debug & DEBUG_GENERAL)
 1520         app_msgf(doc->app, 
 1521             "Skipping missing separation page %d \042%s\042\n",
 1522             i, dsc->page[i].label);
 1523     }
 1524     else if (dcs2_multi) {
 1525         int j;
 1526         int duplicate = 0;
 1527         memset(platename, 0, sizeof(platename));
 1528         cs_to_narrow(platename, sizeof(platename)-1, epsname, 
 1529         (int)cslen(epsname)+1);
 1530         strncat(platename, ".", sizeof(platename) - strlen(platename));
 1531         strncat(platename, sepname, sizeof(platename) - strlen(platename));
 1532         for (j=1; j<i; j++) {
 1533         /* Check if separation name is a duplicate */ 
 1534         if (strcmp(sepname, renamed[j]) == 0)
 1535             duplicate = 1;
 1536         }
 1537         if (duplicate) /* append page number to make the filename unique */
 1538         snprintf(platename+strlen(platename), 
 1539             sizeof(platename) - strlen(platename),
 1540             ".%d", i);
 1541         snprintf(outbuf, sizeof(outbuf)-1,  
 1542         "%%%%PlateFile: (%s) EPS Local %s",
 1543         sepname, platename);
 1544         gfile_puts(epsfile, outbuf);
 1545         gfile_puts(epsfile, eol_str);   /* change EOL */
 1546         if (write_all) {
 1547         /* Write out multi file separations */
 1548             TCHAR wfname[MAXSTR];
 1549         GFile *pf;
 1550         narrow_to_cs(wfname, (int)sizeof(wfname), platename, 
 1551             (int)strlen(platename)+1);
 1552         pf = gfile_open(wfname, gfile_modeWrite | gfile_modeCreate);
 1553         if (pf != (GFile *)NULL) {
 1554             const char *fname = dsc_find_platefile(dsc, i);
 1555             if (fname) {
 1556             narrow_to_cs(wfname, (int)sizeof(wfname), 
 1557                 fname, (int)strlen(fname)+1);
 1558             if ((f = gfile_open(wfname, gfile_modeRead)) 
 1559                 != (GFile *)NULL) {
 1560                 ps_copy(pf, f, begin, end);
 1561                 gfile_close(f);
 1562             }
 1563             }
 1564             else {
 1565             ps_copy(pf, docfile, begin, end);
 1566             }
 1567             gfile_close(pf);
 1568         }
 1569         else {
 1570             return (FILE_POS)-1;    /* error */
 1571         }
 1572         }
 1573     }
 1574     else {
 1575         char fmtbuf[MAXSTR];
 1576         snprintf(fmtbuf, sizeof(fmtbuf)-1,  
 1577             "%%%%%%%%PlateFile: (%%s) EPS #%%010%s %%010%s",
 1578         DSC_OFFSET_FORMAT, DSC_OFFSET_FORMAT);
 1579         snprintf(outbuf, sizeof(outbuf)-1, fmtbuf,
 1580         sepname, offset+file_offset+offset2, len);
 1581         gfile_puts(epsfile, outbuf);
 1582         gfile_puts(epsfile, eol_str);   /* change EOL */
 1583         offset2 += len;
 1584     }
 1585     }
 1586     return offset2;
 1587 }
 1588 
 1589 /* Write out DCS2 single file separations */
 1590 static FILE_POS
 1591 write_singlefile_separations(Doc *doc, GFile *docfile, 
 1592     GFile *epsfile, 
 1593     BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
 1594     BOOL some_renamed)
 1595 {
 1596     int i;
 1597     CDSC *dsc = doc->dsc;
 1598     FILE_POS begin, end;
 1599     FILE_POS len;
 1600     GFile *f;
 1601     if (write_all && !dcs2_multi) {
 1602     for (i=1; i<(int)dsc->page_count; i++) {
 1603         int missing;
 1604         const char *fname = NULL;
 1605         missing = dcs2_separation(dsc, i, &fname, &begin, &end);
 1606         len = end - begin;
 1607         if (missing && (missing_separations || some_renamed)) {
 1608         if (debug & DEBUG_GENERAL)
 1609             app_msgf(doc->app, 
 1610             "Skipping missing separation page %d \042%s\042\n",
 1611             i, dsc->page[i].label);
 1612         }
 1613         else if (fname) {
 1614             TCHAR wfname[MAXSTR];
 1615         narrow_to_cs(wfname, (int)sizeof(wfname), fname, 
 1616             (int)strlen(fname)+1);
 1617         if ((f = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) {
 1618             begin = 0;
 1619             end = gfile_get_length(f);
 1620             if (debug & DEBUG_GENERAL)
 1621             app_msgf(doc->app, 
 1622                 "Copying page %d from \042%s\042  %ld %ld\n",
 1623                 i, fname, begin, end);
 1624             ps_copy(epsfile, f, begin, end);
 1625             gfile_close(f);
 1626         }
 1627         }
 1628         else {
 1629         begin = dsc->page[i].begin;
 1630         end = dsc->page[i].end;
 1631         if (debug & DEBUG_GENERAL)
 1632             app_msgf(doc->app, 
 1633             "Copying page %d  %ld %ld\n",
 1634             i, fname, begin, end);
 1635         ps_copy(epsfile, docfile, begin, end);
 1636         }
 1637     }
 1638     }
 1639     return 0;
 1640 }
 1641 
 1642 /* Check that two DCS2 files can be combined */
 1643 static int 
 1644 check_dcs2_combine(Doc *doc1, Doc *doc2, 
 1645     const char **renamed1, const char **renamed2, int tolerance)
 1646 {
 1647     CDSC *dsc1;
 1648     CDSC *dsc2;
 1649     const char *sepname1;
 1650     const char *sepname2;
 1651     int i, j;
 1652 
 1653     if (doc1 == NULL)
 1654     return -1;
 1655     if (doc2 == NULL)
 1656     return -1;
 1657     dsc1 = doc1->dsc;
 1658     dsc2 = doc2->dsc;
 1659     if (!dsc1->dcs2)
 1660     return -1;
 1661     if (!dsc2->dcs2)
 1662     return -1;
 1663     if (dsc1->bbox == NULL)
 1664     return -1;
 1665     if (dsc2->bbox == NULL)
 1666     return -1;
 1667     /* Check that bounding boxes match */
 1668     if ((dsc1->bbox->llx > dsc2->bbox->llx + tolerance) ||
 1669         (dsc1->bbox->llx < dsc2->bbox->llx - tolerance) ||
 1670         (dsc1->bbox->lly > dsc2->bbox->lly + tolerance) ||
 1671         (dsc1->bbox->lly < dsc2->bbox->lly - tolerance) ||
 1672         (dsc1->bbox->urx > dsc2->bbox->urx + tolerance) ||
 1673         (dsc1->bbox->urx < dsc2->bbox->urx - tolerance) ||
 1674         (dsc1->bbox->ury > dsc2->bbox->ury + tolerance) ||
 1675         (dsc1->bbox->ury < dsc2->bbox->ury - tolerance)) {
 1676     app_msgf(doc1->app, "Bounding Boxes don't match\n");
 1677     return -1;
 1678     }
 1679     /* Check that separations don't conflict */
 1680     for (i=1; i<(int)dsc1->page_count; i++) {
 1681     sepname1 = renamed1[i];
 1682     for (j=1; i<(int)dsc2->page_count; i++) {
 1683         sepname2 = renamed2[j];
 1684         if (strcmp(sepname1, sepname2) == 0) {
 1685         app_msgf(doc1->app, 
 1686             "Separation \042%s\042 appears in both files\n",
 1687             sepname1);
 1688         return -1;
 1689         }
 1690     }
 1691     }
 1692     return 0;
 1693 }
 1694 
 1695 /* Copy a DCS 2.0 file.
 1696  * DSC 2.0 as single file looks like concatenated EPS files.
 1697  * DSC parser treats these as separate pages and the
 1698  * entire first EPS file is contained in the first page.
 1699  * That is, there is no header, prolog or trailer.
 1700  * Don't update the bounding box.
 1701  * Do update the %%PlateFile comments.
 1702  * If missing_separations is true, remove the names of missing
 1703  * separations from the DSC comments.
 1704  * The length of the composite page is returned in complen.
 1705  * If composite is not NULL, use this file as the new composite page
 1706  * with the existing header.
 1707  * If rs is not NULL, rename some separations.
 1708  * If doc2 is not NULL, add its separations.  It is an error if
 1709  * separations are duplicated or the bounding box differs by more
 1710  * than tolerance points.
 1711  */
 1712 int
 1713 copy_dcs2(Doc *doc, GFile *docfile, 
 1714     Doc *doc2, GFile *docfile2,
 1715     GFile *epsfile, LPCTSTR epsname,
 1716     int offset, BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
 1717     FILE_POS *complen, GFile *composite, RENAME_SEPARATION *rs,
 1718     int tolerance)
 1719 {
 1720     const char platefile_str[] = "%%PlateFile:";
 1721     const char cyanplate_str[] = "%%CyanPlate:";
 1722     const char magentaplate_str[] = "%%MagentaPlate:";
 1723     const char yellowplate_str[] = "%%YellowPlate:";
 1724     const char blackplate_str[] = "%%BlackPlate:";
 1725     const char endcomments_str[] = "%%EndComments";
 1726     char buf[DSC_LINE_LENGTH+1];
 1727     char outbuf[MAXSTR];
 1728     CDSC *dsc = doc->dsc;
 1729     FILE_POS len;
 1730     FILE_POS file_offset = *complen;
 1731     FILE_POS begin, end;
 1732     FILE_POS header_position;
 1733     BOOL found_endheader = FALSE;
 1734     BOOL ignore_continuation = FALSE;
 1735     int count;
 1736     const char **renamed1 = NULL;
 1737     const char **renamed2 = NULL;
 1738     
 1739     if (dsc->page_count == 0)
 1740     return -1;
 1741 
 1742     /* Get renamed separations */
 1743     renamed1 = (const char **)malloc(sizeof(const char *) * dsc->page_count);
 1744     if (renamed1 == NULL)
 1745     return -1;
 1746     if (rename_separations(dsc, rs, renamed1) != 0) {
 1747     free((void *)renamed1);
 1748     return -1;
 1749     }
 1750     if (doc2) {
 1751     renamed2 = (const char **)
 1752         malloc(sizeof(const char *) * doc2->dsc->page_count);
 1753     if (renamed2 == NULL) {
 1754         free((void *)renamed1);
 1755         return -1;
 1756     }
 1757     if (rename_separations(doc2->dsc, rs, renamed2) != 0) {
 1758         free((void *)renamed1);
 1759         free((void *)renamed2);
 1760         return -1;
 1761     }
 1762     }
 1763 
 1764     if (doc2 && check_dcs2_combine(doc, doc2, renamed1, renamed2, tolerance)) {
 1765     free((void *)renamed1);
 1766     free((void *)renamed2);
 1767     return -1;
 1768     }
 1769 
 1770     gfile_seek(docfile, dsc->page[0].begin, gfile_begin);
 1771     memset(buf, 0, sizeof(buf)-1);
 1772     count = ps_fgets(buf, 
 1773     min(sizeof(buf)-1, dsc->page[0].end - dsc->page[0].begin), docfile);
 1774     header_position = gfile_get_position(docfile);
 1775     if (count) { 
 1776     /* copy version line */
 1777     gfile_write(epsfile, buf, without_eol(buf, count));
 1778     gfile_puts(epsfile, eol_str);   /* change EOL */
 1779     }
 1780     while ((count = ps_fgets(buf, 
 1781     min(sizeof(buf)-1, dsc->page[0].end - header_position), 
 1782     docfile)) != 0) {
 1783     header_position = gfile_get_position(docfile);
 1784     /* check if end of header */
 1785         if (count < 2)
 1786         found_endheader = TRUE;
 1787     if (buf[0] != '%')
 1788         found_endheader = TRUE;
 1789     if ((buf[0] == '%') && ((buf[1] == ' ') || 
 1790          (buf[1] == '\t') || (buf[1] == '\r') || (buf[1] == '\n')))
 1791         found_endheader = TRUE;
 1792     if (strncmp(buf, endcomments_str, strlen(endcomments_str)) == 0)
 1793         found_endheader = TRUE;
 1794     if (strncmp(buf, "%%Begin", 7) == 0)
 1795         found_endheader = TRUE;
 1796     if (found_endheader)
 1797         break;  /* write out count characters from buf later */
 1798     if ((buf[0] == '%') && (buf[1] == '%') && (buf[2] == '+') &&
 1799         ignore_continuation)
 1800         continue;
 1801     else
 1802         ignore_continuation = FALSE;
 1803     if ((strncmp(buf, platefile_str, strlen(platefile_str)) != 0) &&
 1804          (strncmp(buf, cyanplate_str, strlen(cyanplate_str)) != 0) &&
 1805          (strncmp(buf, magentaplate_str, strlen(magentaplate_str)) != 0) &&
 1806          (strncmp(buf, yellowplate_str, strlen(yellowplate_str)) != 0) &&
 1807          (strncmp(buf, blackplate_str, strlen(blackplate_str)) != 0)) {
 1808         /* Write all header lines except for DCS plate lines */
 1809         if ((rs != NULL) || missing_separations || doc2) {
 1810         /* but don't write custom/process colour lines */
 1811             if (strncmp(buf, custom_str, strlen(custom_str)) == 0) {
 1812             count = 0;
 1813             ignore_continuation = TRUE;
 1814         }
 1815         else if (strncmp(buf, process_str, strlen(process_str)) == 0) {
 1816             count = 0;
 1817             ignore_continuation = TRUE;
 1818         }
 1819         else if (strncmp(buf, cmyk_custom_str, 
 1820             strlen(cmyk_custom_str)) == 0) {
 1821             count = 0;
 1822             ignore_continuation = TRUE;
 1823         }
 1824         else if (strncmp(buf, rgb_custom_str, 
 1825             strlen(rgb_custom_str)) == 0) {
 1826             count = 0;
 1827             ignore_continuation = TRUE;
 1828         }
 1829         }
 1830         if (count == 0)
 1831         continue;
 1832         gfile_write(epsfile, buf, without_eol(buf, count));
 1833         gfile_puts(epsfile, eol_str);   /* change EOL */
 1834     }
 1835     }
 1836 
 1837     /* Now write DocumentProcessColors, DocumentCustomColors,
 1838      * CMYKCustomColor and RGBCustomColor
 1839      */
 1840     if ((rs!=NULL) || missing_separations || doc2) {
 1841     int n;  /* number of entries written */
 1842         strncpy(outbuf, process_str, sizeof(outbuf));
 1843     n = fix_process(doc, outbuf, sizeof(outbuf), renamed1);
 1844     if (doc2)
 1845         n += fix_process(doc2, outbuf, sizeof(outbuf), renamed2);
 1846     if (n) {
 1847         gfile_write(epsfile, outbuf, 
 1848         without_eol(outbuf, (int)strlen(outbuf)));
 1849         gfile_puts(epsfile, eol_str);   /* change EOL */
 1850     }
 1851         strncpy(outbuf, custom_str, sizeof(outbuf));
 1852     n = fix_custom(doc, outbuf, sizeof(outbuf), renamed1);
 1853     if (doc2)
 1854         n += fix_custom(doc2, outbuf, sizeof(outbuf), renamed2);
 1855     if (n) {
 1856         gfile_write(epsfile, outbuf, 
 1857         without_eol(outbuf, (int)strlen(outbuf)));
 1858         gfile_puts(epsfile, eol_str);   /* change EOL */
 1859     }
 1860     n = write_cmyk_custom(epsfile, doc, renamed1, 0);
 1861     if (doc2)
 1862         write_cmyk_custom(epsfile, doc2, renamed2, n);
 1863     n = write_rgb_custom(epsfile, doc, renamed1, 0);
 1864     if (doc2)
 1865         write_rgb_custom(epsfile, doc2, renamed2, n);
 1866     }
 1867 
 1868 
 1869     /* Write out the platefile comments and any multiple file separations */
 1870     len = write_platefile_comments(doc, docfile, epsfile, epsname, 
 1871     offset, file_offset, 
 1872     dcs2_multi, write_all, missing_separations, renamed1, (rs != NULL));
 1873     if (len == (FILE_POS)-1) {
 1874     free((void *)renamed1);
 1875     if (renamed2)
 1876         free((void *)renamed2);
 1877     return -1;
 1878     }
 1879     file_offset += len;
 1880     if (doc2) {
 1881     len = write_platefile_comments(doc2, docfile2, epsfile, epsname, 
 1882         offset, file_offset, 
 1883         dcs2_multi, write_all, missing_separations, renamed2, (rs != NULL));
 1884     if (len == (FILE_POS)-1) {
 1885         free((void *)renamed1);
 1886         if (renamed2)
 1887         free((void *)renamed2);
 1888         return -1;
 1889     }
 1890     file_offset += len;
 1891     }
 1892 
 1893     /* Copy last line of header */
 1894     if (found_endheader) {
 1895     gfile_write(epsfile, buf, without_eol(buf, count));
 1896     gfile_puts(epsfile, eol_str);   /* change EOL */
 1897     }
 1898     /* copy rest of composite */
 1899     if (composite) {
 1900     if (dsc->page_pages == 1) {
 1901         gfile_puts(epsfile, "%%Page: 1 1");
 1902         gfile_puts(epsfile, eol_str);   /* change EOL */
 1903     }
 1904     end = gfile_get_length(composite);
 1905     gfile_seek(composite, 0, gfile_begin);
 1906     snprintf(outbuf, sizeof(outbuf)-1, "%%BeginDocument: composite");
 1907     gfile_puts(epsfile, "%%BeginDocument: composite");
 1908     gfile_puts(epsfile, eol_str);   /* change EOL */
 1909     ps_copy(epsfile, composite, 0, end);
 1910     gfile_puts(epsfile, "%%EndDocument");
 1911     gfile_puts(epsfile, eol_str);   /* change EOL */
 1912     gfile_puts(epsfile, "%%Trailer");
 1913     gfile_puts(epsfile, eol_str);   /* change EOL */
 1914     }
 1915     else {
 1916     begin = header_position;
 1917     end = dsc->page[0].end;
 1918     ps_copy(epsfile, docfile, begin, end);
 1919     }
 1920 
 1921     file_offset = gfile_get_position(epsfile);
 1922     *complen = file_offset;
 1923 
 1924     /* Write out single file separations */
 1925     write_singlefile_separations(doc, docfile, epsfile, 
 1926         dcs2_multi, write_all, missing_separations, (rs != NULL));
 1927     if (doc2)
 1928         write_singlefile_separations(doc2, docfile2, epsfile, 
 1929             dcs2_multi, write_all, missing_separations, (rs != NULL));
 1930     free((void *)renamed1);
 1931     if (renamed2)
 1932     free((void *)renamed2);
 1933     return 0;
 1934 }
 1935 
 1936 
 1937 
 1938 /* Copy an EPS file.
 1939  * %%BoundingBox and %%HiResBoundingBox will be brought to
 1940  * the start of the header.
 1941  * The new EPS file will have a prolog of "offset" bytes,
 1942  * so update DCS 2.0 offsets accordingly.
 1943  */
 1944 int
 1945 copy_eps(Doc *doc, LPCTSTR epsname, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, 
 1946     int offset, BOOL dcs2_multi)
 1947 {
 1948     GFile *docfile;
 1949     GFile *f = NULL;
 1950     CDSC *dsc = doc->dsc;
 1951     int code = 0;
 1952 
 1953     docfile = gfile_open(doc_name(doc), gfile_modeRead);
 1954     if (docfile == (GFile *)NULL) {
 1955     app_csmsgf(doc->app, 
 1956         TEXT("Can't open document file \042%s\042\n"), doc_name(doc));
 1957     return -1;
 1958     }
 1959 
 1960     f = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
 1961     if (f == (GFile *)NULL) {
 1962     app_csmsgf(doc->app, 
 1963         TEXT("Can't open EPS file \042%s\042\n"), epsname);
 1964     gfile_close(docfile);
 1965     return -1;
 1966     }
 1967 
 1968     if (dsc->dcs2) {
 1969     /* Write DCS 2.0, updating the %%PlateFile, but don't update
 1970      * %%BoundingBox.
 1971      */
 1972     FILE_POS complen = 0;   /* length of composite page */
 1973     /* Write once to calculate the offsets */
 1974     code = copy_dcs2(doc, docfile, NULL, NULL, f, epsname, 
 1975         offset, dcs2_multi, FALSE, FALSE, &complen, NULL, NULL, 0);
 1976     gfile_seek(docfile, 0, gfile_begin);
 1977     gfile_close(f);
 1978     f = NULL;
 1979     if (code == 0) {
 1980         f = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
 1981         if (f == (GFile *)NULL) {
 1982         app_csmsgf(doc->app, 
 1983             TEXT("Can't open EPS file \042%s\042\n"), epsname);
 1984         gfile_close(docfile);
 1985         return -1;
 1986         }
 1987     }
 1988     if (code == 0) {
 1989         /* Then again with the correct offsets */
 1990         gfile_seek(f, 0, gfile_begin);
 1991         code = copy_dcs2(doc, docfile, NULL, NULL, f, epsname,
 1992         offset, dcs2_multi, TRUE, FALSE, &complen, NULL, NULL, 0);
 1993     }
 1994     }
 1995     else {
 1996     /* Update the bounding box in the header and remove it from
 1997      * the trailer
 1998      */
 1999     copy_bbox_header(f, docfile, 
 2000         dsc->begincomments, dsc->endcomments,
 2001         bbox, hires_bbox);
 2002     ps_copy(f, docfile, dsc->begindefaults, dsc->enddefaults);
 2003     ps_copy(f, docfile, dsc->beginprolog, dsc->endprolog);
 2004     ps_copy(f, docfile, dsc->beginsetup, dsc->endsetup);
 2005     if (dsc->page_count)
 2006         ps_copy(f, docfile, dsc->page[0].begin, dsc->page[0].end);
 2007     copy_nobbox(f, docfile, dsc->begintrailer, dsc->endtrailer);
 2008     }
 2009     if (f)
 2010     gfile_close(f);
 2011     gfile_close(docfile);
 2012     return code;
 2013 }
 2014 
 2015 
 2016 
 2017 /*********************************************************/
 2018 
 2019 /* make an EPSI file with an Interchange Preview */
 2020 /* from a PS file and a bitmap */
 2021 int
 2022 make_eps_interchange(Doc *doc, IMAGE *img, CDSCBBOX devbbox, 
 2023     CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, LPCTSTR epsname)
 2024 {
 2025     GFile *epsfile;
 2026     GFile *docfile;
 2027     int code;
 2028     CDSC *dsc = doc->dsc;
 2029 
 2030     if (dsc == NULL)
 2031     return -1;
 2032 
 2033     if ((docfile = gfile_open(doc_name(doc), gfile_modeRead)) 
 2034     == (GFile *)NULL) {
 2035     app_csmsgf(doc->app, 
 2036         TEXT("Can't open EPS file \042%s\042\n"),
 2037         doc_name(doc));
 2038     return -1;
 2039     }
 2040 
 2041     epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
 2042 
 2043     if (epsfile == (GFile *)NULL) {
 2044     app_csmsgf(doc->app, 
 2045         TEXT("Can't open output EPS file \042%s\042\n"),
 2046         epsname);
 2047     gfile_close(docfile);
 2048     return -1;
 2049     }
 2050 
 2051     /* adjust %%BoundingBox: and %%HiResBoundingBox: comments */
 2052     copy_bbox_header(epsfile, docfile, dsc->begincomments, dsc->endcomments, 
 2053     bbox, hires_bbox);
 2054 
 2055     code = write_interchange(epsfile, img, devbbox);
 2056 
 2057     ps_copy(epsfile, docfile, dsc->begindefaults, dsc->enddefaults);
 2058     ps_copy(epsfile, docfile, dsc->beginprolog, dsc->endprolog);
 2059     ps_copy(epsfile, docfile, dsc->beginsetup, dsc->endsetup);
 2060     if (dsc->page_count)
 2061     ps_copy(epsfile, docfile, dsc->page[0].begin, dsc->page[0].end);
 2062     copy_nobbox(epsfile, docfile, dsc->begintrailer, dsc->endtrailer);
 2063     gfile_close(docfile);
 2064     if (*epsname!='\0') {
 2065     gfile_close(epsfile);
 2066     if (code && (!(debug & DEBUG_GENERAL)))
 2067         csunlink(epsname);
 2068     }
 2069     return code;
 2070 }
 2071 
 2072 
 2073 /*********************************************************/
 2074 
 2075 
 2076 /* make a PC EPS file with a Windows Metafile Preview */
 2077 /* from a PS file and a bitmap */
 2078 int
 2079 make_eps_metafile(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox, 
 2080     CDSCFBBOX *hires_bbox, float xdpi, float ydpi, BOOL reverse,
 2081     LPCTSTR epsname)
 2082 {
 2083     MFH mf;
 2084     GFile *epsfile;
 2085     GFile *tpsfile;
 2086     TCHAR tpsname[MAXSTR];
 2087     int code;
 2088     int count;
 2089     char *buffer;
 2090     CDSCDOSEPS doseps;
 2091 
 2092     /* prepare metafile header and calculate length */
 2093     code = metafile_init(img, &devbbox, &mf);
 2094 
 2095     /* Create temporary EPS file with updated headers */
 2096     tpsfile = NULL;
 2097     memset(tpsname, 0, sizeof(tpsname));
 2098     if ((tpsfile = app_temp_gfile(doc->app, tpsname, 
 2099     sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
 2100     app_csmsgf(doc->app, 
 2101         TEXT("Can't create temporary EPS file \042%s\042\n"),
 2102         tpsname);
 2103     return -1;
 2104     }
 2105     gfile_close(tpsfile);
 2106 
 2107     code = copy_eps(doc, tpsname, bbox, hires_bbox, DOSEPS_HEADER_SIZE, FALSE); 
 2108     if (code)
 2109     return -1;
 2110 
 2111     if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
 2112     app_csmsgf(doc->app, 
 2113         TEXT("Can't open temporary EPS file \042%s\042\n"),
 2114         tpsname);
 2115     return -1;
 2116     }
 2117 
 2118     /* Create DOS EPS output file */
 2119     epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
 2120     if (epsfile == (GFile *)NULL) {
 2121     app_csmsgf(doc->app, 
 2122         TEXT("Can't open output EPS file \042%s\042\n"),
 2123         epsname);
 2124     gfile_close(tpsfile);
 2125     if (!(debug & DEBUG_GENERAL))
 2126         csunlink(tpsname);
 2127     return -1;
 2128     }
 2129 
 2130     doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile);
 2131     doseps.wmf_length = mf.size * 2;
 2132     doseps.tiff_begin = 0;
 2133     doseps.tiff_length = 0;
 2134     doseps.checksum = 0xffff;
 2135     if (reverse) {
 2136     doseps.wmf_begin = DOSEPS_HEADER_SIZE;
 2137     doseps.ps_begin = doseps.wmf_begin + doseps.wmf_length;
 2138     }
 2139     else {
 2140     doseps.ps_begin = DOSEPS_HEADER_SIZE;
 2141     doseps.wmf_begin = doseps.ps_begin + doseps.ps_length;
 2142     }
 2143     write_doseps_header(&doseps, epsfile);
 2144 
 2145     buffer = (char *)malloc(COPY_BUF_SIZE);
 2146     if (buffer == (char *)NULL) {
 2147     if (epsname[0]) {
 2148         gfile_close(epsfile);
 2149         if (!(debug & DEBUG_GENERAL))
 2150         csunlink(epsname);
 2151     }
 2152     gfile_close(tpsfile);
 2153     if (!(debug & DEBUG_GENERAL))
 2154         csunlink(tpsname);
 2155     return -1;
 2156     }
 2157 
 2158     gfile_seek(tpsfile, 0, gfile_begin);
 2159     if (!reverse) {
 2160     /* copy EPS file */
 2161     while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
 2162         gfile_write(epsfile, buffer, count);
 2163     }
 2164 
 2165     /* copy metafile */
 2166     code = write_metafile(epsfile, img, devbbox, xdpi, ydpi, &mf);
 2167 
 2168     if (reverse) {
 2169     /* copy EPS file */
 2170     while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
 2171         gfile_write(epsfile, buffer, count);
 2172     }
 2173 
 2174     free(buffer);
 2175     gfile_close(tpsfile);
 2176     if (!(debug & DEBUG_GENERAL))
 2177     csunlink(tpsname);
 2178     if (epsname[0])
 2179        gfile_close(epsfile);
 2180     return 0;
 2181 }
 2182 
 2183 /*********************************************************/
 2184 /* Create a Macintosh file with PICT preview */
 2185 /* from a PS file and a bitmap */
 2186 
 2187 int
 2188 make_eps_pict(Doc *doc, IMAGE *img, CDSCBBOX *bbox, 
 2189     CDSCFBBOX *hires_bbox, float xdpi, float ydpi, CMAC_TYPE mac_type,
 2190     LPCTSTR epsname)
 2191 {
 2192     GFile *epsfile;
 2193     GFile *tpsfile;
 2194     TCHAR tpsname[MAXSTR];
 2195     GFile *tpictfile;
 2196     TCHAR tpictname[MAXSTR];
 2197     char filename[MAXSTR];
 2198     int code = 0;
 2199     int len;
 2200     CMAC_TYPE type = mac_type;
 2201     const TCHAR *tp, *tq;
 2202 
 2203     len = (int)cslen(epsname);
 2204     if (mac_type != CMAC_TYPE_NONE)
 2205     type = mac_type;
 2206     else if (epsname[0] == '.')
 2207     type = CMAC_TYPE_DOUBLE;
 2208     else if ((len > 3) &&
 2209     (epsname[len-3] == '.') &&
 2210     ((epsname[len-2] == 'a') || (epsname[len-2] == 'A')) &&
 2211     ((epsname[len-1] == 's') || (epsname[len-1] == 'S')) )
 2212     type = CMAC_TYPE_SINGLE;
 2213     else if ((len > 5) &&
 2214     ((epsname[len-5] == '.') || (epsname[len-5] == '/')) &&
 2215     ((epsname[len-4] == 'r') || (epsname[len-4] == 'R')) &&
 2216     ((epsname[len-3] == 's') || (epsname[len-3] == 'S')) &&
 2217     ((epsname[len-2] == 'r') || (epsname[len-2] == 'R')) &&
 2218     ((epsname[len-1] == 'c') || (epsname[len-1] == 'C')) )
 2219     type = CMAC_TYPE_RSRC;
 2220     else
 2221     type = CMAC_TYPE_MACBIN;
 2222 
 2223     /* Create temporary EPS file with updated headers */
 2224     tpsfile = NULL;
 2225     memset(tpsname, 0, sizeof(tpsname));
 2226     if ((tpsfile = app_temp_gfile(doc->app, tpsname, 
 2227     sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
 2228     app_csmsgf(doc->app, 
 2229         TEXT("Can't create temporary EPS file \042%s\042\n"),
 2230         tpsname);
 2231     return -1;
 2232     }
 2233     gfile_close(tpsfile);
 2234 
 2235     code = copy_eps(doc, tpsname, bbox, hires_bbox, 0, FALSE); 
 2236     if (code)
 2237     return -1;
 2238 
 2239     if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
 2240     app_csmsgf(doc->app, 
 2241         TEXT("Can't open temporary EPS file \042%s\042\n"),
 2242         tpsname);
 2243     return -1;
 2244     }
 2245     gfile_close(tpsfile);
 2246 
 2247     /* Create temporary PICT file */
 2248     tpictfile = NULL;
 2249     memset(tpictname, 0, sizeof(tpictname));
 2250     if ((tpictfile = app_temp_gfile(doc->app, tpictname, 
 2251     sizeof(tpictname)/sizeof(TCHAR))) == (GFile *)NULL) {
 2252     app_csmsgf(doc->app, 
 2253         TEXT("Can't create temporary PICT file \042%s\042\n"),
 2254         tpictname);
 2255     return -1;
 2256     }
 2257     gfile_close(tpictfile);
 2258     code = image_to_pictfile(img, tpictname, xdpi, ydpi);
 2259 
 2260     /* Create Mac output file */
 2261     epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
 2262     if (epsfile == (GFile *)NULL) {
 2263     app_csmsgf(doc->app, 
 2264         TEXT("Can't open output EPS file \042%s\042\n"),
 2265         epsname);
 2266     gfile_close(tpsfile);
 2267     if (!(debug & DEBUG_GENERAL))
 2268         csunlink(tpsname);
 2269     return -1;
 2270     }
 2271     
 2272     switch (type) {
 2273     case CMAC_TYPE_SINGLE:
 2274         code = write_applesingle(epsfile, tpsname, tpictname);
 2275         break;
 2276     case CMAC_TYPE_DOUBLE:
 2277         code = write_appledouble(epsfile, tpictname);
 2278         break;
 2279     case CMAC_TYPE_MACBIN:
 2280         memset(filename, 0, sizeof(filename));
 2281             /* Remove path information */
 2282         tp = tq = epsname;
 2283         while (*tp != '\0') {
 2284         if ((*tp == '\\') || (*tp == '/') || (*tp == ':'))
 2285             tq = CHARNEXT(tp);
 2286         tp = CHARNEXT(tp);
 2287         }
 2288         cs_to_narrow(filename, (int)sizeof(filename)-1, 
 2289             tq, (int)cslen(tq)+1);
 2290         len = (int)strlen(filename);
 2291         /* Remove trailing .bin */
 2292             if ((len > 4) &&
 2293         (filename[len-4] == '.') &&
 2294         ((filename[len-3] == 'b') || (filename[len-3] == 'B')) && 
 2295         ((filename[len-2] == 'i') || (filename[len-2] == 'I')) &&
 2296         ((filename[len-1] == 'n') || (filename[len-1] == 'N')) )
 2297         filename[len-4] = '\0'; /* remove ".bin" inside MacBinary */
 2298         code = write_macbin(epsfile, filename, tpsname, tpictname);
 2299         break;
 2300     case CMAC_TYPE_RSRC:
 2301         /* Just copy the resources */
 2302             code = (write_resource_pict(epsfile, tpictname) < 0);
 2303         break;
 2304     default:
 2305         code = -1;
 2306     }
 2307 
 2308     if (!(debug & DEBUG_GENERAL))
 2309     csunlink(tpsname);
 2310     if (!(debug & DEBUG_GENERAL))
 2311     csunlink(tpictname);
 2312     if (epsname[0]) {
 2313         gfile_close(epsfile);
 2314     if ((code<0) && (!(debug & DEBUG_GENERAL)))
 2315         csunlink(epsname);
 2316     }
 2317     return code;
 2318 }
 2319 
 2320 /*********************************************************/
 2321 /* Copy one page to a file. 
 2322  * This will be used for feeding directly to Ghostscript,
 2323  * so don't bother updating header comments.
 2324  * Add code to force one and one only showpage.
 2325  */
 2326 int
 2327 copy_page_temp(Doc *doc, GFile *f, int page)
 2328 {
 2329     const char save_str[] = 
 2330     "%!\nsave /GSview_save exch def\n/showpage {} def\n";
 2331     const char restore_str[] = 
 2332         "\nclear cleardictstack GSview_save restore\nshowpage\n";
 2333     int code;
 2334     gfile_puts(f, save_str);
 2335     code  = copy_page_nosave(doc, f, page);
 2336     gfile_puts(f, restore_str);
 2337     return code;
 2338 }
 2339 
 2340 int
 2341 copy_page_nosave(Doc *doc, GFile *f, int page)
 2342 {
 2343     CDSC *dsc = doc->dsc;
 2344     GFile *docfile;
 2345     const char *fname;
 2346     if (dsc == NULL)
 2347     return -1;
 2348    
 2349     fname = dsc_find_platefile(dsc, page);
 2350     if (fname) {
 2351     /* A separation in a separate file */
 2352     FILE_POS end;
 2353     TCHAR wfname[MAXSTR];
 2354     narrow_to_cs(wfname, (int)sizeof(wfname), fname, (int)strlen(fname)+1);
 2355     if ((docfile = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) {
 2356         end = gfile_get_length(docfile);
 2357         ps_copy(f, docfile, 0, end);
 2358         gfile_close(docfile);
 2359     }
 2360     /* else separation is missing, don't flag an error */
 2361     }
 2362     else {
 2363     /* ordinary file */
 2364     if ((docfile = gfile_open(doc_name(doc), gfile_modeRead)) 
 2365         == (GFile *)NULL) {
 2366         app_csmsgf(doc->app, 
 2367         TEXT("Can't open document file \042%s\042\n"),
 2368         doc_name(doc));
 2369         return -1;
 2370     }
 2371     ps_copy(f, docfile, dsc->begincomments, dsc->endcomments);
 2372     ps_copy(f, docfile, dsc->begindefaults, dsc->enddefaults);
 2373     ps_copy(f, docfile, dsc->beginprolog, dsc->endprolog);
 2374     ps_copy(f, docfile, dsc->beginsetup, dsc->endsetup);
 2375     if (dsc->page_count && (page >= 0) && (page < (int)dsc->page_count))
 2376         ps_copy(f, docfile, dsc->page[page].begin, dsc->page[page].end);
 2377     ps_copy(f, docfile, dsc->begintrailer, dsc->endtrailer);
 2378         gfile_close(docfile);
 2379     }
 2380 
 2381     return 0;
 2382 }
 2383 
 2384 
 2385 /*********************************************************/