/* * post.c */ /* * mpage: a program to reduce pages of print so that several pages * of output appear on one printed page. * * Copyright (c) 1994-2004 Marcel J.E. Mol, The Netherlands * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia * * Permission is granted to anyone to make or distribute verbatim * copies of this document as received, in any medium, provided * that this copyright notice is preserved, and that the * distributor grants the recipient permission for further * redistribution as permitted by this notice. * */ #include "mpage.h" #include /* * character spaces used throughout for holding the current line from * the input file */ static char currline[LINESIZE]; static char *file_name; /* * for ps documents, used to remember if we have come across the * tailer section. reset at the beginning of processing for each file */ static int ps_at_trailer; /* * this is the type of postscript document we are processing */ static int ps_posttype; /* * set to one if we have a inputline that must be preceded by something... * used for dvips output without PS comments. */ static int have_line = 0; /* * number of output lines on current logical page */ static int plcnt; int have_showsheet = 0; char ps_roff_xi [16]; /* to hold the DITROFF xi line... */ static char * tex1; /* to capture important dvi2ps lines... */ static char * tex2; /* * Function declarations */ static int ps_gettype(); static void do_post_doc(); #if 0 static void do_other_doc(); #endif static void ps_copyprolog(); static void ps_roff_copyprolog(); static void ps_mpage_copyprolog(); static void ps_skip_to_page(); static int do_post_sheet(); static void ps_sheetsetup(); static int post_onepage(); static int post_flush_onepage(); static int post_one_line(); static void do_roff_tailer(); int ps_check(); void do_ps_doc(); static int post_flush_onepage(); static int ps_store_to_page(); /* * Peek at the first two chacters on the open file and check for the * two character postscript flag "%!". If the file is not postscript * then the characters are pushed back into the input stream (hopefully). */ int ps_check(infd) FILE *infd; { int firstchar; int secondchar; Debug(DB_PSCHECK, "%%ps_check: in ps_check\n", 0); /* * eliminate blank files */ if ((firstchar = fgetc(infd)) == EOF) { Debug(DB_PSCHECK, "%%ps_check: file is blank\n", 0); return 0; } /* * Skip any CTRL-D chars * Hope there are no text files starting with ctrl-d's */ while (firstchar == 4) firstchar = fgetc(infd); /* * eliminate non-postscript files */ if (firstchar != '%') { Debug(DB_PSCHECK, "%ps_check: 1st char is '%c' not '%'\n", firstchar); if (ungetc(firstchar, infd) == EOF) { fprintf(stderr, "%s: Lost first character of file ", MPAGE); fprintf(stderr, "while checking for postscript\n."); } return 0; } Debug(DB_PSCHECK, "%%ps_check: 1st char is '%c'\n", firstchar); /* * eliminate one character files (containing only a %) */ if ((secondchar = fgetc(infd)) == EOF) { Debug(DB_PSCHECK, "%%ps_check: no second char\n", 0); if (ungetc(firstchar, infd) == EOF) { fprintf(stderr, "%s: Lost first character of file ", MPAGE); fprintf(stderr, "while checking for postscript\n."); } return 0; } /* * eliminate files that don't have the full two character * sequence of "%!". */ if (secondchar != '!') { Debug(DB_PSCHECK, "%%ps_check: 2nd char is '%c' not '!'\n", secondchar); if (ungetc(secondchar, infd) == EOF) { fprintf(stderr, "%s: Lost first two characters of ", MPAGE); fprintf(stderr, "file while checking for postscript\n."); return 0; } if (ungetc(firstchar, infd) == EOF) { fprintf(stderr, "%s: Lost first character of file ", MPAGE); fprintf(stderr, "while checking for postscript.\n"); } return 0; } /* * for post script files the first two characters (the "%!") are * digested by this routine. It's just easier than dealing * with the problems encounted if the characters can't be ungetc'ed. */ Debug(DB_PSCHECK, "%%ps_check: 2nd char is '%c'\n", secondchar); Debug(DB_PSCHECK, "%%ps_check: input is postscript\n", 0); return 1; } /* ps_check */ static int ps_gettype(fd, outfd) FILE *fd; FILE *outfd; { int ps_type, end_comments; Debug(DB_PSDOC, "%%ps_gettype: in ps_gettype\n", 0); /* * error check for truncated files */ if (fgets(currline, LINESIZE-1, fd) == NULL) { Debug(DB_PSDOC, "%%ps_gettype: got eof on first line\n", 0); return PS_NONE; } /* * check for non-conforming postscript * Note that %! is already gone down the drain... */ if (strncmp(currline, PS_FLAG, strlen(PS_FLAG)) != 0) { Debug(DB_PSDOC, "%%ps_gettype: no match PS_FLAG \"%s\"\n", currline); return PS_OTHER; } /* * we have some form of conforming postscript, try to identify the * type */ Debug(DB_PSDOC, "%%ps_gettype: conforming postscript\n", 0); end_comments = 0; ps_type = PS_CONFORM; while (!end_comments) { /* * if we get end of file then we assume non-conforming PS */ if (fgets(currline, LINESIZE-1, fd) == NULL) { Debug(DB_PSDOC, "%%ps_gettype: eof in comments\n", 0); return PS_OTHER; } /* * if we have run out of leading comments then assume * conforming PS (because we had a valid "%!" line) */ if (currline[0] != '%') { Debug(DB_PSDOC, "%%ps_gettype: out off comments\n", 0); fprintf(outfd, "%s", currline); return PS_CONFORM; } /* * print out the comment line with an extra % to disguise the comment */ fprintf(outfd, "%%%s", currline); /* * check for the end of the leading comments section */ if (strncmp(currline, "%%EndComments", 13) == 0) end_comments = 1; /* * Some tricky way to handle MS-windows postscript files... * probably doesn't work. */ if (strncmp(currline, "%%Pages:", 8) == 0 && ps_type == PS_MSWINDOWS) return ps_type; /* * once we know the type of PS, we no longer need to keep * checking. */ if (ps_type != PS_CONFORM) continue; /* * check for mpage output */ if (!strncmp(currline, "%%Creator: ", 11)) { if (!strncmp(currline+11, MPAGE, strlen(MPAGE))) { Debug(DB_PSDOC, "%%ps_gettype: mpage document\n", 0); ps_type = PS_MPAGE; } else if (!strncmp(currline+11, "Windows PSCRIPT", 15)) { Debug(DB_PSDOC, "%%ps_gettype: windows document\n", 0); ps_type = PS_MSWINDOWS; } else if (!strncmp(currline+11, "dvips", 5)) { Debug(DB_PSDOC, "%%ps_gettype: dvips\n", 0); ps_type = PS_TEX; } } /* * check for psroff/tex output */ if (strncmp(currline, "%%Title: ", 9) == 0) { if (strstr(currline, "ditroff")) { Debug(DB_PSDOC, "%%ps_gettype: psroff\n", 0); ps_type = PS_PSROFF; } else if (strstr(currline, ".dvi")) { Debug(DB_PSDOC, "%%ps_gettype: dvi2ps\n", 0); ps_type = PS_TEX; } } if (strncmp(currline, "%DVIPS", 6) == 0) { Debug(DB_PSDOC, "%%ps_gettype: dvips\n", 0); if (ps_type != PS_TEX) ps_type = PS_TEX2; return ps_type; } } #ifdef DEBUG if (ps_type == PS_CONFORM) { Debug(DB_PSDOC, "%%ps_gettype: unknown type, conforming PS\n", 0); } #endif return ps_type; } /* ps_gettype */ void do_ps_doc(fd, asheet, outfd, fname) FILE *fd; struct sheet *asheet; FILE *outfd; char * fname; { Debug(DB_PSDOC, "%%do_ps_doc: postscript document\n", 0); file_name = fname; ps_posttype = ps_gettype(fd,outfd); Debug(DB_PSDOC, "%%do_ps_doc: document type is %d\n", ps_posttype); if (ps_posttype != PS_NONE) do_post_doc(fd, asheet, outfd); return; } /* do_ps_doc */ static void do_post_doc(fd, asheet, outfd) FILE *fd; struct sheet *asheet; FILE *outfd; { ps_at_trailer = FALSE; Debug(DB_POST, "%%do_post_doc: prolog\n", 0); ps_copyprolog(fd, outfd); /* * while there is still input, print pages */ Debug(DB_POST, "%%do_post_doc: pages\n", 0); do_sheets(do_post_sheet, fd, asheet, outfd); Debug(DB_POST, "%%do_post_doc: trailer\n", 0); do_roff_tailer(fd, outfd); return; } /* do_post_doc */ #if 0 /* not used yet... */ static void do_other_doc(fd, asheet, outfd) FILE *fd; struct sheet *asheet; FILE *outfd; { ps_at_trailer = FALSE; ps_copyprolog(fd, outfd); return; } /* do_other_doc */ #endif static void ps_copyprolog(fd, outfd) FILE *fd; FILE *outfd; { Debug(DB_PSDOC, "%%ps_copyprolog: adding mpage prolog\n", 0); if (!have_showsheet) { #if 1 fprintf(outfd, "/showsheet /showpage load def\n"); #else fprintf(outfd, "/showsheet { showpage } bind def\n"); #endif fprintf(outfd, "/showpage { } def\n"); have_showsheet = 1; } had_ps = 1; Debug(DB_PSDOC, "%%ps_copyprolog: copying prolog\n", 0); if (ps_posttype == PS_PSROFF) { Debug(DB_PSDOC, "%%ps_copyprolog: calling ps_roff_copyprolog\n",0); ps_roff_copyprolog(fd, outfd); return; } if (ps_posttype == PS_MPAGE) { Debug(DB_PSDOC, "%%ps_copyprolog: calling ps_mpage_copyprolog\n",0); ps_mpage_copyprolog(fd, outfd); return; } while (fgets(currline, LINESIZE-1, fd) != NULL) { if (strncmp(currline, "%%Page:", 7) == 0) { fprintf(outfd, "%% %s", currline); return; } if (ps_posttype == PS_TEX || ps_posttype == PS_TEX2) { if (ps_posttype == PS_TEX2 && strstr(currline, " bop ")) { /* dvips output without comments... */ have_line = 1; return; } if (strncmp(currline, "TeXDict", 7) == 0) { /* SHOULD PROBABLY REMOVE THIS. SEE BELOW /dictionarystack */ /* * Hope all dvi2ps progs work the same: * capture the TeX init code so we can run it 'manually' for * every page. This is needed as this code sets up a gstate * that conflicts with mpage... * This trick seems to work for text, but figures within the dvi * file seem to have a mind of their own... */ if (tex1) free(tex1); tex1 = malloc(strlen(currline)+1); strcpy(tex1, currline); fprintf(outfd, "%s", currline); fgets(currline, LINESIZE-1, fd); if (tex2) free(tex2); tex2 = malloc(strlen(currline)+1); strcpy(tex2, currline); } } fprintf(outfd, "%s", currline); } Debug(DB_PSDOC, "%%ps_copyprolog: eof before %%%%EndProlog\n", 0); fprintf(outfd, "%%%%EndProlog\n"); return; } /* ps_copyprolog */ static void ps_roff_copyprolog(fd, outfd) FILE *fd; FILE *outfd; { Debug(DB_PSDOC, "%%ps_roff_copyprolog: copying psroff prolog\n", 0); while(fgets(currline, LINESIZE-1, fd) != NULL) { /* if (strcmp(currline, "xi\n") == 0) */ if (strstr(currline, "xi\n")) { fprintf(outfd, "%%%s", currline); strcpy(ps_roff_xi, currline); } else if (strncmp(currline, "%%Page:", 7) == 0) { fprintf(outfd, "/p { } def\n"); fprintf(outfd, "/xt { } def\n"); fprintf(outfd, "/xs { } def\n"); fprintf(outfd, "%% %s", currline); Debug(DB_PSDOC, "%%ps_copyprolog: Done\n", 0); return; } else fprintf(outfd, "%s", currline); } Debug(DB_PSDOC, "%%ps_copyprolog: eof before %%%%EndProlog\n", 0); fprintf(outfd, "/p { } def\n"); fprintf(outfd, "/xt { } def\n"); fprintf(outfd, "/xs { } def\n"); fprintf(outfd, "%%%%EndProlog\n"); return; } /* ps_roff_copyprolog */ static void ps_mpage_copyprolog(fd, outfd) FILE *fd; FILE *outfd; { Debug(DB_PSDOC, "%%ps_mpage_copyprolog: skipping mpage prolog\n", 0); while(fgets(currline, LINESIZE-1, fd) != NULL) { if (strncmp(currline, "%%Page:", 7) == 0) { fprintf(outfd, "%% %s", currline); Debug(DB_PSDOC, "%%ps_copyprolog: Done\n", 0); return; } } } /* ps_mpage_copyprolog */ static void ps_skip_to_page(fd) FILE *fd; { Debug(DB_PSDOC, "%%ps_skip to page: reading until %%%%Page:\n", 0); while(fgets(currline, LINESIZE-1, fd) != NULL) { Debug(DB_PSDOC, "%% %s", currline); if (strncmp(currline, "%%Page:", 7) == 0) return; } Debug(DB_PSDOC, "%%ps_skip_to_page: eof before %%%%Page:\n", 0); return; } /* ps_skip_to_page */ static char *stored_page = NULL; static int stored_page_size = 0; static int ps_store_to_page(fd) FILE *fd; { int totlen = 0; Debug(DB_PSDOC, "%%ps_store to page: reading until %%%%Page:\n", 0); while(fgets(currline, LINESIZE-1, fd) != NULL) { int len; if (strncmp(currline, "%%Page:", 7) == 0) return totlen; len = strlen(currline); totlen += len; if (totlen > stored_page_size){ stored_page = realloc(stored_page, totlen); stored_page_size = totlen; } /* do not copy the '\0' */ memcpy(stored_page + totlen - len, currline, len); Debug(DB_PSDOC, "%% %s", currline); } Debug(DB_PSDOC, "%%ps_store_to_page: eof before %%%%Page:\n", 0); return totlen; } /* ps_store_to_page */ /* GPN */ /* #define NSCALE to take care of previous scaling */ #ifdef NSCALE char *NScale = "/gpnsavematrix {orgmatrix currentmatrix pop} bind def\n" "/gpnrestorematrix {orgmatrix setmatrix} bind def\n" "/orgmatrix matrix def\n" "gpnsavematrix\n" "orgmatrix orgmatrix invertmatrix pop\n" "/gpnxs\n" " orgmatrix 0 get 0.0000 eq\n" " {orgmatrix 1 get abs}\n" " {orgmatrix 0 get abs}\n" " ifelse def\n" "/gpnys\n" " orgmatrix 3 get 0.0000 eq\n" " {orgmatrix 2 get abs}\n" " {orgmatrix 3 get abs}\n" " ifelse def\n" "/gpnxs gpnxs gscurrentresolution 0 get 72 div mul def\n" "/gpnys gpnys gscurrentresolution 1 get 72 div mul def\n"; #endif /* NSCALE */ static int do_post_sheet(fd, asheet, outfd) FILE *fd; struct sheet *asheet; FILE *outfd; { int rtn_val = FILE_MORE; int sh_high, sh_wide; struct pagepoints *stored_points = NULL, *flush_points = NULL; int flush = 0, totlen = 0; do { if ((points->pp_origin_x == 0 && !points->skip) || opt_file || flush) { /* * keep track of the pages processed */ ps_pagenum++; fprintf(outfd, "%%%%Page: %d %d\n", ps_pagenum, ps_pagenum); # ifdef DEBUG if (Debug_flag & DB_PSMPAGE) fprintf(outfd, "(Page: %d\\n) print flush\n", ps_pagenum); # endif /* DEBUG */ #if 0 /* seems to give memory problems... */ fprintf(outfd, "/sheetsave save def\n"); #endif /* * Now is the time to print a sheet header... * for now, this has to be done before outline... */ sheetheader(outfd, file_name); /* * print the page outline */ mp_outline(outfd, asheet); /* * run through the list of base points for putting reduced pages * on the printed page */ if (!flush) points = asheet->sh_pagepoints; else points++; } while ((points->pp_origin_x!=0 || points->skip) && rtn_val == FILE_MORE) { /* GPN. skip this page ?*/ if (points->skip!=0) { switch (points->skip) { case SKIP_PS: /* * Skip this page. User needs another run with the other * of -O/-E option. */ ps_skip_to_page(fd); points++; continue; case STORE_PS: /* * stored_page could also be an array * if more than one page * is needed */ totlen = ps_store_to_page(fd); stored_points = points; flush = STORE_PS; points++; continue; case FLUSH_PS: if (stored_points) { /* * Ok I have to print the page and start a new one. * This could be more elegant, but for now... */ /* fprintf(outfd, "showsheet\n"); ps_pagenum++; fprintf(outfd, "%%%%Page: %d %d\n", ps_pagenum, ps_pagenum); sheetheader(outfd, file_name); mp_outline(outfd, asheet); */ flush = FLUSH_PS; flush_points = points; points = stored_points; } else flush = 0; } } /* * Save current graphics context so we can scale/translate * from known position and size. */ fprintf(outfd, "gsave\n"); /* * print one reduced page by moving to the proper point, * turning to the proper aspect, scaling to the proper * size, and setting up a clip path to prevent overwritting; * then print a reduced page of output. */ Debug(DB_PSMPAGE, "%%%% %%%%ReducedPageStartsHere\n", outfd); # ifdef DEBUG if (Debug_flag & DB_PSMPAGE) { fprintf(outfd, "( %d %d translate %d rotate\\n)", points->pp_origin_x(), points->pp_origin_y(), asheet->sh_rotate); fprintf(outfd, " print flush\n"); } # endif /* DEBUG */ #ifdef NSCALE /*GPN*/ fprintf (outfd, NScale); fprintf(outfd, "%d gpnxs mul %d gpnxs mul translate %d rotate\n", points->pp_origin_x(), points->pp_origin_y(), asheet->sh_rotate); #else /* NSCALE */ fprintf(outfd, "%d %d translate\n", points->pp_origin_x(), points->pp_origin_y()); if (asheet->sh_rotate) fprintf(outfd, "%d rotate\n", asheet->sh_rotate); #endif sh_wide = (*asheet->sh_width)(); sh_high = (*asheet->sh_height)(); /* output the clip path */ #ifdef NSCALE /*GPN*/ fprintf(outfd, "0 0 moveto 0 %d gpnys mul lineto %d gpnxs mul" " %d gpnys mul lineto ", sh_high, sh_wide, sh_high); fprintf(outfd, "%d gpnxs mul 0 lineto\n", sh_wide); fprintf(outfd, "closepath clip\n"); #else /* NSCALE */ #if 0 fprintf(outfd, "0 0 moveto 0 %d lineto %d %d lineto ", sh_high, sh_wide, sh_high); fprintf(outfd, "%d 0 lineto\n", sh_wide); #else fprintf(outfd, "1 1 moveto 1 %d lineto %d %d lineto ", sh_high - 1, sh_wide - 1, sh_high - 1); fprintf(outfd, "%d 1 lineto\n", sh_wide - 1); #endif fprintf(outfd, "closepath clip newpath\n"); #endif /* NSCALE */ if (opt_square) { int newhigh = sh_high, newwide = sh_wide; if (sh_wide * ps_height > sh_high * ps_width) newwide = (sh_high * ps_width) / ps_height; else newhigh = (sh_wide * ps_height) / ps_width; #ifdef NSCALE /*GPN*/ fprintf(outfd, "%d gpnxs mul %d gpnys mul translate\n", #else fprintf(outfd, "%d %d translate\n", #endif (sh_wide - newwide) / 2, (sh_high - newhigh) / 2); sh_wide = newwide; sh_high = newhigh; } fprintf(outfd, "%d %d div %d %d div scale\n", sh_wide, ps_width, sh_high, ps_height); /* * Take extra page margins into account */ fprintf(outfd, "%d %d div %d %d div scale\n", ps_width, ps_width + pagemargin_left + pagemargin_right, ps_height, ps_height + pagemargin_top + pagemargin_bottom); #ifndef NSCALE fprintf(outfd, "%d %d translate\n", pagemargin_left, pagemargin_bottom); #endif #if 0 /* does not seem to be neccessary. seems to create dictionary * stack underflows... */ if ((ps_posttype == PS_TEX || ps_posttype == PS_TEX2) && tex1) /* start dvi2ps init every page */ fprintf(outfd, "%s%s", tex1, tex2); #endif /* * do the individual sheet setup */ ps_sheetsetup(outfd); /* * place one reduce page on the printed page */ plcnt = 0; if (flush == FLUSH_PS) { rtn_val = post_flush_onepage(totlen, asheet, outfd); stored_points = NULL; points = flush_points; } else { rtn_val = post_onepage(fd, asheet, outfd); points++; } /* * clean up after mpage has drawn its page */ fprintf(outfd, "grestore\n"); } #if 0 fprintf(outfd, "sheetsave restore\n"); #endif /* * print the sheet */ if (points->pp_origin_x == 0 || (rtn_val == FILE_EOF && opt_file)) fprintf(outfd, "showsheet\n"); } while (flush && rtn_val == FILE_MORE); if (stored_points) { flush_points = points; points = stored_points; /* * Save current graphics context so we can scale/translate * from known position and size. */ fprintf(outfd, "gsave\n"); /* * print one reduced page by moving to the proper point, * turning to the proper aspect, scaling to the proper * size, and setting up a clip path to prevent overwritting; * then print a reduced page of output. */ Debug(DB_PSMPAGE, "%%%% %%%%ReducedPageStartsHere\n", outfd); # ifdef DEBUG if (Debug_flag & DB_PSMPAGE) { fprintf(outfd, "( %d %d translate %d rotate\\n)", points->pp_origin_x(), points->pp_origin_y(), asheet->sh_rotate); fprintf(outfd, " print flush\n"); } # endif /* DEBUG */ #ifdef NSCALE /*GPN*/ fprintf (outfd, NScale); fprintf(outfd, "%d gpnxs mul %d gpnxs mul translate %d rotate\n", points->pp_origin_x(), points->pp_origin_y(), asheet->sh_rotate); #else /* NSCALE */ fprintf(outfd, "%d %d translate\n", points->pp_origin_x(), points->pp_origin_y()); if (asheet->sh_rotate) fprintf(outfd, "%d rotate\n", asheet->sh_rotate); #endif sh_wide = (*asheet->sh_width)(); sh_high = (*asheet->sh_height)(); /* output the clip path */ #ifdef NSCALE /*GPN*/ fprintf(outfd, "0 0 moveto 0 %d gpnys mul lineto %d gpnxs mul" " %d gpnys mul lineto ", sh_high, sh_wide, sh_high); fprintf(outfd, "%d gpnxs mul 0 lineto\n", sh_wide); fprintf(outfd, "closepath clip\n"); #else /* NSCALE */ #if 0 fprintf(outfd, "0 0 moveto 0 %d lineto %d %d lineto ", sh_high, sh_wide, sh_high); fprintf(outfd, "%d 0 lineto\n", sh_wide); #else fprintf(outfd, "1 1 moveto 1 %d lineto %d %d lineto ", sh_high - 1, sh_wide - 1, sh_high - 1); fprintf(outfd, "%d 1 lineto\n", sh_wide - 1); #endif fprintf(outfd, "closepath clip newpath\n"); #endif /* NSCALE */ if (opt_square) { int newhigh = sh_high, newwide = sh_wide; if (sh_wide * ps_height > sh_high * ps_width) newwide = (sh_high * ps_width) / ps_height; else newhigh = (sh_wide * ps_height) / ps_width; #ifdef NSCALE /*GPN*/ fprintf(outfd, "%d gpnxs mul %d gpnys mul translate\n", #else fprintf(outfd, "%d %d translate\n", #endif (sh_wide - newwide) / 2, (sh_high - newhigh) / 2); sh_wide = newwide; sh_high = newhigh; } fprintf(outfd, "%d %d div %d %d div scale\n", sh_wide, ps_width, sh_high, ps_height); /* * Take extra page margins into account */ fprintf(outfd, "%d %d div %d %d div scale\n", ps_width, ps_width + pagemargin_left + pagemargin_right, ps_height, ps_height + pagemargin_top + pagemargin_bottom); #ifndef NSCALE fprintf(outfd, "%d %d translate\n", pagemargin_left, pagemargin_bottom); #endif #if 0 /* does not seem to be neccessary. seems to create dictionary * stack underflows... */ if ((ps_posttype == PS_TEX || ps_posttype == PS_TEX2) && tex1) /* start dvi2ps init every page */ fprintf(outfd, "%s%s", tex1, tex2); #endif /* * do the individual sheet setup */ ps_sheetsetup(outfd); /* * place one reduce page on the printed page */ plcnt = 0; rtn_val = post_flush_onepage(totlen, asheet, outfd); stored_points = NULL; /* * clean up after mpage as drawn its page */ fprintf(outfd, "grestore\n"); #if 0 fprintf(outfd, "sheetsave restore\n"); #endif /* * print the sheet */ if (points->pp_origin_x == 0 || (rtn_val == FILE_EOF && opt_file)) fprintf(outfd, "showsheet\n"); } /* * let the upper level know about the status of possible EOF */ return rtn_val; } /* do_post_sheet */ static void ps_sheetsetup(outfd) FILE *outfd; { switch (ps_posttype) { case PS_PSROFF: fprintf(outfd, "%s", ps_roff_xi); fprintf(outfd, "/p {} def\n"); break; /* case PS_MPAGE: fprintf(outfd, "/showpage {} def\n"); break; */ } return; } /* ps_sheetsetup */ static int post_onepage(fd, asheet, outfd) FILE *fd; struct sheet *asheet; FILE *outfd; { int indoc = 0; Debug(DB_PSROFF, "%%post_onepage: Begin page\n", 0); if (ps_at_trailer) { Debug(DB_PSROFF, "%%post_onepage: still at trailer\n", 0); return FILE_EOF; } if (have_line) { fprintf(outfd, "%s", currline); have_line = 0; } while(fgets(currline, LINESIZE-1, fd) != NULL) { int line_rc; line_rc = post_one_line(currline, fd, outfd, &indoc, 0); if (line_rc != FILE_CONT) return line_rc; } Debug(DB_PSROFF, "%%post_onepage: eof\n", 0); return FILE_EOF; } /* post_onepage */ static int post_flush_onepage(totlen, asheet, outfd) int totlen; struct sheet *asheet; FILE *outfd; { int indoc = 0; Debug(DB_PSROFF, "%%post_flush_onepage: Begin page\n", 0); /* if (ps_at_trailer) { Debug(DB_PSROFF, "%%post_flush_onepage: still at trailer\n", 0); return FILE_EOF; } */ if (have_line) { fprintf(outfd, "%s", currline); have_line = 0; } memgets_init(stored_page, totlen); while (memgets(currline, LINESIZE-1) != NULL) { int line_rc; line_rc = post_one_line(currline, (FILE *) NULL, outfd, &indoc, 1); if (line_rc != FILE_CONT) return line_rc; } Debug(DB_PSROFF, "%%post_flush_onepage: eof\n", 0); return FILE_MORE; } /* post_flush_onepage */ static int post_one_line(line, fd, outfd, indoc, flush_page) char * line; FILE *fd; FILE *outfd; int * indoc; int flush_page; { if (strncmp(line, "%%BeginDocument", 15) == 0) { (*indoc)++; } if (strncmp(line, "%%EndDocument", 13) == 0) { (*indoc)--; } if (!*indoc) { if (strncmp(line, "%%Page:", 7) == 0) { fprintf(outfd, "%% %s", line); /* * only if there is already output to this logical page */ if (!plcnt) return FILE_CONT; Debug(DB_PSROFF, "%%post_one_line: next page\n", 0); return FILE_MORE; } if (opt_killtrail && (strncmp(line, "%%Trailer", 9) == 0 || strncmp(line, "%%PSTrailer", 11) == 0)) { fprintf(outfd, "%% %s", line); Debug(DB_PSROFF, "%%post_one_line: found trailer\n", 0); ps_at_trailer = TRUE; return FILE_EOF; } /* For netscape output */ if (strncmp(line, "%%EOF", 5) == 0) { fprintf(outfd, "%% %s", line); Debug(DB_PSROFF, "%%post_one_line: Netscape EOF\n", 0); return FILE_EOF; } if (ps_posttype == PS_MPAGE && strncmp(line, "showsheet", 9) == 0) return FILE_CONT; if (ps_posttype == PS_TEX || ps_posttype == PS_TEX2) { if (ps_posttype == PS_TEX2 && (strstr(line, "eop\n") || strstr(line, "eop end\n"))) { fprintf(outfd, "%s", line); Debug(DB_PSROFF, "%%post_one_line: found TEX eop\n", 0); return FILE_MORE; } if (strncmp(line, "TeXDict", 7) == 0) { /* * Hope all dvi2ps progs work the same: * capture the TeX init code so we can run it 'manually' for * every page. This is needed as this code sets up a gstate * that conflicts with mpage... * This trick seems to work for text, but figures within the dvi * file seem to have a mind of their own... */ if (tex1) free(tex1); tex1 = malloc(strlen(line)+1); strcpy(tex1, line); fprintf(outfd, "%s", line); flush_page ? memgets(line, LINESIZE-1) : fgets(line, LINESIZE-1, fd); if (tex2) free(tex2); tex2 = malloc(strlen(line)+1); strcpy(tex2, line); } } } fprintf(outfd, "%s", line); plcnt++; return FILE_CONT; } /* post_one_line */ static void do_roff_tailer(fd, outfd) FILE *fd, *outfd; { #ifdef DEBUG int i = 0; #endif Debug(DB_PSDOC, "%%do_roff_trailer: looking for eof\n", 0); while(fgets(currline, LINESIZE-1, fd) != NULL) { #ifdef DEBUG i++; Debug(DB_PSDOC, "%%%s", currline); #endif ; } Debug(DB_PSDOC, "%%do_roff_trailer: tailer of %d lines\n", i); return; } /* do_roff_tailer */