/*--------------------------------------------------------------------
 *Program (file) name:  printPS.c
 *Copyright: */
static char *last_mod = "(C) 1991-2004,2010,2012 Miroslav Kolar (18 Nov 2012 version)";
/*Purpose: To convert text files (or standard input) to PostScript.
	The output goes to standard output and may be piped directly to
	a PostScript printer (via lpr).
  The encoding of the input text can be:
	ASCII (Standard), ISO-8859-1 (Latin 1), ISO-8859-2 (Latin2) or
	ISO-8859-5 (Latin/Cyrillic)

  E.g., to print UTF-8 text file <FILE> containing a mixture of languages from
  one of these three groups, (1) West-European, (2) East-European Latin-based,
  (3) all East-European Cyrillic languages, one can do, respectively:
 (1): iconv -f UTF-8 -t LATIN1//TRANSLIT <FILE> | printPS -H -bxoff ... - | lpr
 (2): iconv -f UTF-8 -t LATIN2//TRANSLIT <FILE> | printPS -encLatin2 -H -bxoff - | lpr
 (3): iconv -f UTF-8 -t CYRILLIC//TRANSLIT <FILE> | printPS -encCyril -H -bxoff - | lpr
 [(3) will actually print a readable mixture of all three groups, but all accents
  will be missing in the Latin-based scripts.]

 *--------------------------------------------------------------------
 *Author: http://mkolar.org/
 *Originally: http://www.pangea.ca/~kolar/software/printPS.html
 *Now: http://code.mkolar.org/printPS/
 *License, no warranty - see below
 *--------------------------------------------------------------------

  Compilation:
    UNIX: cc -O -o printPS printPS.c
	  gcc -s -O3 -o printPS printPS.c
	  cc -fast -arch host -tune host -o printPS printPS.c (DIGITAL)
	  etc.
    MS C: QCL /AS /Ot printps.c
    VMS:  CC/names=AS_IS/OPTIMIZE PRINTPS.C
	  CC/names=AS_IS/OPTIMIZE/define=NO_TIME_ZONE PRINTPS.C (see below)

  Then type 'printPS -help' to get all the information about the program.

  If the time-zone part of the file's last-modification time is not desired
  as part of the file's header (or if tz name is not properly defined as
  may often be the case on VMS), compile with -DNO_TIME_ZONE option (UNIX)
  or /DNO_TIME_ZONE (MS C) or /define=NO_TIME_ZONE (VMS).
  (If you are getting incorrect (Pacific) time zone in MS C, set properly
  the TZ environment variable, e.g., set TZ=CST6CDT.)

  On VMS the case of all variables must be preserved during compilation:
  the switch /names=AS_IS must be used with DECC and VAXC compilers.

  Some stand-alone printers (e.g., Apple Laserwriter) require that a
  PostScript job be terminated with the "quit" command. In such a case,
  compile with the name QUIT_PRINTER defined (-DQUIT_PRINTER, etc.).
*/
//#define DEBUG

/* Return code:  0 = successful completion
		 1 = illegal command line options encountered
		-1 = getcwd failed
		-2 = no file processed
		-3 : DATELEN too small
		-4 : output file could not be opened (non UNIX only)

                     -----------------

LICENSE:

 1. You may copy and distribute verbatim copies of this source code as you
 receive it, in any medium, provided that you conspicuously and appropriately
 publish on each copy the following copyright notice
		Copyright  1991-2010  Miroslav Kolar 
 and keep intact the notice on all files that refer to this License Agreement
 and to the absence of any warranty; and give any other recipient of the
 program a copy of this License Agreement along with the program.

 2. You may modify your copies of this code, and copy and distribute
 such modifications under the terms of Par. 1 above, provided that you also:
  * cause the modified files to carry prominent notices stating that you
    changed the files and the date of any change; and
  * cause the whole of any work that you distribute or publish, that in whole
    or in part contains or is a derivative of this program or any part thereof,
    to be licensed at no charge to all third parties on terms identical to
    those contained in this License Agreement (except that you may choose
    to grant more extensive warranty protection to any third party,
    at your option, possibly in exchange for a fee).
  Mere aggregation of another unrelated program with this program (or its
  derivative) on a volume of storage or distribution medium does not bring
  the other program under the scope of these terms.

 3. You may copy and distribute this code (or a portion or derivative of it,
 under Par. 2) in object code or executable form under the terms of Paragraphs
 1 and 2 above provided that you also accompany it with the complete
 corresponding machine-readable source code, which must be distributed under
 the terms of Par's 1 and 2 above.

 4. You may not copy, sublicense, distribute or transfer this code except
 as expressly provided under this License Agreement. If you do so, your
 rights to use the program under this License Agreement shall be
 automatically terminated.

 ABSOLUTELY NO WARRANTY IS PROVIDED.
 THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.  SHOULD
THIS PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
SERVICING, REPAIR OR CORRECTION.
 IN NO EVENT WILL THE AUTHOR AND/OR ANY OTHER PARTY WHO MAY MODIFY AND
REDISTRIBUTE THIS PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR ANY
DAMAGES.


----------------------------------------------------------------------
Started: in 1991, using only the Standard (ASCII) encoding,
	 for the purpose of economical printing of computer programs.

Changes (further capabilities added with time):
	Dec. 1992: Option -K2 added for printing of
		multiple files on both sides of paper

	Nov. 1993: Printing of sub/superscripts added

	Nov. 1994: Header generation improved, different font for headers;
		Helvetica fonts added;
		-4port mode added

	Aug. 1995: PC (MS C) version added, with output to a  .ps  file

	Sep. 1995: Option -K2 removed, instead options -port2,
		-land2, -2land2, -4port2, -portT, -landT, -2landT,
		-4portT, -port1, -land1, -2land1, -4port1 added	to
		enable switching of one/twosided printing between files

	Nov. 1995: Output to a .ps file also in the VMS version;
		need for DCL procedures eliminated

	Apr. 1996: Made compilable under HP-UX

	May  1996: Corrected error involving a parenthesis
		following a backspace; improved treatment
		of backspacing especially for Courier fonts

	Oct. 1996: Added AvantGarde-Book font

	July 1997: Added -sson/-ssoff options to switch off
		sub/superscripts capability when needed

	May  1998: Added #ifdefs for the GNU gcc compiler

	Nov. 1998: Changed default orientation to -port2 (I got
		eyglasses and started to prefer larger letters :-));
		added DEFduplex, DEFtumble macros

	Oct. 1999: Added %%Page: line before each physical page
		to have all the pages displayed in GhostScript;
		also more code beautification done

	Mar. 2000: Y2K'd; options -y2 -yA added

	Apr. 2000: _Corrected error involving BCKSP: previously was
		not set if backspace was encountered in initial pages of
		the first file that were skipped due to -sXXX option;
		_Improved weeding out of illegal command line options;
		_More DSC comments added (but (i) psview and Ghostscript seem
		to have problems with certain page aspect ratios, different
		for each one, no matter what DSC version number X.x one
		uses for the initial %!PS-Adobe-X.x line;
		(ii) printPS was designed so that physical pages may not be
		completely independent if more than one file is processed,
		and then may not be rendered correctly when viewed in
		screen viewers in ARBITRARY order);
		_Corrected layout for extreme sizes of header/text fonts;
		_Corrected error involving line truncation within a TAB;
		_Line continuation mark printing removed if -numOn and -wr .

	July 2000: Time zone patch for CYGWIN32 gcc compiler added
		(for MS Windows 95/NT)

	April 2002: sys_errlist not awailable in Cygwin V1.1.3 ???

	November 2002: but sys_errlist awailable in Cygwin V1.3.15

	October 2004: added ISO Latin1 and ISO Latin2 encodings

	February 2010: added legal paper size; adjusted margins
		and text widths; replaced deprecated sys_errlist by strerror;
		replaced statusdict by PostScript Level 2 setpagedevice;
		added ISO-8859-5 encoding.

	November 2012: improved -help output 
----------------------------------------------------------------------*/

#if defined(MSDOS) || defined(__BORLANDC__) || defined(_MSC_VER) || defined(_Windows) || defined(_WINDOWS)
#define _PC_
#endif

#if defined(vms) || defined(VMS)
#define _VMS
#endif

#if defined(_PC_) || defined(_VMS)
#define NOTUNIX
#endif

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#ifndef _VMS
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#else
#include <types.h>
#include <stat.h>
#endif
#ifdef _PC_
#include <direct.h>
#else
#include <unistd.h>
#endif

