"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 * ps.c -- Postscript scanning and copying routines.
3 * Copyright (C) 1992 Timothy O. Theisen
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Tim Theisen Systems Programmer
20 * Internet: tim@cs.wisc.edu Department of Computer Sciences
21 * UUCP: uwvax!tim University of Wisconsin-Madison
22 * Phone: (608)262-0438 1210 West Dayton Street
23 * FAX: (608)262-9777 Madison, WI 53706
24 */
25
26 #include <stdio.h>
27 #ifndef SEEK_SET
28 #define SEEK_SET 0
29 #endif
30 #ifndef BUFSIZ
31 #define BUFSIZ 1024
32 #endif
33 #include <ctype.h>
34 #include <X11/Xos.h> /* #includes the appropriate <string.h> */
35 #include "ps.h"
36
37 #ifdef BSD4_2
38 #define memset(a,b,c) bzero(a,c)
39 #endif
40
41 /* length calculates string length at compile time */
42 /* can only be used with character constants */
43 #define length(a) (sizeof(a)-1)
44 #define iscomment(a, b) (strncmp(a, b, length(b)) == 0)
45
46 /* list of standard paper sizes from Adobe's PPD. */
47
48 struct documentmedia papersizes[] = {
49 "Letter", 612, 792,
50 "LetterSmall", 612, 792,
51 "Tabloid", 792, 1224,
52 "Ledger", 1224, 792,
53 "Legal", 612, 1008,
54 "Statement", 396, 612,
55 "Executive", 540, 720,
56 "A3", 842, 1190,
57 "A4", 595, 842,
58 "A4Small", 595, 842,
59 "A5", 420, 595,
60 "B4", 729, 1032,
61 "B5", 516, 729,
62 "Folio", 612, 936,
63 "Quarto", 610, 780,
64 "10x14", 720, 1008,
65 NULL, 0, 0
66 };
67
68
69 static char *readline();
70 static char *gettextline();
71 static char *gettext();
72 static int blank();
73
74 /*
75 * psscan -- scan the PostScript file for document structuring comments.
76 *
77 * This scanner is designed to retrieve the information necessary for
78 * the ghostview previewer. It will scan files that conform to any
79 * version (1.0, 2.0, 2.1, or 3.0) of the document structuring conventions.
80 * It does not really care which version of comments the file contains.
81 * (The comments are largely upward compatible.) It will scan a number
82 * of non-conforming documents. (You could have part of the document
83 * conform to V2.0 and the rest conform to V3.0. It would be similar
84 * to the DC-2 1/2+, it would look funny but it can still fly.)
85 *
86 * This routine returns a pointer to the document structure.
87 * The structure contains the information relevant to previewing.
88 * These include EPSF flag (to tell if the file is a encapsulated figure),
89 * Page Media (for the Page Size), Bounding Box (to minimize backing
90 * pixmap size or determine window size for encapsulated PostScript),
91 * Orientation of Paper (for default transformation matrix), and
92 * Page Order. The title and CreationDate are also retrieved to
93 * help identify the document.
94 *
95 * The following comments are examined:
96 *
97 * Header section:
98 * Must start with %!PS-Adobe-. Version numbers ignored.
99 *
100 * %!PS-Adobe-* [EPSF-*]
101 * %%BoundingBox: <int> <int> <int> <int>|(atend)
102 * %%CreationDate: <textline>
103 * %%Orientation: Portrait|Landscape|(atend)
104 * %%Pages: <uint> [<int>]|(atend)
105 * %%PageOrder: Ascend|Descend|Special|(atend)
106 * %%Title: <textline>
107 * %%DocumentMedia: <text> <real> <real> <real> <text> <text>
108 * %%DocumentPageSizes: <text>
109 * %%EndComments
110 *
111 * Note: Either the 3.0 or 2.0 syntax for %%Pages is accepted.
112 * Also either the 2.0 %%DocumentPageSizes or the 3.0
113 * %%DocumentMedia comments are accepted as well.
114 *
115 * The header section ends either explicitly with %%EndComments or
116 * implicitly with any line that does not begin with %X where X is
117 * a not whitespace character.
118 *
119 * If the file is encapsulated PostScript the optional Preview section
120 * is next:
121 *
122 * %%BeginPreview
123 * %%EndPreview
124 *
125 * This section explicitly begins and ends with the above comments.
126 *
127 * Next the Defaults section for version 3 page defaults:
128 *
129 * %%BeginDefaults
130 * %%PageBoundingBox: <int> <int> <int> <int>
131 * %%PageOrientation: Portrait|Landscape
132 * %%PageMedia: <text>
133 * %%EndDefaults
134 *
135 * This section explicitly begins and ends with the above comments.
136 *
137 * The prolog section either explicitly starts with %%BeginProlog or
138 * implicitly with any nonblank line.
139 *
140 * %%BeginProlog
141 * %%EndProlog
142 *
143 * The Prolog should end with %%EndProlog, however the proglog implicitly
144 * ends when %%BeginSetup, %%Page, %%Trailer or %%EOF are encountered.
145 *
146 * The Setup section is where the version 2 page defaults are found.
147 * This section either explicitly begins with %%BeginSetup or implicitly
148 * with any nonblank line after the Prolog.
149 *
150 * %%BeginSetup
151 * %%PageBoundingBox: <int> <int> <int> <int>
152 * %%PageOrientation: Portrait|Landscape
153 * %%PaperSize: <text>
154 * %%EndSetup
155 *
156 * The Setup should end with %%EndSetup, however the setup implicitly
157 * ends when %%Page, %%Trailer or %%EOF are encountered.
158 *
159 * Next each page starts explicitly with %%Page and ends implicitly with
160 * %%Page or %%Trailer or %%EOF. The following comments are recognized:
161 *
162 * %%Page: <text> <uint>
163 * %%PageBoundingBox: <int> <int> <int> <int>|(atend)
164 * %%PageOrientation: Portrait|Landscape
165 * %%PageMedia: <text>
166 * %%PaperSize: <text>
167 *
168 * The tralier section start explicitly with %%Trailer and end with %%EOF.
169 * The following comment are examined with the proper (atend) notation
170 * was used in the header:
171 *
172 * %%Trailer
173 * %%BoundingBox: <int> <int> <int> <int>|(atend)
174 * %%Orientation: Portrait|Landscape|(atend)
175 * %%Pages: <uint> [<int>]|(atend)
176 * %%PageOrder: Ascend|Descend|Special|(atend)
177 * %%EOF
178 *
179 *
180 * + A DC-3 received severe damage to one of its wings. The wing was a total
181 * loss. There was no replacement readily available, so the mechanic
182 * installed a wing from a DC-2.
183 */
184
185 struct document *
186 psscan(file)
187 FILE *file;
188 {
189 struct document *doc;
190 int bb_set = NONE;
191 int pages_set = NONE;
192 int page_order_set = NONE;
193 int orientation_set = NONE;
194 int page_bb_set = NONE;
195 int page_media_set = NONE;
196 int preread; /* flag which tells the readline isn't needed */
197 int i;
198 unsigned int maxpages = 0;
199 unsigned int nextpage = 1; /* Next expected page */
200 unsigned int thispage;
201 int ignore = 0; /* whether to ignore page ordinals */
202 char *label;
203 char line[PSLINELENGTH]; /* 255 characters + 1 newline + 1 NULL */
204 char text[PSLINELENGTH]; /* Temporary storage for text */
205 long position; /* Position of the current line */
206 unsigned int line_len; /* Length of the current line */
207 unsigned int section_len; /* Place to accumulate the section length */
208 char *next_char; /* 1st char after text returned by gettext() */
209 char *cp;
210 struct documentmedia *dmp;
211
212 rewind(file);
213 if (readline(line, sizeof line, file, &position, &line_len) == NULL) {
214 fprintf(stderr, "Warning: empty file.\n");
215 return(NULL);
216 }
217
218 /* Header comments */
219
220 if (iscomment(line,"%!PS-Adobe-")) {
221 doc = (struct document *) malloc(sizeof(struct document));
222 if (doc == NULL) {
223 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
224 exit(-1);
225 }
226 memset(doc, 0, sizeof(struct document));
227 sscanf(line, "%*s %s", text);
228 doc->epsf = iscomment(text, "EPSF-");
229 doc->beginheader = position;
230 section_len = line_len;
231 } else {
232 return(NULL);
233 }
234
235 preread = 0;
236 while (preread || readline(line, sizeof line, file, &position, &line_len)) {
237 if (!preread) section_len += line_len;
238 preread = 0;
239 if (iscomment(line, "%%EndComments") ||
240 line[0] != '%' ||
241 (!isprint(line[1]) || line[1] == ' ' ||
242 line[1] == '\t' || line[1] == '\n')) {
243 break;
244 } else if (!iscomment(line, "%%")) {
245 /* Do nothing */
246 } else if (doc->title == NULL && iscomment(line+2, "Title:")) {
247 doc->title = gettextline(line+length("%%Title:"));
248 } else if (doc->date == NULL && iscomment(line+2, "CreationDate:")) {
249 doc->date = gettextline(line+length("%%CreationDate:"));
250 } else if (bb_set == NONE && iscomment(line+2, "BoundingBox:")) {
251 sscanf(line+length("%%BoundingBox:"), "%s", text);
252 if (strcmp(text, "(atend)") == 0) {
253 bb_set = ATEND;
254 } else {
255 if (sscanf(line+length("%%BoundingBox:"), "%d %d %d %d",
256 &(doc->boundingbox[LLX]),
257 &(doc->boundingbox[LLY]),
258 &(doc->boundingbox[URX]),
259 &(doc->boundingbox[URY])) == 4)
260 bb_set = 1;
261 else {
262 float fllx, flly, furx, fury;
263 if (sscanf(line+length("%%BoundingBox:"), "%f %f %f %f",
264 &fllx, &flly, &furx, &fury) == 4) {
265 bb_set = 1;
266 doc->boundingbox[LLX] = fllx;
267 doc->boundingbox[LLY] = flly;
268 doc->boundingbox[URX] = furx;
269 doc->boundingbox[URY] = fury;
270 if (fllx < doc->boundingbox[LLX])
271 doc->boundingbox[LLX]--;
272 if (flly < doc->boundingbox[LLY])
273 doc->boundingbox[LLY]--;
274 if (furx > doc->boundingbox[URX])
275 doc->boundingbox[URX]++;
276 if (fury > doc->boundingbox[URY])
277 doc->boundingbox[URY]++;
278 }
279 }
280 }
281 } else if (orientation_set == NONE &&
282 iscomment(line+2, "Orientation:")) {
283 sscanf(line+length("%%Orientation:"), "%s", text);
284 if (strcmp(text, "(atend)") == 0) {
285 orientation_set = ATEND;
286 } else if (strcmp(text, "Portrait") == 0) {
287 doc->orientation = PORTRAIT;
288 orientation_set = 1;
289 } else if (strcmp(text, "Landscape") == 0) {
290 doc->orientation = LANDSCAPE;
291 orientation_set = 1;
292 }
293 } else if (page_order_set == NONE && iscomment(line+2, "PageOrder:")) {
294 sscanf(line+length("%%PageOrder:"), "%s", text);
295 if (strcmp(text, "(atend)") == 0) {
296 page_order_set = ATEND;
297 } else if (strcmp(text, "Ascend") == 0) {
298 doc->pageorder = ASCEND;
299 page_order_set = 1;
300 } else if (strcmp(text, "Descend") == 0) {
301 doc->pageorder = DESCEND;
302 page_order_set = 1;
303 } else if (strcmp(text, "Special") == 0) {
304 doc->pageorder = SPECIAL;
305 page_order_set = 1;
306 }
307 } else if (pages_set == NONE && iscomment(line+2, "Pages:")) {
308 sscanf(line+length("%%Pages:"), "%s", text);
309 if (strcmp(text, "(atend)") == 0) {
310 pages_set = ATEND;
311 } else {
312 switch (sscanf(line+length("%%Pages:"), "%d %d",
313 &maxpages, &i)) {
314 case 2:
315 if (page_order_set == NONE) {
316 if (i == -1) {
317 doc->pageorder = DESCEND;
318 page_order_set = 1;
319 } else if (i == 0) {
320 doc->pageorder = SPECIAL;
321 page_order_set = 1;
322 } else if (i == 1) {
323 doc->pageorder = ASCEND;
324 page_order_set = 1;
325 }
326 }
327 case 1:
328 doc->pages = (struct page *) calloc(maxpages,
329 sizeof(struct page));
330 if (doc->pages == NULL) {
331 fprintf(stderr,
332 "Fatal Error: Dynamic memory exhausted.\n");
333 exit(-1);
334 }
335 }
336 }
337 } else if (doc->nummedia == NONE &&
338 iscomment(line+2, "DocumentMedia:")) {
339 float w, h;
340 doc->media = (struct documentmedia *)
341 malloc(sizeof (struct documentmedia));
342 if (doc->media == NULL) {
343 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
344 exit(-1);
345 }
346 doc->media[0].name = gettext(line+length("%%DocumentMedia:"),
347 &next_char);
348 if (doc->media[0].name != NULL) {
349 if (sscanf(next_char, "%f %f", &w, &h) == 2) {
350 doc->media[0].width = w + 0.5;
351 doc->media[0].height = h + 0.5;
352 }
353 if (doc->media[0].width != 0 && doc->media[0].height != 0)
354 doc->nummedia = 1;
355 else
356 free(doc->media[0].name);
357 }
358 preread=1;
359 while (readline(line, sizeof line, file, &position, &line_len) &&
360 iscomment(line, "%%+")) {
361 section_len += line_len;
362 doc->media = (struct documentmedia *)
363 realloc(doc->media,
364 (doc->nummedia+1)*
365 sizeof (struct documentmedia));
366 if (doc->media == NULL) {
367 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
368 exit(-1);
369 }
370 doc->media[doc->nummedia].name = gettext(line+length("%%+"),
371 &next_char);
372 if (doc->media[doc->nummedia].name != NULL) {
373 if (sscanf(next_char, "%f %f", &w, &h) == 2) {
374 doc->media[doc->nummedia].width = w + 0.5;
375 doc->media[doc->nummedia].height = h + 0.5;
376 }
377 if (doc->media[doc->nummedia].width != 0 &&
378 doc->media[doc->nummedia].height != 0) doc->nummedia++;
379 else
380 free(doc->media[doc->nummedia].name);
381 }
382 }
383 section_len += line_len;
384 if (doc->nummedia != 0) doc->default_page_media = doc->media;
385 } else if (doc->nummedia == NONE &&
386 iscomment(line+2, "DocumentPaperSizes:")) {
387
388 doc->media = (struct documentmedia *)
389 malloc(sizeof (struct documentmedia));
390 if (doc->media == NULL) {
391 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
392 exit(-1);
393 }
394 doc->media[0].name = gettext(line+length("%%DocumentPaperSizes:"),
395 &next_char);
396 if (doc->media[0].name != NULL) {
397 doc->media[0].width = 0;
398 doc->media[0].height = 0;
399 for (dmp=papersizes; dmp->name != NULL; dmp++) {
400 /* Note: Paper size comment uses down cased paper size
401 * name. Case insensitive compares are only used for
402 * PaperSize comments.
403 */
404 if (strcasecmp(doc->media[0].name, dmp->name) == 0) {
405 free(doc->media[0].name);
406 doc->media[0].name =
407 (char *)malloc(strlen(dmp->name)+1);
408 if (doc->media[0].name == NULL) {
409 fprintf(stderr,
410 "Fatal Error: Dynamic memory exhausted.\n");
411 exit(-1);
412 }
413 strcpy(doc->media[0].name, dmp->name);
414 doc->media[0].width = dmp->width;
415 doc->media[0].height = dmp->height;
416 break;
417 }
418 }
419 if (doc->media[0].width != 0 && doc->media[0].height != 0)
420 doc->nummedia = 1;
421 else
422 free(doc->media[0].name);
423 }
424 while (cp = gettext(next_char, &next_char)) {
425 doc->media = (struct documentmedia *)
426 realloc(doc->media,
427 (doc->nummedia+1)*
428 sizeof (struct documentmedia));
429 if (doc->media == NULL) {
430 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
431 exit(-1);
432 }
433 doc->media[doc->nummedia].name = cp;
434 doc->media[doc->nummedia].width = 0;
435 doc->media[doc->nummedia].height = 0;
436 for (dmp=papersizes; dmp->name != NULL; dmp++) {
437 /* Note: Paper size comment uses down cased paper size
438 * name. Case insensitive compares are only used for
439 * PaperSize comments.
440 */
441 if (strcasecmp(doc->media[doc->nummedia].name,
442 dmp->name) == 0) {
443 free(doc->media[doc->nummedia].name);
444 doc->media[doc->nummedia].name =
445 (char *)malloc(strlen(dmp->name)+1);
446 if (doc->media[doc->nummedia].name == NULL) {
447 fprintf(stderr,
448 "Fatal Error: Dynamic memory exhausted.\n");
449 exit(-1);
450 }
451 strcpy(doc->media[doc->nummedia].name, dmp->name);
452 doc->media[doc->nummedia].name = dmp->name;
453 doc->media[doc->nummedia].width = dmp->width;
454 doc->media[doc->nummedia].height = dmp->height;
455 break;
456 }
457 }
458 if (doc->media[doc->nummedia].width != 0 &&
459 doc->media[doc->nummedia].height != 0) doc->nummedia++;
460 else
461 free(doc->media[doc->nummedia].name);
462 }
463 preread=1;
464 while (readline(line, sizeof line, file, &position, &line_len) &&
465 iscomment(line, "%%+")) {
466 section_len += line_len;
467 next_char = line + length("%%+");
468 while (cp = gettext(next_char, &next_char)) {
469 doc->media = (struct documentmedia *)
470 realloc(doc->media,
471 (doc->nummedia+1)*
472 sizeof (struct documentmedia));
473 if (doc->media == NULL) {
474 fprintf(stderr,
475 "Fatal Error: Dynamic memory exhausted.\n");
476 exit(-1);
477 }
478 doc->media[doc->nummedia].name = cp;
479 doc->media[doc->nummedia].width = 0;
480 doc->media[doc->nummedia].height = 0;
481 for (dmp=papersizes; dmp->name != NULL; dmp++) {
482 /* Note: Paper size comment uses down cased paper size
483 * name. Case insensitive compares are only used for
484 * PaperSize comments.
485 */
486 if (strcasecmp(doc->media[doc->nummedia].name,
487 dmp->name) == 0) {
488 doc->media[doc->nummedia].width = dmp->width;
489 doc->media[doc->nummedia].height = dmp->height;
490 break;
491 }
492 }
493 if (doc->media[doc->nummedia].width != 0 &&
494 doc->media[doc->nummedia].height != 0) doc->nummedia++;
495 else
496 free(doc->media[doc->nummedia].name);
497 }
498 }
499 section_len += line_len;
500 if (doc->nummedia != 0) doc->default_page_media = doc->media;
501 }
502 }
503
504 if (iscomment(line, "%%EndComments")) {
505 readline(line, sizeof line, file, &position, &line_len);
506 section_len += line_len;
507 }
508 doc->endheader = position;
509 doc->lenheader = section_len - line_len;
510
511 /* Optional Preview comments for encapsulated PostScript files */
512
513 while (blank(line) &&
514 readline(line, sizeof line, file, &position, &line_len)) {
515 }
516
517 if (doc->epsf && iscomment(line, "%%BeginPreview")) {
518 doc->beginpreview = position;
519 section_len = line_len;
520 while (readline(line, sizeof line, file, &position, &line_len) &&
521 !iscomment(line, "%%EndPreview")) {
522 section_len += line_len;
523 }
524 section_len += line_len;
525 readline(line, sizeof line, file, &position, &line_len);
526 section_len += line_len;
527 doc->endpreview = position;
528 doc->lenpreview = section_len - line_len;
529 }
530
531 /* Page Defaults for Version 3.0 files */
532
533 while (blank(line) &&
534 readline(line, sizeof line, file, &position, &line_len)) {
535 }
536
537 if (iscomment(line, "%%BeginDefaults")) {
538 doc->begindefaults = position;
539 section_len = line_len;
540 while (readline(line, sizeof line, file, &position, &line_len) &&
541 !iscomment(line, "%%EndDefaults")) {
542 section_len += line_len;
543 if (!iscomment(line, "%%")) {
544 /* Do nothing */
545 } else if (doc->default_page_orientation == NONE &&
546 iscomment(line+2, "PageOrientation:")) {
547 sscanf(line+length("%%PageOrientation:"), "%s", text);
548 if (strcmp(text, "Portrait") == 0) {
549 doc->default_page_orientation = PORTRAIT;
550 } else if (strcmp(text, "Landscape") == 0) {
551 doc->default_page_orientation = LANDSCAPE;
552 }
553 } else if (page_media_set == NONE &&
554 iscomment(line+2, "PageMedia:")) {
555 cp = gettext(line+length("%%PageMedia:"), NULL);
556 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
557 if (strcmp(cp, dmp->name) == 0) {
558 doc->default_page_media = dmp;
559 page_media_set = 1;
560 break;
561 }
562 }
563 free(cp);
564 } else if (page_bb_set == NONE &&
565 iscomment(line+2, "PageBoundingBox:")) {
566 if (sscanf(line+length("%%PageBoundingBox:"), "%d %d %d %d",
567 &(doc->default_page_boundingbox[LLX]),
568 &(doc->default_page_boundingbox[LLY]),
569 &(doc->default_page_boundingbox[URX]),
570 &(doc->default_page_boundingbox[URY])) == 4)
571 page_bb_set = 1;
572 else {
573 float fllx, flly, furx, fury;
574 if (sscanf(line+length("%%PageBoundingBox:"), "%f %f %f %f",
575 &fllx, &flly, &furx, &fury) == 4) {
576 page_bb_set = 1;
577 doc->default_page_boundingbox[LLX] = fllx;
578 doc->default_page_boundingbox[LLY] = flly;
579 doc->default_page_boundingbox[URX] = furx;
580 doc->default_page_boundingbox[URY] = fury;
581 if (fllx < doc->default_page_boundingbox[LLX])
582 doc->default_page_boundingbox[LLX]--;
583 if (flly < doc->default_page_boundingbox[LLY])
584 doc->default_page_boundingbox[LLY]--;
585 if (furx > doc->default_page_boundingbox[URX])
586 doc->default_page_boundingbox[URX]++;
587 if (fury > doc->default_page_boundingbox[URY])
588 doc->default_page_boundingbox[URY]++;
589 }
590 }
591 }
592 }
593 section_len += line_len;
594 readline(line, sizeof line, file, &position, &line_len);
595 section_len += line_len;
596 doc->enddefaults = position;
597 doc->lendefaults = section_len - line_len;
598 }
599
600 /* Document Prolog */
601
602 while (blank(line) &&
603 readline(line, sizeof line, file, &position, &line_len)) {
604 }
605
606 if (!iscomment(line, "%%BeginSetup") && !iscomment(line, "%%Page:") &&
607 !iscomment(line, "%%Trailer") && !iscomment(line, "%%EOF")) {
608 doc->beginprolog = position;
609 section_len = line_len;
610 preread = 1;
611
612 while ((preread ||
613 readline(line, sizeof line, file, &position, &line_len)) &&
614 !iscomment(line, "%%EndProlog") &&
615 !iscomment(line, "%%BeginSetup") &&
616 !iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") &&
617 !iscomment(line, "%%EOF")) {
618 if (!preread) section_len += line_len;
619 preread = 0;
620 }
621 section_len += line_len;
622 if (iscomment(line, "%%EndProlog")) {
623 readline(line, sizeof line, file, &position, &line_len);
624 section_len += line_len;
625 }
626 doc->endprolog = position;
627 doc->lenprolog = section_len - line_len;
628 }
629
630 /* Document Setup, Page Defaults found here for Version 2 files */
631
632 while (blank(line) &&
633 readline(line, sizeof line, file, &position, &line_len)) {
634 }
635
636 if (!iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") &&
637 !iscomment(line, "%%EOF")) {
638 doc->beginsetup = position;
639 section_len = line_len;
640 preread = 1;
641 while ((preread ||
642 readline(line, sizeof line, file, &position, &line_len)) &&
643 !iscomment(line, "%%EndSetup") && !iscomment(line, "%%Page:") &&
644 !iscomment(line, "%%Trailer") && !iscomment(line, "%%EOF")) {
645 if (!preread) section_len += line_len;
646 preread = 0;
647 if (!iscomment(line, "%%")) {
648 /* Do nothing */
649 } else if (doc->default_page_orientation == NONE &&
650 iscomment(line+2, "PageOrientation:")) {
651 sscanf(line+length("%%PageOrientation:"), "%s", text);
652 if (strcmp(text, "Portrait") == 0) {
653 doc->default_page_orientation = PORTRAIT;
654 } else if (strcmp(text, "Landscape") == 0) {
655 doc->default_page_orientation = LANDSCAPE;
656 }
657 } else if (page_media_set == NONE &&
658 iscomment(line+2, "PaperSize:")) {
659 cp = gettext(line+length("%%PaperSize:"), NULL);
660 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
661 /* Note: Paper size comment uses down cased paper size
662 * name. Case insensitive compares are only used for
663 * PaperSize comments.
664 */
665 if (strcasecmp(cp, dmp->name) == 0) {
666 doc->default_page_media = dmp;
667 page_media_set = 1;
668 break;
669 }
670 }
671 free(cp);
672 } else if (page_bb_set == NONE &&
673 iscomment(line+2, "PageBoundingBox:")) {
674 if (sscanf(line+length("%%PageBoundingBox:"), "%d %d %d %d",
675 &(doc->default_page_boundingbox[LLX]),
676 &(doc->default_page_boundingbox[LLY]),
677 &(doc->default_page_boundingbox[URX]),
678 &(doc->default_page_boundingbox[URY])) == 4)
679 page_bb_set = 1;
680 else {
681 float fllx, flly, furx, fury;
682 if (sscanf(line+length("%%PageBoundingBox:"), "%f %f %f %f",
683 &fllx, &flly, &furx, &fury) == 4) {
684 page_bb_set = 1;
685 doc->default_page_boundingbox[LLX] = fllx;
686 doc->default_page_boundingbox[LLY] = flly;
687 doc->default_page_boundingbox[URX] = furx;
688 doc->default_page_boundingbox[URY] = fury;
689 if (fllx < doc->default_page_boundingbox[LLX])
690 doc->default_page_boundingbox[LLX]--;
691 if (flly < doc->default_page_boundingbox[LLY])
692 doc->default_page_boundingbox[LLY]--;
693 if (furx > doc->default_page_boundingbox[URX])
694 doc->default_page_boundingbox[URX]++;
695 if (fury > doc->default_page_boundingbox[URY])
696 doc->default_page_boundingbox[URY]++;
697 }
698 }
699 }
700 }
701 section_len += line_len;
702 if (iscomment(line, "%%EndSetup")) {
703 readline(line, sizeof line, file, &position, &line_len);
704 section_len += line_len;
705 }
706 doc->endsetup = position;
707 doc->lensetup = section_len - line_len;
708 }
709
710 /* Individual Pages */
711
712 while (blank(line) &&
713 readline(line, sizeof line, file, &position, &line_len)) {
714 }
715
716 newpage:
717 while (iscomment(line, "%%Page:")) {
718 if (maxpages == 0) {
719 maxpages = 1;
720 doc->pages = (struct page *) calloc(maxpages, sizeof(struct page));
721 if (doc->pages == NULL) {
722 fprintf(stderr,
723 "Fatal Error: Dynamic memory exhausted.\n");
724 exit(-1);
725 }
726 }
727 label = gettext(line+length("%%Page:"), &next_char);
728 if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0;
729 if (nextpage == 1) {
730 ignore = thispage != 1;
731 }
732 if (!ignore && thispage != nextpage) {
733 free(label);
734 doc->numpages--;
735 goto continuepage;
736 }
737 nextpage++;
738 if (doc->numpages == maxpages) {
739 maxpages++;
740 doc->pages = (struct page *)
741 realloc(doc->pages, maxpages*sizeof (struct page));
742 if (doc->pages == NULL) {
743 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
744 exit(-1);
745 }
746 }
747 memset(&(doc->pages[doc->numpages]), 0, sizeof(struct page));
748 page_bb_set = NONE;
749 doc->pages[doc->numpages].label = label;
750 doc->pages[doc->numpages].begin = position;
751 section_len = line_len;
752 continuepage:
753 while (readline(line, sizeof line, file, &position, &line_len) &&
754 !iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") &&
755 !iscomment(line, "%%EOF")) {
756 section_len += line_len;
757 if (!iscomment(line, "%%")) {
758 /* Do nothing */
759 } else if (doc->pages[doc->numpages].orientation == NONE &&
760 iscomment(line+2, "PageOrientation:")) {
761 sscanf(line+length("%%PageOrientation:"), "%s", text);
762 if (strcmp(text, "Portrait") == 0) {
763 doc->pages[doc->numpages].orientation = PORTRAIT;
764 } else if (strcmp(text, "Landscape") == 0) {
765 doc->pages[doc->numpages].orientation = LANDSCAPE;
766 }
767 } else if (doc->pages[doc->numpages].media == NULL &&
768 iscomment(line+2, "PageMedia:")) {
769 cp = gettext(line+length("%%PageMedia:"), NULL);
770 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
771 if (strcmp(cp, dmp->name) == 0) {
772 doc->pages[doc->numpages].media = dmp;
773 break;
774 }
775 }
776 free(cp);
777 } else if (doc->pages[doc->numpages].media == NULL &&
778 iscomment(line+2, "PaperSize:")) {
779 cp = gettext(line+length("%%PaperSize:"), NULL);
780 for (dmp = doc->media, i=0; i<doc->nummedia; i++, dmp++) {
781 /* Note: Paper size comment uses down cased paper size
782 * name. Case insensitive compares are only used for
783 * PaperSize comments.
784 */
785 if (strcasecmp(cp, dmp->name) == 0) {
786 doc->pages[doc->numpages].media = dmp;
787 break;
788 }
789 }
790 free(cp);
791 } else if ((page_bb_set == NONE || page_bb_set == ATEND) &&
792 iscomment(line+2, "PageBoundingBox:")) {
793 sscanf(line+length("%%PageBoundingBox:"), "%s", text);
794 if (strcmp(text, "(atend)") == 0) {
795 page_bb_set = ATEND;
796 } else {
797 if (sscanf(line+length("%%PageBoundingBox:"), "%d %d %d %d",
798 &(doc->pages[doc->numpages].boundingbox[LLX]),
799 &(doc->pages[doc->numpages].boundingbox[LLY]),
800 &(doc->pages[doc->numpages].boundingbox[URX]),
801 &(doc->pages[doc->numpages].boundingbox[URY])) == 4)
802 if (page_bb_set == NONE) page_bb_set = 1;
803 else {
804 float fllx, flly, furx, fury;
805 if (sscanf(line+length("%%PageBoundingBox:"),
806 "%f %f %f %f",
807 &fllx, &flly, &furx, &fury) == 4) {
808 if (page_bb_set == NONE) page_bb_set = 1;
809 doc->pages[doc->numpages].boundingbox[LLX] = fllx;
810 doc->pages[doc->numpages].boundingbox[LLY] = flly;
811 doc->pages[doc->numpages].boundingbox[URX] = furx;
812 doc->pages[doc->numpages].boundingbox[URY] = fury;
813 if (fllx <
814 doc->pages[doc->numpages].boundingbox[LLX])
815 doc->pages[doc->numpages].boundingbox[LLX]--;
816 if (flly <
817 doc->pages[doc->numpages].boundingbox[LLY])
818 doc->pages[doc->numpages].boundingbox[LLY]--;
819 if (furx >
820 doc->pages[doc->numpages].boundingbox[URX])
821 doc->pages[doc->numpages].boundingbox[URX]++;
822 if (fury >
823 doc->pages[doc->numpages].boundingbox[URY])
824 doc->pages[doc->numpages].boundingbox[URY]++;
825 }
826 }
827 }
828 }
829 }
830 section_len += line_len;
831 doc->pages[doc->numpages].end = position;
832 doc->pages[doc->numpages].len = section_len - line_len;
833 doc->numpages++;
834 }
835
836 /* Document Trailer */
837
838 doc->begintrailer = position;
839 section_len = line_len;
840
841 preread = 1;
842 while ((preread ||
843 readline(line, sizeof line, file, &position, &line_len)) &&
844 !iscomment(line, "%%EOF")) {
845 if (!preread) section_len += line_len;
846 preread = 0;
847 if (!iscomment(line, "%%")) {
848 /* Do nothing */
849 } else if (iscomment(line+2, "Page:")) {
850 free(gettext(line+length("%%Page:"), &next_char));
851 if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0;
852 if (!ignore && thispage == nextpage) {
853 if (doc->numpages > 0) {
854 doc->pages[doc->numpages-1].end = position;
855 doc->pages[doc->numpages-1].len += section_len - line_len;
856 }
857 goto newpage;
858 }
859 } else if (bb_set == ATEND && iscomment(line+2, "BoundingBox:")) {
860 if (sscanf(line+length("%%BoundingBox:"), "%d %d %d %d",
861 &(doc->boundingbox[LLX]),
862 &(doc->boundingbox[LLY]),
863 &(doc->boundingbox[URX]),
864 &(doc->boundingbox[URY])) != 4) {
865 float fllx, flly, furx, fury;
866 if (sscanf(line+length("%%BoundingBox:"), "%f %f %f %f",
867 &fllx, &flly, &furx, &fury) == 4) {
868 doc->boundingbox[LLX] = fllx;
869 doc->boundingbox[LLY] = flly;
870 doc->boundingbox[URX] = furx;
871 doc->boundingbox[URY] = fury;
872 if (fllx < doc->boundingbox[LLX])
873 doc->boundingbox[LLX]--;
874 if (flly < doc->boundingbox[LLY])
875 doc->boundingbox[LLY]--;
876 if (furx > doc->boundingbox[URX])
877 doc->boundingbox[URX]++;
878 if (fury > doc->boundingbox[URY])
879 doc->boundingbox[URY]++;
880 }
881 }
882 } else if (orientation_set == ATEND &&
883 iscomment(line+2, "Orientation:")) {
884 sscanf(line+length("%%Orientation:"), "%s", text);
885 if (strcmp(text, "Portrait") == 0) {
886 doc->orientation = PORTRAIT;
887 } else if (strcmp(text, "Landscape") == 0) {
888 doc->orientation = LANDSCAPE;
889 }
890 } else if (page_order_set == ATEND && iscomment(line+2, "PageOrder:")) {
891 sscanf(line+length("%%PageOrder:"), "%s", text);
892 if (strcmp(text, "Ascend") == 0) {
893 doc->pageorder = ASCEND;
894 } else if (strcmp(text, "Descend") == 0) {
895 doc->pageorder = DESCEND;
896 } else if (strcmp(text, "Special") == 0) {
897 doc->pageorder = SPECIAL;
898 }
899 } else if (pages_set == ATEND && iscomment(line+2, "Pages:")) {
900 if (sscanf(line+length("%%Pages:"), "%*u %d", &i) == 1) {
901 if (page_order_set == NONE) {
902 if (i == -1) doc->pageorder = DESCEND;
903 else if (i == 0) doc->pageorder = SPECIAL;
904 else if (i == 1) doc->pageorder = ASCEND;
905 }
906 }
907 }
908 }
909 section_len += line_len;
910 if (iscomment(line, "%%EOF")) {
911 readline(line, sizeof line, file, &position, &line_len);
912 section_len += line_len;
913 }
914 doc->endtrailer = position;
915 doc->lentrailer = section_len - line_len;
916
917 section_len = line_len;
918 preread = 1;
919 while (preread ||
920 readline(line, sizeof line, file, &position, &line_len)) {
921 if (!preread) section_len += line_len;
922 preread = 0;
923 if (iscomment(line, "%%Page:")) {
924 free(gettext(line+length("%%Page:"), &next_char));
925 if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0;
926 if (!ignore && thispage == nextpage) {
927 doc->pages[doc->numpages-1].end = position;
928 doc->pages[doc->numpages-1].len += doc->lentrailer +
929 section_len - line_len;
930 goto newpage;
931 }
932 }
933 }
934 return doc;
935 }
936
937 /*
938 * psfree -- free dynamic storage associated with document structure.
939 */
940
941 void
942 psfree(doc)
943 struct document *doc;
944 {
945 int i;
946
947 if (doc) {
948 for (i=0; i<doc->numpages; i++) {
949 if (doc->pages[i].label) free(doc->pages[i].label);
950 }
951 for (i=0; i<doc->nummedia; i++) {
952 if (doc->media[i].name) free(doc->media[i].name);
953 }
954 if (doc->title) free(doc->title);
955 if (doc->date) free(doc->date);
956 if (doc->pages) free(doc->pages);
957 if (doc->media) free(doc->media);
958 free(doc);
959 }
960 }
961
962 /*
963 * gettextine -- skip over white space and return the rest of the line.
964 * If the text begins with '(' return the text string
965 * using gettext().
966 */
967
968 static char *
969 gettextline(line)
970 char *line;
971 {
972 char *cp;
973
974 while (*line && (*line == ' ' || *line == '\t')) line++;
975 if (*line == '(') {
976 return gettext(line, NULL);
977 } else {
978 if (strlen(line) == 0) return NULL;
979 cp = (char *) malloc(strlen(line));
980 if (cp == NULL) {
981 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
982 exit(-1);
983 }
984 strncpy(cp, line, strlen(line)-1);
985 cp[strlen(line)-1] = '\0';
986 return cp;
987 }
988 }
989
990 /*
991 * gettext -- return the next text string on the line.
992 * return NULL if nothing is present.
993 */
994
995 static char *
996 gettext(line, next_char)
997 char *line;
998 char **next_char;
999 {
1000 char text[PSLINELENGTH]; /* Temporary storage for text */
1001 char *cp;
1002 int quoted=0;
1003
1004 while (*line && (*line == ' ' || *line == '\t')) line++;
1005 cp = text;
1006 if (*line == '(') {
1007 int level = 0;
1008 quoted=1;
1009 line++;
1010 while (*line && !(*line == ')' && level == 0 )) {
1011 if (*line == '\\') {
1012 if (*(line+1) == 'n') {
1013 *cp++ = '\n';
1014 line += 2;
1015 } else if (*(line+1) == 'r') {
1016 *cp++ = '\r';
1017 line += 2;
1018 } else if (*(line+1) == 't') {
1019 *cp++ = '\t';
1020 line += 2;
1021 } else if (*(line+1) == 'b') {
1022 *cp++ = '\b';
1023 line += 2;
1024 } else if (*(line+1) == 'f') {
1025 *cp++ = '\f';
1026 line += 2;
1027 } else if (*(line+1) == '\\') {
1028 *cp++ = '\\';
1029 line += 2;
1030 } else if (*(line+1) == '(') {
1031 *cp++ = '(';
1032 line += 2;
1033 } else if (*(line+1) == ')') {
1034 *cp++ = ')';
1035 line += 2;
1036 } else if (*(line+1) >= '0' && *(line+1) <= '9') {
1037 if (*(line+2) >= '0' && *(line+2) <= '9') {
1038 if (*(line+3) >= '0' && *(line+3) <= '9') {
1039 *cp++ = ((*(line+1) - '0')*8 + *(line+2) - '0')*8 +
1040 *(line+3) - '0';
1041 line += 4;
1042 } else {
1043 *cp++ = (*(line+1) - '0')*8 + *(line+2) - '0';
1044 line += 3;
1045 }
1046 } else {
1047 *cp++ = *(line+1) - '0';
1048 line += 2;
1049 }
1050 } else {
1051 line++;
1052 *cp++ = *line++;
1053 }
1054 } else if (*line == '(') {
1055 level++;
1056 *cp++ = *line++;
1057 } else if (*line == ')') {
1058 level--;
1059 *cp++ = *line++;
1060 } else {
1061 *cp++ = *line++;
1062 }
1063 }
1064 } else {
1065 while (*line && !(*line == ' ' || *line == '\t' || *line == '\n'))
1066 *cp++ = *line++;
1067 }
1068 *cp = '\0';
1069 if (next_char) *next_char = line;
1070 if (!quoted && strlen(text) == 0) return NULL;
1071 cp = (char *) malloc(strlen(text)+1);
1072 if (cp == NULL) {
1073 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
1074 exit(-1);
1075 }
1076 strcpy(cp, text);
1077 return cp;
1078 }
1079
1080 /*
1081 * readline -- Read the next line in the postscript file.
1082 * Automatically skip over data (as indicated by
1083 * %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
1084 * comments.)
1085 * Also, skip over included documents (as indicated by
1086 * %%BeginDocument/%%EndDocument comments.)
1087 */
1088
1089 static char *
1090 readline(line, size, fp, position, line_len)
1091 char *line;
1092 int size;
1093 FILE *fp;
1094 long *position;
1095 unsigned int *line_len;
1096 {
1097 char text[PSLINELENGTH]; /* Temporary storage for text */
1098 char save[PSLINELENGTH]; /* Temporary storage for text */
1099 char *cp;
1100 unsigned int num;
1101 unsigned int nbytes;
1102 int i;
1103 char buf[BUFSIZ];
1104
1105 if (position) *position = ftell(fp);
1106 cp = fgets(line, size, fp);
1107 if (cp == NULL) line[0] = '\0';
1108 *line_len = strlen(line);
1109 if (iscomment(line, "%%BeginDocument:")) {
1110 strcpy(save, line+7);
1111 while (readline(line, size, fp, NULL, &nbytes) &&
1112 !iscomment(line, "%%EndDocument")) {
1113 *line_len += nbytes;
1114 }
1115 *line_len += nbytes;
1116 strcpy(line, save);
1117 } else if (iscomment(line, "%%BeginFeature:")) {
1118 strcpy(save, line+7);
1119 while (readline(line, size, fp, NULL, &nbytes) &&
1120 !iscomment(line, "%%EndFeature")) {
1121 *line_len += nbytes;
1122 }
1123 *line_len += nbytes;
1124 strcpy(line, save);
1125 } else if (iscomment(line, "%%BeginFile:")) {
1126 strcpy(save, line+7);
1127 while (readline(line, size, fp, NULL, &nbytes) &&
1128 !iscomment(line, "%%EndFile")) {
1129 *line_len += nbytes;
1130 }
1131 *line_len += nbytes;
1132 strcpy(line, save);
1133 } else if (iscomment(line, "%%BeginFont:")) {
1134 strcpy(save, line+7);
1135 while (readline(line, size, fp, NULL, &nbytes) &&
1136 !iscomment(line, "%%EndFont")) {
1137 *line_len += nbytes;
1138 }
1139 *line_len += nbytes;
1140 strcpy(line, save);
1141 } else if (iscomment(line, "%%BeginProcSet:")) {
1142 strcpy(save, line+7);
1143 while (readline(line, size, fp, NULL, &nbytes) &&
1144 !iscomment(line, "%%EndProcSet")) {
1145 *line_len += nbytes;
1146 }
1147 *line_len += nbytes;
1148 strcpy(line, save);
1149 } else if (iscomment(line, "%%BeginResource:")) {
1150 strcpy(save, line+7);
1151 while (readline(line, size, fp, NULL, &nbytes) &&
1152 !iscomment(line, "%%EndResource")) {
1153 *line_len += nbytes;
1154 }
1155 *line_len += nbytes;
1156 strcpy(line, save);
1157 } else if (iscomment(line, "%%BeginData:")) {
1158 text[0] = '\0';
1159 strcpy(save, line+7);
1160 if (sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text) >= 1) {
1161 if (strcmp(text, "Lines") == 0) {
1162 for (i=0; i < num; i++) {
1163 cp = fgets(line, size, fp);
1164 *line_len += cp ? strlen(line) : 0;
1165 }
1166 } else {
1167 while (num > BUFSIZ) {
1168 fread(buf, sizeof (char), BUFSIZ, fp);
1169 *line_len += BUFSIZ;
1170 num -= BUFSIZ;
1171 }
1172 fread(buf, sizeof (char), num, fp);
1173 *line_len += num;
1174 }
1175 }
1176 while (readline(line, size, fp, NULL, &nbytes) &&
1177 !iscomment(line, "%%EndData")) {
1178 *line_len += nbytes;
1179 }
1180 *line_len += nbytes;
1181 strcpy(line, save);
1182 } else if (iscomment(line, "%%BeginBinary:")) {
1183 strcpy(save, line+7);
1184 if(sscanf(line+length("%%BeginBinary:"), "%d", &num) == 1) {
1185 while (num > BUFSIZ) {
1186 fread(buf, sizeof (char), BUFSIZ, fp);
1187 *line_len += BUFSIZ;
1188 num -= BUFSIZ;
1189 }
1190 fread(buf, sizeof (char), num, fp);
1191 *line_len += num;
1192 }
1193 while (readline(line, size, fp, NULL, &nbytes) &&
1194 !iscomment(line, "%%EndBinary")) {
1195 *line_len += nbytes;
1196 }
1197 *line_len += nbytes;
1198 strcpy(line, save);
1199 }
1200 return cp;
1201 }
1202
1203 /*
1204 * pscopy -- copy lines of Postscript from a section of one file
1205 * to another file.
1206 * Automatically switch to binary copying whenever
1207 * %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
1208 * comments are encountered.
1209 */
1210
1211 void
1212 pscopy(from, to, begin, end)
1213 FILE *from;
1214 FILE *to;
1215 long begin; /* set negative to avoid initial seek */
1216 long end;
1217 {
1218 char line[PSLINELENGTH]; /* 255 characters + 1 newline + 1 NULL */
1219 char text[PSLINELENGTH]; /* Temporary storage for text */
1220 unsigned int num;
1221 int i;
1222 char buf[BUFSIZ];
1223
1224 if (begin >= 0) fseek(from, begin, SEEK_SET);
1225 while (ftell(from) < end) {
1226
1227 fgets(line, sizeof line, from);
1228 fputs(line, to);
1229
1230 if (iscomment(line, "%%BeginData:")) {
1231 text[0] = '\0';
1232 if (sscanf(line+length("%%BeginData:"),
1233 "%d %*s %s", &num, text) >= 1) {
1234 if (strcmp(text, "Lines") == 0) {
1235 for (i=0; i < num; i++) {
1236 fgets(line, sizeof line, from);
1237 fputs(line, to);
1238 }
1239 } else {
1240 while (num > BUFSIZ) {
1241 fread(buf, sizeof (char), BUFSIZ, from);
1242 fwrite(buf, sizeof (char), BUFSIZ, to);
1243 num -= BUFSIZ;
1244 }
1245 fread(buf, sizeof (char), num, from);
1246 fwrite(buf, sizeof (char), num, to);
1247 }
1248 }
1249 } else if (iscomment(line, "%%BeginBinary:")) {
1250 if(sscanf(line+length("%%BeginBinary:"), "%d", &num) == 1) {
1251 while (num > BUFSIZ) {
1252 fread(buf, sizeof (char), BUFSIZ, from);
1253 fwrite(buf, sizeof (char), BUFSIZ, to);
1254 num -= BUFSIZ;
1255 }
1256 fread(buf, sizeof (char), num, from);
1257 fwrite(buf, sizeof (char), num, to);
1258 }
1259 }
1260 }
1261 }
1262
1263 /*
1264 * pscopyuntil -- copy lines of Postscript from a section of one file
1265 * to another file until a particular comment is reached.
1266 * Automatically switch to binary copying whenever
1267 * %%BeginBinary/%%EndBinary or %%BeginData/%%EndData
1268 * comments are encountered.
1269 */
1270
1271 char *
1272 pscopyuntil(from, to, begin, end, comment)
1273 FILE *from;
1274 FILE *to;
1275 long begin; /* set negative to avoid initial seek */
1276 long end;
1277 #if NeedFunctionPrototypes
1278 const
1279 #endif
1280 char *comment;
1281 {
1282 char line[PSLINELENGTH]; /* 255 characters + 1 newline + 1 NULL */
1283 char text[PSLINELENGTH]; /* Temporary storage for text */
1284 unsigned int num;
1285 int comment_length;
1286 int i;
1287 char buf[BUFSIZ];
1288 char *cp;
1289
1290 comment_length = strlen(comment);
1291 if (begin >= 0) fseek(from, begin, SEEK_SET);
1292 while (ftell(from) < end) {
1293
1294 fgets(line, sizeof line, from);
1295
1296 /* iscomment cannot be used here,
1297 * because comment_length is not known at compile time. */
1298 if (strncmp(line, comment, comment_length) == 0) {
1299 cp = (char *) malloc(strlen(line)+1);
1300 if (cp == NULL) {
1301 fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n");
1302 exit(-1);
1303 }
1304 strcpy(cp, line);
1305 return cp;
1306 }
1307 fputs(line, to);
1308 if (iscomment(line, "%%BeginData:")) {
1309 text[0] = '\0';
1310 if (sscanf(line+length("%%BeginData:"),
1311 "%d %*s %s", &num, text) >= 1) {
1312 if (strcmp(text, "Lines") == 0) {
1313 for (i=0; i < num; i++) {
1314 fgets(line, sizeof line, from);
1315 fputs(line, to);
1316 }
1317 } else {
1318 while (num > BUFSIZ) {
1319 fread(buf, sizeof (char), BUFSIZ, from);
1320 fwrite(buf, sizeof (char), BUFSIZ, to);
1321 num -= BUFSIZ;
1322 }
1323 fread(buf, sizeof (char), num, from);
1324 fwrite(buf, sizeof (char), num, to);
1325 }
1326 }
1327 } else if (iscomment(line, "%%BeginBinary:")) {
1328 if(sscanf(line+length("%%BeginBinary:"), "%d", &num) == 1) {
1329 while (num > BUFSIZ) {
1330 fread(buf, sizeof (char), BUFSIZ, from);
1331 fwrite(buf, sizeof (char), BUFSIZ, to);
1332 num -= BUFSIZ;
1333 }
1334 fread(buf, sizeof (char), num, from);
1335 fwrite(buf, sizeof (char), num, to);
1336 }
1337 }
1338 }
1339 return NULL;
1340 }
1341
1342 /*
1343 * blank -- determine whether the line contains nothing but whitespace.
1344 */
1345
1346 static int
1347 blank(line)
1348 char *line;
1349 {
1350 char *cp = line;
1351
1352 while (*cp == ' ' || *cp == '\t') cp++;
1353 return *cp == '\n' || (*cp == '%' && (line[0] != '%' || line[1] != '%'));
1354 }