[comp.lang.postscript] Summary: Printing two pages on one

riem@ztivax.UUCP (Raimund Riem) (03/08/90)

Sometimes ago I asked for help on printing two or four
pages on one sheet of paper. Now I will summarized the
repies to all interested people.

Someone know about a solution for the Macintosh?
Thanks for all replies.


From rei Wed Feb 21 13:28:37 1990
From: rei (Dr Manfred Reitenspiess)
Date: Wed, 21 Feb 90 13:28:36 -0100
Message-Id: <9002211228.AA19196@ztivax.uucp>
Received: by ztivax.uucp; Wed, 21 Feb 90 13:28:36 -0100
To: riem
Subject: re psnews: two pages on one
Status: RO

the standard ensrcript package on the VAX does exactly that:
	enscript -2rk -p<outfile> <infile>

However, I have another question: when printing the thereby generated
postscript file on an Apple laserwriter, the top of the page is moving
too far down. This results in a missing first column of first of each
two printed pages.

If you find something more convenient than enscript or if you find a
solution to my problem, please send mail to rei@ztivax

--------------------------------------------------------------------
Manfred Reitenspiess
ZFE IS SOF42, Siemens AG, Otto-Hahn-Ring 6, 8000 Muenchen 83
Tel.: 089-636-42393                     Mail: rei@ztivax
--------------------------------------------------------------------






ENSCRIPT(1)         UNIX Programmer's Manual          ENSCRIPT(1)



NAME
     enscript - convert text files to POSTSCRIPT format for
     printing

SYNOPSIS
     enscript [ -12BGghKklmoqRr ] [ -L_l_i_n_e_s ] [ -f_f_o_n_t ] [
     -F_h_f_o_n_t ] [ -b_h_e_a_d_e_r ] [ -p_o_u_t ] [ _s_p_o_o_l_o_p_t_s ] [ _f_i_l_e_s ]

DESCRIPTION
     _e_n_s_c_r_i_p_t reads in plain text files, converts them to
     POSTSCRIPT format, and spools them for printing on a
     POSTSCRIPT printer.  Fonts, headings, limited formatting
     options and spooling options may be specified.

     For example:
          enscript -Paleph boring.txt
     prints a copy of the file called boring.txt on the printer
     called "aleph".
          enscript -2r boring.c
     prints a two-up landscape listing of the file called
     boring.c on the default printer (see below).

     Font specifications have two parts: A font name as known to
     POSTSCRIPT (e.g., Times-Roman, Times-BoldItalic Helvetica,
     Courier), and a point size (1 point=1/72 inch - 8 point is a
     good small font).  So Courier-Bold8 is 8 point Courier Bold,
     Helvetica12 is 12 point Helvetica.

     The environment variable ENSCRIPT may be used to specify
     defaults.  The value of ENSCRIPT is parsed as a string of
     arguments _b_e_f_o_r_e the arguments that appear on the command
     line.  For example "ENSCRIPT='-fTimes-Roman8'" sets your
     default body font to 8 point Times Roman.

     The possible options are:

     -2   set in two columns.

     -1   set in one column (the default).

     -r   rotate the output 90 degrees (landscape mode).  This is
          good for output that requires a wide page or for pro-
          gram listings when used in conjunction with -2.
          "enscript -2r files" is a nice way to get program list-
          ings.

     -R   don't rotate, also known as portrait mode (the
          default).

     -G   print in gaudy mode: causes page headings, dates, page
          numbers to be printed in a flashy style, at some slight



12 Nov 1985 Image Network Development System-4.2 BSD            1