/*---------------------------------------------------------------------------
  See the help() function or type 'printPS -help' after compilation to
  get additional information about the printPS, especially on handling
  of control characters.

 Usage on UNIX, PC:
  printPS   or   printPS -help       (to get help)
  printPS [_o_p_t_i_o_n_s] [-] _f_i_l_e [[_o_p_t_i_o_n_s] [-] _f_i_l_e ...] [-]
			                         [|lpr -P_p_r_i_n_t_e_r]
  - (if last argument) ... process standard input
  (On a PC output is put into the file 'first_file_name'.ps)

 Usage on VMS:
  Image/ProcName   or   Image/ProcName -help       (to get help)
  Image/ProcName [_o_p_t_i_o_n_s] _f_i_l_e [[_o_p_t_i_o_n_s] _f_i_l_e ...]

  options: {-A4 -LTR -LGL}
	   -s_F_i_r_s_t_p_a_g_e -e_L_a_s_t_p_a_g_e {_O_r_i_e_n_t_a_t_i_o_n} {-wr -tr} {-sson -ssoff}
	   {-dh -H_H_e_a_d_e_r -noH} {-bxon -bxoff} -fn_F_o_n_t -fh_F_o_n_t -lines_L_i_n_e_s
	   {-numon -numoff} {-Ig -Sp -Sh -ShAll} -cp_C_o_p_i_e_s {-y2 -yA}
	   {-enc_E_n_c_o_d_i_n_g_}

	     All options are in fact case-insensitive except for -H_H_e_a_d_e_r

  _O_r_i_e_n_t_a_t_i_o_n: given by the following 12 (16) options:
    One sided printing: -port1   (portrait)
			  -land1   (landscape)
			  -2land1  (two-up (2x1) landscape mode)
			  -4port1  (2x2 portrait mode)
    The same for two sided printing (flip about the long edge of paper):
			   -port2, -land2, -2land2, -4port2
    Two sided printing with flip about the short edge of paper (tumble):
			   -portT, -landT, -2landT, -4portT
    Abbreviations for the expected most frequent use:
		-port   is the same as   -port2
		-land         "          -landT
		-2land        "          -2landT
		-4port        "          -4port2
  Long lines: -tr ... truncate;  -wr ... wrap around (has effect for the
		fixed width Courier fonts only)
  -dh ... use default header made of file name and last modification time
  _H_e_a_d_e_r = user supplied header string
  -noH ... no header line printed
  -bxoff/on ... (do not) draw box around each page
  -fn ... font for the main text
  -fh ... font for headers
  Both fonts can be one of the following:
  _F_o_n_t = #   ... Courier                   (# is the height in points -
	 B#  ... Courier-Bold               an arbitrary positive number;
	 O#  ... Courier-Oblique            72 points = 1 inch)
	 BO# ... Courier-BoldOblique
	 H#   ... Helvetica
	 HB#  ... Helvetica-Bold
	 HO#  ... Helvetica-Oblique
	 HBO# ... Helvetica-BoldOblique
	 A#   ... AvantGarde-Book
  _L_i_n_e_s = maximum number of lines on each page
  -numoff/on ... (do not) print line numbers
  _C_o_p_i_e_s = number of copies to be printed
  Paper size: -A4 ; -LTR (8.5" x 11") ; -LGL (8.5" x 14")
		(must appear before 1st file name)
  Control characters: -Ig (ignore), -Sp (replace by spaces),
			-Sh (show most of them), -ShAll (show all of them)
  Sub/superscripts:   -sson/off (has effect only with -Ig, -Sp and -Sh
  _E_n_c_o_d_i_n_g_: Standard, Latin1, Latin2, Cyril
			(must appear before the 1st file name)

 Defaults: -cp1  -s1  -e0 (means print till the end of file)
	   -lines0  (calculate reasonable default for each font height)
	   -OR[DEForient]  (default orientation)
	   -dh/-H_H_e_a_d_e_r  ...  DEFheaderOn = 1
	   -noH				   ...  DEFheaderOn = 0
	   -TR[DEFtrunC]		(truncation/wrapping)
	   -CNTRL[DEFconvert]		(control character rendering)
	   -PAPER[DEFpaper]		(paper format)
	   -bxNFF[DEFbox]		(box)
	   -numNFF[DEFnumOn]		(line numbers)
	   -ssNFF[DEFssOn]		(sub/superscripts)
	   -fn'font_n_s[DEFfont]DEFheight' (for -port and -land orientations)
	   -fn'font_n_s[DEFfont]DEFaHeight' (for -2land and -4port)
	   -fh'font_n_s[DEFHfont]DEFHheight'
	   -y2  ...  DEFyear2 = 1	(last 2 digits of year in the header)
	   -yA  ...  DEFyear2 = 0	(all digits of year in the header)
           -ENC[DEFenc]			(encoding)
   'printPS' or 'printPS [-]-h[elp]'  will print the current defaults.
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 Defaults can be reset by changing the following definitions:
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#define DEFfont      0
#define DEFheight    9.
#define DEFHfont     4
#define DEFHheight   8.
#define DEFaHeight   7.
#define DEForient    0
#define DEFduplex    1
#define DEFtumble    0
#define DEFtrunC     0
#define DEFbox       1
#define DEFnumOn     0
#define DEFheaderOn  1
#define DEFconvert   0
#define DEFpaper     1
#define DEFssOn      0
#define DEFyear2     0
#define DEFenc	     1
/*
 Here the values can be: DEFfont, DEFHfont: 0 = Courier
			    /		 /    1 = Courier-Bold
			   /		/     2 = Courier-Oblique
			  /	       /      3 = Courier-BoldOblique
			text	   header     4 = Helvetica
					      5 = Helvetica-Bold
					      6 = Helvetica-Oblique
					      7 = Helvetica-BoldOblique
					      8 = AvantGarde-Book
   font heights: DEFheight (text for  -port  and  -land),
		   DEFaHeight (text for  -2land  and  -4port) and
		   DEFHheight (header)  are all in points
   DEForient: 0 = -port,  1 = -land,  2 = -2land,  3 = -4port
   DEFduplex: 0 = 1-sided printing, 1 = 2-sided printig
   DEFtumble: 0 = flip along the long side, 1 = along the short side (for duplex)
   DEFtrunC: 0 = -wr, 1 = -tr
   DEFbox: 0 = -bxon, 1 = -bxoff
   DEFnumOn: 0 = -numon, 1 = -numoff
   DEFheaderOn: 0 = -noH (only page #s),
		  1 = -dh or -H (page #s and file name or supplied header)
   DEFconvert: 0 = -Ig, 1 = -Sp, 2 = -Sh, 3 = -ShAll
   DEFpaper: 0 = -A4, 1 = -LTR, 2 = -LGL
   DEFssOn: 0 = -ssoff, 1 = -sson
   DEFyear2: 0 = -yA, 1 = -y2
   DEFenc: 0 = Standard, 1 = Latin1, 2 = Latin2, 3 = Cyrillic (ISO8859-5)

 Further examples of usage of this program under UNIX:
	printPS -4port -e5 -fnB16.5 - -a  -s3 -H graph.c  -HDATA fil3
 (prints the first 5 pages of the file -a and pages 3 to 5 of graph.c and fil3)
	printPS -LGL -2landT -fn8 code.c
 (well-readable paper-saving way to print computer code)

---------------------------------------------------------------------------*/

/* Page dimensions (in points):
 * ..WIDTH and ..HEIGHT are the dimensions of the area to be filled with text
 */
#define MARGINpX    49
#define MARGINpY    44
#define MARGINlX    44
#define MARGINlY    49
/* A4 format: */
#define A4HEIGHT   748
#define A4WIDTH    504
#define A4paperHEIGHT   841
#define A4paperWIDTH    595
/* letter (8.5" x 11"): */
#define LTRHEIGHT  698
#define LTRWIDTH   520
#define LTRpaperHEIGHT   792
#define LTRpaperWIDTH    612
/* legal (8.5" x 14"): */
#define LGLHEIGHT  914
#define LGLWIDTH   520
#define LGLpaperHEIGHT  1008
#define LGLpaperWIDTH    612

#ifdef NOTUNIX
#define PF        (void)(*printProc)(psfile,
#define PCh(x)    (void)(*putProc)(x,psfile)
#define PH        (void)fprintf(stdout,
#else
#define PF        (void)(*printProc)(stdout,
#define PCh(x)    (void)(*putProc)(x,stdout)
#define PH        (void)fprintf(stderr,
#endif

#define PE        (void)fprintf(stderr,
#define STRLEN(x) ((x) == NULL ? 0 : strlen(x))
#define ILLEGAL   {PE"%s: illegal option\n",argv[i]); illegal=1;}

#if defined(_VMS) || defined(__hpux) || defined(__CYGWIN32__) && !defined(__CYGWIN__)
#define NO_SYS_ERRLIST
#else
#if defined(ultrix) || defined(sun)
extern char *sys_errlist[];
#define FIERROR   PE" %s: %s\n",filename,sys_errlist[errno])
#else
#define FIERROR   PE" %s: %s\n",filename,strerror(errno))
#endif
#endif
#define NEWLINE   lineOnPage++; if(numOn) {if(!i_orig_line) PF"(%4d  ",\
		  currentLine); else PF"(      "); } else PCh('(')
#define TITLE	  PH"\n Program: printPS, %s\n", last_mod);

/* Global declarations:
 * ==================*/
#ifdef sun
int fprintf(), fputc();
#endif
#ifdef _VMS
extern char *getcwd();
extern int chdir();
#endif
static int null()
{ /* dummy printing procedure */
return 0;
}
static void (*BACKSP)();
static int (*putProc)(), (*printProc)();

static char
	mon[12][4] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
			   "Sep","Oct","Nov","Dec" },
	*font_n[9] =  { "Courier","Courier-Bold","Courier-Oblique",
			"Courier-BoldOblique","Helvetica","Helvetica-Bold",
			"Helvetica-Oblique","Helvetica-BoldOblique",
			"AvantGarde-Book" },
	*font_n_s[9] = { "","B","O","BO","H","HB","HO","HBO","A" },
	*OR[4] = { "port","land","2land","4port" },
	*TR[2] = { "wr","tr" },
	*NFF[2] = { "off","on" },
	*CNTRL[4] = { "Ig","Sp","Sh","ShAll" },
	*PAPER[3] = { "A4","LTR","LGL" },
	*ENC[4] = { "Standard","Latin1","Latin2","Cyril" },
	*progName;  /* to be set equal to argv[0] (or part of it) */
static int  sizeDirName = 64;
#ifdef NOTUNIX
static FILE *psfile;
static char *psName;
#endif
static FILE /*@null@*/ *infile;
static int
    font = DEFfont, Hfont = DEFHfont,
    fontChange = 0,
    convert = DEFconvert,
    paper = DEFpaper,
    firstPage = 1,
    lastPage = 0,
    orientation = DEForient,
    oldOrientation = DEForient,
    duplex = DEFduplex,
    oldDuplex = 0,
    tumble = DEFtumble,
    box = DEFbox,
    trunC = DEFtrunC,
    numOn = DEFnumOn,
    ssOn = DEFssOn,
    copies = 1,
    maxLines = 0,
    firstfile = 1, /* change to 0 after the processing of the first input
	file started (after PSprolog was written) */
    illegal = 0, /* change to 1 if an illegal/uknown option is processed */
    year2 = DEFyear2,
    enc = DEFenc, Enc; // Enc is used for the whole job, not changed between files
#define HDRLEN  200
#define DATELEN  32
static int
    hdrlenM1 = HDRLEN - 1;
static char
    header[HDRLEN],
    dateTime[DATELEN],
    *origDir,
    *suppliedHeader;
#define MAXSS 20
static int
    ssStack[MAXSS],	/* used for	  */
    ssLevel,		/* subscripts and */
    ssIgnore;		/* superscripts   */
static float
    relLetWidth = 1.;  /* when ssOn=1    */
static int
    headerFlag = 1,    /* construct default headers from file names and last
			* modification times;
			* = 0 : use user supplied headers */
    headerOn = DEFheaderOn,    /* = 1 :  header printed as specified by
				*         headerFlag;
				* = 0 :  no header al all */
    currentPage,
    currentLine,
    lineOnPage,
    linesPerPage,
    charPerLine,
    totalCharPerLine, totalCharPerHeader,
    printFlag, /* = number of processed (printed) pages  of a file
		  = 0  if  currentPage < firstPage */
    i_orig_line,   /* position of the processed character on the input line */
    truncatedChar, /* counter for truncated characters in case of the
			-tr  option */
    textHeightPhP, textHeight, textWidth,
    paperHeight, paperWidth,
    isProportnl, isHProportnl,
    noPhysPages = 0, /* number of physical pages to be printed */
    ch_prev,
    capOff = (int)'@';
static float
    lineHeight, HlineHeight,
    Height, HHeight = DEFHheight;

