#include #include #include #include #define ON 1 #define OFF 0 /* P S P R This program is a text file printing filter which paginates, prints optional page headers, provides margin and font control for a Postscript printer. Output is sent to standard output and can be redirected to a printer. The calling sequence looks like: pspr -[options...] files... Printing defaults are: Left margin set for hole punch, page headers on, portrait mode. These settings can be modified with the command line options and can be freely mixed with file names on the command line. A '-' indicates option flags, all characters after the '-' are processed as options until a blank is seen. The valid options are: 1 - one sided printing h - turn off page headers l - landscape mode printing m - turn off margins All other characters in the option field are silently ignored. Not all combinations of options can be applied at the same time. The program uses the last option requested before the file name is encountered. Written by: Marc W. Buie, Lowell Observatory 4 February 1992 94/1/13, MWB, added one sided printing option */ /* GLOBAL DECLARATIONS */ int margins=ON; /* Automatic left margin placement (defaults to on) */ int headers=ON; /* page headers (defaults to on) */ int landscape=OFF; /* Landscape or portrait mode (defaults to portrait) */ int first=1; /* First file flag */ int oneside=OFF; /* One sided printing flag (defaults to 2-sided) */ /* END OF GLOBALS */ main(argc, argv) int argc; char *argv[]; { char *s; /* pointer to current argument */ *argv++; /* skip first (zeroth) argument */ while (*argv) { /* execute until there are no more arguments */ s = argv[0]; /* Decode the arguments which tell us how to manipulate the printer */ if( *s == '-' ) { while ( *s != '\0' ) { switch (*s) { case '1': oneside = ON; break; case 'h': headers = OFF; break; case 'l': landscape = ON; break; case 'm': margins = OFF; break; default: break; /* Ignore illegal options */ } /* end switch */ s++; /* increment to look at next option */ } /* end option while */ } /* end argument decoding if */ else copyfile(*argv); /* increment pointer to the next argument now that we are done with this one */ *argv++; } /* end argument while */ exit(0); } /* END OF MAIN PROGRAM */ copyfile(name) /* copy file to standard output, formatting as we go. */ char *name; { int c; FILE *fopen(), *fp; char line[201]; char lineok[301]; struct stat stbuf; char *strptr,year[5],tim[17]; int i,nlines,headfont,npages,page,namelen,lineno; char lastmod[26]; int headlen; int expand,font; int maxlen; int len; float pts; float dy; int lines_per_page; fp = fopen(name,"r"); if (fp == NULL) { perror(name); return; } if (first) { job_setup(); first=0; } if (stat(name, &stbuf) == -1) perror(name); else if ( !S_ISREG(stbuf.st_mode) ) fprintf(stderr, "mpr: can only process regular files (%s)\n",name); else { /* find out the maximum line length and number of lines */ nlines = 0; maxlen = 0; while ((len=flinelen(fp)) != EOF) { nlines++; if ( len > maxlen ) maxlen = len; } if (nlines == 0) fprintf(stderr, "pspr: %s is an empty file.\n",name); else { /* let's send it on its way. */ if (maxlen > 80) pts = 10.0 * 80.0/maxlen; else pts = 10.0; dy = pts * 1.05; lines_per_page = (int) 702.0/dy; /* Count the number of pages, watching for formfeeds */ fseek(fp,0L,0); /* rewind the file */ npages=i=0; while ( fgetline(fp,line,200) != EOF ) { if (line[0] == '\014') { npages++; i=0; } else { i++; if (i == lines_per_page) { npages++; i=0; } } } if (i != 0) npages++; /* Copy the time and date of the last modification for use in the header. */ strcpy(lastmod,ctime(&stbuf.st_mtime)); for ( i=20,strptr=year; i<=23; i++ ) *strptr++ = lastmod[i]; *strptr = '\0'; for ( i=3,strptr=tim; i <= 18; i++ ) *strptr++ = lastmod[i]; *strptr = '\0'; lineno = 0; page = 0; /* setup the counters */ fseek(fp,0L,0); /* rewind the file */ while (fgetline(fp,line,200) != EOF) { if (line[0] == '\014') { footer(); lineno=0; continue; } if (lineno == 0) { /* spit out a header */ page++; header(headers,name,year,tim,page,npages); page_setup(pts,dy); } lineno++; if (lineno == 1) printf("y"); protect(line,lineok); printf(" dy sub dup x exch moveto (%s) show\n",lineok); if (lineno == lines_per_page) { footer(); lineno = 0; } } /* end while */ if (lineno != 0) footer(); if ( ((npages % 2) == 1) && (oneside == OFF) ) printf("showpage\n"); } /* end else */ } /* end else */ fclose(fp); } job_setup() { printf("%%!\n"); printf("/cshow { dup stringwidth pop 2 div neg 0 rmoveto show } def\n"); printf("/rshow { dup stringwidth neg exch neg exch rmoveto show } def\n"); } page_setup(pts,dy) float pts; float dy; { printf("/height %.4f def\n",pts); printf("/Courier findfont height scalefont setfont\n"); printf("/dy %.6f def\n",dy); } header(fancy,name,year,tim,page,npages) int fancy; char *name; char *year; char *tim; int page; int npages; { if (fancy) { printf("/x 72 def\n"); printf("/y 738 def\n"); printf("/Times-Roman findfont 16 scalefont setfont\n"); printf("0.90 setgray\n"); printf("newpath 18 y moveto 576 0 rlineto 0 18 rlineto -576 0 rlineto closepath fill\n"); printf("0.6 setgray\n"); printf("newpath 18 y 18 add moveto 144 0 rlineto 0 18 rlineto -144 0 rlineto closepath fill \n"); printf("newpath 450 y 18 add moveto 144 0 rlineto 0 18 rlineto -144 0 rlineto closepath fill\n"); printf("0.0 setgray\n"); printf("306 y 4 add moveto (%s) cshow\n",name); if ( ((page % 2) == 1) || (oneside == ON) ) { printf("/Times-Bold findfont 12 scalefont setfont\n"); printf("90 y 22 add moveto (%s%s) cshow\n",year,tim); printf("/Helvetica-Bold findfont 16 scalefont setfont\n"); printf("1.0 setgray\n"); printf("522 y 22 add moveto (Page %d of %d) cshow\n",page,npages); } else { printf("/Times-Bold findfont 12 scalefont setfont\n"); printf("522 y 22 add moveto (%s%s) cshow\n",year,tim); printf("/Helvetica-Bold findfont 16 scalefont setfont\n"); printf("1.0 setgray\n"); printf("90 y 22 add moveto (Page %d of %d) cshow\n",page,npages); } printf("0.0 setgray\n"); } else { printf("/x 72 def\n"); printf("/y 738 def\n"); } } footer() { printf("pop showpage\n"); } protect(str1,str2) char *str1; char *str2; { while (*str1 != '\0') { if ( (*str1 == '\(') || (*str1 == '%' ) || (*str1 == '\\' ) || (*str1 == '\)') ) *str2++ = '\\'; *str2++ = *str1++; } *str2 = '\0'; } int flinelen(fp) FILE *fp; { int i=0; char c; while ( (c = getc(fp)) != EOF ) { if ( c == '\t' ) i += 8; else if ( c != '\n' ) i++; else return(i); } if ( i == 0 ) return(EOF); else return(i); }