ENSCRIPT(1)         UNIX Programmer's Manual          ENSCRIPT(1)



          performance expense.

     -l   simulate a line printer: make pages 66 lines long and
          omit headers.

     -B   omit page headings.

     -b_h_e_a_d_e_r
          sets the string to be used for page headings to _h_e_a_d_e_r.
          The default header is constructed from the file name,
          its last modification date, and a page number.

     -L_l_i_n_e_s
          set the maximum number of lines to output on a page.
          _E_n_s_c_r_i_p_t usually computes how many to put on a page
          based on point size, and may put fewer per page than
          requested by _l_i_n_e_s.

     -f_f_o_n_t
          sets the font to be used for the body of each page.
          Defaults to Courier10, unless two column rotated mode
          is used, in which case it defaults to Courier7.

     -F_h_f_o_n_t
          sets the font to be used for page headings.  Defaults
          to Courier-Bold10.

     -p_o_u_t
          causes the POSTSCRIPT file to be written to the named
          file rather than being spooled for printing.  As a spe-
          cial case, -p - will send the POSTSCRIPT to the stan-
          dard output.

     -g   causes the fact that a file is garbage to be ignored.
          Normally, any file with more than a small number of
          non-printing characters is suspected of being garbage,
          and not printed - this option means "print it anyway."

     -o   If _e_n_s_c_r_i_p_t cannot find characters in a font, the miss-
          ing characters are listed.

     -q   causes _e_n_s_c_r_i_p_t to be quiet about what it is doing.
          _E_n_s_c_r_i_p_t won't report about pages, destination, omitted
          characters, etc. Fatal errors are still reported to the
          standard error output.

     -k   enables page prefeed (if the printer supports it).
          This allows simple documents (e.g., program listings in
          one font) to print somewhat faster by keeping the
          printer running between pages.




12 Nov 1985 Image Network Development System-4.2 BSD            2







ENSCRIPT(1)         UNIX Programmer's Manual          ENSCRIPT(1)



     -K   disable page prefeed (the default).

     -h   suppress printing of job burst page.

     In 4.2bsd systems, the following spooler options are also
     recognized:

     -P_p_r_i_n_t_e_r
          causes the output to be sent to the named printer.

     -#_n  causes _n copies of the output to be produced.  The
          default is one.

     -m   causes the printer daemon to send mail upon job comple-
          tion.

     -J_n_a_m_e
          sets the job name for use on the burst page.  Other-
          wise, the name of the first input file will be used.

     -C_c_l_a_s_s
          set the job classification for use on the burst page.

     In System V, the following spooler options are also recog-
     nized:

     -t_t_i_t_l_e
          sets job title for use on the burst page.

     -d_d_e_s_t
          causes the output to be sent to the named printer or
          printer class.

     -n_n  causes _n copies of the output to be produced. The
          default is one.

     -w or -m
          causes the printer daemon to write or send mail upon
          job completion.

ENVIRONMENT
     ENSCRIPT
          string of options to be used by _e_n_s_c_r_i_p_t.

     PSLIBDIR
          path name of a directory to use instead of
          /usr/local/lib/ps for enscript prologue and font metric
          files.

     PSTEMPDIR
          path name of temporary directory to use instead of



12 Nov 1985 Image Network Development System-4.2 BSD            3







ENSCRIPT(1)         UNIX Programmer's Manual          ENSCRIPT(1)



          XPSTEMDIRX of spooled temporary files.

     PRINTER (4.2bsd)
          the name of a printer (as in the -P option) for _l_p_r to
          use.  If no -P option is specified, _l_p_r will use this
          printer.  If neither -P nor PRINTER is set, _e_n_s_c_r_i_p_t
          will spool to a printer named ``PostScript''.

     LPDEST (System V)
          the name of a printer (as in the -d option) for _l_p to
          use.  If no -d option is specified, _l_p will use this
          printer.  If neither -d nor LPDEST is set, _e_n_s_c_r_i_p_t
          will spool to a printer class named ``PostScript''.