static void help1()
/*===============*/
{
PH"\n Usage:\n");
PH"  %s\n", progName);
PH"  %s [-]-h[elp]   (to get more extensive help)\n", progName);
#ifndef _VMS
PH"  %s [options] [-] [file [[options] [-] file ... [-]]]", progName);
#ifdef _PC_
PH"\n");
#else
PH" [| lpr -Pprinter]\n");
#endif
PH"    - (if last argument) ... process standard input\n");
PH"    - (otherwise) ... next argument is a file name (may start with a '-')\n\n");
#else
PH"  %s [options] file [[options] file ...]\n", progName);
#endif
PH"  options: {-A4 -LTR -LGL} -sFirstpage -eLastpage {-wr -tr} {-sson -ssoff}\n");
PH"           {-port  -land  -2land  -4port  -port1 -land1 -2land1 -4port1}\n");
PH"           {-port2 -land2 -2land2 -4port2 -portT -landT -2landT -4portT}\n");
PH"           {-dh -HHeader -noH} {-bxon -bxoff} -fnFont -fhFont -linesLines\n");
PH"           {-numon -numoff}  {-Ig -Sp -Sh -ShAll}  -cpCopies  {-y2 -yA}\n");
PH"           {-encEncoding}\n");
PH"  All options are case-insensitive, except for the Header string.\n\n");
}

static void help2()
/*===============*/
{
PH" Defaults: ");
if(DEFheaderOn) PH"-dh"); else PH"-noH");
PH"  -y%c  -cp1  -%s%c  -%s  -%s  -%s  -ss%s  -s1\n",
		(DEFyear2 ? '2' : 'A'), OR[DEForient],
		duplex ? (tumble ? 'T' : '2') : '1', TR[DEFtrunC],
		CNTRL[DEFconvert], PAPER[DEFpaper], NFF[DEFssOn]);
PH"           -e0 (= print till the end of file)\n");
PH"           -lines0 (= calculate reasonable default for each font height)\n");
PH"           -bx%s  -num%s  -fh%s%g  -enc%s\n", NFF[DEFbox], NFF[DEFnumOn],
		font_n_s[DEFHfont], DEFHheight, ENC[DEFenc]);
PH"           -fn%s%g  (for all  -port  and  -land)\n",
		font_n_s[DEFfont], DEFheight);
PH"           -fn%s%g  (for all  -2land  and  -4port)\n\n",
		font_n_s[DEFfont], DEFaHeight);
#ifdef _VMS
PH" Examples: The same result can be obtained with either of the two commands\n");
PH" %s -4port -e5 -fnB16.5 [-]a.pam -s3 -H [-.plot]graph.c \"-HDATA\" fil3\n",
						progName);
PH" %s -4PoRt -E5 -fNB16.5 [-]A.Pam -s3 -H [-.plot]graph.c -h\"DATA\" FIL3\n",
						progName);
PH"  (prints the first 5 pages of the file [-]a.pam and pages 3 to 5 of files\n");
PH"      [-.plot]graph.c and fil3)\n");
PH" To preserve the case of the suplied header, use quotes as above.\n");
#else
PH" Examples:\n\
 %s -port -e5 -fnB16.5 - -a -s3 -H -4port graph.c -HDATA fil3\n", progName);
PH"   (the first 5 pages of the file -a and pages 3 to 5 of graph.c and fil3)\n");
#endif
PH" %s -LGL -2landT -fn8 code.c\n", progName);
PH"   (paper-saving well-readable printout of computer code)\n");
PH" iconv -f UTF-8 -t LATIN1//TRANSLIT uni.txt | %s -H -bxoff - | lpr\n",
		progName);
PH" iconv -f UTF-8 -t LATIN2//TRANSLIT uni.txt | %s -encLatin2 ... - | lpr\n",
		progName);
PH" iconv -f UTF-8 -t CYRILLIC//TRANSLIT uni.txt | %s -encCyril ... - | lpr\n",
		progName);
PH"   (uni.txt is a UTF-8 encoded itext file containing a mixture of, respectively,\n\
   all West-European languages, all East-European Latin-based languages, and\n\
   all East-European Cyrillic languages; the last example would actually print\n\
   a readable mixture of all three groups, but with all accents missing)\n");
#ifdef _VMS 
PH"\n Output: into a file in the current directory with the extension .PS\n");
 /* On _PC_ there is no space on a standard screen for this */
#endif
}

static void shorthelp()
/*===================*/
{
help1();
help2();
}

static void help()
/*==============*/
{
char *t1, *t2;
PH"\n Purpose: To convert ASCII files to PostScript + some extensions\n");
PH" =======\n");
PH"  Up to 8 logical pages on a single sheet of paper in various formats.\n");
PH"  Arbitrary font size and number of lines per page. Control character\n");
PH"  visualization, overprinting the preceding character, and multilevel\n");
PH"  subscripts and superscripts also available.\n");
help1();
PH"  Orientation:\n");
PH"                   1-sided      2-sided printing with flip about\n");
PH"                   printing     long edge    short edge (tumble)\n");
if(DEFtumble) {t1="2  ";t2="[T]";} else {t1="[2]";t2="T  ";}
PH"   portrait:       -port1       -port%s        -port%s\n",t1,t2);
PH"   landscape:      -land1       -land%s        -land%s\n",t1,t2);
PH"   2-up landscape: -2land1      -2land%s       -2land%s\n",t1,t2);
PH"   2x2 portrait:   -4port1      -4port%s       -4port%s\n\n",t1,t2);  
PH"  Long lines: -tr ... truncate;  -wr ... wrap around  (has effect for the\n");
PH"              Courier fonts only)\n");
PH"  -dh ... use default header made of file name and Last Modification Time (LMT)\n");
PH"  -y2/A ... print only the last 2/all digits of the year of the LMT\n");
PH"  Header = user supplied header string\n");
PH"  -noH ... no header line printed\n");
PH"  -bxoff/on ... (do not) draw box around each page\n");
PH"  -fn ... font for the main text\n");
PH"  -fh ... font for headers\n");
PH"  Both fonts can be one of the following:\n");
PH"  Font = #    ... Courier                 (# is the height in points - \n");
PH"         B#   ... Courier-Bold             an arbitrary positive number;\n");
PH"         O#   ... Courier-Oblique          72 points = 1 inch)\n");
PH"         BO#  ... Courier-BoldOblique\n");
PH"         H#   ... Helvetica\n");
PH"         HB#  ... Helvetica-Bold\n");
PH"         HO#  ... Helvetica-Oblique\n");
PH"         HBO# ... Helvetica-BoldOblique\n");
PH"         A#   ... AvantGarde-Book\n");
PH"  Lines = maximum number of lines on a page\n");
PH"  -numoff/on ... (do not) print line numbers\n");
PH"  Control character rendering: -Ig ; -Sp ; -Sh ; -ShAll (see below)\n");
PH"  Sub/superscript control: -sson (enabled); -ssoff (disabled) (see below)\n");
PH"  Copies = number of copies to be printed\n");
PH"	The following two options must appear before the 1st file name:\n");
PH"  Paper size: -A4 (21 x 29.7 cm) ; -LTR (8.5\" x 11\") ; -LGL (8.5\" x 14\")\n");
PH"  Encoding: Standard ; Latin1 ; Latin2 ; Cyril\n\
       (i.e., ASCII, ISO8859-1, ISO8859-2, ISO8859-5)\n\n");
help2();
#ifdef _VMS 
PH"         For the first example above, the output file name would be A.PS\n");
#endif
#ifdef _PC_
PH"\n Output: into a file in the current directory with the extension .PS\n");
PH"         For the above example, the output file name would be -A.PS\n");
PH"         For the standard input, it would be -STDIN.PS\n");
#endif
PH"\n  Control characters are either ignored (option -Ig), or printed as\n");
PH"  spaces (option -Sp), or shown as capital letters with a caret (circumflex\n");
PH"  accent) above them (option -Sh), except for ^H, ^I, ^J, ^L, and when -sson\n");
PH"  is on, also ^^, ^_ and ^]. Backspace (^H), Tab (^I), Newline (^J) and\n");
PH"  Formfeed (^L) retain their natural functions in all three cases.\n");
PH"  When -sson is on, ^^ and ^_ can be used to mark the beginning\n");
PH"  of superscripts and subscripts, respectively, and ^] their end.\n");
PH"  Multiple-level sub/superscripts are allowed, e.g. A^^B^_c^^a^]d^_3^]^]^].\n\n");
PH"  Backspace can be used for overprinting of two or more characters\n");
PH"  (e.g. for underlining) and Formfeed for page breaks. Tabs are expanded.\n\n");
PH"  If option -ShAll is specified, all control characters will be shown\n");
PH"  and only Newline will retain its function.\n\n");
PH"  For Courier fonts, long input lines are either truncated or printed on\n");
PH"  several output lines (wrapped around). In each case, a small double\n");
PH"  right angle bracket marks the end of an unfinished line. In case of\n");
PH"  input lines that do not fit on one output line, long sequences of\n");
PH"  consecutive Backspaces may sometime not be rendered correctly (for -Ig,\n");
PH"  -Sp or -Sh only). For the proportional Helvetica and AvantGarde-Book\n");
PH"  fonts, long lines are always clipped at the right page margin.\n");
TITLE
PH" http://code.mkolar.org/printPS/\n");
}


// Defined below:
static void
	processFile(char *, int), processFileName(char *),
	PSprolog(void), addPage(void), ssLineBreak(void),
	ssCheck(int), BACKSPhel(float *i), BACKSPcour(float *i),
	convert012(FILE *), convert3(FILE *),
	startPage(int),
	CyrilEnc(void), Latin2enc(void);
static int
	makeDate(char *), makeHeader(char *), GETC(FILE *),
	posIntLen(int), lineBreak(int), pageBreak(void);

#if !defined(NO_TIME_ZONE) && defined(__CYGWIN32__)
#define tzname _tzname
#endif
 	
