home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Spezial
/
SPEZIAL2_97.zip
/
SPEZIAL2_97.iso
/
ANWEND
/
TOOLS
/
MPAGE
/
MPAGE.ZIP
/
mp_post.c
< prev
next >
Wrap
Text File
|
1997-09-25
|
15KB
|
545 lines
# include <stdio.h>
# include <sys/types.h>
# ifndef lint
static char *rcs_id =
"@(#) $Header: mp_post.c,v 2.9 89/08/09 11:30:39 mark Exp $";
# endif
# include "mp_head.h"
/*
* mpage: a program to reduce pages of print so that several pages
* of output appear on one printed page.
*
* Written by:
* ...!uunet!\ Mark Hahn, Sr Systems Engineer
* >pyrdc!mark Pyramid Technology Corporation
* ...!pyramid!/ Vienna, Va (703)848-2050
*
*
* 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 notice is preserved, and that the
* distributor grants the recipient permission for further
* redistribution as permitted by this notice.
*
*/
/* $Log: mp_post.c,v $
* Revision 2.9 89/08/09 11:30:39 mark
* fixed bug in get_psstr. it did not return a value if it failed
* to find a string in parparentheses. the code "lucked-out" on risc
* machines but failed on machines that use different locations for
* the function arguments and return values, (680x0s and VAXen).
* (First time I've seen poor coding work on a RISC but be-fuddle a CISC.
*
* Revision 2.8 89/05/25 10:25:34 mark
* add new debugging keyword for tracking the processing of postscript
* documents.
*
* Revision 2.7 89/05/25 10:20:38 mark
* changed the format of debugging prints in the PS code.
*
* Revision 2.6 89/05/25 08:58:30 mark
* rearranged the rcs header keywords for better readability.
*
* Revision 2.5 89/05/25 08:49:49 mark
* added code to disable showpage durring the printing of postscript
* documents. we define our own routine to do the showpage.
*
* Revision 2.4 89/05/23 09:39:36 mark
* Changes to deal with %%BeginSetup sections. We now scan all the way
* to the first %%Page comment assuming this will cover everything.
* Actually we should do something more intelligent, saving the %%BeginSetup
* section and putting after our page reduction but before the page is
* printed.
*
* Revision 2.3 89/05/22 14:40:56 mark
* Fixed the type-o in the rcs identification string
*
* Revision 2.2 89/05/22 14:37:56 mark
* Added rcs identification usable with the "what" program
*
* Revision 2.1 89/05/22 14:31:22 mark
* New Major Revision
*
* Revision 1.2 89/05/22 13:49:58 mark
* placed the log keywork after the initial notice
*
* Revision 1.1 89/05/22 13:48:43 mark
* Initial revision
* */
/*
* character spaces used throughout for holding the current line from
* the input file
*/
static char currline[LINESIZE];
/*
* 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;
/*
* 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).
*/
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;
}
/*
* 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.");
}
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.");
}
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.");
return 0;
}
if (ungetc(firstchar, infd) == EOF) {
fprintf(stderr, "%s: Lost first character of file ",
MPAGE);
fprintf(stderr, "while checking for postscript.");
}
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_gettype(fd, outfd)
FILE *fd;
FILE *outfd;
{
int type_known, ps_type, end_comments;
char *get_psstr();
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
*/
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;
type_known = 0;
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: eof in 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;
}
/*
* once we know the type of PS, we no longer need to keep
* checking.
*/
if (type_known) {
continue;
}
/*
* check for mpage output
*/
if (strncmp(currline, "%%Creator: mpage", 16) == 0) {
Debug(DB_PSDOC, "%%ps_gettype: mpage document\n", 0);
type_known = 1;
ps_type = PS_MPAGE;
}
/*
* check for psroff output
*/
if (strncmp(currline, "%%Title: ", 9) == 0) {
if (strcmp(get_psstr(currline), "ditroff") == 0) {
Debug(DB_PSDOC, "%%ps_gettype: psroff\n", 0);
type_known = 1;
ps_type = PS_PSROFF;
}
}
}
if (type_known) {
return ps_type;
}
Debug(DB_PSDOC, "%%ps_gettype: unknow type conforming PS\n", 0);
return PS_CONFORM;
}
/*
* get_psstr will extract (and return a pointer to) a string in parentheses.
* it is used for checking for psroff (ditroff) postscript.
*/
char *get_psstr(line)
char *line;
{
char space[LINESIZE];
char *p1, *p2;
p1 = line;
while (*p1) {
if (*p1 == '(') {
p1++;
p2 = space;
while (*p1 && (*p1 != ')')) {
*p2++ = *p1++;
}
*p2 = 0;
return space;
}
p1++;
}
return line;
}
do_ps_doc(fd, asheet, outfd)
FILE *fd;
struct sheet *asheet;
FILE *outfd;
{
Debug(DB_PSDOC, "%%do_ps_doc: postscript document\n", 0);
ps_posttype = ps_gettype(fd,outfd);
Debug(DB_PSDOC, "%%do_ps_doc: document type is %d\n", ps_posttype);
switch(ps_posttype) {
case PS_NONE:
/*
* why bother?
*/
break;
default:
do_post_doc(fd, asheet, outfd);
break;
}
}
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);
Debug(DB_POST, "%%do_post_doc: pages\n", 0);
/*
* while there is still input, print pages
*/
while (do_post_sheet(fd, asheet, outfd) != FILE_EOF)
;
Debug(DB_POST, "%%do_post_doc: trailer\n", 0);
do_roff_tailer(fd, outfd);
}
do_other_doc(fd, asheet, outfd)
FILE *fd;
struct sheet *asheet;
FILE *outfd;
{
ps_at_trailer = FALSE;
ps_copyprolog(fd, outfd);
}
ps_copyprolog(fd, outfd)
FILE *fd;
FILE *outfd;
{
char *rtn;
Debug(DB_PSDOC, "%%ps_copyprolog: adding mpage prolog\n", 0);
fprintf(outfd, "/showsheet { showpage } bind def\n");
fprintf(outfd, "/showpage { } def\n");
Debug(DB_PSDOC, "%%ps_copyprolog: copying prolog\n", 0);
if (ps_posttype == PS_PSROFF) {
Debug(DB_PSDOC, "%%ps_copyprolog: calling ps_roff_prolog\n",0);
ps_roff_copyprolog(fd, outfd);
return;
}
rtn = fgets(currline, LINESIZE-1, fd);
while (rtn) {
if (strncmp(currline, "%%Page:", 7) == 0) {
fprintf(outfd, "%% %s", currline);
return;
}
fprintf(outfd, "%s", currline);
rtn = fgets(currline, LINESIZE-1, fd);
}
Debug(DB_PSDOC, "%%ps_copyprolog: eof before %%%%EndProlog\n", 0);
fprintf(outfd, "%%%%EndProlog\n");
}
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) {
fprintf(outfd, "%%%s", 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");
}
ps_skip_to_page(fd)
FILE *fd;
{
Debug(DB_PSDOC, "%%ps_skip to page: copying psroff prolog\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);
}
do_post_sheet(fd, asheet, outfd)
FILE *fd;
struct sheet *asheet;
FILE *outfd;
{
char **outline;
struct pagepoints *points;
int rtn_val;
/*
* keep track of the pages printed
*/
ps_pagenum += 1;
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
/*
* print the page outline
*/
mp_outline(outfd, asheet);
/*
* run through the list of base points for putting reduced pages
* on the printed page
*/
points = asheet->sh_pagepoints;
while (points->pp_origin_x != 0) {
/*
* print one reduced page by moveing to the proper point,
* turning to the proper aspect, scaling to the proper
* size, and setting up a clip path to prevent overwritting;
* the print a reduced page of output
*/
# ifdef DEBUG
if (Debug_flag & DB_PSMPAGE) {
fprintf(outfd, "%%%% %%%%ReducedPageStartsHere\n");
}
# endif DEBUG
fprintf(outfd, "/sheetsave save def\n");
fprintf(outfd, "gsave\n");
# 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
fprintf(outfd, "%d %d translate %d rotate\n",
points->pp_origin_x(), points->pp_origin_y(),
asheet->sh_rotate);
fprintf(outfd, "%d %d div %d %d div scale\n",
(*asheet->sh_width)(), ps_width,
(*asheet->sh_height)(), ps_height);
/* output the clip path */
fprintf(outfd, "0 0 moveto 0 %d lineto %d %d lineto ",
ps_height, ps_width, ps_height);
fprintf(outfd, "%d 0 lineto\n", ps_width);
fprintf(outfd, "closepath clip newpath\n");
/*
* do the individual sheet setup
*/
ps_sheetsetup(outfd);
/*
* place one reduce page on the printed page
*/
rtn_val = post_onepage(fd, asheet, outfd);
/*
* clean up after mpage as drawn its page
*/
fprintf(outfd, "grestore sheetsave restore\n");
points++;
}
/*
* print the sheet
*/
fprintf(outfd, "showsheet\n");
/*
* let the upper level know about the status of possible EOF
*/
return rtn_val;
}
ps_sheetsetup(outfd)
FILE *outfd;
{
switch (ps_posttype) {
case PS_PSROFF:
fprintf(outfd, "xi\n");
fprintf(outfd, "/p {} def\n");
break;
case PS_MPAGE:
fprintf(outfd, "/showpage {} def\n");
break;
}
}
post_onepage(fd, asheet, outfd)
FILE *fd;
struct sheet *asheet;
FILE *outfd;
{
int len;
char *test;
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;
}
while(fgets(currline, LINESIZE-1, fd) != NULL) {
if (strncmp(currline, "%%Page:",7) == 0) {
fprintf(outfd, "%% %s", currline);
Debug(DB_PSROFF, "%%post_onepage: next page\n", 0);
return FILE_MORE;
}
if (strncmp(currline, "%%Trailer",8) == 0) {
fprintf(outfd, "%% %s", currline);
Debug(DB_PSROFF, "%%post_onepage: found trailer\n", 0);
ps_at_trailer = TRUE;
return FILE_EOF;
}
fprintf(outfd, "%s", currline);
}
Debug(DB_PSROFF, "%%post_onepage: eof\n", 0);
return FILE_EOF;
}
do_roff_tailer(fd, outfd)
FILE *fd, *outfd;
{
int i;
Debug(DB_PSDOC, "%%do_roff_trailer: looking for eof\n", 0);
i = 0;
while(fgets(currline, LINESIZE-1, fd) != NULL) {
i++;
Debug(DB_PSDOC, "%%%s", currline);
}
Debug(DB_PSDOC, "%%do_roff_trailer: tailer of %d lines\n", i);
}