FILES
     /usr/local/lib/ps/*.afm
                           font metrics files.

     /usr/local/lib/ps/enscript.pro
                           prologue for enscript files.

     lpr(1 bsd), lp(1 V)   Printer spooler

SEE ALSO
     pr(1), ps630(1), getopt(3).
     4.2bsd: lpr(1), lpq(1), lprm(1).
     System V: lp(1), cancel(1), lpstat(1).

DIAGNOSTICS
     Should be self explanatory.

AUTHOR
     Adobe Systems Incorporated
     Gaudy mode by Guy Riddle of AT&T Bell Laboratories

FEATURES
     Options and the ENSCRIPT environment string are parsed in
     _g_e_t_o_p_t(3) fashion.

BUGS
     Long lines are truncated.  Line truncation may be off by a
     little bit as printer margins vary.  There should be a
     "wrap" option and multiple (truncated or wrapped) columns.

     _E_n_s_c_r_i_p_t generates temporary files which are spooled for
     printing.  The temporary file names are used by the spooling
     software (e.g., _l_p_q), rather than the symbolic job name
     passed to _l_p_r.

     There are too many options.




12 Nov 1985 Image Network Development System-4.2 BSD            4







ENSCRIPT(1)         UNIX Programmer's Manual          ENSCRIPT(1)



NOTES
     POSTSCRIPT is a trademark of Adobe Systems Incorporated.
     Times and Helvetica are registered trademarks of Allied Cor-
     poration.

12 Nov 1985 Image Network Development System-4.2 BSD            5

From leoh%hardy%relay.EU.net@unido Fri Feb 23 16:57:49 1990
Date: Fri, 23 Feb 90 08:56:57 EST
From: leoh%hardy@uunet.UU.NET (Leo Hinds)
To: riem@ztivax
Subject: Re: Printing two pages on one sheet
Newsgroups: comp.sys.mac,comp.lang.postscript
In-Reply-To: <904@ztivax.UUCP>
Organization: Harris Computer Systems, Fort Lauderdale, FL

There is a program that was posted to the net a while back (not sure of exact 
date), that would do 2/4/8/16/n up ... without much effort.  I have a copy of 
the shar file (~30k in size) ... let me know if you want it.


-- 
leoh@hdw.csd.harris.com                  H    H     i                 d   sssss
L        eeeee    oooo                   H    H          nnnn     ddddd   ss
L        eee     o    o                  HHHHHH     i    n   n   d    d     ss
LLLLLL   eeeee    oooo                   H    H     i    n    n   ddddd  sssss

From jw%owf%ethz%chx400%cernvax@unido Fri Feb 23 17:48:00 1990
Date: Fri, 23 Feb 90 09:58:10 +0100
From: jw%owf%chx400@cernvax
Message-Id: <9002230858.AA00653@thor.owf.uucp>
To: riem@ztivax
Subject: Re: Printing two pages on one sheet
Newsgroups: comp.sys.mac,comp.lang.postscript
In-Reply-To: <904@ztivax.UUCP>
Organization: OWF AG Zurich, Switzerland
Status: RO

Providing, your postscript file is a *conforming* postscript file
the program below will generate exactly what you want

Juerg Wanner	(jw@owf.uucp)
OWF AG
Asylstr. 125
CH-8032 Zuerich

----- snip snip snip ------
/* a5.c
 *
 * mutilates a conforming postscript file for 2 pages per A4
 *
 */

#include <stdio.h>

#define BUFSIZ	1024

static char buf[BUFSIZ];