int main(int argc, char *argv[])
/*============================*/
{
  int  i, A1;
  char *ARG;

#if !defined(NO_TIME_ZONE) && defined(__CYGWIN32__)
{
 int tz;
 tzset();
 tz = _timezone/360; /* tz offset in hours*10 */
 if(tz == -120) {
	(void)strcpy(tzname[0],"NZST");
	(void)strcpy(tzname[1],"NZDT");
 } else if(tz == -100) {
	(void)strcpy(tzname[0],"AusEST");
	(void)strcpy(tzname[1],"AusEDT");
 } else if(tz == -95) {
	(void)strcpy(tzname[0],"AusCST");
	(void)strcpy(tzname[1],"AusCDT");
 } else if(tz == -90) {
	(void)strcpy(tzname[0],"JST");
 } else if(tz == -55) {
	(void)strcpy(tzname[0],"IndiaST");
 } else if(tz == -45) {
	(void)strcpy(tzname[0],"AfghaST");
 } else if(tz == -35) {
	(void)strcpy(tzname[0],"IranST");
	(void)strcpy(tzname[1],"IranDT");
 } else if(tz == -30) {
	(void)strcpy(tzname[0],"RussST");
	(void)strcpy(tzname[1],"RussDT");
 } else if(tz == -20) {
	(void)strcpy(tzname[0],"EEST");
	(void)strcpy(tzname[1],"EEDT");
 } else if(tz == -10) {
	(void)strcpy(tzname[0],"CEST");
	(void)strcpy(tzname[1],"CEDT");
 } else if(tz == 0) {
	(void)strcpy(tzname[0],"GMT");
	(void)strcpy(tzname[1],"GMDT");
 } else if(tz == 35) {
	(void)strcpy(tzname[0],"NewfdST");
	(void)strcpy(tzname[1],"NewfdDT");
 } else if(tz == 40) {
	(void)strcpy(tzname[0],"AtlST");
	(void)strcpy(tzname[1],"AtlDT");
 } else if(tz == 50) {
	(void)strcpy(tzname[0],"EST");
	(void)strcpy(tzname[1],"EDT");
 } else if(tz == 60) {
	if(_daylight) {
		(void)strcpy(tzname[0],"CST");
		(void)strcpy(tzname[1],"CDT");
	} else (void)strcpy(tzname[0],"SaskST");
 } else if(tz == 70) {
	(void)strcpy(tzname[0],"MST");
	(void)strcpy(tzname[1],"MDT");
 } else if(tz == 80) {
	(void)strcpy(tzname[0],"PST");
	(void)strcpy(tzname[1],"PDT");
 } else if(tz == 90) {
	(void)strcpy(tzname[0],"AlaST");
	(void)strcpy(tzname[1],"AlaDT");
 } else if(tz == 100) {
	(void)strcpy(tzname[0],"HawaiST");
 } else {
	(void)sprintf(tzname[0],"gmt%+.3g",-0.1*tz);
	if(_daylight) (void)sprintf(tzname[1],"gmt%+.3g",-0.1*tz+1);
 }
}
#endif

#if defined(_PC_) || defined(__CYGWIN__) || defined(__CYGWIN32__)
progName = strrchr(argv[0],'.');
// To hide the terminating ".EXE":
if(progName && (progName[1]=='e'||progName[1]=='E')) *progName = 0;
#endif
#ifdef _PC_
progName = strrchr(argv[0],'\\');
if(progName == NULL) progName = argv[0]; else progName++;
#elif defined(_VMS)
if((progName = strrchr(argv[0],';'))) *progName = 0;
		/* To hide the VMS version numbers */
progName = strrchr(argv[0],']');
if(progName == NULL) progName = argv[0]; else progName++;
#else
progName = strrchr(argv[0],'/');
if(progName == NULL) progName = argv[0]; else progName++;
#endif
#ifdef DEBUG
   PE"\n argv[0] = %s\n",argv[0]);
   PE" progName = %s\n",progName);
#endif

if(argc == 1) { TITLE; shorthelp(); exit(0); }
if((!strncmp(argv[1],"--h",3) || !strncmp(argv[1],"-h",2)) && argc == 2)
	{ help(); exit(0); }

while((origDir = getcwd((char *)NULL, sizeDirName)) == NULL &&
		  sizeDirName < 1024) sizeDirName += 64;
if(origDir == NULL) {
#ifdef NO_SYS_ERRLIST
	PE"Present directory pathname could not be obtained\n");
#else
	PE"Present directory: %s\n", strerror(errno));
#ifdef _PC_
	exit(-1);
#endif
#endif
}
#ifdef DEBUG
   PE" origDir = %s\n",origDir);
#endif

A1 = argc - 1;
for (i=1; i<argc; i++) {

   ARG = argv[i];
#ifdef DEBUG
   PE"\n..... processing '%s'\n",ARG);
#endif
   if(*ARG != '-') processFileName(ARG);
#ifndef _VMS
   else if(!strcmp(ARG,"-")) {
		if(i < A1) processFileName(argv[++i]);
		else	processFile("- standard input",1);
	}
#endif
   else {
     ARG++;

     /* Convert an option to lower case:
     a = ARG;
     if(*a != 'h' && *a != 'H') {
	while(*a != '\0') {
	         if(*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
	         a++;
	}
     }
     */

     if(!strcasecmp(ARG,"ig"))		convert = 0;
     else if(!strcasecmp(ARG,"sp"))		convert = 1;
     else if(!strcasecmp(ARG,"sh"))		convert = 2;
     else if(!strcasecmp(ARG,"shall"))	convert = 3;
     else if(!strcasecmp(ARG,"port"))  {orientation = 0; duplex = 1; tumble = DEFtumble;}
     else if(!strcasecmp(ARG,"land"))  {orientation = 1; duplex = 1; tumble = DEFtumble;}
     else if(!strcasecmp(ARG,"2land")) {orientation = 2; duplex = 1; tumble = DEFtumble;}
     else if(!strcasecmp(ARG,"4port")) {orientation = 3; duplex = 1; tumble = DEFtumble;}
     else if(!strcasecmp(ARG,"port1")) {orientation = 0; duplex = 0; tumble = 0;}
     else if(!strcasecmp(ARG,"land1")) {orientation = 1; duplex = 0; tumble = 0;}
     else if(!strcasecmp(ARG,"2land1")){orientation = 2; duplex = 0; tumble = 0;}
     else if(!strcasecmp(ARG,"4port1")){orientation = 3; duplex = 0; tumble = 0;}
     else if(!strcasecmp(ARG,"port2")) {orientation = 0; duplex = 1; tumble = 0;}
     else if(!strcasecmp(ARG,"land2")) {orientation = 1; duplex = 1; tumble = 0;}
     else if(!strcasecmp(ARG,"2land2")){orientation = 2; duplex = 1; tumble = 0;}
     else if(!strcasecmp(ARG,"4port2")){orientation = 3; duplex = 1; tumble = 0;}
     else if(!strcasecmp(ARG,"portt")) {orientation = 0; duplex = 1; tumble = 1;}
     else if(!strcasecmp(ARG,"landt")) {orientation = 1; duplex = 1; tumble = 1;}
     else if(!strcasecmp(ARG,"2landt")){orientation = 2; duplex = 1; tumble = 1;}
     else if(!strcasecmp(ARG,"4portt")){orientation = 3; duplex = 1; tumble = 1;}
     else if(!strcasecmp(ARG,"tr"))     trunC = 1;
     else if(!strcasecmp(ARG,"wr"))     trunC = 0;
     else if(!strcasecmp(ARG,"bxoff"))  box = 0;
     else if(!strcasecmp(ARG,"bxon"))   box = 1;
     else if(!strcasecmp(ARG,"numoff")) numOn = 0;
     else if(!strcasecmp(ARG,"numon"))  numOn = 1;
     else if(!strcasecmp(ARG,"ssoff"))  ssOn = 0;
     else if(!strcasecmp(ARG,"sson"))   ssOn = 1;
     else if(!strcasecmp(ARG,"dh"))    { headerFlag = 1; headerOn = 1; }
     else if(*ARG=='h' || *ARG=='H'){headerFlag = 0; headerOn = 1;
				     suppliedHeader = ARG + 1; }
     else if(!strcasecmp(ARG,"noh"))    headerOn = 0;
     else if(!strcasecmp(ARG,"y2"))     year2 = 1;
     else if(!strcasecmp(ARG,"ya"))     year2 = 0;
     else if(!strcasecmp(ARG,"a4"))     paper = 0;
     else if(!strcasecmp(ARG,"ltr"))    paper = 1;
     else if(!strcasecmp(ARG,"lgl"))    paper = 2;
     else if(!strncasecmp(ARG,"enc",3)) {
	if(!strcasecmp(ARG,"encStandard"))	  enc = 0;
	else if(!strcasecmp(ARG,"encLatin1")) enc = 1;
	else if(!strcasecmp(ARG,"encLatin2")) enc = 2;
	else if(!strcasecmp(ARG,"encCyril")) enc = 3;
	else {
		PE"Unsupported encoding %s\n",ARG+3);
		illegal = 1;
		break;
	}
	if(!firstfile && enc!=Enc) {
		PE"Encoding cannot be changed between files.\nPlease, process\
 files with different encodings separately.\nExiting ...\n");
		illegal = 1;
		break;
	}
     } else if(!strncasecmp(ARG,"fh",2)) {
	register float aux;
	register int HFnew;
	ARG += 2;
	if(!strncasecmp(ARG,"hbo",3))    { ARG += 3; HFnew = 7; }
	else if(!strncasecmp(ARG,"ho",2)){ ARG += 2; HFnew = 6; }
	else if(!strncasecmp(ARG,"hb",2)){ ARG += 2; HFnew = 5; }
	else if(!strncasecmp(ARG,"h",1)) { ARG++; HFnew = 4; }
	else if(!strncasecmp(ARG,"bo",2)){ ARG += 2; HFnew = 3; }
	else if(!strncasecmp(ARG,"o",1)) { ARG++; HFnew = 2; }
	else if(!strncasecmp(ARG,"b",1)) { ARG++; HFnew = 1; }
	else if(!strncasecmp(ARG,"a",1)) { ARG++; HFnew = 8; }
	else HFnew = 0;
	if((aux = atof(ARG)) > 0.) {
		HHeight = aux;
		Hfont = HFnew;
	} else ILLEGAL
     }
     else if(!strncasecmp(ARG,"fn",2)) {
	register float aux;
	register int Fnew;
	ARG += 2;
	if(!strncasecmp(ARG,"hbo",3))    { ARG += 3; Fnew = 7; }
	else if(!strncasecmp(ARG,"ho",2)){ ARG += 2; Fnew = 6; }
	else if(!strncasecmp(ARG,"hb",2)){ ARG += 2; Fnew = 5; }
	else if(!strncasecmp(ARG,"h",1)) { ARG++; Fnew = 4; }
	else if(!strncasecmp(ARG,"bo",2)){ ARG += 2; Fnew = 3; }
	else if(!strncasecmp(ARG,"o",1)) { ARG++; Fnew = 2; }
	else if(!strncasecmp(ARG,"b",1)) { ARG++; Fnew = 1; }
	else if(!strncasecmp(ARG,"a",1)) { ARG++; Fnew = 8; }
	else Fnew = 0;
	if((aux = atof(ARG)) > 0.) {
		fontChange = 1;
		Height = aux;
		font = Fnew;
	} else ILLEGAL
     }
     else if(!strncasecmp(ARG,"cp",2)) {
	register int new;
	ARG += 2;
	if((new = atoi(ARG)) > 0) copies = new; else ILLEGAL
     } else if(!strncasecmp(ARG,"lines",5)) {
	register int new;
	ARG += 5;
	if(*ARG == '0' && atoi(ARG) == 0) maxLines = 0;
	else if((new = atoi(ARG)) > 0) maxLines = new; else ILLEGAL
     } else if(!strncasecmp(ARG,"s",1)) {
	register int new;
	ARG++;
	if((new = atoi(ARG)) > 0) firstPage = new; else ILLEGAL
     } else if(!strncasecmp(ARG,"e",1)) {
	register int new;
	ARG++;
	if(*ARG == '0' && atoi(ARG) == 0) lastPage = 0;
	else if((new = atoi(ARG)) > 0) lastPage = new; else ILLEGAL
     } else ILLEGAL
   }
#ifdef DEBUG
   PE"..... end of processing '%s'\n",argv[i]);
#endif
} /* end of for */

if(illegal) PE"\n Check your command line arguments!\n");
if(firstfile) {
	PE" No file processed!\n");
	shorthelp();
	exit(-2);
}

