Main Page   Modules   Alphabetical List   Compound List   File List   Compound Members   File Members  

psdoc.h

00001 /*
00002  * ps.c -- Postscript scanning and copying routines.
00003  * Copyright (C) 1992  Timothy O. Theisen
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  *
00019  *   Author: Tim Theisen           Systems Programmer
00020  * Internet: tim@cs.wisc.edu       Department of Computer Sciences
00021  *     UUCP: uwvax!tim             University of Wisconsin-Madison
00022  *    Phone: (608)262-0438         1210 West Dayton Street
00023  *      FAX: (608)262-9777         Madison, WI   53706
00024 */
00025 
00026 /*
00027  * Added the ps_io_*() routines, rewrote readline(), modified
00028  * pscopyuntil() and pscopydoc() and eliminated pscopy().
00029  * The modifications mainly aim at
00030  *    - elimination of the (line length <= 255) constraint since
00031  *      there are just too many documents ignoring this requirement. 
00032  *    - acceptance of '\r' as line terminator as suggested by
00033  *      Martin Buck (martin-2.buck@student.uni-ulm.de).
00034  * Johannes Plass, 04/96 (plass@thep.physik.uni-mainz.de)
00035  *
00036 */
00037 
00038 /*
00039  * > Believe it or not--even Adobe doesn't know how to produce correct
00040  * > PS-files. Their Acrobat Reader sometimes starts including other files
00041  * > with %%BeginFile instead of %%BeginFile: and even more often ends them
00042  * > with just %%EOF instead of %%EndFile.
00043  * >    Martin Buck, martin-2.buck@student.uni-ulm.de
00044  *
00045  * Therefore we use Martin's ACROREAD_WORKAROUND (thanks for the patch, Martin).
00046  * ###jp### 04/96
00047  * 
00048  */
00049 #define USE_ACROREAD_WORKAROUND
00050 
00051 /*
00052 #define MESSAGES
00053 #define MESSAGE_NO_ESC
00054 */
00055 #include "message.h"
00056 
00057 #include "config.h"
00058 
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 
00062 #ifdef VMS
00063 #   include <unixio.h>
00064 #   include "strcasecmp.h"
00065 #   define unlink remove
00066 #   define USE_FTELL_FOR_FILEPOS
00067 #else
00068 #   include <string.h>
00069 #endif
00070 
00071 #ifndef SEEK_SET
00072 #define SEEK_SET 0
00073 #endif
00074 #ifndef BUFSIZ
00075 #define BUFSIZ 1024
00076 #endif
00077 #include <ctype.h>
00078 
00079 #include "paths.h"
00080 #include INC_X11(Intrinsic.h)
00081 #include INC_X11(Xos.h)                /* #includes the appropriate <string.h> */
00082 #include INC_X11(Xfuncs.h)
00083 
00084 #include "types.h"
00085 #include "file.h"
00086 #include "misc.h"
00087 #include "ps.h"
00088 #include "note.h"
00089 #include "d_memdebug.h"
00090 extern Media *gv_medias;
00091 
00092 #ifdef BSD4_2
00093 #define memset(a,b,c) bzero(a,c)
00094 #endif
00095 
00096 /* length calculates string length at compile time */
00097 /* can only be used with character constants */
00098 #define length(a)       (sizeof((a))-1)
00099 #define iscomment(a, b) (strncmp((a), (b), length((b))) == 0)
00100 #define DSCcomment(a)   ((a)[0] == '%' && (a)[1] == '%')
00101 
00102 /* list of standard paper sizes from Adobe's PPD. */
00103 
00104 #if 0
00105 struct documentmedia papersizes[] = {
00106     {"BBox",             0,  0},
00107     {"Letter",           612,  792},
00108     {"LetterSmall",      612,  792},
00109     {"Legal",            612, 1008},
00110     {"Statement",        396,  612},
00111     {"Tabloid",          792, 1224},
00112     {"Ledger",          1224,  792},
00113     {"Executive",        540,  720},
00114     {"A0",              2384, 3370},
00115     {"A1",              1684, 2384},
00116     {"A2",              1191, 1684},
00117     {"A3",               842, 1191},
00118     {"A4",               595,  842},
00119     {"A4Small",          595,  842},
00120     {"A5",               420,  595},
00121     {"B4",               729, 1032},
00122     {"B5",               516,  729},
00123     {"Folio",            612,  936},
00124     {"Quarto",           610,  780},
00125     {"10x14",            720, 1008},
00126     {  NULL,               0,    0}
00127 };
00128 #endif
00129 
00130 
00131 #if NeedFunctionPrototypes
00132 #   define PT(aaa) aaa
00133 #else 
00134 #   define PT(aaa) ()
00135 #endif
00136 
00137 /*--------------------------------------------------*/
00138 /* Declarations for ps_io_*() routines. */
00139 
00140 typedef struct FileDataStruct_ *FileData;
00141 
00142 typedef struct FileDataStruct_ {
00143    FILE *file;           /* file */
00144    int   file_desc;      /* file descriptor corresponding to file */
00145    int   filepos;        /* file position corresponding to the start of the line */
00146    char *buf;            /* buffer */
00147    int   buf_size;       /* size of buffer */
00148    int   buf_end;        /* last char in buffer given as offset to buf */
00149    int   line_begin;     /* start of the line given as offset to buf */
00150    int   line_end;       /* end of the line given as offset to buf */
00151    int   line_len;       /* length of line, i.e. (line_end-line_begin) */
00152    char  line_termchar;  /* char exchanged for a '\0' at end of line */
00153    int   status;         /* 0 = okay, 1 = failed */
00154 } FileDataStruct;
00155 
00156 static FileData ps_io_init PT((FILE *));
00157 static void     ps_io_exit PT((FileData));
00158 static char    *ps_io_fgetchars PT((FileData, int));
00159 static int      ps_io_fseek PT((FileData, int));
00160 static int      ps_io_ftell PT((FileData));
00161 
00162 static char    *readline PT((FileData, char **, long *, unsigned int *));
00163 static char    *gettextline PT((char *));
00164 static char    *gettext PT((char *,char **));
00165 static int      blank PT((char *));
00166 static char    *pscopyuntil PT((FileData,FILE *,long,long,char *));
00167 
00168 static char    *skipped_line = "% ps_io_fgetchars: skipped line";
00169 static char    *empty_string = "";
00170 
00171 /*--------------------------------------------------*/
00172 
00173 /*
00174  *      psscan -- scan the PostScript file for document structuring comments.
00175  *
00176  *      This scanner is designed to retrieve the information necessary for
00177  *      the ghostview previewer.  It will scan files that conform to any
00178  *      version (1.0, 2.0, 2.1, or 3.0) of the document structuring conventions.
00179  *      It does not really care which version of comments the file contains.
00180  *      (The comments are largely upward compatible.)  It will scan a number
00181  *      of non-conforming documents.  (You could have part of the document
00182  *      conform to V2.0 and the rest conform to V3.0.  It would be similar
00183  *      to the DC-2 1/2+, it would look funny but it can still fly.)
00184  *
00185  *      This routine returns a pointer to the document structure.
00186  *      The structure contains the information relevant to previewing.
00187  *      These include EPSF flag (to tell if the file is a encapsulated figure),
00188  *      Page Media (for the Page Size), Bounding Box (to minimize backing
00189  *      pixmap size or determine window size for encapsulated PostScript), 
00190  *      Orientation of Paper (for default transformation matrix), and
00191  *      Page Order.  The title and CreationDate are also retrieved to
00192  *      help identify the document.
00193  *
00194  *      The following comments are examined:
00195  *
00196  *      Header section: 
00197  *      Must start with %!PS-Adobe-.  Version numbers ignored.
00198  *
00199  *      %!PS-Adobe-* [EPSF*] (changed EPSF-* to EPSF* to do XFig a favor ...###jp###)
00200  *      %%BoundingBox: <int> <int> <int> <int>|(atend)
00201  *      %%CreationDate: <textline>
00202  *      %%Orientation: Portrait|Landscape|(atend)
00203  *      %%Pages: <uint> [<int>]|(atend)
00204  *      %%PageOrder: Ascend|Descend|Special|(atend)
00205  *      %%Title: <textline>
00206  *      %%DocumentMedia: <text> <real> <real> <real> <text> <text>
00207  *      %%DocumentPaperSizes: <text>
00208  *      %%EndComments
00209  *
00210  *      Note: Either the 3.0 or 2.0 syntax for %%Pages is accepted.
00211  *            Also either the 2.0 %%DocumentPaperSizes or the 3.0
00212  *            %%DocumentMedia comments are accepted as well.
00213  *
00214  *      The header section ends either explicitly with %%EndComments or
00215  *      implicitly with any line that does not begin with %X where X is
00216  *      a not whitespace character.
00217  *
00218  *      If the file is encapsulated PostScript the optional Preview section
00219  *      is next:
00220  *
00221  *      %%BeginPreview
00222  *      %%EndPreview
00223  *
00224  *      This section explicitly begins and ends with the above comments.
00225  *
00226  *      Next the Defaults section for version 3 page defaults:
00227  *
00228  *      %%BeginDefaults
00229  *      %%PageBoundingBox: <int> <int> <int> <int>
00230  *      %%PageOrientation: Portrait|Landscape
00231  *      %%PageMedia: <text>
00232  *      %%EndDefaults
00233  *
00234  *      This section explicitly begins and ends with the above comments.
00235  *
00236  *      The prolog section either explicitly starts with %%BeginProlog or
00237  *      implicitly with any nonblank line.
00238  *
00239  *      %%BeginProlog
00240  *      %%EndProlog
00241  *
00242  *      The Prolog should end with %%EndProlog, however the proglog implicitly
00243  *      ends when %%BeginSetup, %%Page, %%Trailer or %%EOF are encountered.
00244  *
00245  *      The Setup section is where the version 2 page defaults are found.
00246  *      This section either explicitly begins with %%BeginSetup or implicitly
00247  *      with any nonblank line after the Prolog.
00248  *
00249  *      %%BeginSetup
00250  *      %%PageBoundingBox: <int> <int> <int> <int>
00251  *      %%PageOrientation: Portrait|Landscape
00252  *      %%PaperSize: <text>
00253  *      %%EndSetup
00254  *
00255  *      The Setup should end with %%EndSetup, however the setup implicitly
00256  *      ends when %%Page, %%Trailer or %%EOF are encountered.
00257  *
00258  *      Next each page starts explicitly with %%Page and ends implicitly with
00259  *      %%Page or %%Trailer or %%EOF.  The following comments are recognized:
00260  *
00261  *      %%Page: <text> <uint>
00262  *      %%PageBoundingBox: <int> <int> <int> <int>|(atend)
00263  *      %%PageOrientation: Portrait|Landscape
00264  *      %%PageMedia: <text>
00265  *      %%PaperSize: <text>
00266  *
00267  *      The trailer section start explicitly with %%Trailer and end with %%EOF.
00268  *      The following comment are examined with the proper (atend) notation
00269  *      was used in the header:
00270  *
00271  *      %%Trailer
00272  *      %%BoundingBox: <int> <int> <int> <int>|(atend)
00273  *      %%Orientation: Portrait|Landscape|(atend)
00274  *      %%Pages: <uint> [<int>]|(atend)
00275  *      %%PageOrder: Ascend|Descend|Special|(atend)
00276  *      %%EOF
00277  *
00278  *
00279  *  + A DC-3 received severe damage to one of its wings.  The wing was a total
00280  *    loss.  There was no replacement readily available, so the mechanic
00281  *    installed a wing from a DC-2.
00282  */
00283 
00284 #ifndef VMS
00285 #  define ps_system system
00286 #else
00287 
00288 /*############################################################
00289  * ps_system        (VMS only, otherwise same as system())
00290  * Similar to system(), except it allows I/O redirection with <in >out
00291  * at the end of the line, and returns a more Unix-compatible status (0=OK).
00292  * The I/O redirection is very rudimentary. >> and | are NOT supported.
00293  * No error checking is performed, though hopefully the command will return
00294  * a reasonable error message when it can't access the file.
00295  * < or > in the command (eg. in directory spec), unless followed by another
00296  * < or >, will always be interpreted as I/O redirection, so be careful!
00297  *############################################################*/
00298 
00299 int ps_system(cmd)
00300   char *cmd;
00301 {
00302   char *inpf=NULL,*outf=NULL,*cf=NULL,*s,*t;
00303   int status;
00304 
00305   if (!cmd) cmd="";
00306   cmd = PS_XtNewString(cmd);
00307   s = strrchr(cmd,'>'); if (s) { outf = s+1; *s='\n'; }
00308   s = strrchr(cmd,'<'); if (s) { inpf = s+1; *s='\n'; }
00309   while ((s=strrchr(cmd,'\n'))) *s='\0';
00310   if (outf) {
00311     for (s=t=outf; *s; s++) if (!isspace(*s)) *t++=*s; 
00312     *t='\0';
00313     if (!(*outf)) outf=NULL;
00314   }
00315   if (inpf) {
00316     for (s=t=inpf; *s; s++) if (!isspace(*s)) *t++=*s;
00317     *t='\0';
00318     if (!(*inpf)) inpf=NULL;
00319   }
00320   if (outf || inpf) {
00321     FILE *com;
00322     cf=file_getTmpFilename (NULL, outf ? outf : inpf);
00323     com=fopen(cf, "w");
00324     if (!com) return 1;
00325     if (inpf) fprintf(com, "$DEFINE_/NOLOG SYS$INPUT  %s\n",inpf);
00326     if (outf) fprintf(com, "$DEFINE_/NOLOG SYS$OUTPUT %s\n",outf);
00327     fprintf(com,"$%s\n",cmd);
00328     fclose(com);
00329     PS_XtFree(cmd);
00330     cmd = PS_XtMalloc((1+strlen(cf)+1)*sizeof(char));
00331     sprintf(cmd,"@%s",cf);
00332   }
00333   status=system(cmd);
00334   if (cf) unlink(cf);
00335   PS_XtFree(cmd);
00336   return((status&7)==1 ? 0 : status);
00337 }
00338 #endif
00339 
00340 /*-----------------------------------------------------------*/
00341 
00342 static void ps_dynMemExhaust()
00343 {
00344    fprintf(stderr,"Fatal Error: Dynamic memory exhausted.\n");
00345    exit(EXIT_STATUS_FATAL);
00346 }
00347 #define CHECK_MALLOCED(aaa)  if (!(aaa)) ps_dynMemExhaust()
00348 
00349 /*###########################################################*/
00350 /* psscan */
00351 /*###########################################################*/
00352 
00353 struct document *
00354 psscan(fileP,filename,filename_raw,filename_dscP,cmd_scan_pdf,filename_uncP,cmd_uncompress,scanstyle)
00355     FILE **fileP;
00356     char *filename;
00357     char *filename_raw;
00358     char **filename_dscP;
00359     char *cmd_scan_pdf;
00360     char **filename_uncP;
00361     char *cmd_uncompress;
00362     int scanstyle;
00363 {
00364     FILE *file;
00365     struct document *doc;
00366     int bb_set = NONE;
00367     int pages_set = NONE;
00368     int page_order_set = NONE;
00369     int orientation_set = NONE;
00370     int page_bb_set = NONE;
00371     int page_media_set = NONE;
00372     int preread;                /* flag which tells the readline isn't needed */
00373     int i;
00374     unsigned int maxpages = 0;
00375     unsigned int nextpage = 1;  /* Next expected page */
00376     unsigned int thispage;
00377     int ignore = 0;             /* whether to ignore page ordinals */
00378     char *label;
00379     char *line;
00380                                 /* 255 characters + 1 newline + 1 NULL */
00381     char text[PSLINELENGTH];    /* Temporary storage for text */
00382     long position;              /* Position of the current line */
00383     long beginsection;          /* Position of the beginning of the section */
00384     unsigned int line_len;      /* Length of the current line */
00385     unsigned int section_len;   /* Place to accumulate the section length */
00386     char *next_char;            /* 1st char after text returned by gettext() */
00387     char *cp;
00388     Media dmp;
00389     FileData fd;
00390     int respect_eof;            /* Derived from the scanstyle argument.
00391                                    If set to 0 EOF comments will be ignored,
00392                                    if set to 1 they will be taken seriously.
00393                                    Purpose; Out there are many documents which 
00394                                    include other DSC conforming documents without
00395                                    without enclosing them by 'BeginDocument' and
00396                                    'EndDocument' comments. This may cause fake EOF 
00397                                    comments to appear in the body of a page.
00398                                    Similarly, if respect_eof is set to false
00399                                    'Trailer' comments are ignored except of the
00400                                    last one found in the document.
00401                                 */
00402     int ignore_dsc;             /* Derived from scanstyle.
00403                                    If set the document structure will be ignored.
00404                                 */
00405 
00406     BEGINMESSAGE(psscan)
00407 
00408     if (cmd_uncompress) {
00409       char b[2];
00410       if (!(fread(b, sizeof(char),2, *fileP) == 2)
00411           || b[0] != '\037' || (b[1] != '\235' && b[1] != '\213')) {
00412         rewind(*fileP);
00413         cmd_uncompress=NULL;
00414       }
00415     }
00416     if (cmd_uncompress) {
00417       struct document *retval = NULL;
00418       FILE *tmpfile = (FILE*)NULL;
00419       char *filename_unc;
00420       char cmd[512];
00421       char s[512];
00422       filename_unc=file_getTmpFilename(NULL,filename_raw);
00423       sprintf(cmd,cmd_uncompress,filename,filename_unc);
00424       INFMESSAGE(is compressed)
00425       INFSMESSAGE(uncompress command,cmd)
00426       if (ps_system(cmd) || file_fileIsNotUseful(filename_unc)) {
00427         INFMESSAGE(uncompressing failed)
00428 unc_exec_failed:
00429         sprintf(s,"Execution of\n%s\nfailed.",cmd);
00430 #if 0
00431 unc_failed:
00432 #endif
00433         NotePopupShowMessage(s);
00434         if (tmpfile) fclose(tmpfile);
00435         unlink(filename_unc);
00436 unc_ok:
00437         GV_XtFree(filename_unc);
00438         ENDMESSAGE(psscan)
00439         return(retval);
00440       }
00441       tmpfile = fopen(filename_unc, "r");
00442       if (!tmpfile) goto unc_exec_failed;
00443       fclose(*fileP);
00444       *fileP = tmpfile;
00445       retval = psscan(fileP,filename_unc,filename_raw,filename_dscP,cmd_scan_pdf,NULL,NULL,scanstyle);
00446 #if 0
00447       if (!retval) {
00448         sprintf(s,"333 Scanning\n%s\nfailed.",filename_unc);
00449         goto unc_failed;
00450       }
00451 #endif
00452       *filename_uncP = (char*)GV_XtNewString(filename_unc);
00453       goto unc_ok;
00454     }
00455 
00456     respect_eof = (scanstyle & SCANSTYLE_IGNORE_EOF) ? 0 : 1;
00457     ignore_dsc = (scanstyle & SCANSTYLE_IGNORE_DSC) ? 1 : 0;
00458     file = *fileP;
00459 
00460     if (ignore_dsc) {
00461       INFMESSAGE(ignoring DSC)
00462       ENDMESSAGE(psscan)
00463       return(NULL);
00464     }
00465 
00466     fd =  ps_io_init(file);
00467     if (!readline(fd,&line, &position, &line_len)) {
00468         fprintf(stderr, "Warning: empty file.\n");
00469         ENDMESSAGE(psscan)
00470         ps_io_exit(fd);
00471         return(NULL);
00472     }
00473 
00474     /* Header comments */
00475 
00476     if (line_len>1 && (iscomment(line,"%!PS-Adobe-") || iscomment(line + 1,"%!PS-Adobe-"))) {
00477       INFMESSAGE(found "PS-Adobe-" comment)
00478       doc = (struct document *) PS_malloc(sizeof(struct document));
00479       CHECK_MALLOCED(doc);
00480       memset(doc, 0, sizeof(struct document));
00481       sscanf(line, "%*s %s", text);
00482       /*###jp###*/
00483       /*doc->epsf = iscomment(text, "EPSF-");*/
00484       doc->epsf = iscomment(text, "EPSF");
00485       doc->beginheader = position;
00486       section_len = line_len;
00487     } else if (iscomment(line,"%PDF-") && cmd_scan_pdf) {
00488       struct document *retval = NULL;
00489       FILE *tmpfile = (FILE*)NULL;
00490       char *filename_dsc;
00491       char cmd[512];
00492       char s[512];
00493       filename_dsc=file_getTmpFilename(NULL,filename_raw);
00494       sprintf(cmd,cmd_scan_pdf,filename,filename_dsc);
00495       INFMESSAGE(is PDF)
00496       INFSMESSAGE(scan command,cmd)
00497 #ifdef VMS
00498       if ((system(cmd)&7)!=1 || file_fileIsNotUseful(filename_dsc)) {
00499 #else
00500       if (system(cmd) || file_fileIsNotUseful(filename_dsc)) {
00501 #endif
00502         INFMESSAGE(scan subprocess failed)
00503 scan_exec_failed:
00504         sprintf(s,"Execution of\n%s\nfailed.",cmd);
00505 scan_failed:
00506         NotePopupShowMessage(s);
00507         if (tmpfile) fclose(tmpfile);
00508         unlink(filename_dsc);
00509 scan_ok:
00510         GV_XtFree(filename_dsc);
00511         ps_io_exit(fd);
00512         ENDMESSAGE(psscan)
00513         return(retval);
00514       }
00515       tmpfile = fopen(filename_dsc, "r");
00516       if (!tmpfile) goto scan_exec_failed;
00517       fclose(*fileP);
00518       *fileP = tmpfile;
00519       retval = psscan(fileP,filename_dsc,filename_raw,filename_dscP,cmd_scan_pdf,NULL,NULL,scanstyle);
00520       if (!retval) {
00521         sprintf(s,"Scanning\n%s\nfailed.",filename_dsc);
00522         goto scan_failed;
00523       }
00524       *filename_dscP = (char*)GV_XtNewString(filename_dsc);
00525       goto scan_ok;
00526     } else {
00527       INFMESSAGE(unable to classify document)
00528       ENDMESSAGE(psscan)
00529       ps_io_exit(fd);
00530       return(NULL);
00531     }
00532     
00533     preread = 0;
00534     while (preread || readline(fd, &line, &position, &line_len)) {
00535         if (!preread) section_len += line_len;
00536         preread = 0;
00537         if (line[0] != '%' ||
00538             iscomment(line+1, "%EndComments") ||
00539             line[1] == ' ' || line[1] == '\t' || line[1] == '\n' ||
00540             !isprint(line[1])) {
00541             break;
00542         } else if (line[1] != '%') {
00543             /* Do nothing */
00544         } else if (doc->title == NULL && iscomment(line+2, "Title:")) {
00545             doc->title = gettextline(line+length("%%Title:"));
00546         } else if (doc->date == NULL && iscomment(line+2, "CreationDate:")) {
00547             doc->date = gettextline(line+length("%%CreationDate:"));
00548         } else if (bb_set == NONE && iscomment(line+2, "BoundingBox:")) {
00549             sscanf(line+length("%%BoundingBox:"), "%s", text);
00550             if (strcmp(text, "(atend)") == 0) {
00551                 bb_set = ATEND;
00552             } else {
00553                 if (sscanf(line+length("%%BoundingBox:"), "%d %d %d %d",
00554                            &(doc->boundingbox[LLX]),
00555                            &(doc->boundingbox[LLY]),
00556                            &(doc->boundingbox[URX]),
00557                            &(doc->boundingbox[URY])) == 4)
00558                     bb_set = 1;
00559                 else {
00560                     float fllx, flly, furx, fury;
00561                     if (sscanf(line+length("%%BoundingBox:"), "%f %f %f %f",
00562                                &fllx, &flly, &furx, &fury) == 4) {
00563                         bb_set = 1;
00564                         doc->boundingbox[LLX] = fllx;
00565                         doc->boundingbox[LLY] = flly;
00566                         doc->boundingbox[URX] = furx;
00567                         doc->boundingbox[URY] = fury;
00568                         if (fllx < doc->boundingbox[LLX])
00569                             doc->boundingbox[LLX]--;
00570                         if (flly < doc->boundingbox[LLY])
00571                             doc->boundingbox[LLY]--;
00572                         if (furx > doc->boundingbox[URX])
00573                             doc->boundingbox[URX]++;
00574                         if (fury > doc->boundingbox[URY])
00575                             doc->boundingbox[URY]++;
00576                     }
00577                 }
00578             }
00579         } else if (orientation_set == NONE &&
00580                    iscomment(line+2, "Orientation:")) {
00581             sscanf(line+length("%%Orientation:"), "%s", text);
00582             if (strcmp(text, "(atend)") == 0) {
00583                 orientation_set = ATEND;
00584             } else if (strcmp(text, "Portrait") == 0) {
00585                 doc->orientation = PORTRAIT;
00586                 orientation_set = 1;
00587             } else if (strcmp(text, "Landscape") == 0) {
00588                 doc->orientation = LANDSCAPE;
00589                 orientation_set = 1;
00590             }
00591         } else if (page_order_set == NONE && iscomment(line+2, "PageOrder:")) {
00592             sscanf(line+length("%%PageOrder:"), "%s", text);
00593             if (strcmp(text, "(atend)") == 0) {
00594                 page_order_set = ATEND;
00595             } else if (strcmp(text, "Ascend") == 0) {
00596                 doc->pageorder = ASCEND;
00597                 page_order_set = 1;
00598             } else if (strcmp(text, "Descend") == 0) {
00599                 doc->pageorder = DESCEND;
00600                 page_order_set = 1;
00601             } else if (strcmp(text, "Special") == 0) {
00602                 doc->pageorder = SPECIAL;
00603                 page_order_set = 1;
00604             }
00605         } else if (pages_set == NONE && iscomment(line+2, "Pages:")) {
00606             sscanf(line+length("%%Pages:"), "%s", text);
00607             if (strcmp(text, "(atend)") == 0) {
00608                 pages_set = ATEND;
00609             } else {
00610                 switch (sscanf(line+length("%%Pages:"), "%d %d",
00611                                &maxpages, &i)) {
00612                     case 2:
00613                         if (page_order_set == NONE) {
00614                             if (i == -1) {
00615                                 doc->pageorder = DESCEND;
00616                                 page_order_set = 1;
00617                             } else if (i == 0) {
00618                                 doc->pageorder = SPECIAL;
00619                                 page_order_set = 1;
00620                             } else if (i == 1) {
00621                                 doc->pageorder = ASCEND;
00622                                 page_order_set = 1;
00623                             }
00624                         }
00625                     case 1:
00626                         if (maxpages > 0) {
00627                             doc->pages = (struct page *) PS_calloc(maxpages,
00628                                                            sizeof(struct page));
00629                             CHECK_MALLOCED(doc->pages);
00630                         }
00631                 }
00632             }
00633         } else if (doc->nummedia == NONE &&
00634                    iscomment(line+2, "DocumentMedia:")) {
00635             float w, h;
00636             doc->media = (Media)
00637                          PS_malloc(sizeof (MediaStruct));
00638             CHECK_MALLOCED(doc->media);
00639             doc->media[0].name = gettext(line+length("%%DocumentMedia:"),
00640                                          &next_char);
00641             if (doc->media[0].name != NULL) {
00642                 if (sscanf(next_char, "%f %f", &w, &h) == 2) {
00643                     doc->media[0].width = w + 0.5;
00644                     doc->media[0].height = h + 0.5;
00645                 }
00646                 if (doc->media[0].width != 0 && doc->media[0].height != 0)
00647                     doc->nummedia = 1;
00648                 else
00649                     PS_free(doc->media[0].name);
00650             }
00651             preread=1;
00652             while (readline(fd, &line, &position, &line_len) &&
00653                    DSCcomment(line) && iscomment(line+2, "+")) {
00654                 section_len += line_len;
00655                 doc->media = (Media)
00656                              PS_realloc(doc->media,
00657                                      (doc->nummedia+1)*
00658                                      sizeof (MediaStruct));
00659                 CHECK_MALLOCED(doc->media);
00660                 doc->media[doc->nummedia].name = gettext(line+length("%%+"),
00661                                                          &next_char);
00662                 if (doc->media[doc->nummedia].name != NULL) {
00663                     if (sscanf(next_char, "%f %f", &w, &h) == 2) {
00664                         doc->media[doc->nummedia].width = w + 0.5;
00665                         doc->media[doc->nummedia].height = h + 0.5;
00666                     }
00667                     if (doc->media[doc->nummedia].width != 0 &&
00668                         doc->media[doc->nummedia].height != 0) doc->nummedia++;
00669                     else
00670                         PS_free(doc->media[doc->nummedia].name);
00671                 }
00672             }
00673             section_len += line_len;
00674             if (doc->nummedia != 0) doc->default_page_media = doc->media;
00675         } else if (doc->nummedia == NONE &&
00676                    iscomment(line+2, "DocumentPaperSizes:")) {
00677 
00678             doc->media = (Media)
00679                          PS_malloc(sizeof (MediaStruct));
00680             CHECK_MALLOCED(doc->media);
00681             doc->media[0].name = gettext(line+length("%%DocumentPaperSizes:"),
00682                                          &next_char);
00683             if (doc->media[0].name != NULL) {
00684                 doc->media[0].width = 0;
00685                 doc->media[0].height = 0;
00686                 for (i=0; gv_medias[i]; i++) {
00687                     dmp = gv_medias[i];
00688                     /* Note: Paper size comment uses down cased paper size
00689                      * name.  Case insensitive compares are only used for
00690                      * PaperSize comments.
00691                      */
00692                     if (strcasecmp(doc->media[0].name, dmp->name) == 0) {
00693                         PS_free(doc->media[0].name);
00694                         doc->media[0].name = (char *)PS_malloc(strlen(dmp->name)+1);
00695                         CHECK_MALLOCED(doc->media[0].name);
00696                         strcpy(doc->media[0].name, dmp->name);
00697                         doc->media[0].width = dmp->width;
00698                         doc->media[0].height = dmp->height;
00699                         break;
00700                     }
00701                 }
00702                 if (doc->media[0].width != 0 && doc->media[0].height != 0)
00703                     doc->nummedia = 1;
00704                 else
00705                     PS_free(doc->media[0].name);
00706             }
00707             while ((cp = gettext(next_char, &next_char))) {
00708                 doc->media = (Media)
00709                              PS_realloc(doc->media,
00710                                      (doc->nummedia+1)*
00711                                      sizeof (MediaStruct));
00712                 CHECK_MALLOCED(doc->media);
00713                 doc->media[doc->nummedia].name = cp;
00714                 doc->media[doc->nummedia].width = 0;
00715                 doc->media[doc->nummedia].height = 0;
00716                 for (i=0; gv_medias[i]; i++) {
00717                    dmp = gv_medias[i];
00718                     /* Note: Paper size comment uses down cased paper size
00719                      * name.  Case insensitive compares are only used for
00720                      * PaperSize comments.
00721                      */
00722                     if (strcasecmp(doc->media[doc->nummedia].name,
00723                                dmp->name) == 0) {
00724                         PS_free(doc->media[doc->nummedia].name);
00725                         doc->media[doc->nummedia].name =
00726                                 (char *)PS_malloc(strlen(dmp->name)+1);
00727                         CHECK_MALLOCED(doc->media[doc->nummedia].name);
00728                         strcpy(doc->media[doc->nummedia].name, dmp->name);
00729                         doc->media[doc->nummedia].width = dmp->width;
00730                         doc->media[doc->nummedia].height = dmp->height;
00731                         break;
00732                     }
00733                 }
00734                 if (doc->media[doc->nummedia].width != 0 &&
00735                     doc->media[doc->nummedia].height != 0) doc->nummedia++;
00736                 else
00737                     PS_free(doc->media[doc->nummedia].name);
00738             }
00739             preread=1;
00740             while (readline(fd, &line, &position, &line_len) &&
00741                    DSCcomment(line) && iscomment(line+2, "+")) {
00742                 section_len += line_len;
00743                 next_char = line + length("%%+");
00744                 while ((cp = gettext(next_char, &next_char))) {
00745                     doc->media = (Media)
00746                                  PS_realloc(doc->media,
00747                                          (doc->nummedia+1)*
00748                                          sizeof (MediaStruct));
00749                     CHECK_MALLOCED(doc->media);
00750                     doc->media[doc->nummedia].name = cp;
00751                     doc->media[doc->nummedia].width = 0;
00752                     doc->media[doc->nummedia].height = 0;
00753                     for (i=0; gv_medias[i]; i++) {
00754                         dmp = gv_medias[i];
00755                         /* Note: Paper size comment uses down cased paper size
00756                          * name.  Case insensitive compares are only used for
00757                          * PaperSize comments.
00758                          */
00759                         if (strcasecmp(doc->media[doc->nummedia].name,
00760                                    dmp->name) == 0) {
00761                             doc->media[doc->nummedia].width = dmp->width;
00762                             doc->media[doc->nummedia].height = dmp->height;
00763                             break;
00764                         }
00765                     }
00766                     if (doc->media[doc->nummedia].width != 0 &&
00767                         doc->media[doc->nummedia].height != 0) doc->nummedia++;
00768                     else
00769                         PS_free(doc->media[doc->nummedia].name);
00770                 }
00771             }
00772             section_len += line_len;
00773             if (doc->nummedia != 0) doc->default_page_media = doc->media;
00774         }
00775     }
00776 
00777     if (DSCcomment(line) && iscomment(line+2, "EndComments")) {
00778         readline(fd, &line, &position, &line_len);
00779         section_len += line_len;
00780     }
00781     doc->endheader = position;
00782     doc->lenheader = section_len - line_len;
00783 
00784     /* Optional Preview comments for encapsulated PostScript files */ 
00785 
00786     beginsection = position;
00787     section_len = line_len;
00788     while (blank(line) && readline(fd, &line, &position, &line_len)) {
00789         section_len += line_len;
00790     }
00791 
00792     if (doc->epsf && DSCcomment(line) && iscomment(line+2, "BeginPreview")) {
00793         doc->beginpreview = beginsection;
00794         beginsection = 0;
00795         while (readline(fd, &line, &position, &line_len) &&
00796                !(DSCcomment(line) && iscomment(line+2, "EndPreview"))) {
00797             section_len += line_len;
00798         }
00799         section_len += line_len;
00800         readline(fd, &line, &position, &line_len);
00801         section_len += line_len;
00802         doc->endpreview = position;
00803         doc->lenpreview = section_len - line_len;
00804     }
00805 
00806     /* Page Defaults for Version 3.0 files */
00807 
00808     if (beginsection == 0) {
00809         beginsection = position;
00810         section_len = line_len;
00811     }
00812     while (blank(line) && readline(fd, &line, &position, &line_len)) {
00813         section_len += line_len;
00814     }
00815 
00816     if (DSCcomment(line) && iscomment(line+2, "BeginDefaults")) {
00817         doc->begindefaults = beginsection;
00818         beginsection = 0;
00819         while (readline(fd, &line, &position, &line_len) &&
00820                !(DSCcomment(line) && iscomment(line+2, "EndDefaults"))) {
00821             section_len += line_len;
00822             if (!DSCcomment(line)) {
00823                 /* Do nothing */
00824             } else if (doc->default_page_orientation == NONE &&
00825                 iscomment(line+2, "PageOrientation:")) {
00826                 sscanf(line+length("%%PageOrientation:"), "%s", text);
00827                 if (strcmp(text, "Portrait") == 0) {
00828                     doc->default_page_orientation = PORTRAIT;
00829                 } else if (strcmp(text, "Landscape") == 0) {
00830                     doc->default_page_orientation = LANDSCAPE;
00831                 }
00832             } else if (page_media_set == NONE &&
00833                        iscomment(line+2, "PageMedia:")) {
00834                 cp = gettext(line+length("%%PageMedia:"), NULL);
00835                 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
00836                     if (strcmp(cp, dmp->name) == 0) {
00837                         doc->default_page_media = dmp;
00838                         page_media_set = 1;
00839                         break;
00840                     }
00841                 }
00842                 PS_free(cp);
00843             } else if (page_bb_set == NONE &&
00844                        iscomment(line+2, "PageBoundingBox:")) {
00845                 if (sscanf(line+length("%%PageBoundingBox:"), "%d %d %d %d",
00846                            &(doc->default_page_boundingbox[LLX]),
00847                            &(doc->default_page_boundingbox[LLY]),
00848                            &(doc->default_page_boundingbox[URX]),
00849                            &(doc->default_page_boundingbox[URY])) == 4)
00850                     page_bb_set = 1;
00851                 else {
00852                     float fllx, flly, furx, fury;
00853                     if (sscanf(line+length("%%PageBoundingBox:"), "%f %f %f %f",
00854                                &fllx, &flly, &furx, &fury) == 4) {
00855                         page_bb_set = 1;
00856                         doc->default_page_boundingbox[LLX] = fllx;
00857                         doc->default_page_boundingbox[LLY] = flly;
00858                         doc->default_page_boundingbox[URX] = furx;
00859                         doc->default_page_boundingbox[URY] = fury;
00860                         if (fllx < doc->default_page_boundingbox[LLX])
00861                             doc->default_page_boundingbox[LLX]--;
00862                         if (flly < doc->default_page_boundingbox[LLY])
00863                             doc->default_page_boundingbox[LLY]--;
00864                         if (furx > doc->default_page_boundingbox[URX])
00865                             doc->default_page_boundingbox[URX]++;
00866                         if (fury > doc->default_page_boundingbox[URY])
00867                             doc->default_page_boundingbox[URY]++;
00868                     }
00869                 }
00870             }
00871         }
00872         section_len += line_len;
00873         readline(fd, &line, &position, &line_len);
00874         section_len += line_len;
00875         doc->enddefaults = position;
00876         doc->lendefaults = section_len - line_len;
00877     }
00878 
00879     /* Document Prolog */
00880 
00881     if (beginsection == 0) {
00882         beginsection = position;
00883         section_len = line_len;
00884     }
00885     while (blank(line) && readline(fd, &line, &position, &line_len)) {
00886         section_len += line_len;
00887     }
00888 
00889     if (!(DSCcomment(line) &&
00890           (iscomment(line+2, "BeginSetup") ||
00891            iscomment(line+2, "Page:") ||
00892            iscomment(line+2, "Trailer") ||
00893            iscomment(line+2, "EOF")))) {
00894         doc->beginprolog = beginsection;
00895         beginsection = 0;
00896         preread = 1;
00897 
00898         while ((preread ||
00899                 readline(fd, &line, &position, &line_len)) &&
00900                !(DSCcomment(line) &&
00901                  (iscomment(line+2, "EndProlog") ||
00902                   iscomment(line+2, "BeginSetup") ||
00903                   iscomment(line+2, "Page:") ||
00904                   iscomment(line+2, "Trailer") ||
00905                   iscomment(line+2, "EOF")))) {
00906             if (!preread) section_len += line_len;
00907             preread = 0;
00908         }
00909         section_len += line_len;
00910         if (DSCcomment(line) && iscomment(line+2, "EndProlog")) {
00911             readline(fd, &line, &position, &line_len);
00912             section_len += line_len;
00913         }
00914         doc->endprolog = position;
00915         doc->lenprolog = section_len - line_len;
00916     }
00917 
00918     /* Document Setup,  Page Defaults found here for Version 2 files */
00919 
00920     if (beginsection == 0) {
00921         beginsection = position;
00922         section_len = line_len;
00923     }
00924     while (blank(line) && readline(fd, &line, &position, &line_len)) {
00925         section_len += line_len;
00926     }
00927 
00928     if (!(DSCcomment(line) &&
00929           (iscomment(line+2, "Page:") ||
00930            iscomment(line+2, "Trailer") ||
00931            (respect_eof && iscomment(line+2, "EOF"))))) {
00932         doc->beginsetup = beginsection;
00933         beginsection = 0;
00934         preread = 1;
00935         while ((preread ||
00936                 readline(fd, &line, &position, &line_len)) &&
00937                !(DSCcomment(line) &&
00938                  (iscomment(line+2, "EndSetup") ||
00939                   iscomment(line+2, "Page:") ||
00940                   iscomment(line+2, "Trailer") ||
00941                   (respect_eof && iscomment(line+2, "EOF"))))) {
00942             if (!preread) section_len += line_len;
00943             preread = 0;
00944             if (!DSCcomment(line)) {
00945                 /* Do nothing */
00946             } else if (doc->default_page_orientation == NONE &&
00947                 iscomment(line+2, "PageOrientation:")) {
00948                 sscanf(line+length("%%PageOrientation:"), "%s", text);
00949                 if (strcmp(text, "Portrait") == 0) {
00950                     doc->default_page_orientation = PORTRAIT;
00951                 } else if (strcmp(text, "Landscape") == 0) {
00952                     doc->default_page_orientation = LANDSCAPE;
00953                 }
00954             } else if (page_media_set == NONE &&
00955                        iscomment(line+2, "PaperSize:")) {
00956                 cp = gettext(line+length("%%PaperSize:"), NULL);
00957                 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
00958                     /* Note: Paper size comment uses down cased paper size
00959                      * name.  Case insensitive compares are only used for
00960                      * PaperSize comments.
00961                      */
00962                     if (strcasecmp(cp, dmp->name) == 0) {
00963                         doc->default_page_media = dmp;
00964                         page_media_set = 1;
00965                         break;
00966                     }
00967                 }
00968                 PS_free(cp);
00969             } else if (page_bb_set == NONE &&
00970                        iscomment(line+2, "PageBoundingBox:")) {
00971                 if (sscanf(line+length("%%PageBoundingBox:"), "%d %d %d %d",
00972                            &(doc->default_page_boundingbox[LLX]),
00973                            &(doc->default_page_boundingbox[LLY]),
00974                            &(doc->default_page_boundingbox[URX]),
00975                            &(doc->default_page_boundingbox[URY])) == 4)
00976                     page_bb_set = 1;
00977                 else {
00978                     float fllx, flly, furx, fury;
00979                     if (sscanf(line+length("%%PageBoundingBox:"), "%f %f %f %f",
00980                                &fllx, &flly, &furx, &fury) == 4) {
00981                         page_bb_set = 1;
00982                         doc->default_page_boundingbox[LLX] = fllx;
00983                         doc->default_page_boundingbox[LLY] = flly;
00984                         doc->default_page_boundingbox[URX] = furx;
00985                         doc->default_page_boundingbox[URY] = fury;
00986                         if (fllx < doc->default_page_boundingbox[LLX])
00987                             doc->default_page_boundingbox[LLX]--;
00988                         if (flly < doc->default_page_boundingbox[LLY])
00989                             doc->default_page_boundingbox[LLY]--;
00990                         if (furx > doc->default_page_boundingbox[URX])
00991                             doc->default_page_boundingbox[URX]++;
00992                         if (fury > doc->default_page_boundingbox[URY])
00993                             doc->default_page_boundingbox[URY]++;
00994                     }
00995                 }
00996             }
00997         }
00998         section_len += line_len;
00999         if (DSCcomment(line) && iscomment(line+2, "EndSetup")) {
01000             readline(fd, &line, &position, &line_len);
01001             section_len += line_len;
01002         }
01003         doc->endsetup = position;
01004         doc->lensetup = section_len - line_len;
01005     }
01006 
01007     /* BEGIN Windows NT fix ###jp###
01008        Mark Pfeifer (pfeiferm%ppddev@comet.cmis.abbott.com) told me
01009        about problems when viewing Windows NT 3.51 generated postscript
01010        files with gv. He found that the relevant postscript files
01011        show important postscript code after the '%%EndSetup' and before
01012        the first page comment '%%Page: x y'.
01013     */
01014     if (doc->beginsetup) {
01015       while (!(DSCcomment(line) &&
01016               (iscomment(line+2, "EndSetup") ||
01017               (iscomment(line+2, "Page:") ||
01018                iscomment(line+2, "Trailer") ||
01019                (respect_eof && iscomment(line+2, "EOF"))))) &&
01020              (readline(fd, &line, &position, &line_len))) {
01021         section_len += line_len;
01022         doc->lensetup = section_len - line_len;
01023         doc->endsetup = position;
01024       }
01025     }
01026     /* END Windows NT fix ###jp##*/
01027 
01028     /* Individual Pages */
01029 
01030     if (beginsection == 0) {
01031         beginsection = position;
01032         section_len = line_len;
01033     }
01034     while (blank(line) && readline(fd, &line, &position, &line_len)) {
01035         section_len += line_len;
01036     }
01037 
01038 
01039 newpage:
01040     while (DSCcomment(line) && iscomment(line+2, "Page:")) {
01041         if (maxpages == 0) {
01042             maxpages = 1;
01043             doc->pages = (struct page *) PS_calloc(maxpages, sizeof(struct page));
01044             CHECK_MALLOCED(doc->pages);
01045         }
01046         label = gettext(line+length("%%Page:"), &next_char);
01047         if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0;
01048         if (nextpage == 1) {
01049             ignore = thispage != 1;
01050         }
01051         if (!ignore && thispage != nextpage) {
01052             PS_free(label);
01053             doc->numpages--;
01054             goto continuepage;
01055         }
01056         nextpage++;
01057         if (doc->numpages == maxpages) {
01058             maxpages++;
01059             doc->pages = (struct page *)
01060                          PS_realloc(doc->pages, maxpages*sizeof (struct page));
01061             CHECK_MALLOCED(doc->pages);
01062 
01063         }
01064         memset(&(doc->pages[doc->numpages]), 0, sizeof(struct page));
01065         page_bb_set = NONE;
01066         doc->pages[doc->numpages].label = label;
01067         if (beginsection) {
01068             doc->pages[doc->numpages].begin = beginsection;
01069             beginsection = 0;
01070         } else {
01071             doc->pages[doc->numpages].begin = position;
01072             section_len = line_len;
01073         }
01074 continuepage:
01075         while (readline(fd, &line, &position, &line_len) &&
01076                !(DSCcomment(line) &&
01077                  (iscomment(line+2, "Page:") ||
01078                   iscomment(line+2, "Trailer") ||
01079                   (respect_eof && iscomment(line+2, "EOF"))))) {
01080             section_len += line_len;
01081             if (!DSCcomment(line)) {
01082                 /* Do nothing */
01083             } else if (doc->pages[doc->numpages].orientation == NONE &&
01084                 iscomment(line+2, "PageOrientation:")) {
01085                 sscanf(line+length("%%PageOrientation:"), "%s", text);
01086                 if (strcmp(text, "Portrait") == 0) {
01087                     doc->pages[doc->numpages].orientation = PORTRAIT;
01088                 } else if (strcmp(text, "Landscape") == 0) {
01089                     doc->pages[doc->numpages].orientation = LANDSCAPE;
01090                 }
01091             } else if (doc->pages[doc->numpages].media == NULL &&
01092                        iscomment(line+2, "PageMedia:")) {
01093                 cp = gettext(line+length("%%PageMedia:"), NULL);
01094                 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
01095                     if (strcmp(cp, dmp->name) == 0) {
01096                         doc->pages[doc->numpages].media = dmp;
01097                         break;
01098                     }
01099                 }
01100                 PS_free(cp);
01101             } else if (doc->pages[doc->numpages].media == NULL &&
01102                        iscomment(line+2, "PaperSize:")) {
01103                 cp = gettext(line+length("%%PaperSize:"), NULL);
01104                 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
01105                     /* Note: Paper size comment uses down cased paper size
01106                      * name.  Case insensitive compares are only used for
01107                      * PaperSize comments.
01108                      */
01109                     if (strcasecmp(cp, dmp->name) == 0) {
01110                         doc->pages[doc->numpages].media = dmp;
01111                         break;
01112                     }
01113                 }
01114                 PS_free(cp);
01115             } else if ((page_bb_set == NONE || page_bb_set == ATEND) &&
01116                        iscomment(line+2, "PageBoundingBox:")) {
01117                 sscanf(line+length("%%PageBoundingBox:"), "%s", text);
01118                 if (strcmp(text, "(atend)") == 0) {
01119                     page_bb_set = ATEND;
01120                 } else {
01121                     if (sscanf(line+length("%%PageBoundingBox:"), "%d %d %d %d",
01122                             &(doc->pages[doc->numpages].boundingbox[LLX]),
01123                             &(doc->pages[doc->numpages].boundingbox[LLY]),
01124                             &(doc->pages[doc->numpages].boundingbox[URX]),
01125                             &(doc->pages[doc->numpages].boundingbox[URY])) == 4)
01126                         if (page_bb_set == NONE) page_bb_set = 1;
01127                     else {
01128                         float fllx, flly, furx, fury;
01129                         if (sscanf(line+length("%%PageBoundingBox:"),
01130                                    "%f %f %f %f",
01131                                    &fllx, &flly, &furx, &fury) == 4) {
01132                             if (page_bb_set == NONE) page_bb_set = 1;
01133                             doc->pages[doc->numpages].boundingbox[LLX] = fllx;
01134                             doc->pages[doc->numpages].boundingbox[LLY] = flly;
01135                             doc->pages[doc->numpages].boundingbox[URX] = furx;
01136                             doc->pages[doc->numpages].boundingbox[URY] = fury;
01137                             if (fllx <
01138                                     doc->pages[doc->numpages].boundingbox[LLX])
01139                                 doc->pages[doc->numpages].boundingbox[LLX]--;
01140                             if (flly <
01141                                     doc->pages[doc->numpages].boundingbox[LLY])
01142                                 doc->pages[doc->numpages].boundingbox[LLY]--;
01143                             if (furx >
01144                                     doc->pages[doc->numpages].boundingbox[URX])
01145                                 doc->pages[doc->numpages].boundingbox[URX]++;
01146                             if (fury >
01147                                     doc->pages[doc->numpages].boundingbox[URY])
01148                                 doc->pages[doc->numpages].boundingbox[URY]++;
01149                         }
01150                     }
01151                 }
01152             }
01153         }
01154         section_len += line_len;
01155         doc->pages[doc->numpages].end = position;
01156         doc->pages[doc->numpages].len = section_len - line_len;
01157         doc->numpages++;
01158     }
01159 
01160     /* Document Trailer */
01161 
01162     if (beginsection) {
01163         doc->begintrailer = beginsection;
01164         beginsection = 0;
01165     } else {
01166         doc->begintrailer = position;
01167         section_len = line_len;
01168     }
01169 
01170     preread = 1;
01171     while ((preread ||
01172             readline(fd, &line, &position, &line_len)) &&
01173            !(respect_eof && DSCcomment(line) && iscomment(line+2, "EOF"))) {
01174         if (!preread) section_len += line_len;
01175         preread = 0;
01176         if (!DSCcomment(line)) {
01177             /* Do nothing */
01178         } else if (iscomment(line+2, "Page:")) {
01179             PS_free(gettext(line+length("%%Page:"), &next_char));
01180             if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0;
01181             if (!ignore && thispage == nextpage) {
01182                 if (doc->numpages > 0) {
01183                     doc->pages[doc->numpages-1].end = position;
01184                     doc->pages[doc->numpages-1].len += section_len - line_len;
01185                 } else {
01186                     if (doc->endsetup) {
01187                         doc->endsetup = position;
01188                         doc->endsetup += section_len - line_len;
01189                     } else if (doc->endprolog) {
01190                         doc->endprolog = position;
01191                         doc->endprolog += section_len - line_len;
01192                     }
01193                 }
01194                 goto newpage;
01195             }
01196         } else if (!respect_eof && iscomment(line+2, "Trailer")) {
01197             /* What we thought was the start of the trailer was really */
01198             /* the trailer of an EPS on the page. */
01199             /* Set the end of the page to this trailer and keep scanning. */
01200             if (doc->numpages > 0) {
01201                 doc->pages[ doc->numpages-1 ].end = position;
01202                 doc->pages[ doc->numpages-1 ].len += section_len - line_len;
01203             }
01204             doc->begintrailer = position;
01205             section_len = line_len;
01206         } else if (bb_set == ATEND && iscomment(line+2, "BoundingBox:")) {
01207             if (sscanf(line+length("%%BoundingBox:"), "%d %d %d %d",
01208                        &(doc->boundingbox[LLX]),
01209                        &(doc->boundingbox[LLY]),
01210                        &(doc->boundingbox[URX]),
01211                        &(doc->boundingbox[URY])) != 4) {
01212                 float fllx, flly, furx, fury;
01213                 if (sscanf(line+length("%%BoundingBox:"), "%f %f %f %f",
01214                            &fllx, &flly, &furx, &fury) == 4) {
01215                     doc->boundingbox[LLX] = fllx;
01216                     doc->boundingbox[LLY] = flly;
01217                     doc->boundingbox[URX] = furx;
01218                     doc->boundingbox[URY] = fury;
01219                     if (fllx < doc->boundingbox[LLX])
01220                         doc->boundingbox[LLX]--;
01221                     if (flly < doc->boundingbox[LLY])
01222                         doc->boundingbox[LLY]--;
01223                     if (furx > doc->boundingbox[URX])
01224                         doc->boundingbox[URX]++;
01225                     if (fury > doc->boundingbox[URY])
01226                         doc->boundingbox[URY]++;
01227                 }
01228             }
01229         } else if (orientation_set == ATEND &&
01230                    iscomment(line+2, "Orientation:")) {
01231             sscanf(line+length("%%Orientation:"), "%s", text);
01232             if (strcmp(text, "Portrait") == 0) {
01233                 doc->orientation = PORTRAIT;
01234             } else if (strcmp(text, "Landscape") == 0) {
01235                 doc->orientation = LANDSCAPE;
01236             }
01237         } else if (page_order_set == ATEND && iscomment(line+2, "PageOrder:")) {
01238             sscanf(line+length("%%PageOrder:"), "%s", text);
01239             if (strcmp(text, "Ascend") == 0) {
01240                 doc->pageorder = ASCEND;
01241             } else if (strcmp(text, "Descend") == 0) {
01242                 doc->pageorder = DESCEND;
01243             } else if (strcmp(text, "Special") == 0) {
01244                 doc->pageorder = SPECIAL;
01245             }
01246         } else if (pages_set == ATEND && iscomment(line+2, "Pages:")) {
01247             if (sscanf(line+length("%%Pages:"), "%*u %d", &i) == 1) {
01248                 if (page_order_set == NONE) {
01249                     if (i == -1) doc->pageorder = DESCEND;
01250                     else if (i == 0) doc->pageorder = SPECIAL;
01251                     else if (i == 1) doc->pageorder = ASCEND;
01252                 }
01253             }
01254         }
01255     }
01256     section_len += line_len;
01257     if (DSCcomment(line) && iscomment(line+2, "EOF")) {
01258         readline(fd, &line, &position, &line_len);
01259         section_len += line_len;
01260     }
01261     doc->endtrailer = position;
01262     doc->lentrailer = section_len - line_len;
01263 
01264 #if 0
01265     section_len = line_len;
01266     preread = 1;
01267     while (preread ||
01268            readline(fd, &line, &position, &line_len)) {
01269         if (!preread) section_len += line_len;
01270         preread = 0;
01271         if (DSCcomment(line) && iscomment(line+2, "Page:")) {
01272             PS_free(gettext(line+length("%%Page:"), &next_char));
01273             if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0;
01274             if (!ignore && thispage == nextpage) {
01275                 if (doc->numpages > 0) {
01276                     doc->pages[doc->numpages-1].end = position;
01277                     doc->pages[doc->numpages-1].len += doc->lentrailer +
01278                                                        section_len - line_len;
01279                 } else {
01280                     if (doc->endsetup) {
01281                         doc->endsetup = position;
01282                         doc->endsetup += doc->lentrailer +
01283                                          section_len - line_len;
01284                     } else if (doc->endprolog) {
01285                         doc->endprolog = position;
01286                         doc->endprolog += doc->lentrailer +
01287                                           section_len - line_len;
01288                     }
01289                 }
01290                 goto newpage;
01291             }
01292         }
01293     }
01294 #endif
01295     ENDMESSAGE(psscan)
01296     ps_io_exit(fd);
01297     return doc;
01298 }
01299 
01300 /*###########################################################*/
01301 /*
01302  *      psfree -- free dynamic storage associated with document structure.
01303  */
01304 /*###########################################################*/
01305 
01306 void
01307 psfree(doc)
01308     struct document *doc;
01309 {
01310     int i;
01311 
01312     BEGINMESSAGE(psfree)
01313     if (doc) {
01314         for (i=0; i<doc->numpages; i++) {
01315             if (doc->pages[i].label) PS_free(doc->pages[i].label);
01316         }
01317         for (i=0; i<doc->nummedia; i++) {
01318             if (doc->media[i].name) PS_free(doc->media[i].name);
01319         }
01320         if (doc->title) PS_free(doc->title);
01321         if (doc->date) PS_free(doc->date);
01322         if (doc->pages) PS_free(doc->pages);
01323         if (doc->media) PS_free(doc->media);
01324         PS_free(doc);
01325     }
01326     ENDMESSAGE(psfree)
01327 }
01328 
01329 /*----------------------------------------------------------*/
01330 /*
01331  * gettextline -- skip over white space and return the rest of the line.
01332  *               If the text begins with '(' return the text string
01333  *               using gettext().
01334  */
01335 /*----------------------------------------------------------*/
01336 
01337 static char *
01338 gettextline(line)
01339     char *line;
01340 {
01341     char *cp;
01342 
01343     BEGINMESSAGE(gettextline)
01344     while (*line && (*line == ' ' || *line == '\t')) line++;
01345     if (*line == '(') {
01346         ENDMESSAGE(gettextline)
01347         return gettext(line, NULL);
01348     } else {
01349         if (strlen(line) == 0) {ENDMESSAGE(gettextline) return NULL;}
01350         cp = (char *) PS_malloc(strlen(line));
01351         CHECK_MALLOCED(cp);
01352         strncpy(cp, line, strlen(line)-1);
01353         cp[strlen(line)-1] = '\0';
01354         ENDMESSAGE(gettextline)
01355         return cp;
01356     }
01357 }
01358 
01359 /*----------------------------------------------------------*/
01360 /*
01361  *      gettext -- return the next text string on the line.
01362  *                 return NULL if nothing is present.
01363  */
01364 /*----------------------------------------------------------*/
01365 
01366 static char *
01367 gettext(line, next_char)
01368     char *line;
01369     char **next_char;
01370 {
01371     char text[PSLINELENGTH];    /* Temporary storage for text */
01372     char *cp;
01373     int quoted=0;
01374 
01375     BEGINMESSAGE(gettext)
01376     while (*line && (*line == ' ' || *line == '\t')) line++;
01377     cp = text;
01378     if (*line == '(') {
01379         int level = 0;
01380         quoted=1;
01381         line++;
01382         while (*line && !(*line == ')' && level == 0 )) {
01383             if (*line == '\\') {
01384                 if (*(line+1) == 'n') {
01385                     *cp++ = '\n';
01386                     line += 2;
01387                 } else if (*(line+1) == 'r') {
01388                     *cp++ = '\r';
01389                     line += 2;
01390                 } else if (*(line+1) == 't') {
01391                     *cp++ = '\t';
01392                     line += 2;
01393                 } else if (*(line+1) == 'b') {
01394                     *cp++ = '\b';
01395                     line += 2;
01396                 } else if (*(line+1) == 'f') {
01397                     *cp++ = '\f';
01398                     line += 2;
01399                 } else if (*(line+1) == '\\') {
01400                     *cp++ = '\\';
01401                     line += 2;
01402                 } else if (*(line+1) == '(') {
01403                     *cp++ = '(';
01404                     line += 2;
01405                 } else if (*(line+1) == ')') {
01406                     *cp++ = ')';
01407                     line += 2;
01408                 } else if (*(line+1) >= '0' && *(line+1) <= '9') {
01409                     if (*(line+2) >= '0' && *(line+2) <= '9') {
01410                         if (*(line+3) >= '0' && *(line+3) <= '9') {
01411                             *cp++ = ((*(line+1) - '0')*8 + *(line+2) - '0')*8 +
01412                                     *(line+3) - '0';
01413                             line += 4;
01414                         } else {
01415                             *cp++ = (*(line+1) - '0')*8 + *(line+2) - '0';
01416                             line += 3;
01417                         }
01418                     } else {
01419                         *cp++ = *(line+1) - '0';
01420                         line += 2;
01421                     }
01422                 } else {
01423                     line++;
01424                     *cp++ = *line++;
01425                 }
01426             } else if (*line == '(') {
01427                 level++;
01428                 *cp++ = *line++;
01429             } else if (*line == ')') {
01430                 level--;
01431                 *cp++ = *line++;
01432             } else {
01433                 *cp++ = *line++;
01434             }
01435         }
01436     } else {
01437         while (*line && !(*line == ' ' || *line == '\t' || *line == '\n'))
01438             *cp++ = *line++;
01439     }
01440     *cp = '\0';
01441     if (next_char) *next_char = line;
01442     if (!quoted && strlen(text) == 0) {ENDMESSAGE(gettext) return NULL;}
01443     cp = (char *) PS_malloc(strlen(text)+1);
01444     CHECK_MALLOCED(cp);
01445     strcpy(cp, text);
01446     ENDMESSAGE(gettext)
01447     return cp;
01448 }
01449 
01450 /*----------------------------------------------------------*/
01451 /* ps_io_init */
01452 /*----------------------------------------------------------*/
01453 
01454 #define FD_FILE             (fd->file)
01455 #define FD_FILE_DESC        (fd->file_desc)
01456 #define FD_FILEPOS          (fd->filepos)
01457 #define FD_LINE_BEGIN       (fd->line_begin)
01458 #define FD_LINE_END         (fd->line_end)
01459 #define FD_LINE_LEN         (fd->line_len)
01460 #define FD_LINE_TERMCHAR    (fd->line_termchar)
01461 #define FD_BUF              (fd->buf)
01462 #define FD_BUF_END          (fd->buf_end)
01463 #define FD_BUF_SIZE         (fd->buf_size)
01464 #define FD_STATUS           (fd->status)
01465 
01466 #define FD_STATUS_OKAY        0
01467 #define FD_STATUS_BUFTOOLARGE 1
01468 #define FD_STATUS_NOMORECHARS 2
01469 
01470 #define LINE_CHUNK_SIZE     4096
01471 #define MAX_PS_IO_FGETCHARS_BUF_SIZE 57344
01472 #define BREAK_PS_IO_FGETCHARS_BUF_SIZE 49152
01473 
01474 static FileData ps_io_init(file)
01475    FILE *file;
01476 {
01477    FileData fd;
01478    Cardinal size = sizeof(FileDataStruct);
01479 
01480    BEGINMESSAGE(ps_io_init)
01481 
01482    fd = (FileData) PS_XtMalloc(size);
01483    memset((void*) fd ,0,(size_t)size);
01484 
01485    rewind(file);
01486    FD_FILE      = file;
01487    FD_FILE_DESC = fileno(file);
01488    FD_FILEPOS   = ftell(file);
01489    FD_BUF_SIZE  = (2*LINE_CHUNK_SIZE)+1;
01490    FD_BUF       = PS_XtMalloc(FD_BUF_SIZE);
01491    FD_BUF[0]    = '\0';
01492    ENDMESSAGE(ps_io_init)
01493    return(fd);
01494 }
01495 
01496 /*----------------------------------------------------------*/
01497 /* ps_io_exit */
01498 /*----------------------------------------------------------*/
01499 
01500 static void
01501 ps_io_exit(fd)
01502    FileData fd;
01503 {
01504    BEGINMESSAGE(ps_io_exit)
01505    PS_XtFree(FD_BUF);
01506    PS_XtFree(fd);
01507    ENDMESSAGE(ps_io_exit)
01508 }
01509 
01510 /*----------------------------------------------------------*/
01511 /* ps_io_fseek */
01512 /*----------------------------------------------------------*/
01513 
01514 static int
01515 ps_io_fseek(fd,offset)
01516    FileData fd;
01517    int offset;
01518 {
01519    int status;
01520    BEGINMESSAGE(ps_io_fseek)
01521    status=fseek(FD_FILE,(long)offset,SEEK_SET);
01522    FD_BUF_END = FD_LINE_BEGIN = FD_LINE_END = FD_LINE_LEN = 0;
01523    FD_FILEPOS = offset;
01524    FD_STATUS  = FD_STATUS_OKAY;
01525    ENDMESSAGE(ps_io_fseek)
01526    return(status);
01527 }
01528 
01529 /*----------------------------------------------------------*/
01530 /* ps_io_ftell */
01531 /*----------------------------------------------------------*/
01532 
01533 static int
01534 ps_io_ftell(fd)
01535    FileData fd;
01536 {
01537    BEGINMESSAGE(ps_io_ftell)
01538    IMESSAGE(FD_FILEPOS)
01539    ENDMESSAGE(ps_io_ftell)
01540    return(FD_FILEPOS);
01541 }
01542 
01543 /*----------------------------------------------------------*/
01544 /* ps_io_fgetchars */
01545 /*----------------------------------------------------------*/
01546 
01547 #ifdef USE_MEMMOVE_CODE
01548 static void ps_memmove (d, s, l)
01549   char *d;
01550   const char *s;
01551   unsigned l;
01552 {
01553   if (s < d) for (s += l, d += l; l; --l) *--d = *--s;
01554   else if (s != d) for (; l; --l)         *d++ = *s++;
01555 }
01556 #else
01557 #   define ps_memmove memmove
01558 #endif
01559 
01560 static char * ps_io_fgetchars(fd,num)
01561    FileData fd;
01562    int num;
01563 {
01564    char *eol=NULL,*tmp;
01565    size_t size_of_char = sizeof(char);
01566 
01567    BEGINMESSAGE(ps_io_fgetchars)
01568 
01569    if (FD_STATUS != FD_STATUS_OKAY) {
01570       INFMESSAGE(aborting since status not okay)
01571       ENDMESSAGE(ps_io_fgetchars)
01572       return(NULL);
01573    }
01574 
01575    FD_BUF[FD_LINE_END] = FD_LINE_TERMCHAR; /* restoring char previously exchanged against '\0' */
01576    FD_LINE_BEGIN       = FD_LINE_END;
01577 
01578 #if 0
01579    {
01580       int fp = (int)(ftell(FD_FILE));
01581       if (num<0)  { INFMESSAGE(reading line) }
01582       else        { INFMESSAGE(reading specified num of chars) }
01583       IIMESSAGE(FD_BUF_SIZE,FD_BUF_END)
01584       IIMESSAGE(FD_LINE_BEGIN,FD_LINE_END)
01585       INFIMESSAGE(unparsed:,FD_BUF_END-FD_LINE_END)
01586       IMESSAGE(fp)
01587       IIMESSAGE(FD_FILEPOS,fp-(FD_BUF_END-FD_LINE_END))
01588    }
01589 #endif /* 0 */
01590 
01591    do {
01592       if (num<0) { /* reading whole line */
01593          if (FD_BUF_END-FD_LINE_END) {
01594             /* strpbrk is faster but fails on lines with embedded NULLs 
01595               eol = strpbrk(FD_BUF+FD_LINE_END,"\n\r");
01596             */
01597             tmp = FD_BUF + FD_BUF_END;
01598             eol = FD_BUF + FD_LINE_END;
01599             while (eol < tmp && *eol != '\n' && *eol != '\r') eol++;
01600             if (eol >= tmp) eol = NULL;
01601             if (eol) {
01602                if (*eol=='\r' && *(eol+1)=='\n') eol += 2;
01603                else eol++;
01604                break;
01605             }
01606          }
01607       } else { /* reading specified num of chars */
01608          if (FD_BUF_END >= FD_LINE_BEGIN+num) {
01609             eol = FD_BUF+FD_LINE_BEGIN+num;
01610             break;
01611          }
01612       }
01613 
01614       INFMESSAGE(no end of line yet)
01615 
01616       if (FD_BUF_END - FD_LINE_BEGIN > BREAK_PS_IO_FGETCHARS_BUF_SIZE) {
01617         INFMESSAGE(breaking line artificially)
01618         eol = FD_BUF + FD_BUF_END - 1;
01619         break;
01620       }
01621 
01622       while (FD_BUF_SIZE < FD_BUF_END+LINE_CHUNK_SIZE+1) {
01623          if (FD_BUF_SIZE > MAX_PS_IO_FGETCHARS_BUF_SIZE) {
01624            /* we should never get here, since the line is broken
01625              artificially after BREAK_PS_IO_FGETCHARS_BUF_SIZE bytes. */
01626             INFMESSAGE(buffer became to large)
01627             ENDMESSAGE(ps_io_fgetchars)
01628             fprintf(stderr, "gv: ps_io_fgetchars: Fatal Error: buffer became too large.\n");
01629             exit(-1);
01630          }
01631          if (FD_LINE_BEGIN) {
01632             INFMESSAGE(moving line to begin of buffer)
01633             ps_memmove((void*)FD_BUF,(void*)(FD_BUF+FD_LINE_BEGIN),
01634                     ((size_t)(FD_BUF_END-FD_LINE_BEGIN+1))*size_of_char);
01635             FD_BUF_END    -= FD_LINE_BEGIN; 
01636             FD_LINE_BEGIN  = 0;
01637          } else {
01638             INFMESSAGE(enlarging buffer)
01639             /*
01640               FD_BUF_SIZE    = FD_BUF_END+LINE_CHUNK_SIZE+1;
01641             */
01642             FD_BUF_SIZE    = FD_BUF_SIZE+LINE_CHUNK_SIZE+1;
01643             IMESSAGE(FD_BUF_SIZE)
01644             FD_BUF         = PS_XtRealloc(FD_BUF,FD_BUF_SIZE);
01645          }
01646       }
01647 
01648       FD_LINE_END = FD_BUF_END;
01649 #ifdef VMS
01650       /* different existing VMS file formats require that we use read here ###jp###,10/12/96 */ 
01651       if (num<0) FD_BUF_END += read(FD_FILE_DESC,FD_BUF+FD_BUF_END,LINE_CHUNK_SIZE);
01652       else       FD_BUF_END += fread(FD_BUF+FD_BUF_END,size_of_char,LINE_CHUNK_SIZE,FD_FILE);
01653 #else
01654       /* read() seems to fail sometimes (? ? ?) so we always use fread ###jp###,07/31/96*/
01655       FD_BUF_END += fread(FD_BUF+FD_BUF_END,size_of_char,LINE_CHUNK_SIZE,FD_FILE);
01656 #endif
01657 
01658       FD_BUF[FD_BUF_END] = '\0';
01659       if (FD_BUF_END-FD_LINE_END == 0) {
01660          INFMESSAGE(failed to read more chars)
01661          ENDMESSAGE(ps_io_fgetchars)
01662          FD_STATUS = FD_STATUS_NOMORECHARS;
01663          return(NULL);
01664       }
01665    }
01666    while (1);
01667 
01668    FD_LINE_END          = eol - FD_BUF;
01669    FD_LINE_LEN          = FD_LINE_END - FD_LINE_BEGIN;
01670    FD_LINE_TERMCHAR     = FD_BUF[FD_LINE_END];
01671    FD_BUF[FD_LINE_END]  = '\0';
01672 #ifdef USE_FTELL_FOR_FILEPOS
01673    if (FD_LINE_END==FD_BUF_END) {
01674       INFMESSAGE(### using ftell to get FD_FILEPOS)
01675       /*
01676       For VMS we cannot assume that the record is FD_LINE_LEN bytes long
01677       on the disk. For stream_lf and stream_cr that is true, but not for
01678       other formats, since VAXC/DECC converts the formatting into a single \n.
01679       eg. variable format files have a 2-byte length and padding to an even
01680       number of characters. So, we use ftell for each record.
01681       This still will not work if we need to fseek to a \n or \r inside a
01682       variable record (ftell always returns the start of the record in this
01683       case).
01684       (Tim Adye, adye@v2.rl.ac.uk)
01685       */
01686       FD_FILEPOS         = ftell(FD_FILE);
01687    } else
01688 #endif /* USE_FTELL_FOR_FILEPOS */
01689       FD_FILEPOS        += FD_LINE_LEN;
01690 
01691 #if 0
01692    SMESSAGE(FD_BUF+FD_LINE_BEGIN)
01693    IIMESSAGE(FD_LINE_BEGIN,FD_LINE_END)
01694    IIMESSAGE(FD_BUF_END,FD_LINE_LEN)
01695 #endif
01696 
01697    ENDMESSAGE(ps_io_fgetchars)
01698    return(FD_BUF+FD_LINE_BEGIN);
01699 }
01700 
01701 /*----------------------------------------------------------*/
01702 /*
01703    readline()
01704    Read the next line in the postscript file.
01705    Automatically skip over data (as indicated by
01706    %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
01707    comments.)
01708    Also, skip over included documents (as indicated by
01709    %%BeginDocument/%%EndDocument comments.)
01710 */
01711 /*----------------------------------------------------------*/
01712 
01713 static char * readline (fd, lineP, positionP, line_lenP)
01714    FileData fd;
01715    char **lineP;
01716    long *positionP;
01717    unsigned int *line_lenP;
01718 {
01719    unsigned int nbytes=0;
01720    int skipped=0;
01721    char *line;
01722 
01723    BEGINMESSAGE(readline)
01724 
01725    if (positionP) *positionP = FD_FILEPOS;
01726    line = ps_io_fgetchars(fd,-1);
01727    if (!line) {
01728       INFMESSAGE(could not get line)
01729       *line_lenP = 0;
01730       *lineP     = empty_string;
01731       ENDMESSAGE(readline)
01732       return(NULL); 
01733    }
01734 
01735    *line_lenP = FD_LINE_LEN;
01736 
01737 #define IS_COMMENT(comment)                             \
01738            (DSCcomment(line) && iscomment(line+2,(comment)))
01739 #define IS_BEGIN(comment)                               \
01740            (iscomment(line+7,(comment)))
01741 #define SKIP_WHILE(cond)                                \
01742            while (readline(fd, &line, NULL, &nbytes) && (cond)) *line_lenP += nbytes;\
01743            skipped=1;
01744 #define SKIP_UNTIL_1(comment) {                         \
01745            INFMESSAGE(skipping until comment)           \
01746            SKIP_WHILE((!IS_COMMENT(comment)))           \
01747            INFMESSAGE(completed skipping until comment) \
01748         }
01749 #define SKIP_UNTIL_2(comment1,comment2) {               \
01750            INFMESSAGE(skipping until comment1 or comment2)\
01751            SKIP_WHILE((!IS_COMMENT(comment1) && !IS_COMMENT(comment2)))\
01752            INFMESSAGE(completed skipping until comment1 or comment2)\
01753         }
01754 
01755 #if 0
01756    if ((scanstyle&SCANSTYLE_MISSING_BEGINDOCUMENT) &&
01757        (line[0] == '%') &&
01758        (*line_lenP > 11) &&
01759        (iscomment(line,"%!PS-Adobe-") || iscomment(line + 1,"%!PS-Adobe-"))) {
01760      char *c=line+11;
01761      while (*c && !isspace(*c)) c++;
01762      if (isspace(*c)) while (*c && isspace(*c)) c++;
01763      /* don't skip EPSF files */
01764        printf("line in question: %s\n",line);
01765      if (strncmp(c,"EPSF",4)) {
01766        printf("skipping starts here: %s\n",line);
01767        SKIP_UNTIL_1("EOF")
01768        *line_lenP += nbytes;
01769        readline(fd, &line, NULL, &nbytes);
01770        printf("skipping ends here: %s\n",line);
01771      }
01772    }
01773    else
01774 #endif
01775    if  (!IS_COMMENT("Begin"))     {} /* Do nothing */
01776    else if IS_BEGIN("Document:")  SKIP_UNTIL_1("EndDocument")
01777    else if IS_BEGIN("Feature:")   SKIP_UNTIL_1("EndFeature")
01778 #ifdef USE_ACROREAD_WORKAROUND
01779    else if IS_BEGIN("File")       SKIP_UNTIL_2("EndFile","EOF")
01780 #else
01781    else if IS_BEGIN("File")       SKIP_UNTIL_1("EndFile")
01782 #endif
01783    else if IS_BEGIN("Font")       SKIP_UNTIL_1("EndFont")
01784    else if IS_BEGIN("ProcSet")    SKIP_UNTIL_1("EndProcSet")
01785    else if IS_BEGIN("Resource")   SKIP_UNTIL_1("EndResource")
01786    else if IS_BEGIN("Data:")      {
01787       int  num;
01788       char text[101];
01789       INFMESSAGE(encountered "BeginData:")
01790       if (FD_LINE_LEN > 100) FD_BUF[100] = '\0';
01791       text[0] = '\0';
01792       if (sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text) >= 1) {
01793          if (strcmp(text, "Lines") == 0) {
01794             INFIMESSAGE(number of lines to skip:,num)
01795             while (num) {
01796                line = ps_io_fgetchars(fd,-1);
01797                if (line) *line_lenP += FD_LINE_LEN;
01798                num--;
01799             }
01800          } else {
01801             int read_chunk_size = LINE_CHUNK_SIZE;
01802             INFIMESSAGE(number of chars to skip:,num)
01803             while (num>0) {
01804                if (num <= LINE_CHUNK_SIZE) read_chunk_size=num;
01805                line = ps_io_fgetchars(fd,read_chunk_size);
01806                if (line) *line_lenP += FD_LINE_LEN;
01807                num -= read_chunk_size;
01808             }
01809          }
01810       }
01811       SKIP_UNTIL_1("EndData")
01812    }
01813    else if IS_BEGIN("Binary:") {
01814       int  num;
01815       INFMESSAGE(encountered "BeginBinary:")
01816       if (sscanf(line+length("%%BeginBinary:"), "%d", &num) == 1) {
01817          int read_chunk_size = LINE_CHUNK_SIZE;
01818          INFIMESSAGE(number of chars to skip:,num)
01819          while (num>0) {
01820             if (num <= LINE_CHUNK_SIZE) read_chunk_size=num;
01821             line = ps_io_fgetchars(fd,read_chunk_size);
01822             if (line) *line_lenP += FD_LINE_LEN;
01823             num -= read_chunk_size;
01824          }
01825          SKIP_UNTIL_1("EndBinary")
01826       }
01827    }
01828 
01829    if (skipped) {
01830       INFMESSAGE(skipped lines)
01831       *line_lenP += nbytes;
01832       *lineP = skipped_line;      
01833    } else {
01834       *lineP = FD_BUF+FD_LINE_BEGIN;
01835    }
01836 
01837    ENDMESSAGE(readline)
01838    return(FD_BUF+FD_LINE_BEGIN);
01839 }
01840 
01841 /*###########################################################*/
01842 /*
01843  *      pscopyuntil -- copy lines of Postscript from a section of one file
01844  *                     to another file until a particular comment is reached.
01845  *                     Automatically switch to binary copying whenever
01846  *                     %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
01847  *                     comments are encountered.
01848  */
01849 /*###########################################################*/
01850 
01851 char *
01852 pscopyuntil(fd, to, begin, end, comment)
01853    FileData fd;
01854    FILE *to;
01855    long begin;                  /* set negative to avoid initial seek */
01856    long end;
01857    char *comment;
01858 {
01859    char *line;
01860    int comment_length;
01861 
01862    BEGINMESSAGE(pscopyuntil)
01863    if (comment) {
01864       INFSMESSAGE(will copy until,comment)
01865       comment_length = strlen(comment);
01866    }
01867    else {
01868       INFMESSAGE(will copy until specified file position)
01869       comment_length = 0;
01870    }
01871    if (begin >= 0) ps_io_fseek(fd, begin);
01872    while (ps_io_ftell(fd) < end) {
01873       line = ps_io_fgetchars(fd,-1);
01874       if (!line) break;
01875       if (comment && strncmp(line, comment, comment_length) == 0) {
01876          char *cp = (char *) PS_malloc(strlen(line)+1);
01877          INFSMESSAGE(encountered specified,comment)
01878          CHECK_MALLOCED(cp);
01879          strcpy(cp, line);
01880          ENDMESSAGE(pscopyuntil)
01881          return cp;
01882       }
01883       fputs(line, to);
01884       if  (!IS_COMMENT("Begin"))     {} /* Do nothing */
01885       else if IS_BEGIN("Data:")      {
01886          int  num;
01887          char text[101];
01888          INFMESSAGE(encountered "BeginData:")
01889          if (FD_LINE_LEN > 100) FD_BUF[100] = '\0';
01890          text[0] = '\0';
01891          if (sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text) >= 1) {
01892             if (strcmp(text, "Lines") == 0) {
01893                INFIMESSAGE(number of lines:,num)
01894                while (num) {
01895                   line = ps_io_fgetchars(fd,-1);
01896                   if (line) fputs(line,to);
01897                   num--;
01898                }
01899             } else {
01900                int read_chunk_size = LINE_CHUNK_SIZE;
01901                INFIMESSAGE(number of chars:,num)
01902                while (num>0) {
01903                   if (num <= LINE_CHUNK_SIZE) read_chunk_size=num;
01904                   line = ps_io_fgetchars(fd,read_chunk_size);
01905                   if (line) fwrite(line,sizeof(char),FD_LINE_LEN, to);
01906                   num -= read_chunk_size;
01907                }
01908             }
01909          }
01910       }
01911       else if IS_BEGIN("Binary:") {
01912          int  num;
01913          INFMESSAGE(encountered "BeginBinary:")
01914          if (sscanf(line+length("%%BeginBinary:"), "%d", &num) == 1) {
01915             int read_chunk_size = LINE_CHUNK_SIZE;
01916             INFIMESSAGE(number of chars:,num)
01917             while (num>0) {
01918                if (num <= LINE_CHUNK_SIZE) read_chunk_size=num;
01919                line = ps_io_fgetchars(fd,read_chunk_size);
01920                if (line) fwrite(line, sizeof (char),FD_LINE_LEN, to);
01921                num -= read_chunk_size;
01922             }
01923          }
01924       }
01925    }
01926    ENDMESSAGE(pscopyuntil)
01927    return NULL;
01928 }
01929 
01930 /*----------------------------------------------------------*/
01931 /* blank */
01932 /* Check whether the line contains nothing but white space. */
01933 /*----------------------------------------------------------*/
01934 
01935 static int blank(line)
01936    char *line;
01937 {
01938    char *cp = line;
01939 
01940    BEGINMESSAGE(blank)
01941    while (*cp == ' ' || *cp == '\t') cp++;
01942    ENDMESSAGE(blank)
01943    return *cp == '\n' || *cp== '\r' || (*cp == '%' && (line[0] != '%' || line[1] != '%'));
01944 }
01945 
01946 /*##########################################################*/
01947 /* pscopydoc */
01948 /* Copy the headers, marked pages, and trailer to fp */
01949 /*##########################################################*/
01950 
01951 void
01952 pscopydoc(dest_file,src_filename,d,pagelist)
01953     FILE *dest_file;
01954     char *src_filename;
01955     Document d;
01956     char *pagelist;
01957 {
01958     FILE *src_file;
01959     char text[PSLINELENGTH];
01960     char *comment;
01961     Boolean pages_written = False;
01962     Boolean pages_atend = False;
01963     int pages;
01964     int page = 1;
01965     int i, j;
01966     int here;
01967     FileData fd;
01968 
01969     BEGINMESSAGE(pscopydoc)
01970 
01971     INFSMESSAGE(copying from file, src_filename)
01972     src_file = fopen(src_filename, "r");
01973     fd = ps_io_init(src_file);
01974 
01975     i=0;
01976     pages=0;
01977     while (pagelist[i]) { if (pagelist[i]=='*') pages++; i++; }
01978     INFIMESSAGE(number of pages to be copied,pages)
01979 
01980     here = d->beginheader;
01981     while ((comment=pscopyuntil(fd,dest_file,here,d->endheader,"%%Pages:"))) {
01982        SMESSAGE(comment)
01983        here = ps_io_ftell(fd);
01984        if (pages_written || pages_atend) {
01985           PS_free(comment);
01986           continue;
01987        }
01988        sscanf(comment+length("%%Pages:"), "%s", text);
01989        if (strcmp(text, "(atend)") == 0) {
01990           fputs(comment, dest_file);
01991           pages_atend = True;
01992        } else {
01993           switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) {
01994              case 1:
01995                 fprintf(dest_file, "%%%%Pages: %d %d\n", pages, i);
01996                 break;
01997              default:
01998                 fprintf(dest_file, "%%%%Pages: %d\n", pages);
01999                 break;
02000           }
02001           pages_written = True;
02002        }
02003        PS_free(comment);
02004    }
02005    pscopyuntil(fd, dest_file, d->beginpreview, d->endpreview,NULL);
02006    pscopyuntil(fd, dest_file, d->begindefaults, d->enddefaults,NULL);
02007    pscopyuntil(fd, dest_file, d->beginprolog, d->endprolog,NULL);
02008    pscopyuntil(fd, dest_file, d->beginsetup, d->endsetup,NULL);
02009 
02010    for (i = 0; i < d->numpages; i++) {
02011       if (d->pageorder == DESCEND) j = (d->numpages - 1) - i;
02012       else                         j = i;
02013       if (pagelist[j]=='*') {
02014           comment = pscopyuntil(fd,dest_file,d->pages[i].begin,d->pages[i].end, "%%Page:");
02015           fprintf(dest_file, "%%%%Page: %s %d\n",d->pages[i].label, page++);
02016           PS_free(comment);
02017           pscopyuntil(fd, dest_file, -1, d->pages[i].end,NULL);
02018       }
02019    }
02020 
02021    here = d->begintrailer;
02022    while ((comment = pscopyuntil(fd, dest_file, here, d->endtrailer, "%%Pages:"))) {
02023       here = ps_io_ftell(fd);
02024       if (pages_written) {
02025          PS_free(comment);
02026          continue;
02027       }
02028       switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) {
02029          case 1:
02030             fprintf(dest_file, "%%%%Pages: %d %d\n", pages, i);
02031             break;
02032          default:
02033             fprintf(dest_file, "%%%%Pages: %d\n", pages);
02034             break;
02035       }
02036       pages_written = True;
02037       PS_free(comment);
02038    }
02039    fclose(src_file);
02040    ps_io_exit(fd);
02041 
02042    ENDMESSAGE(pscopydoc)
02043 }
02044 #undef length
02045 
02046 

Generated at Mon Dec 11 22:46:27 2000 for Postscript Utility Library by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000