main(argc, argv)
int argc;
char **argv;
{
    int page = 0, trail = 0;
    register int cnt, c;
    register char *bp;

    while ((c = getchar()) != EOF) {
	bp = buf;
	*bp = '\0';
	if (c != '%') {
	    copyline(buf, c);
	}
	else {
	    cnt = BUFSIZ - 1;
	    do {
		if (c == EOF) {
		    *bp = '\0';
		}
		else *bp++ = c;
	    } while ((c = getchar()) != '\n' && --cnt > 0);
	    *bp = 0;
	    if ((c == EOF) && (bp == buf)) break;
	    else if (strncmp(buf,"%%Page:",7) == 0) {
		if (++page & 1) {
		    printf("%%%%Page: %d %d\n", (page+1) >> 1, (page+1) >> 1);
		    while (c != '\n' && c != EOF) c = getchar();
		}
	    }
	    else if (strncmp(buf,"%%EndComments",13) == 0) {
		copyline(buf, c);
		printf("/$first$ true def\n");
		printf("/$a4height$ 297 25.4 div 72 mul def\n");
		printf("/$a4width$ 210 25.4 div 72 mul def\n");
		printf("/$xlate$ {\n");
		printf("    90 rotate\n");
		printf("    -72 25.4 div $a4width$ neg translate\n");
		printf("    210 297 div dup scale\n");
		printf("} bind def\n");
		printf("/$oshow$ {\n");
		/* uncomment this if you want a 'gutter' line
		  printf("    1 setlinewidth\n");
		  printf("    0 0 moveto 0 $a4height$ lineto stroke\n");
		*/
		printf("    showpage\n");
		printf("    /$first$ true store\n");
		printf("    $xlate$\n");
		printf("} bind def\n");
		printf("/showpage {\n");
		printf("    /$first$ load {\n");
		printf("\t$a4width$ 0 translate\n");
		printf("\t/$first$ false store\n");
		printf("\t} {\n");
		printf("\t$oshow$\n");
		printf("    } ifelse\n");
		printf("} bind def\n");
		printf("$xlate$\n");
	    }
	    else if (strncmp(buf,"%%Trailer",9) == 0) {
		if (page++ & 1) printf("\n$oshow$\n\n");
		copyline(buf, c);
		trail++;
	    }
	    else if (strncmp(buf, "%%Pages:", 8) == 0) {
		if (!trail) printf("%%%%Pages: (atend)\n");
	    }
	    else copyline(buf, c);
	}
    }
    printf("%%%%Pages: %d\n", page>>1);

    exit(0);
}

copyline(buf, c)
char *buf;
register char c;
{
    printf("%s", buf);
    while (c != '\n' && c != EOF) {
	putchar(c);
	c = getchar();
    }
    putchar('\n');
}