printProc = fprintf;
#ifdef QUIT_PRINTER
PF"quit\n");
#endif
PF"%%%%Trailer\n%%%%Pages: %d\n%%%%EOF\n", noPhysPages);

#ifdef NOTUNIX
	(void)fclose(psfile);
	PE"> %s:  PostScript file created\n", psName);
#endif

if(illegal) {
	shorthelp();
	exit(1);
}

exit(0);
}


static void processFileName(char *filename)
/*=======================================*/
{
#ifdef NOTUNIX
/* Convert filename to upper case: */
char *a = filename;
while(*a != '\0') {
	if(*a > 0140 && *a < 0173) *a -= 040;
	a++;
}

#ifdef _PC_
if(strpbrk(filename,"*?") != NULL)
#else
if(strpbrk(filename,"*%") != NULL)
#endif
  { PE" %s:  wild card characters not allowed\n", filename);
    return;
  }
#endif

#ifdef DEBUG
   PE" filename = %s\n",filename);
#endif
processFile(filename, 0);
if(infile!=NULL) (void)fclose(infile);
}


static void processFile(char *filename, int inType)
/*===============================================*/
{
  int maxLinesPerPage, i;
  float headerHeight;
			/* disk file: inType = 0
			   stdin:     inType = 1 */
#ifdef NOTUNIX
if(firstfile) {
   char *pe;
   int len;
   if(inType) { psName = "-stdin"; len = 6; }
   else {
#ifdef _PC_
	psName = strrchr(filename,'\\');
#else
	psName = strrchr(filename,']');
#endif
	if(psName == NULL) psName = strrchr(filename,':');
	if(psName == NULL) psName = filename; else psName += 1;
	pe = strrchr(psName,'.');
	len = pe == NULL ? STRLEN(psName) : pe - psName;
   }
   pe = (char *)malloc((len+4)*sizeof(char));
   strncpy(pe, psName, len);
   psName = pe;
   psName[len] = 0;  /* to make sure that the filename
			extension (if present) is cut-off */
   strcat(psName,".PS");
#ifdef DEBUG
   PE" psName = %s\n",psName);
#endif
}
#endif

switch(paper) {
	case 0:
		textHeight = A4HEIGHT;
		textWidth = A4WIDTH;
		paperHeight = A4paperHEIGHT;
		paperWidth = A4paperWIDTH;
		break;
	case 1:
		textHeight = LTRHEIGHT;
		textWidth = LTRWIDTH;
		paperHeight = LTRpaperHEIGHT;
		paperWidth = LTRpaperWIDTH;
		break;
	default:
		textHeight = LGLHEIGHT;
		textWidth = LGLWIDTH;
		paperHeight = LGLpaperHEIGHT;
		paperWidth = LGLpaperWIDTH;
}
textHeightPhP = textHeight;

if(orientation == 1 || orientation == 2) { i = textHeight;
					   textHeight = textWidth;
					   textWidth = i; }
if(orientation >= 2) textWidth /= 2;
if(orientation == 3) textHeight /= 2;

isProportnl = (font_n[font][0] == 'H' || font_n[font][0] == 'A');
isHProportnl = (font_n[Hfont][0] == 'H' || font_n[Hfont][0] == 'A');

if(lastPage && lastPage < firstPage)
   { PE" Last page < first page for file '%s'!\n", filename); return; }

if(!fontChange) Height = ((orientation > 1) ? DEFaHeight : DEFheight);
headerHeight = (headerOn ? 1.4 * HHeight/Height : 0.5) + box;
if(maxLines)
   { maxLinesPerPage = textHeight / (0.85 * Height) - headerHeight;
     linesPerPage = (maxLines < maxLinesPerPage ? maxLines : maxLinesPerPage);
   }
   else linesPerPage = textHeight / (1.11 * Height) - headerHeight;
lineHeight = (float)textHeight / (linesPerPage + headerHeight);
if(lineHeight > 5. * Height) lineHeight = 5. * Height;
HlineHeight = lineHeight * HHeight/Height;
totalCharPerLine = 1.66 * textWidth / Height;
totalCharPerHeader = 1.66 * textWidth / HHeight;
charPerLine = totalCharPerLine;
if(numOn) charPerLine -= (trunC ? 6 : 5);
if(isProportnl) {
	charPerLine = 10000000;
	BACKSP = BACKSPhel;
} else {
	BACKSP = BACKSPcour;
}

#ifdef DEBUG
   PE" Before header in processfile()\n");
#endif

if(headerOn && headerFlag) {
   if(inType) { header[0] = '\0'; dateTime[0] = '\0'; }
   else if(makeDate(filename) || makeHeader(filename)) return;
} else {
#ifdef _PC_
  if(!inType) { if(makeHeader(filename)) return;
		/* Check input - output conflicts */ }
#endif
  if(headerOn) {
    (void)strncpy(header,suppliedHeader,hdrlenM1);
    header[hdrlenM1] = '\0';
  }
}

if(inType) infile = stdin;
else {
  if( (infile = fopen(filename,"r")) == NULL )
#ifdef NO_SYS_ERRLIST
	{ PE" %s: cannot be opened\n", filename); return; }
#else
	{ FIERROR; return; }
#endif

}

#ifdef DEBUG
PE" Filename: %s\n", filename);
if(headerOn) {
	PE" Header: %s\n", header);
	if(headerFlag) PE" Time: %s\n", dateTime);
} else PE" No header\n");
PE" Firstpage: %d, lastpage %d, lines per page: %d, chars per line: %d\n",
	firstPage, lastPage, linesPerPage, charPerLine);
PE" Text font: %s  %g\n", font_n[font], Height);
PE" Header font: %s  %g\n", font_n[Hfont], HHeight);
PE" -%s%c -%s -%s -bx%s -num%s -cp%d -%s\n\n", OR[orientation],
   duplex ? (tumble ? 'T' : '2') : '1', TR[trunC],
   CNTRL[convert], NFF[box], NFF[numOn], copies, PAPER[paper]);
#endif

addPage();
currentPage = 0;
currentLine = 1;
truncatedChar = 0;
printFlag = 0;
if(convert == 3) convert3(infile); else convert012(infile);
oldOrientation = orientation;
oldDuplex = duplex;

#ifdef NOTUNIX
PE"<");
#endif
PE" %s: ", filename);
if(printFlag) {
	PE" %d page", printFlag);
	if(printFlag > 1) PE"s");
	PE" of %d lines  x  %d cop", linesPerPage, copies);
	if(copies == 1) PE"y"); else PE"ies");
	PE" converted to PostScript\n");
	if(truncatedChar) {
	  for(i=0; i < strlen(filename); i++) PE" ");
		PE"    %d characters in long lines truncated\n",truncatedChar);
	   }
}
else  PE" No pages converted (file contains only %d pages)\n", currentPage);
}


static int makeDate(char *filename)
/*===============================*/
{
 struct tm *tms;
 static struct stat buf;
 int len, yer;

/* Find the time of last modification of the file to be printed: */
if(stat(filename,&buf) == -1) {
#ifdef NO_SYS_ERRLIST
  PE" %s: cannot be accessed\n", filename);
#else
  FIERROR;
#endif
  infile=NULL;
  return(1);
}
tms = localtime((time_t *)&buf.st_mtime);
yer= 1900 + tms->tm_year;
if(year2) yer= yer - (yer/100)*100;

dateTime[0] = 0;
(void)snprintf(dateTime,DATELEN,"  %02d-%s-%d %d:%02d",
   yer, mon[tms->tm_mon], tms->tm_mday, tms->tm_hour, tms->tm_min);
len = STRLEN(dateTime);
if(len > 0) {
 if(len >= DATELEN) {
   PE" Program error: Line %d: DATELEN must be increased at least to %d!\n",
			__LINE__, len + 1);
   exit(-3);
 }
#ifndef NO_TIME_ZONE
#if defined(sparc) || defined(ultrix) || defined(__osf__) || defined(_PC_)\
 || defined(SYSTEM_FIVE) || defined(sgi) || defined(_VMS) || defined(__GNUC__)
 { int LEN;
   char *TZ;
#if defined(sparc) || defined(ultrix) || defined(__osf__)
   TZ = tms->tm_zone;
#else
   TZ = tms->tm_isdst ? tzname[1] : tzname[0];
#endif
   LEN = len + 1 + STRLEN(TZ);
    if(LEN >= DATELEN) {
     PE" Program error: Line %d: DATELEN must be increased at least to %d!\n", 
			__LINE__, LEN + 1);
     exit(-3);
    }
 (void)sprintf(dateTime + len," %s", TZ);
 }
#endif
#endif
}
return(0);
}


static int makeHeader(char *filename)
/*=================================*/
{
 char /*@null@*/ *propername, *cwd;
 int len;

/* Find the full path for the file to be included into the header:   */
#ifdef _VMS
if((propername = strstr(filename,"::")) != NULL) {
	if(propername == filename) filename += 2; /* file is on the
						current machine */
	else goto Simple; /* file is on different machine; we won't
			bother with trying to find the full pathname */
} 
propername = strrchr(filename,']');
#elif defined(_PC_)
propername = strrchr(filename,'\\');
#else
propername = strrchr(filename,'/');
#endif
#ifdef NOTUNIX
if(propername == NULL) propername = strrchr(filename,':');
#endif
len = STRLEN(propername);
if(len > hdrlenM1) {
  PE" Line %d: HDRLEN should be increased at least to %d\n",__LINE__,len+1);
  PE"    to accommodate at least the proper filename\n");
}
#ifndef _VMS
#ifdef _PC_
if(filename[1] == ':' && filename[0] != origDir[0]) {
	goto Simple1;
}
#else
if(filename[0] == '/') goto Simple;
#endif
if(propername == NULL)
	{ propername = filename; header[0] = '.'; header[1] = '\0'; }
