[alt.sources] i2ps, version 1.7

aas@boeygen.nr.no (Gisle Aas) (10/31/90)

This is the newest version of the i2ps perl script. You need perl 3.0
patchlevel 36 or better.  Again; bug reports, complains, suggestions
are welcome!  My email address is <Gisle.Aas@nr.no>.

-----------cut here---------------------------------------
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 10/30/1990 16:17 UTC by aas@boeygen
# Source directory /home/boeygen/aas/Bin
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#  17974 -r-xr-xr-x i2ps
#
# ============= i2ps ==============
if test -f 'i2ps' -a X"$1" != X"-c"; then
	echo 'x - skipping i2ps (File already exists)'
else
echo 'x - extracting i2ps (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'i2ps' &&
#!/local/boeygen/bin/perl
'di';
'ig00';
X
# "i2ps" text to PostScript filter written in perl by Gisle Aas, NCC 1990
# $Id: i2ps,v 1.7 90/10/30 16:54:46 aas Exp $
#
# Whish list:  (this may become a feature some time)
#     Marking (by some funny char) truncation and wrapping of lines
#     Faster execution (rewrite the hole thing in C?)
#     Parsing of backspace to produce bold and underlined fonts.
X
#
# $Log:	i2ps,v $
# Revision 1.7  90/10/30  16:54:46  aas
# Options can be specified with the environment variable I2PS.
# New option -w.  Fixed bug which made -n option act like the -f
# option.
# 
# Revision 1.6  90/10/24  12:00:43  aas
# Applied patch from Tor Lillqvist. I2ps now supports finnish/swedish
# ISO-646.
# 
# Revision 1.5  90/10/18  10:26:45  aas
# Changed the name from a2ps to i2ps. Merged the manual-page with the
# program. I2ps now rejects garbage files. I2ps was confused about what
# to put in the header when some of the specified files did not exist.
# Some minor spelling corrections.
# 
# Revision 1.4  90/10/01  15:57:46  aas
# Simplify reencoding to ISO-Latin1. (newencode)
# Fixed problem with showpage after page level restore. Graphic state
# initialized on each page. Included the ISOLatin1Encoding-vector
# in the script. Linenumber on last line when the -l option is used.
# Linenumbers are moved to the left margin.
# 
# Revision 1.3  90/09/27  14:05:31  aas
# Cleaned up the use of A4 variables.
# 
# Revision 1.2  90/09/27  13:18:31  aas
# Removed sccs-stuff, replaced it with rcs-stuff.
# 
X
# Some configuration constants, meassured in points (1/72 inch)
sub page_top        { 841; }    # A4 = 297mm x 210mm = 841pt x 595pt
sub page_right_edge { 595; }
# Uncomment next line if your printer doesn't have iso encoding builtin.
#$isoencoding_not_builtin = 1; #true
X
# The next few entries are from the AFM file for Adobe's font Courier
sub cour_char_width     { 600; }   # The width of each char in 1000x1000 square
#sub underline_position  { -82; }   # Where underline goes relative to baseline
#sub underline_thickness {  40; }   # and it's thickness
X
# Parse command line for options and flags
$prog_name = substr($0,rindex($0,"/")+1);
($upcase_name = $prog_name) =~ tr/a-z/A-Z/;
unshift(@ARGV,$ENV{$upcase_name}) if defined($ENV{$upcase_name});
require 'getopts.pl';
unless (&Getopts('nfrth123s:b:lgw:')) {
X   print STDERR
X        "Usage: $prog_name [-<options>] [file]...\n" .
X        "Options: -l        print with line numbers\n" .
X        "         -r        rotated, landscape orientation\n" .
X        "         -t        truncate long lines, default is to wrap lines\n" .
X        "         -b\"text\"  replaces the text in the page header\n" .
X        "         -h        no page headers\n" .
X        "         -2        set text in two columns format\n" .
X        "         -3        set text in three columns format\n" .
X        "         -s<size>  select new text fontsize, default 10pt\n" .
X        "         -w<width> char positions per column\n" .
X        "         -g        don't reject garbage files\n" .
X        "         -n        norwegian 7bit-ascii encoding\n" .
X        "         -f        finnish/swedish 7bit-ascii encoding\n";
X   exit(1);
}
X
if (defined($opt_s) && $opt_s <= 0) {
X   printf STDERR "Illegal argument \"$opt_s\" to -s option\n";
X   exit(1);
}
if (defined($opt_w) && $opt_w <= 0) {
X   printf STDERR "Illegal argument \"$opt_w\" to -w option\n";
X   exit(1);
}
X
# Set default values, some based on command line options
$left_margin  = 80;
$right_margin = 40;
$tb_margin    = 45;
$font         = "Courier";
$header_font  = "Helvetica-Bold";
$header_font_size = 12;
$line_number_font = "Helvetica";
$line_number_size = 5;
X
$no_columns = defined($opt_2) ? 2 : defined($opt_3) ? 3 : 1;
$col_separation = 30;
$sep_bars = 0;  # false
$landscape = defined($opt_r);
$header_height = 30;
$show_header = !defined($opt_h);
$wrap_lines = !defined($opt_t);
$truncate_lines = !$wrap_lines; # don't change this
$norsk_ascii = defined($opt_n);
$sw_fi_ascii = defined($opt_f);
X
# Some initial values
$opt_b = &ps_string($opt_b) if ($opt_b);
$form_feed = 0; # false;
$page_no  = 0;
$line_no = 0;
if ($landscape) {
X    $top = &page_right_edge;
X    $right_edge = &page_top;
X    $left_margin = $right_margin; # this is a dirty one
} else {
X    $top = &page_top;
X    $right_edge = &page_right_edge;
}
$home_pos = $top - $tb_margin - ($show_header ? $header_height : 0);
$col_width = ($right_edge - $left_margin - $right_margin
X              - ($no_columns - 1) * $col_separation) / $no_columns;
$font_size    = $opt_s || 10;
if (defined($opt_w)) {
X    $font_size = ($col_width / $opt_w) / (&cour_char_width / 1000);
X    printf STDERR "New font size is %.2g points\n", $font_size;
}
$line_height = $font_size * 1.08;
$char_width = &cour_char_width * $font_size / 1000;
$chars_per_line = int ($col_width / $char_width + 1);
X
&prolog;
X
unshift(@ARGV,'-') if $#ARGV < $[;
FILE:
while ($FILEHAND = shift) {
X    unless (open(FILEHAND)) {
X        print STDERR "Can't open \"$FILEHAND\"\n";
X        next FILE;
X    }
X    if (!defined($opt_g) && -B FILEHAND) {
X        print STDERR "Skipping binary file \"$FILEHAND\"\n";
X        close(FILEHAND);
X        next FILE;
X    }
X    $file_name = ($FILEHAND eq '-') ? '' : &ps_string($FILEHAND);
X    $cur_pos = -1;     # this will force a new column next time
X    $cur_col = 100;    # this will force a new page next time
X    $line_no = 0;
X    LINE:
X    while (<FILEHAND>) {
X        chop;
X        $line_no++;
X        if (ord == 014) {		# form feed
X            s/.//;	# chop off first char
X            $cur_pos = -1; 
X            next LINE if (length == 0);
X        }
X        while (s/\t/' ' x (8 - length($`) % 8)/e) {}   # expand tabs
X        do {
X            if ($cur_pos < $tb_margin) {
X                $cur_pos = $home_pos;
X                if ($cur_col < $no_columns) {
X                     $cur_col++;
X                } else {
X                     $cur_col = 1;
X                     &new_page;
X                }
X            }
X            $text = substr($_,0,$chars_per_line);
X            $_ = $truncate_lines ? '' : substr($_,$chars_per_line,10000);
X            if ($text =~ s/^ +//) {		# suppress leading blanks
X                $indent = $char_width * length($&);
X            } else {
X                $indent = 0;
X            }
X            # Make suitable as a postscript string, same as calling
X            # "ps_string", but the overhead of calling a function is
X            # not acceptable here.
X            $text =~ s/[\\\(\)]/\\$&/g;
X            $text =~ s/[\000-\037\177-\377]/sprintf("\\%03o",ord($&))/ge;
X            # Calculate position
X            $x = $left_margin +
X		 ($cur_col - 1) * ($col_width + $col_separation);
X            $cur_pos -= $line_height;
X            printf "(%s)%.1f %.1f S\n", $text, $x + $indent, $cur_pos 
X                if (length($text));
X            if ($opt_l && (($line_no % 5) == 0 || eof)) { # print line numbers
X                 printf "F2 SF($line_no)%.1f %.1f S F1 SF\n",
X                        $x + $col_width + 5, $cur_pos;
X            }
X        } while (length($_));
X    } # while (each line)
} # while (each file)
&end_page;
print "%%Trailer\n";
print "%%Pages: $page_no\n";
# printf "($prog_name: $page_no page%s for $user\n) print\n",
#     $page_no != 1 ? "s" : "";
X
#--end of main-------------------------------------------------------
X
X
sub prolog {
X   $user = getlogin || "(unknown)";
X   local($sec,$min,$hour,$mday,$mon,$year) = localtime;
X   $date = sprintf("(%s %d, %d) (%2d:%02d)",
X                    ('January','February','March','April','May','June',
X                     'July','August','October','November','Desember')[$mon],
X                     $mday, $year+1900, $hour,$min);
X   print "%!PS-Adobe-2.0\n";
X   print "%%Title: @ARGV\n" if (@ARGV);
X   print <<"EOT";
%%Creator: $prog_name, Text to PostScript filter in perl, (C) 1990 Gisle Aas, NCC
%%CreationDate: $date
%%For: $user
%%Pages: (atend)
EOT
X   print "%%DocumentFonts: $font";
X   print " $line_number_font" if ($opt_l);
X   print " $header_font" if ($show_header);
X   print "\n";
X   print <<"EOT";
%%EndComments
/S{moveto show}bind def
/M/moveto load def
/L/lineto load def
/SF/setfont load def
EOT
X    print <<"EOT" if ($isoencoding_not_builtin && !($norsk_ascii || $sw_fi_ascii));
ISOLatin1Encoding where { pop } { ISOLatin1Encoding
[/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright
/parenleft/parenright/asterisk/plus/comma/minus/period/slash/zero/one
/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal
/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S
/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum
/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s
/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde/.notdef/.notdef
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/dotlessi/grave
/acute/circumflex/tilde/macron/breve/dotaccent/dieresis/.notdef/ring
/cedilla/.notdef/hungarumlaut/ogonek/caron/space/exclamdown/cent
/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine
/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus
/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla
/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters
/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae
/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex
/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide
/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]
def %ISOLatin1Encoding
} ifelse
EOT
X    print <<"EOT" if ($norsk_ascii || $sw_fi_ascii);
%%BeginProcSet: reencode 1.0 0
/RE { %def
X   findfont begin
X   currentdict dup length dict begin
X      { %forall
X         1 index/FID ne {def} {pop pop} ifelse
X      } forall
X      /FontName exch def
X      dup length 0 ne { %if
X         /Encoding Encoding 256 array copy def
X         0 exch { %forall
X            dup type /nametype eq { %ifelse
X               Encoding 2 index 2 index put
X               pop 1 add
X            }{%else
X               exch pop
X            } ifelse
X         } forall
X      } if pop
X      currentdict dup
X   end
X   end
X   /FontName get exch definefont pop
} bind def
%%EndProcSet: reencode 1.0 0
EOT
X   print <<"EOT" if (!($norsk_ascii || $sw_fi_ascii));
%%BeginProcSet: newencode 1.0 0
/NE { %def
X   findfont begin
X      currentdict dup length dict begin
X         { %forall
X            1 index/FID ne {def} {pop pop} ifelse
X         } forall
X         /FontName exch def
X         /Encoding exch def
X         currentdict dup
X      end
X   end
X   /FontName get exch definefont pop
} bind def
%%EndProcSet: newencode 1.0 0
EOT
X   print "%%EndProlog\n%%BeginSetup\n";
X   if ($norsk_ascii || $sw_fi_ascii) {
X      print "[8#133 /AE/Oslash/Aring 8#173 /ae/oslash/aring] dup\n"
X	if ($norsk_ascii);
X      print "[8#133 /Adieresis/Odieresis/Aring" .
X            " 8#173 /adieresis/odieresis/aring] dup\n"
X	if ($sw_fi_ascii);
X      print "/$font-ISO/$font RE\n";
X      print "/$header_font-ISO/$header_font RE\n" if ($show_header);
X   } else {
X      print "ISOLatin1Encoding /$font-ISO/$font NE\n";
X      print "ISOLatin1Encoding /$header_font-ISO/$header_font NE\n"
X         if ($show_header);
X   }
X   printf "/F1/$font-ISO findfont %.2g scalefont def\n", $font_size;
X   print "/F2/$line_number_font findfont $line_number_size scalefont def\n"
X        if ($opt_l);
X   print "/F3/$header_font-ISO findfont $header_font_size scalefont def\n"
X        if ($show_header);
X   print "F1 SF\n";
X   print "%%EndSetup\n";
}
X
X
X
sub new_page {
X   &end_page unless ($page_no == 0);
X   $page_no++;
X   print "%%Page: $page_no $page_no\n";
X   print "%%BeginPageSetup\n";
X   print "/page_save save def\n";
X   printf "90 rotate 0 -%d translate %% landscape mode\n",&page_right_edge
X      if ($landscape);
X   print "0.15 setlinewidth\n" if ($show_header);
X   print "%%EndPageSetup\n";
X   if ($show_header) {
X      # First print a box
X      local($llx,$lly,$urx,$ury) = ($left_margin - 10,
X            $top - $tb_margin - $header_font_size * 1.3,
X            $right_edge - $right_margin + 10, $top - $tb_margin);
X      printf "%.1f %.1f M %.1f %.1f L %.1f %.1f L ",
X             $llx,$lly, $urx,$lly, $urx, $ury;
X      printf "%.1f %.1f L closepath \n",$llx,$ury;
X      print  "gsave .95 setgray fill grestore stroke\n";
X      # Then the banner or the filename
X      print "F3 SF\n";
X      if ($opt_b) {
X         printf "($opt_b)%.1f %.1f S\n",
X                $left_margin,$top - $tb_margin - $header_font_size;
X      }
X      elsif ($file_name) {
X         printf "(%s)%.1f %.1f S\n", $file_name, 
X                      $left_margin,
X                      $top - $tb_margin - $header_font_size;
X      }
X      # Then print page number
X      printf "%.1f %.1f M($page_no)dup stringwidth pop neg 0 rmoveto show\n",
X                 $right_edge - $right_margin, 
X                 $top - $tb_margin - $header_font_size;
X      print  "F1 SF\n";
X   }
X   if ($sep_bars) {
X      print "% Some postscript code to draw horizontal bars.\n";
X      print "% Not implemented yet\n";
X   }
}
X
sub end_page {
X   unless ($page_no == 0) {
X      print "page_save restore\n";
X      print "showpage\n";
X   }
}
X
sub ps_string
{
X   # Prepare text for printing
X   local($_) = shift;
X   s/[\\\(\)]/\\$&/g;
X   s/[\001-\037\177-\377]/sprintf("\\%03o",ord($&))/ge;
X   $_;    # return string
}
X
X
###########################################################################
X	# These next few lines are legal in both Perl and nroff.
X
.00;			# finish .ig
X 
'di			\" finish diversion--previous line must be blank
.nr nl 0-1		\" fake up transition to first page again
.nr % 0			\" start at page 1
';<<'.ex'; #__END__ #### From here on it's a standard manual page #########
.TH I2PS 1 "October 1990"
.SH NAME
i2ps \- convert ISO Latin1 text to PostScript
.SH SYNOPSIS
.B i2ps
[
.B \-nflrth23g
] [
.B \-b
.I "text"
] [
.B \-s
.I size
] [
.B \-w
.I width
] [
.I filename
\&.\|.\|.
]
.SH DESCRIPTION
The
.B i2ps
program is used to print simple
text files (e.g. program listings) on a PostScript\*R device. 
The name
.B i2ps
stands for iso-to-postscript.  The program handles the whole
ISO Latin1 (ISO 8859/1) character set. 
Efforts have been made to ensure that 
.B i2ps
produces good looking and effective PostScript code.
The output conforms to Adobe's
document structuring conventions (version 2.1). The 
.B i2ps 
program
assumes that the page format on the output device is A4. 
(Change the definitions of &page_top and &page_right_edge if you
want something else.)
The meaning of form feed (^L) characters in the input stream is understood.
.PP
The
.B i2ps
program is written in
.I perl.
So if there is something you don't like about how
.B i2ps
works, you can "easily" fix it yourself.
.SH OPTIONS
.TP 5
.B \-n
use the norwegian version of ISO 646 (7-bit ascii) to encode the text.
Norwegian letters will replace the left/right braces, left/right
brackets, backslash and horizontal bar characters.
.TP 5
.B \-f
use the finnish/swedish version of ISO 646.  Like
.BR \-n ,
but instead of the AE ligature and slashed-O you get a and o with two dots.
.TP 5
.B \-l
produces line numbers on each 5'th and the last line.
Nice for program listings.
.TP 5
.B \-t
truncate lines that are to long. The default is to wrap
long lines so that they continue on the next line on the printed output.
.TP 5
.B \-r
rotate the output page 90 degrees. This is called
.I landscape
mode by some people.
.TP 5
.B \-h
suppress generation of page headers.
.TP 5
.B \-2
use two column format.
.TP 5
.B \-3
use three column format.
.TP 5
.BI \-b " text"
the 
.I text
parameter replaces the default text in the header of the pages.
The default text is the filename of the file to be printed. There is no
default if the text comes from standard input.
.TP 5
.BI \-s " size"
specifies a new font size for the body text. The default is 10 point.
.TP 5
.BI \-w " width"
specifies the number of characters per line. This is just another way
of specifying the font size for the body text.  
The w-option takes precedence over the
s-option if both are present.
.TP 5
.B \-g
eat garbage.  The
.B i2ps 
program normally skips binary files. This option means "print it anyway".
.SH ENVIRONMENT
.IP \fBI2PS\fP 10
Options may also be specified with the environment variable "I2PS".
The environment variable is parsed before the command line, so
command line options override the environment variable.
.SH EXAMPLES
To print files on a PostScript printer:
.nf
X    i2ps -l *.[ch] | lpr
.fi
.PP
To find out how many pages i2ps will produce for a given file:
.nf
X    i2ps file.txt | tail -1
.fi
.PP
Our printer stacks the pages the wrong way. To fix it try:
.nf
X    i2ps -2r -w80 file.txt | psrev | lpr
.fi
.SH SEE ALSO
.BR perl (1),
.BR enscript (1),
.BR psrev (1),
.BR ISO8859 (7),
.BR PostScript (7)
.SH BUGS
There is no easy way to change the margins or the fonts that
.B i2ps
insists on using.
The
.B i2ps
filter ought to understand the meaning of the backspace character. It is used
to produce boldfaced and underlined text by programs like 
.BR nroff (1).
.PP
If the you change the name of the file where
.B i2ps
lives, then you must change the name of the I2PS environment variable likewise.
.SH AUTHOR
Gisle Aas, Norwegian Computing Center (NR), Oslo, Norway.
<Gisle.Aas@nr.no>
.ex
SHAR_EOF
chmod 0555 i2ps ||
echo 'restore of i2ps failed'
Wc_c="`wc -c < 'i2ps'`"
test 17974 -eq "$Wc_c" ||
	echo 'i2ps: original size 17974, current size' "$Wc_c"
fi
exit 0
--
Gisle Aas               |  snail: Boks 114 Blindern, N-0314 Oslo, Norway
Norsk Regnesentral      |  X.400: G=Gisle;S=Aas;O=nr;P=uninett;C=no
voice: +47-2-453561     |  inet:  Gisle.Aas@nr.no