From d85-kai%nada.kth.se@unido Fri Feb 23 21:11:24 1990
Date: Fri, 23 Feb 90 20:46:23 +0100
From: d85-kai@nada.kth.se (Kai-Mikael J{{-Aro)
Message-Id: <9002231946.AAdraken14558@nada.kth.se>
To: riem@ztivax
Subject: Re: Printing two pages on one sheet
Newsgroups: comp.sys.mac,comp.lang.postscript
In-Reply-To: <904@ztivax.UUCP>
Organization: Royal Institute of Technology, Stockholm, Sweden

Mark Hahn has written a program, mpage, that does exactly this.  Would
you like me to send you a copy?
-- 
Kai-Mikael J{{-Aro	d85-kai@nada.kth.se	"NO DISASSEMBLE!" - No. 5

From d85-kai%nada.kth.se@unido Fri Mar  2 17:04:43 1990
Date: Fri, 2 Mar 90 15:10:59 +0100
From: d85-kai%nada.kth.se@unido (Kai-Mikael J{{-Aro)
Message-Id: <9003021410.AAdraken28094@nada.kth.se>
To: riem@ztivax
Subject: Printing two pages usw.

Since I wrote to you another program, multi.ps which does something similar, 
popped up.  I do not know if you have received a copy of this, so I will
send you two letters, one containing mpage and one containing multi, both
as shar archives.
Kai-Mikael J{{-Aro	d85-kai@nada.kth.se	"NO DISASSEMBLE!" - No. 5

// Sorry, program still not received

From rob%siesoft.co.uk%siesoft@sinix Wed Mar  7 12:40:12 1990
Subject: PostScript filter
Status: RO

I am currently working on the SINIX spooler project for Siemens
at SDG in England. Here is a filter which we have used for
producing twin-column landscape output. Hope this helps - there is a bug
somewhere which causes an error after the document is printed. I haven't
looked at this problem yet - you'll only see it if you have a PostScript
error handler downloaded in any case.

I don't seem to have a working shar available, so have appended the two
sources!

compile a2ps.c with cc -o a2ps -DUNIX. header.ps should go in /usr/local/lib

We have some other filters if you are interested.

Rob Henley.



8-< LONG TEXT FOLLOWS! ----------- a2ps.c ----------
/************************************************************************/
/*									*/
/* Description: Ascii to PostScript printer program.			*/
/* File: imag:/users/local/a2ps/a2ps.c					*/
/* Created: Mon Nov 28 15:22:15 1988 by miguel@imag (Miguel Santana)	*/
/* Version: 2.0								*/
/*									*/
/* Edit history:							*/
/* 1) Derived of shell program written by evan@csli (Evan Kirshenbaum).	*/
/*    Written in C for improve speed execution and portability. Many	*/
/*    improvements have been added.					*/
/*									*/
/*
/************************************************************************/

/*
 * Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
 *
 * Permission is granted to copy and distribute this file in modified
 * or unmodified form, for noncommercial use, provided (a) this copyright
 * notice is preserved, (b) no attempt is made to restrict redistribution
 * of this file, and (c) this file is not distributed as part of any
 * collection whose redistribution is restricted by a compilation copyright.
*/


#include <stdio.h>
#ifdef ANSIC
#include <time.h>
#else
#ifdef UNIX
#include <sys/time.h>
#else
#ifdef SYSV
#include <sys/types.h>
#include <sys/timeb.h>
#include <time.h>
#else
error !
#endif
#endif
#endif

#ifndef	HEADER_PS
#define	HEADER_PS	"/usr/local/lib/header.ps"
#endif

#ifndef	LINESPERPAGE
#define	LINESPERPAGE	66
#endif

#ifndef	COLUMNSPERLINE
#define	COLUMNSPERLINE	86
#endif

#define	FALSE		0
#define	TRUE		1

int fold_line();
void print_file();
char cut_line();


int column = 0;			/* Column number (in current line) */
int line = 0;			/* Line number (in current page) */
int line_number = 0;		/* Source line number */
int first_page;			/* First page for a file */
int nonprinting_chars, chars;	/* Number of nonprinting and total chars */
int prefix_width;		/* Width in characters for line prefix */
int numbering = TRUE;		/* Line numbering option */
int folding = TRUE;		/* Line folding option */
int restart = TRUE;		/* Restart page number at each file option */
int only_printable = FALSE;	/* Replace non printable char by space option */
int interpret = TRUE;		/* Interpret TAB, FF and BS chars option */
int print_binaries = FALSE;	/* Force printing for binary files */ 

char * pname;

main(argc, argv)
int argc;
char ** argv;
{
	int narg;
	char * arg;
	pname = argv[0];
	/* Option processing */
	arg = argv[narg = 1];
	while (narg < argc && arg[0] == '-')
	{
		switch (arg[1])
		{
		case 'b':
			if (arg[2] != NULL)
				goto usage;
			print_binaries = TRUE;
			break;
		case 'f':
			if (arg[2] != NULL)
				goto usage;
			folding = TRUE;
			break;
		case 'i':
			if (arg[2] != NULL)
				goto usage;
			interpret = TRUE;
			break;
		case 'n':
			if (arg[2] == NULL)
			{
				numbering = TRUE;
				break;
			}
			if (arg[3] != NULL)
				goto usage;
			switch (arg[2])
			{
			case 'b':
				print_binaries = FALSE;
				break;
			case 'f':
				folding = FALSE;
				break;
			case 'i':
				interpret = FALSE;
				break;
			case 'n':
				numbering = FALSE;
				break;
			case 'r':
				restart = FALSE;
				break;
			case 'v':
				only_printable = TRUE;
				break;
			default:
				goto usage;
			}
			break;
		case 'r':
			if (arg[2] != NULL)
				goto usage;
			restart = TRUE;
			break;
		case 'v':
			if (arg[2] != NULL)
				goto usage;
			only_printable = FALSE;
			break;
		default:
		usage:
			fprintf(stderr,
				"%s: usage: a2ps [-n{bfinrv}] [-b] [-f] [-i] [-n] [-r] [-v] [f1 f2 ... fn]\n", pname);
			exit(1);
		}
		arg = argv[++narg];
	}
	/*
	 * the next test was >=, but a2ps didn't work as a filter with
	 * no parameters.
	 */
	if (narg > argc)
		goto usage;
	/* Header printing (postcript prolog) */
	print_header();
	/* Print files designated or standard input */
	prefix_width = numbering ? 6 : 1;
	if (narg >= argc)
		print_file("stdin");
	else
	{
		while (narg < argc)
		{
			if (freopen(arg, "r", stdin) == NULL)
			{
				fprintf(stderr, "%s: Error opening %s\n", pname, arg);
				printf("cleanup\n");
				exit(1);
			}
			print_file(arg);
			arg = argv[++narg];
		}
	}
	printf("cleanup\n");
	printf("\014end\n%% \n%% End Of Job\n%% \n\004");	/* SA 23.2.89 */
}

void
print_file(name)
char *name;
{
   register int c;
   int start_line, continue_exit;
   int char_width;

   /*
    * Printing binary files is not very useful. We stop printing
    * if we detect one of these files. Our heuristic to detect them:
    * if 50% characters of first page are non-printing characters,
    * the file is a binary file.
    * Option -b force binary files impression.
    */
   first_page = TRUE;
   nonprinting_chars = chars = 0;

   /*
    * Preprocessing (before printing):
    * - TABs expansion (see interpret option)
    * - FF and BS interpretation
    * - replace non printable characters by a space or a char sequence
    *   like:
    *     ^X for ascii codes < 0x20 (X = [@, A, B, ...])
    *     ^? for del char
    *     M-c for ascii codes > 0x3f
    * - prefix parents and backslash ['(', ')', '\'] by backslash
    *   (escape character in postcript)
    */
   column = 0;
   line = line_number = 0;
   start_line = TRUE;
   printf("(%s) newfile\n", name);
   if (restart)
      printf("/sheet 1 def\n");
   printf("startpage\n");

   c = getchar();
   while (c != EOF)
   {
      /* Form feed */
      if (c == '\f' && interpret)
      {
	 if (!start_line)
	    printf(") s\n");
	 start_line = TRUE;
	 printf("endpage startpage\n");
	 if (first_page && is_binaryfile(name))
	    return;
	 line = 0;
	 if ((c = getchar()) == EOF)
	    break;
      }

      /* Start a new line? */
      if (start_line)
      {
	 if (numbering)
	    printf("(%-5d ", ++line_number);
	 else
	    printf("( ");
	 start_line = FALSE;
      }

      /* Interpret each character */
      switch (c)
      {
      case '\b':
	 if (!interpret)
	    goto print;
	 if (column > 0)
	    column--;
	 putchar(c);
	 break;
      case '\n':
	 column = 0;
	 start_line = TRUE;
	 printf(") s\n");
	 if (++line >= LINESPERPAGE)
	 {
	    printf("endpage startpage\n");
	    if (first_page && is_binaryfile(name))
	       return;
	    line = 0;
	 }
	 break;
      case '\t':
	 if (interpret)
	 {
	    continue_exit = FALSE;
	    do
	    {
	       if (++column + prefix_width > COLUMNSPERLINE)
		  if (folding)
		  {
		     if (fold_line(name) == FALSE)
			return;
		  }
		  else
		  {
		     c = cut_line();
		     continue_exit = TRUE;
		     break;
		  }
	       putchar(' ');
	    } while (column & 0x7);
	    if (continue_exit)
	       continue;
	    break;
        }
      default:
      print:
	 if (only_printable)
	    char_width = 1;
	 else
	 {
	    char_width = c > 0177 ? 2 : 0;
	    char_width += c < ' ' || c == 0177 ? 2 : 1;
	 }
	 if (prefix_width + (column += char_width) > COLUMNSPERLINE)
	    if (folding)
	    {
	       if (fold_line(name) == FALSE)
		  return;
	    }
	    else
	    {
	       c = cut_line();
	       continue;
	    }
	 if (c == '(' || c == ')' || c == '\\')
	    putchar('\\');
	 if (c >= ' ' && c < 0177)
	    putchar(c);
	 else
	 {
	    nonprinting_chars++;
	    if (only_printable)
	       putchar(' ');
	    else
	    {
	       if (c > 0177)
	       {
		  printf("M-");
		  c &= 0177;
	       }
	       if (c < ' ')
		  printf("^%c", c+'@');
	       else if (c == 0177)
		  printf("^?");
	       else
		  putchar(c);
	    }
	 }
	 chars++;
	 break;
      }
      c = getchar();
   }

   if (!start_line)
      printf(") s\n");
   printf("endpage\n");
}

int fold_line(name)
char *name;
{
   column = 0;
   printf(") s\n");
   if (++line >= LINESPERPAGE)
   {
      printf("endpage startpage\n");
      if (first_page && is_binaryfile(name))
	 return FALSE;
      line = 0;
   }
   if (numbering)
      printf("(      ");
   else
      printf("( ");

   return TRUE;
}

char cut_line()
{
   char c;

   while ((c = getchar()) != EOF && c != '\n' && c != '\f');
   return c;
}

is_binaryfile(name)
char *name;
{
   first_page = FALSE;
   if (!print_binaries && (nonprinting_chars*100 / chars) >= 75)
   {
      fprintf(stderr, "%s: %s is a binary file: printing aborted\n", pname, name);
      return TRUE;
   }
   return FALSE;
}

print_header()
{
   register int c;
   FILE *f;
   char *string;
#ifdef ANSIC
   time_t date;
#else
#ifdef UNIX
   struct timeval date;
   struct tm *p;
#else
#ifdef SYSV
    struct timeb date;
#endif
#endif
#endif

   if ((f = fopen(HEADER_PS, "r")) == NULL)
   {
      fprintf(stderr, "%s: Postscript header missing (%s)\n", pname, HEADER_PS);
      exit(1);
   }

   /* Header file printing */
   while ((c = getc(f)) != EOF)
      putchar(c);

   /* Retrieve date and hour */
#ifdef ANSIC
   if (time(&date) == -1)
   {
      fprintf(stderr, "Error calculing time\n");
      exit(1);
   }
   string = ctime(&date);

   /* and print them */
   printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
#else
#ifdef UNIX
   (void) gettimeofday(&date, (struct timezone *)0);
   p = localtime(&date.tv_sec);
   string = asctime(p);

   /* and print them */
   printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
#else
#ifdef SYSV
   (void)ftime(&date);
   string = ctime(&date.time);
   printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
#endif
#endif
#endif

   /* Go on */
   printf("startdoc\n");
}





8-< --- header.ps

%!  PostScript Source Code
%
%  File: imag:/users/local/a2ps/header.ps
%  Created: Tue Nov 29 12:14:02 1988 by miguel@imag (Miguel Santana)
%  Version: 2.0
%  Description: PostScript prolog for a2ps ascii to PostScript program.
% 
%  Edit History:
%  - Original version by evan@csli (Evan Kirshenbaum).
%  - Modified by miguel@imag to:
%    1) Correct an overflow bug when printing page number 10 (operator
%	cvs).
%    2) Define two other variables (sheetwidth, sheetheight) describing
%	the physical page (actually A4 format).
%    3) Minor changes (reorganization, comments, etc).
%

% Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
%
% Permission is granted to copy and distribute this file in modified
% or unmodified form, for noncommercial use, provided (a) this copyright
% notice is preserved, (b) no attempt is made to restrict redistribution
% of this file, and (c) this file is not distributed as part of any
% collection whose redistribution is restricted by a compilation copyright.
%


% General macros.
/xdef {exch def} bind def
/inch {72 mul} bind def
/getfont {exch findfont exch scalefont} bind def

% Dimensions of a physical page.
/sheetwidth 11.7 inch def
/sheetheight 8.25 inch def

% Character size for differents fonts.
/filenamefontsize 12 def
/datefontsize filenamefontsize 2 sub def
/headerfontsize filenamefontsize 4 add def
/bodyfontsize 6.8 def

% Font assignment to differents kinds of "objects"
/filenamefont /Helvetica-Bold filenamefontsize getfont def
/datefont /Helvetica datefontsize getfont def
/bodyfont /Courier bodyfontsize getfont def


% Logical page attributs (a half of a real page or sheet).
/linesperpage 66 def
/sidemargin 4 def
/topmargin 4 def
/pagewidth 
   bodyfont setfont (0) stringwidth pop 86 mul sidemargin dup add add
   def
/pageheight
   bodyfontsize linesperpage mul topmargin dup add add headerfontsize add
   def

% Upper corner for a logical page. Coordinate x is not the same for left
% and right pages: upperx is an array of two elements, indexed by sheetside.
/uppery sheetheight pageheight add 2 div def
/upperx [ sheetwidth pagewidth 2 mul sub 3 div	% upperx for left page
          dup 2 mul pagewidth add		% upperx for right page
        ] def

% String used to make easy printing numbers
/pnum 12 string def
/empty 12 string def


% Function startdoc: initializes printer and global variables.
/startdoc
    { sheetheight 0 inch translate	% new origin for the coordinate system
      90 rotate				% landscape format
      /sheetside 0 def			% sheet side that contains current page
      /sheet 1 def			% sheet number
    } bind def

% Function newfile: init file name and reset page number for each new file.
/newfile
    { /filename xdef
      /pagenum 1 def 
      cleanup
    } bind def

% Function cleanup: terminates printing, flushing last page if necessary.
/cleanup
    { sheetside 1 eq
         { /sheetside 0 def
           sheetnumber
           /sheet sheet 1 add def
           copypage
           erasepage
         }
      if
    } bind def

%
% Function startpage: prints page header and page border and initializes
% printing of the file lines.
/startpage
    { printheader
      printborder
      upperx sheetside get  sidemargin  add
      uppery topmargin sub  bodyfontsize  sub  headerfontsize  sub
         moveto
      bodyfont setfont
    } bind def

% Function printheader: prints page header.
/printheader
    { upperx sheetside get  uppery headerfontsize sub 1 add  moveto
      datefont setfont
      gsave
        sidemargin 2 rmoveto date show				% date/hour
      grestore
      gsave
        pagenum pnum cvs
        pagewidth sidemargin sub pnum stringwidth pop sub
        (Page ) stringwidth pop sub 3 rmoveto
        (Page ) show pnum show					% page number
      grestore
      empty pnum copy
      gsave
        filenamefont setfont
        pagewidth filename stringwidth pop sub 2 div 2 rmoveto
        filename show						% file name
      grestore
    } bind def

% Function printborder: prints border page.
/printborder 
    { upperx sheetside get uppery moveto
      gsave					% print the four sides
        pagewidth 0 rlineto			% of the square
        0 pageheight neg rlineto
        pagewidth neg 0 rlineto
        closepath stroke
      grestore
      0 headerfontsize neg rmoveto pagewidth 0 rlineto stroke
    } bind def

%
% Function endpage: adds a sheet number to the page (footnote) and prints
% the formatted page (physical impression). Activated at the end of each
% source page (linesperpage reached or FF character).
/endpage
   { sheetside 1 eq
        { /sheetside 0 def
          sheetnumber
          copypage
          erasepage 
          /sheet sheet 1 add def
        }
        { /sheetside 1 def }
     ifelse
     /pagenum pagenum 1 add def
    } bind def

% Function sheetnumber: prints the sheet number.
/sheetnumber
    { sheetwidth  upperx 0 get  sub  sidemargin  add
      sheetheight  uppery  sub  headerfontsize  sub
         moveto
      datefont setfont
      sheet pnum cvs show
      empty pnum copy
    } bind def

% Function s: print a source line
/s  { gsave
        show
      grestore
      0 bodyfontsize neg rmoveto
    } bind def