else { len = propername - filename;
#ifdef _PC_
if(len == 0) len = 1;
if(*propername == ':')
    { propername++; header[0] = '.'; header[1] = '\0'; goto Cont; }
#endif
propername++;
if(len > hdrlenM1) goto Simple;
    else { (void)strncpy(header,filename,len); header[len] = '\0'; }
#else
if(propername == NULL)
	 { propername = filename;
	   header[0] = '['; header[1] = ']'; header[2] = '\0';
	 }
else { len = ++propername - filename; /* ':' or ']' must be in */
	if(len > hdrlenM1) goto Simple;
	   else { (void)strncpy(header,filename,len); header[len] = '\0'; }
#endif
     }
#ifndef _PC_
if(origDir == NULL) goto Simple;
#else
Cont:
#endif
/* Now  header  contains pathname of the directory with the
 * processed file. We want to find out the full name of this
 * directory and thus the file. */
if(!chdir(header)) {
	cwd = getcwd((char *)NULL, HDRLEN + 1);
	if(cwd == NULL) goto Simple;
#ifdef _PC_
   if(!strcmp(cwd,origDir) && !strcmp(propername,psName)) {
	PE" %s: in conflict with the output file name\n", filename);
	return(1);
   }
#endif
#ifndef _VMS
	len = strlen(propername) + strlen(cwd) + 1;
#else
	len = strlen(propername) + STRLEN(cwd);
#endif
	if(len > hdrlenM1) {
		char *p1;
		p1 = header + hdrlenM1;
		len = strlen(propername) - 1;
		while(p1 >= header && len >= 0) *p1-- = propername[len--];
#ifndef _VMS
#ifdef _PC_
		if(p1 >= header) { *p1-- = '\\';
#else
		if(p1 >= header) { *p1-- = '/';
#endif
				   len = strlen(cwd) - 1; }
#else
		if(p1 >= header) len = strlen(cwd) - 1;
#endif
		while(p1 >= header) *p1-- = cwd[len--];
		header[0] = Enc<2 ? 0273 : 0200;
	} else { (void)strcpy(header,cwd);
#ifndef _VMS
#ifdef _PC_
		 if(header[strlen(header)-1] != '\\') (void)strcat(header,"\\");
#else
		 (void)strcat(header,"/");
#endif
#endif
		 (void)strcat(header,propername);
	}
	free(cwd);
	if(chdir(origDir))
#ifdef NO_SYS_ERRLIST
		PE" Couldn't get back to the original directory");
} else { PE"Directory  %s  not found\n", header);
#else
		perror("Couldn't get back to the original directory");
} else { PE"Directory '%s': %s\n", header, strerror(errno));
#endif
	 goto Simple;
}
return(0);

Simple:
#ifdef _PC_
{ char A = *(--propername);
  *propername = 0; /* terminate the filename temporarily after the end
		     of the directory path */
  if(!(len = chdir(filename)))
	while((cwd = getcwd((char *)NULL, sizeDirName)) == NULL &&
		sizeDirName < 1024) sizeDirName += 64;
PE"%s %d %s\n", filename, len, cwd);
  *propername++ = A; /* restore filename */
  (void)chdir(origDir);
  if( (len || cwd == NULL || !strcmp(cwd,origDir))
     && !strcmp(propername,psName) ) {
	PE" %s: in conflict with the output file name\n", filename);
	return(1);
 }
}
Simple1:
#endif
	len = strlen(filename);
	(void)strcpy(header, filename + (len>hdrlenM1 ? len-hdrlenM1 : 0));
	return(0);
}


static void PSprolog(void)
/*======================*/
{
time_t curtime = time(NULL);
struct tm *tms;
int len;
char CreationDate[DATELEN];
tms= localtime(&curtime);
len= (int)strftime (NULL, (size_t)1000., "%a, %d %b %Y %T %z", tms);
if(len >= DATELEN) {
   PE" Program error: Line %d: DATELEN must be increased at least to %d!\n",
                        __LINE__, len + 1);
   exit(-3);
}
(void)strftime (CreationDate, (size_t)DATELEN, "%a, %d %b %Y %T %z", tms);
PF"%%!PS-Adobe-3.0\n");
PF"%%%%Creator: printPS  %s\n", last_mod);
PF"%%%%CreationDate: %s\n", CreationDate);
PF"%%%%BoundingBox: 0 0 %d %d\n", paperWidth, paperHeight);
PF"%%%%DocumentData: Clean7Bit\n\
%%%%LanguageLevel: 2\n\
%%%%Pages: (atend)\n%%%%PageOrder: Ascend\n\
%%%%EndComments\n\
%%%%BeginProlog\n");
PF"0 setgray\n");
PF"/#u {dup show stringwidth pop /width exch def\n");
PF"    lineH 33 div dup setlinewidth 7.7 mul /down exch def\n");
PF"    currentpoint width neg down neg rmoveto width 0 rlineto stroke\n");
PF"    moveto} def   %% underline\n");
PF"/portrait {initmatrix %d %d translate} def\n", MARGINpX, MARGINpY + textHeightPhP);
PF"/landscape {initmatrix 90 rotate %d %d translate} def\n", MARGINlX, -MARGINlY);
PF"/#p {isBox {#b} if showpage} def     %% print page\n");
PF"/offSet 1.5 def\n");
PF"/#N {isPortrait {portrait} {landscape} ifelse\n");
PF"    isProportnl {initclip 1 setgray\n");
PF"    xLeft d moveto 0 Ym neg rlineto Xm 0 rlineto 0 Ym rlineto closepath\n");
PF"    clip newpath 0 setgray} if /line lineH neg isBox not\n");
PF"    {lineheight add} if def /leftmargin offS def leftmargin line\n");
PF"    moveto} def           %% start new page\n");
PF"/#s {show} def\n");
PF"/#B {backsp 0 rmoveto} def\n");
PF"/#S {shift 0 rmoveto} def\n");
PF"/#sB {stringwidth pop neg /backsp exch def} def\n");
PF"/#A {dup stringwidth pop (\\303) stringwidth pop sub 2 div currentpoint\n");
PF"    4 2 roll lineheight 5 div rmoveto (\\303) show 3 1 roll moveto\n");
PF"    show} def             %% prints a caret above a (capital) character\n");
PF"/#c2 {isProportnl {initclip 1 setgray xLeft Xm add d moveto 0 Ym neg rlineto\n");
PF"    Xm 0 rlineto 0 Ym rlineto closepath clip newpath 0 setgray} if\n");
PF"    /line lineH neg isBox not {lineheight add} if def\n");
PF"    /leftmargin Xm offS add def\n");
PF"    leftmargin line moveto} def   %% 2nd page of 2land or 4port\n");
PF"/#c3 {isProportnl {initclip 1 setgray xLeft d Ym sub moveto 0 Ym neg rlineto\n");
PF"    Xm 0 rlineto 0 Ym rlineto closepath clip newpath 0 setgray} if\n");
PF"    /line lineH neg Ym sub isBox not {lineheight add} if def\n");
PF"    /leftmargin offS def\n");
PF"    leftmargin line moveto} def   %% 3rd page of 4port\n");
PF"/#c4 {isProportnl {initclip 1 setgray xLeft Xm add d Ym sub moveto 0 Ym neg rlineto\n");
PF"    Xm 0 rlineto 0 Ym rlineto closepath clip newpath 0 setgray} if\n");
PF"    /line lineH neg Ym sub isBox not {lineheight add} if def\n");
PF"    /leftmargin Xm offS add def\n");
PF"    leftmargin line moveto} def   %% 4th page of 4port\n");
PF"/#  {show /line line lineheight sub def leftmargin line moveto} def\n");
PF"/#b {initclip xLeft d moveto 0 ym neg rlineto xm 0 rlineto 0 ym\n");
PF"    rlineto closepath is2land is4port or {Xm xLeft add d moveto\n");
PF"    0 ym neg rlineto} if is4port {xLeft d Ym sub moveto xm 0 rlineto} if\n");
PF"    0.5 setlinewidth stroke} def      %% draw box\n");
PF"/#wr {show forwd 0 rmoveto (\\%d) show} def   %% line continuation mark\n",
		enc<2 ? 273 : 200);
PF"/#H { currentpoint 0 lineheight 4 div translate moveto .75 .75 scale} def\n");
PF"/#h { 4 3 div dup scale currentpoint 0 lineheight 4 div neg translate moveto} def\n");
PF"/#L { currentpoint 0 lineheight 6 div neg translate moveto .75 .75 scale} def\n");
PF"/#l { 4 3 div dup scale currentpoint 0 lineheight 6 div translate moveto} def\n");
if(enc==2) Latin2enc();
else if(enc==3) CyrilEnc();
Enc=enc;
PF"%%%%BeginFeature: *PageSize\n<< /PageSize [%d %d] >> setpagedevice\n", paperWidth, paperHeight);
PF"%%%%EndFeature\n%%%%EndProlog\n");
}


static void addPage(void)
/*=====================*/
{
  if(oldDuplex &&
	(oldOrientation == 3 && (printFlag+7) % 8 < 4 ||
	 oldOrientation == 2 && (printFlag+3) % 4 < 2 ||
	 oldOrientation < 2 && printFlag % 2)
    ) {
	noPhysPages++;
	PF"%%%%Page: blank %d\nshowpage\n",noPhysPages);
  }
}


static void ssLineBreak(void)
/*=========================*/
{ int ss;

  for(ss = ssLevel; ss > 0; ss--) { if(ssStack[ss - 1] == 1) PF")#s #h(");
				    else PF")#s #l(");
				  }
}


static void ssCheck(int direction)
/*==============================*/
{
  i_orig_line++;
  if(ssLevel == MAXSS)  { if(!ssIgnore) {
			   PE"   line %d: more than %d sub/superscript",
				 currentLine, MAXSS);
			   PE" levels; additional levels ignored!\n");
			 }
			 ssIgnore++;
		       }
  else  { ssStack[ssLevel++] = direction;
	  if(direction == 1) PF")#s #H("); else PF")#s #L(");
	  relLetWidth *= 0.75;
	}
}


static void BACKSPhel(float *i)
/*===========================*/
{
 static int ch_prev_Old = (int)'m';

 PF")#s\n");
 if(ch_prev != ch_prev_Old) {
	ch_prev_Old = ch_prev;
	if((char)ch_prev == '\\') PF"(\\\\");
	else if((char)ch_prev == ')') PF"(\\)");
	else if((char)ch_prev == '(') PF"(\\(");
	else PF"(%c",(char)ch_prev);
	PF")#sB ");
 }
 /* in case of two or more consecutive backspaces, the same value of /backsp
    is used for all of them; see GETC() */
 PF"#B(");
 *i -= relLetWidth;
 i_orig_line--;
}

static void BACKSPcour(float *i)
/*============================*/
{
 PF")#s\n#B(");
 *i -= relLetWidth;
 i_orig_line--;
}


static int GETC(FILE *file)
/*=======================*/
{
 static int CH = 0;
 int ch;
 /* At the beginning of this function, CH is the unconverted last character,
    ch_prev is the converted last but one character */
 /* Get new character: */ ch = getc(file);
 if(CH == 8 && ch == ch_prev) PF")#s #S("); /* If a character is being
   overprinted by itself, we assume that one wants to produce a "bold" type
   (see HP man pages) this is achieved here by shifting the 2nd character slightly.
   In this code, the same shift is obtained even if two identical characters are
   separated by arbitrary # of backspaces. Better treatment of strings of
   backspaces would require extensive rewriting of this program: read in the
   whole line first and then to process it. */
 if(CH < 32) {
	if(convert && (CH < 8 || CH > 10) && CH != 12 && CH < 29)
				ch_prev = convert == 1 ? 32 : capOff + CH;
	// else no change 
 } else
	ch_prev = CH;
 return (CH = ch);
}


static void convert012(FILE *file)
/*==============================*/
{
  int ch, j, J;
  float i;

  ssLevel = 0;
  relLetWidth = 1.;
  ssIgnore = 0;

  i = 0.5; i_orig_line = 0;
  (void) pageBreak();
  if(!printFlag) { printProc = null; putProc = null; }
  while ( (ch = GETC(file)) !=  EOF )
    { Check:
       if(ssOn) {	
	if(ch == 30) {
		/* start superscript */
		ssCheck(1);
		continue;
	}
	if(ch == 31) {
		/* start subscript */
		ssCheck(-1);
		continue;
	}
	if(ch == 29) {
		/* end super/subscript */
		if(ssIgnore) ssIgnore--;
		else	{ if(ssStack[--ssLevel] == 1) PF")#s #h(");
			    else PF")#s #l(");
			  if(ssLevel) relLetWidth /= 0.75;
			    else relLetWidth = 1.;
			}
		i_orig_line++;
		continue;
	}
       }
       if(ch == 9)
		{ /* TAB */
		  J = 8 - i_orig_line % 8;
		  while(J > 0) { if((ch = GETC(file)) != 8) break; J--; }
		  if(J == 0) continue;
		  for (j=1;j<=J;j++) {
			PCh(' ');  i += relLetWidth; i_orig_line++;
			if(i >= charPerLine) {
				if(j == J) goto Newline;
				if(ssOn) ssLineBreak();
				if(trunC) {
					PF")#wr(");
					ssLevel = 0; ssIgnore = 0;
					relLetWidth = 1.;
					while(ch != 10) {
					  if(ch == EOF) goto CloseFile;
					  truncatedChar++;
					  ch = GETC(file);
					}
					i = 0.5;
					goto TRUNCend;
				} else if(!numOn) PF")#wr(");
				if(lineBreak(0)) goto CloseFile;
				i = 0.5;
			}
		  }
		  if(ch == EOF) goto CloseFile;
		  goto Check;
		}
       if(ch == 12)  { /* Formfeed */
			if(numOn && convert == 2) PF")#s(L)#A(");
			if((ch = GETC(file)) == EOF) goto CloseFile;
			if(pageBreak()) goto CloseFile;
			i_orig_line = 0;
			i = 0.5;
			goto Check;
		     }
       if(ch == 10)  { /* Newline */
		       if((ch = GETC(file)) == EOF) goto CloseFile;
			currentLine++; i_orig_line = 0;
			if(lineBreak(1)) goto CloseFile;
			i = 0.5;
			goto Check;
		     }
       if(ch == 8) { /* Backspace */
		     if(i_orig_line > 0) (*BACKSP)(&i);
		   }
	      else {   if((char)ch == '\\') PF"\\\\");
			else if((char)ch == ')') PF"\\)");
			else if((char)ch == '(') PF"\\(");
			else if(ch > 31) PCh((char)ch);
			else if(convert)
			        { if(convert == 1) PCh(' ');
			          else { if(ch == 28) PF")#s(\\\\)#A(");
			                 else PF")#s(%c)#A(", (char)(capOff + ch));
			               }
		   	       }
			if(ch > 31 || convert) i += relLetWidth;
		       i_orig_line++;

		   }
       if(i >= charPerLine)
	  { if((ch = GETC(file)) == 8) (*BACKSP)(&i);
	    else
	      { Newline:
		     i = 0.5;
		     if(ch == 12) {
			if(numOn && convert == 2) PF")#s(L)#A(");
			if((ch = GETC(file)) == EOF) goto CloseFile;
			if(pageBreak()) goto CloseFile;
			i_orig_line = 0;
			goto Check;
		     }
		     if(ch == 10) {
			if((ch = GETC(file)) == EOF) goto CloseFile;
			currentLine++;
			i_orig_line = 0;
			if(lineBreak(1)) goto CloseFile;
			goto Check;
		     }
		     if(ch == EOF) goto CloseFile;
		     if(ssOn) ssLineBreak();
		     if(trunC) {
		        PF")#wr(");
			ssLevel = 0; ssIgnore = 0;
			relLetWidth = 1.;
			truncatedChar++;
			while((ch = GETC(file)) != 10) {
				if(ch == EOF) goto CloseFile;
				truncatedChar++;
			}
		TRUNCend:
			i_orig_line = 0;
			ch = GETC(file);
			if(ch == EOF) goto CloseFile;
			currentLine++;
		     } else if(!numOn) PF")#wr(");
		     if(lineBreak(0)) goto CloseFile;
		     goto Check;
	      }
	  }
     }  /* end of while */
  CloseFile:
	if(printFlag) PF")#s\n#p\n");
}

static void convert3(FILE *file)
/*============================*/
{
  int ch, i;

  ssLevel = 0; /* must be set up also here for lineBreak() */

  i = i_orig_line = 0;
  (void) pageBreak();
  if(!printFlag) { printProc = null; putProc = null; }
  while ( (ch = getc(file)) != EOF ) {
   Check:
    if(ch == 10)  { PF")#s(J)#A(");
			if((ch = getc(file)) == EOF) goto CloseFile;
			currentLine++; i_orig_line = 0;
			if(lineBreak(0)) goto CloseFile;
			i = 0;
			goto Check;
		  }
    if((char)ch == '\\') PF"\\\\");
    else if((char)ch == ')') PF"\\)");
    else if((char)ch == '(') PF"\\(");
    else if(ch > 31) PCh((char)ch);
    else if(ch == 28) PF")#s(\\\\)#A(");
    else PF")#s(%c)#A(", (char)(capOff + ch));
    i++; i_orig_line++;
    if(i == charPerLine) {
	i = 0;
	if((ch = getc(file)) == 10) {
		PF")#s(J)#A(");
		if((ch = getc(file)) == EOF) goto CloseFile;
		currentLine++;
		i_orig_line = 0;
		if(lineBreak(0)) goto CloseFile;
		goto Check;
	}
	if(ch == EOF) goto CloseFile;
	if(trunC) {
		PF")#wr(");
		truncatedChar++;
		while((ch = getc(file)) != 10) {
			if(ch == EOF) goto CloseFile;
			truncatedChar++;
		}
		i_orig_line = 0;
		ch = getc(file);
		if(ch == EOF) goto CloseFile;
		currentLine++;
	} else if(!numOn) PF")#wr(");
	if(lineBreak(0)) goto CloseFile;
	goto Check;
    }
  }  /* end of while */
  CloseFile:
	if(printFlag) PF")#s #p\n");
}

static void startPage(int pagePosition)
/*===================================*/
{
static float headerShift;

if(!pagePosition && printFlag) {
	noPhysPages++;
	PF"%%%%Page: %d %d\n",currentPage,noPhysPages);
	PF"%%%%BeginPageSetup\n");
	PF"%%%%PageBoundingBox: 0 0 %d %d\n", paperWidth, paperHeight);
}
if(currentPage == firstPage) {
 PF"%% ------------------------- New file ------------------- %%\n\
%% For full page independence this setup should be repeated on each page.\n\
%% At present pages may not be viewed in arbitrary order in screen viewers.\n");
/* Old Level 1 way:
 PF"mark {statusdict begin %s setduplexmode %s settumble end} stopped\n",
	duplex ? "true" : "false", tumble ? "true" : "false");
 PF"cleartomark\n");
   replaced by the next 4 lines: */
 PF"%%%%BeginFeature: *Duplex\n\
<< /Duplex %s", duplex ? "true" : "false");
 if(duplex) PF" /Tumble %s", tumble ? "true" : "false");
 PF" >> setpagedevice\n%%%%EndFeature\n");
 if(Enc) {
	if(headerOn) { // Latin1, Latin2 and ISO8859-5 encodings
		PF"/%s findfont\n", font_n[Hfont]);
		PF"dup length dict begin\n\
	{1 index /FID ne {def} {pop pop} ifelse} forall\n\
	/Encoding %sEncoding def\n	currentdict\nend\n",
		Enc==1?"ISOLatin1":(Enc==2?"ISOLatin2":"ISOCyril"));
		PF"/%s-M exch definefont pop\n", font_n[Hfont]);
		PF"/%s-M findfont %g scalefont setfont\ncurrentfont\n",
			font_n[Hfont], HHeight);
	}
		PF"/%s findfont\n", font_n[font]);
		PF"dup length dict begin\n\
	{1 index /FID ne {def} {pop pop} ifelse} forall\n\
	/Encoding %sEncoding def\n	currentdict\nend\n",
		Enc==1?"ISOLatin1":(Enc==2?"ISOLatin2":"ISOCyril"));
		PF"/%s-M exch definefont pop\n", font_n[font]);
		PF"/%s-M findfont %g scalefont setfont\n",
			font_n[font], Height);
 } else { // Standard encoding
	if(headerOn) PF"/%s findfont %g scalefont setfont\ncurrentfont\n",
			font_n[Hfont], HHeight);
	PF"/%s findfont %g scalefont setfont\n", font_n[font], Height);
 }
 PF"/lineheight %f def\n", lineHeight);
 PF"/lineH %f def\n", headerOn ? HlineHeight : 1.5 * lineHeight);
 if(lineHeight > HlineHeight) headerShift = lineHeight;
 else headerShift = 0.9 * lineHeight + 0.35 * HlineHeight;
 if(orientation == 1 || orientation == 2) PF"/isPortrait false def\n");
	 else       PF"/isPortrait true def\n");
 if(orientation == 2) PF"/is2land true def\n");
	 else            PF"/is2land false def\n");
 if(orientation == 3) PF"/is4port true def\n");
	 else            PF"/is4port false def\n");
 if(box)  PF"/isBox true def\n");
      else   PF"/isBox false def\n");
 if(isProportnl) {
	PF"/isProportnl true def\n");
 } else {
	PF"/isProportnl false def\n");
 }
 PF"/shift (n) stringwidth pop 0.032 mul def\n");
 PF"(m) stringwidth pop dup neg /backsp exch def 7 div /forwd exch def\n");
 PF"/d2 %f def /d d2 2 div def /nd d neg def\n",
			         (Height > 20. ? 20. : Height) );
 PF"/Xm d2 %d add def /Ym d2 %d add def\n", textWidth, textHeight);
 PF"/xm Xm is2land is4port or {Xm add} if def\n");
 PF"/ym Ym is4port {Ym add} if def\n");
 PF"/xLeft nd is4port {d2 sub} if def /offS offSet is4port {d2 sub} if def\n");
 PF"/#copies %d def\n", copies);
 if(isHProportnl)  PF"/printPN true def\n");
}
if(!pagePosition && printFlag) PF"%%%%EndPageSetup\n");

if(headerOn) {
 PF"currentfont exch setfont\n");

 if(isHProportnl) {
   PF"(Page %d) stringwidth pop d2 add\n", currentPage);
   if(pagePosition)  PF"#c%d\n", pagePosition + 1);
		else PF"#N dup\n");
   PF"/PW exch def /PB leftmargin Xm add PW sub def\n");
   if(!pagePosition) {
	char *pH;
	PCh('(');
	pH = header;
	while(*pH != 0) {
		PCh(*pH);
		if(*pH++ == '\\') PCh('\\');
	}
	PF" ) stringwidth pop dup 3 1 roll add\n");
	PF"(%s) stringwidth pop add exch dup Xm\n", dateTime);
	if(currentPage == 1 && orientation == 2 && !isProportnl)
	 PF"Xm add PW sub dup 4 1 roll gt {sub d sub 0 rmoveto /printD false def}\n {pop");
	else if(currentPage == 1)
	 PF"gt {Xm sub neg d sub 0 rmoveto /printD false def}\n {");
	else
	 PF"PW sub dup 4 1 roll gt {sub d sub 0 rmoveto /printD false def}\n {pop");
	PF" pop /printD true def} ifelse\n(");
	pH = header;
	while(*pH != 0) {
		PCh(*pH);
		if(*pH++ == '\\') PCh('\\');
	}
	PF")#u printD {(%s)#u} if\n", dateTime);
	if(currentPage == 1 || !pagePosition && orientation > 1)
		PF"Xm gt {/printPN false def} if\n");
	else PF"Xm gt {1 setgray PB d sub line %f sub PW %f rectfill 0 setgray} if\n",
		0.3 * HHeight, 1.6 * HHeight);
   }
   PF"printPN {PB line moveto (Page %d)#u} if\n", currentPage);
   if(currentPage == 1 || !pagePosition && orientation > 1) PF"/printPN true def\n");
 }

 else { /* Header font is Courier: */
   int  i, pageNumPosition, iSpc, printPageNum = 1;
   char *c;

   pageNumPosition = totalCharPerHeader - 4 - posIntLen(currentPage);
				/* 4 = strlen("Page ") - 1 */
   iSpc = (HHeight > 15 ? 1 : 2*HHeight/15);
   i = iSpc + 1;  /*  We want at least  iSpc  spaces between the end of
		   *  the header and the Page number */
   if(pagePosition) PF"#c%d\n", pagePosition + 1);
   else {
	int diff = STRLEN(header) - pageNumPosition + i;
	PF"#N\n(");
	if(currentPage == 1 && diff > 0) {
		printPageNum = 0;
		if(orientation == 2 && !isProportnl) {
					diff -= totalCharPerHeader;
					pageNumPosition += totalCharPerHeader;
		}
		else {  i = 1;
			pageNumPosition = totalCharPerHeader + 1;
			diff = STRLEN(header) - totalCharPerHeader;
		}
	}
	c = header + (diff > 0 ? diff : 0);
	if(diff>0) *c = Enc<2 ? 0273 : 0200;
	while(i < pageNumPosition && *c != '\0') { PCh(*c++); i++; }
	if(headerFlag) {
		c = dateTime;
		if(c!=NULL) {
			if(i+STRLEN(c)>pageNumPosition) c++; /* skip
					one leading space in dateTime */
			while(i < pageNumPosition && *c != '\0') { PCh(*c++); i++; }
		}
	}
	PF")#u\n");
   }
   if(printPageNum) {
	i -= iSpc;
	PCh('(');
	while(i < pageNumPosition) { PCh(' '); i++; }
	PF")#s(Page %d)#u\n", currentPage);
  }
 }

 PF"/line line %f sub def leftmargin line moveto()#\n", headerShift);
 PF"currentfont exch setfont\n");
} else {
	if(pagePosition) PF"#c%d\n", pagePosition + 1);
	else PF"#N\n");
}
NEWLINE; /* starts the Postscript string '(...)' construct for the first
	  * line of text */
}

static int posIntLen(int i)
/*=======================*/
{
  int l = 1, j = 10;

  while(i > j) { j *= 10; l++; }
  return(l);
}

static int lineBreak(int ssFlag)
/*============================*/
{
  int ss;

  if(ssFlag) ssLineBreak();
  if(lineOnPage == linesPerPage) return(pageBreak());
  PF")#\n");
  NEWLINE;
  for(ss = 0; ss < ssLevel; ss++) { if(ssStack[ss] == 1) PF")#s #H(");
				    else PF")#s #L(");
				  }
  return(0);
}

static int pageBreak(void)
/*======================*/
{
  int  pagePosition;

  /* Last line is still unfinished (PostScript: not shown) at this point! */

  currentPage++;
  lineOnPage = 0;
  if(orientation == 2) pagePosition = (currentPage - firstPage) % 2;
  else if(orientation == 3) pagePosition = (currentPage - firstPage) % 4;
  else pagePosition = 0;
  if(printFlag) {
     if(lastPage && (currentPage > lastPage))
	  return(1); /* In case of this return, the current line and page will
		      * be finished after exiting from  while  loop in the
		      * procedure  convert012()  or  convert3() */
     PF")#s\n");
     if(!pagePosition) PF"#p\n");
     startPage(pagePosition);
     printFlag++;
  } else {
     if(firstPage == currentPage) {
	printFlag = 1;
	printProc = fprintf;
	putProc = fputc;
	if(firstfile) {
#ifdef NOTUNIX
	  if( (psfile = fopen(psName,"w")) == NULL ) {
#ifdef _PC_
		PE"File '%s': %s\n",psName,sys_errlist[errno]);
#else
		PE" psfile %s: cannot be opened\n", psName);
#endif
		exit(-4);
	  }
#endif
	  PSprolog();
	  firstfile = 0;
	}
	startPage(pagePosition);
     } else
	lineOnPage++;
  }
  return(0);
}


static void Latin2enc(void)
/*=======================*/
{
// Addition to standard ISOLatin2:
// For octal 200, here /.notdef is replaced by /guillemotright (>>)

PF"/ISOLatin2Encoding [\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/space		/exclam		/quotedbl	/numbersign\n\
/dollar		/percent	/ampersand	/quoteright\n\
/parenleft	/parenright	/asterisk	/plus\n\
/comma		/minus		/period		/slash\n\
/zero		/one		/two		/three\n\
/four		/five		/six		/seven\n\
/eight		/nine		/colon		/semicolon\n\
/less		/equal		/greater	/question\n\
/at		/A		/B		/C\n\
/D		/E		/F		/G\n\
/H		/I		/J		/K\n\
/L		/M		/N		/O\n\
/P		/Q		/R		/S\n\
/T		/U		/V		/W\n\
/X		/Y		/Z		/bracketleft\n\
/backslash	/bracketright	/asciicircum	/underscore\n\
/quoteleft	/a		/b		/c\n\
/d		/e		/f		/g\n\
/h		/i		/j		/k\n\
/l		/m		/n		/o\n\
/p		/q		/r		/s\n\
/t		/u		/v		/w\n\
/x		/y		/z		/braceleft\n\
/bar		/braceright	/tilde		/.notdef\n\
/guillemotright	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/space		/Aogonek	/breve		/Lslash\n\
/currency	/Lcaron		/Sacute		/section\n\
/dieresis	/Scaron		/Scedilla	/Tcaron\n\
/Zacute		/hyphen		/Zcaron		/Zdotaccent\n\
/degree		/aogonek	/ogonek		/lslash\n\
/acute		/lcaron		/sacute		/caron\n\
/cedilla	/scaron		/scedilla	/tcaron\n\
/zacute		/hungarumlaut	/zcaron		/zdotaccent\n\
/Racute		/Aacute		/Acircumflex	/Abreve\n\
/Adieresis	/Lacute		/Cacute		/Ccedilla\n\
/Ccaron		/Eacute		/Eogonek	/Edieresis\n\
/Ecaron		/Iacute		/Icircumflex	/Dcaron\n\
/Eth		/Nacute		/Ncaron		/Oacute\n\
/Ocircumflex	/Ohungarumlaut	/Odieresis	/multiply\n\
/Rcaron		/Uring		/Uacute		/Uhungarumlaut\n\
/Udieresis	/Yacute		/Tcedilla	/germandbls\n\
/racute		/aacute		/acircumflex	/abreve\n\
/adieresis	/lacute		/cacute		/ccedilla\n\
/ccaron		/eacute		/eogonek	/edieresis\n\
/ecaron		/iacute		/icircumflex	/dcaron\n\
/eth		/nacute		/ncaron		/oacute\n\
/ocircumflex	/ohungarumlaut	/odieresis	/divide\n\
/rcaron		/uring		/uacute		/uhungarumlaut\n\
/udieresis	/yacute		/tcedilla	/dotaccent\n\
]	def\n");
}


static void CyrilEnc(void)
/*======================*/
{
// Addition to standard ISO-8859-5:
// For octal 200, here /.notdef is replaced by /guillemotright (>>)

PF"/ISOCyrilEncoding [\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/space		/exclam		/quotedbl	/numbersign\n\
/dollar		/percent	/ampersand	/quoteright\n\
/parenleft	/parenright	/asterisk	/plus\n\
/comma		/minus		/period		/slash\n\
/zero		/one		/two		/three\n\
/four		/five		/six		/seven\n\
/eight		/nine		/colon		/semicolon\n\
/less		/equal		/greater	/question\n\
/at		/A		/B		/C\n\
/D		/E		/F		/G\n\
/H		/I		/J		/K\n\
/L		/M		/N		/O\n\
/P		/Q		/R		/S\n\
/T		/U		/V		/W\n\
/X		/Y		/Z		/bracketleft\n\
/backslash	/bracketright	/asciicircum	/underscore\n\
/quoteleft	/a		/b		/c\n\
/d		/e		/f		/g\n\
/h		/i		/j		/k\n\
/l		/m		/n		/o\n\
/p		/q		/r		/s\n\
/t		/u		/v		/w\n\
/x		/y		/z		/braceleft\n\
/bar		/braceright	/tilde		/.notdef\n\
/guillemotright	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/.notdef	/.notdef	/.notdef	/.notdef\n\
/space		/afii10023	/afii10051	/afii10052\n\
/afii10053	/afii10054	/afii10055	/afii10056\n\
/afii10057	/afii10058	/afii10059	/afii10060\n\
/afii10061	/hyphen		/afii10062	/afii10145\n\
/afii10017	/afii10018	/afii10019	/afii10020\n\
/afii10021	/afii10022	/afii10024	/afii10025\n\
/afii10026	/afii10027	/afii10028	/afii10029\n\
/afii10030	/afii10031	/afii10032	/afii10033\n\
/afii10034	/afii10035	/afii10036	/afii10037\n\
/afii10038	/afii10039	/afii10040	/afii10041\n\
/afii10042	/afii10043	/afii10044	/afii10045\n\
/afii10046	/afii10047	/afii10048	/afii10049\n\
/afii10065	/afii10066	/afii10067	/afii10068\n\
/afii10069	/afii10070	/afii10072	/afii10073\n\
/afii10074	/afii10075	/afii10076	/afii10077\n\
/afii10078	/afii10079	/afii10080	/afii10081\n\
/afii10082	/afii10083	/afii10084	/afii10085\n\
/afii10086	/afii10087	/afii10088	/afii10089\n\
/afii10090	/afii10091	/afii10092	/afii10093\n\
/afii10094	/afii10095	/afii10096	/afii10097\n\
/afii61352	/afii10071	/afii10099	/afii10100\n\
/afii10101	/afii10102	/afii10103	/afii10104\n\
/afii10105	/afii10106	/afii10107	/afii10108\n\
/afii10109	/section	/afii10110	/afii10193\n\
]	def\n");
}
