home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2022 / i2ps
Encoding:
Text File  |  1990-12-28  |  17.6 KB  |  545 lines

  1. #!/local/boeygen/bin/perl
  2. 'di';
  3. 'ig00';
  4.  
  5. # "i2ps" text to PostScript filter written in perl by Gisle Aas, NCC 1990
  6. # $Id: i2ps,v 1.7 90/10/30 16:54:46 aas Exp $
  7. #
  8. # Whish list:  (this may become a feature some time)
  9. #     Marking (by some funny char) truncation and wrapping of lines
  10. #     Faster execution (rewrite the hole thing in C?)
  11. #     Parsing of backspace to produce bold and underlined fonts.
  12.  
  13. #
  14. # $Log:    i2ps,v $
  15. # Revision 1.7  90/10/30  16:54:46  aas
  16. # Options can be specified with the environment variable I2PS.
  17. # New option -w.  Fixed bug which made -n option act like the -f
  18. # option.
  19. # Revision 1.6  90/10/24  12:00:43  aas
  20. # Applied patch from Tor Lillqvist. I2ps now supports finnish/swedish
  21. # ISO-646.
  22. # Revision 1.5  90/10/18  10:26:45  aas
  23. # Changed the name from a2ps to i2ps. Merged the manual-page with the
  24. # program. I2ps now rejects garbage files. I2ps was confused about what
  25. # to put in the header when some of the specified files did not exist.
  26. # Some minor spelling corrections.
  27. # Revision 1.4  90/10/01  15:57:46  aas
  28. # Simplify reencoding to ISO-Latin1. (newencode)
  29. # Fixed problem with showpage after page level restore. Graphic state
  30. # initialized on each page. Included the ISOLatin1Encoding-vector
  31. # in the script. Linenumber on last line when the -l option is used.
  32. # Linenumbers are moved to the left margin.
  33. # Revision 1.3  90/09/27  14:05:31  aas
  34. # Cleaned up the use of A4 variables.
  35. # Revision 1.2  90/09/27  13:18:31  aas
  36. # Removed sccs-stuff, replaced it with rcs-stuff.
  37.  
  38. # Some configuration constants, meassured in points (1/72 inch)
  39. sub page_top        { 841; }    # A4 = 297mm x 210mm = 841pt x 595pt
  40. sub page_right_edge { 595; }
  41. # Uncomment next line if your printer doesn't have iso encoding builtin.
  42. #$isoencoding_not_builtin = 1; #true
  43.  
  44. # The next few entries are from the AFM file for Adobe's font Courier
  45. sub cour_char_width     { 600; }   # The width of each char in 1000x1000 square
  46. #sub underline_position  { -82; }   # Where underline goes relative to baseline
  47. #sub underline_thickness {  40; }   # and it's thickness
  48.  
  49. # Parse command line for options and flags
  50. $prog_name = substr($0,rindex($0,"/")+1);
  51. ($upcase_name = $prog_name) =~ tr/a-z/A-Z/;
  52. unshift(@ARGV,$ENV{$upcase_name}) if defined($ENV{$upcase_name});
  53. require 'getopts.pl';
  54. unless (&Getopts('nfrth123s:b:lgw:')) {
  55.    print STDERR
  56.         "Usage: $prog_name [-<options>] [file]...\n" .
  57.         "Options: -l        print with line numbers\n" .
  58.         "         -r        rotated, landscape orientation\n" .
  59.         "         -t        truncate long lines, default is to wrap lines\n" .
  60.         "         -b\"text\"  replaces the text in the page header\n" .
  61.         "         -h        no page headers\n" .
  62.         "         -2        set text in two columns format\n" .
  63.         "         -3        set text in three columns format\n" .
  64.         "         -s<size>  select new text fontsize, default 10pt\n" .
  65.         "         -w<width> char positions per column\n" .
  66.         "         -g        don't reject garbage files\n" .
  67.         "         -n        norwegian 7bit-ascii encoding\n" .
  68.         "         -f        finnish/swedish 7bit-ascii encoding\n";
  69.    exit(1);
  70. }
  71.  
  72. if (defined($opt_s) && $opt_s <= 0) {
  73.    printf STDERR "Illegal argument \"$opt_s\" to -s option\n";
  74.    exit(1);
  75. }
  76. if (defined($opt_w) && $opt_w <= 0) {
  77.    printf STDERR "Illegal argument \"$opt_w\" to -w option\n";
  78.    exit(1);
  79. }
  80.  
  81. # Set default values, some based on command line options
  82. $left_margin  = 80;
  83. $right_margin = 40;
  84. $tb_margin    = 45;
  85. $font         = "Courier";
  86. $header_font  = "Helvetica-Bold";
  87. $header_font_size = 12;
  88. $line_number_font = "Helvetica";
  89. $line_number_size = 5;
  90.  
  91. $no_columns = defined($opt_2) ? 2 : defined($opt_3) ? 3 : 1;
  92. $col_separation = 30;
  93. $sep_bars = 0;  # false
  94. $landscape = defined($opt_r);
  95. $header_height = 30;
  96. $show_header = !defined($opt_h);
  97. $wrap_lines = !defined($opt_t);
  98. $truncate_lines = !$wrap_lines; # don't change this
  99. $norsk_ascii = defined($opt_n);
  100. $sw_fi_ascii = defined($opt_f);
  101.  
  102. # Some initial values
  103. $opt_b = &ps_string($opt_b) if ($opt_b);
  104. $form_feed = 0; # false;
  105. $page_no  = 0;
  106. $line_no = 0;
  107. if ($landscape) {
  108.     $top = &page_right_edge;
  109.     $right_edge = &page_top;
  110.     $left_margin = $right_margin; # this is a dirty one
  111. } else {
  112.     $top = &page_top;
  113.     $right_edge = &page_right_edge;
  114. }
  115. $home_pos = $top - $tb_margin - ($show_header ? $header_height : 0);
  116. $col_width = ($right_edge - $left_margin - $right_margin
  117.               - ($no_columns - 1) * $col_separation) / $no_columns;
  118. $font_size    = $opt_s || 10;
  119. if (defined($opt_w)) {
  120.     $font_size = ($col_width / $opt_w) / (&cour_char_width / 1000);
  121.     printf STDERR "New font size is %.2g points\n", $font_size;
  122. }
  123. $line_height = $font_size * 1.08;
  124. $char_width = &cour_char_width * $font_size / 1000;
  125. $chars_per_line = int ($col_width / $char_width + 1);
  126.  
  127. &prolog;
  128.  
  129. unshift(@ARGV,'-') if $#ARGV < $[;
  130. FILE:
  131. while ($FILEHAND = shift) {
  132.     unless (open(FILEHAND)) {
  133.         print STDERR "Can't open \"$FILEHAND\"\n";
  134.         next FILE;
  135.     }
  136.     if (!defined($opt_g) && -B FILEHAND) {
  137.         print STDERR "Skipping binary file \"$FILEHAND\"\n";
  138.         close(FILEHAND);
  139.         next FILE;
  140.     }
  141.     $file_name = ($FILEHAND eq '-') ? '' : &ps_string($FILEHAND);
  142.     $cur_pos = -1;     # this will force a new column next time
  143.     $cur_col = 100;    # this will force a new page next time
  144.     $line_no = 0;
  145.     LINE:
  146.     while (<FILEHAND>) {
  147.         chop;
  148.         $line_no++;
  149.         if (ord == 014) {        # form feed
  150.             s/.//;    # chop off first char
  151.             $cur_pos = -1; 
  152.             next LINE if (length == 0);
  153.         }
  154.         while (s/\t/' ' x (8 - length($`) % 8)/e) {}   # expand tabs
  155.         do {
  156.             if ($cur_pos < $tb_margin) {
  157.                 $cur_pos = $home_pos;
  158.                 if ($cur_col < $no_columns) {
  159.                      $cur_col++;
  160.                 } else {
  161.                      $cur_col = 1;
  162.                      &new_page;
  163.                 }
  164.             }
  165.             $text = substr($_,0,$chars_per_line);
  166.             $_ = $truncate_lines ? '' : substr($_,$chars_per_line,10000);
  167.             if ($text =~ s/^ +//) {        # suppress leading blanks
  168.                 $indent = $char_width * length($&);
  169.             } else {
  170.                 $indent = 0;
  171.             }
  172.             # Make suitable as a postscript string, same as calling
  173.             # "ps_string", but the overhead of calling a function is
  174.             # not acceptable here.
  175.             $text =~ s/[\\\(\)]/\\$&/g;
  176.             $text =~ s/[\000-\037\177-\377]/sprintf("\\%03o",ord($&))/ge;
  177.             # Calculate position
  178.             $x = $left_margin +
  179.          ($cur_col - 1) * ($col_width + $col_separation);
  180.             $cur_pos -= $line_height;
  181.             printf "(%s)%.1f %.1f S\n", $text, $x + $indent, $cur_pos 
  182.                 if (length($text));
  183.             if ($opt_l && (($line_no % 5) == 0 || eof)) { # print line numbers
  184.                  printf "F2 SF($line_no)%.1f %.1f S F1 SF\n",
  185.                         $x + $col_width + 5, $cur_pos;
  186.             }
  187.         } while (length($_));
  188.     } # while (each line)
  189. } # while (each file)
  190. &end_page;
  191. print "%%Trailer\n";
  192. print "%%Pages: $page_no\n";
  193. # printf "($prog_name: $page_no page%s for $user\n) print\n",
  194. #     $page_no != 1 ? "s" : "";
  195.  
  196. #--end of main-------------------------------------------------------
  197.  
  198.  
  199. sub prolog {
  200.    $user = getlogin || "(unknown)";
  201.    local($sec,$min,$hour,$mday,$mon,$year) = localtime;
  202.    $date = sprintf("(%s %d, %d) (%2d:%02d)",
  203.                     ('January','February','March','April','May','June',
  204.                      'July','August','October','November','Desember')[$mon],
  205.                      $mday, $year+1900, $hour,$min);
  206.    print "%!PS-Adobe-2.0\n";
  207.    print "%%Title: @ARGV\n" if (@ARGV);
  208.    print <<"EOT";
  209. %%Creator: $prog_name, Text to PostScript filter in perl, (C) 1990 Gisle Aas, NCC
  210. %%CreationDate: $date
  211. %%For: $user
  212. %%Pages: (atend)
  213. EOT
  214.    print "%%DocumentFonts: $font";
  215.    print " $line_number_font" if ($opt_l);
  216.    print " $header_font" if ($show_header);
  217.    print "\n";
  218.    print <<"EOT";
  219. %%EndComments
  220. /S{moveto show}bind def
  221. /M/moveto load def
  222. /L/lineto load def
  223. /SF/setfont load def
  224. EOT
  225.     print <<"EOT" if ($isoencoding_not_builtin && !($norsk_ascii || $sw_fi_ascii));
  226. ISOLatin1Encoding where { pop } { ISOLatin1Encoding
  227. [/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  228. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  229. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  230. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
  231. /exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright
  232. /parenleft/parenright/asterisk/plus/comma/minus/period/slash/zero/one
  233. /two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal
  234. /greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S
  235. /T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum
  236. /underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s
  237. /t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde/.notdef/.notdef
  238. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  239. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/dotlessi/grave
  240. /acute/circumflex/tilde/macron/breve/dotaccent/dieresis/.notdef/ring
  241. /cedilla/.notdef/hungarumlaut/ogonek/caron/space/exclamdown/cent
  242. /sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine
  243. /guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus
  244. /twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla
  245. /onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters
  246. /questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
  247. /Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
  248. /Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
  249. /multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
  250. /germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae
  251. /ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex
  252. /idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide
  253. /oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]
  254. def %ISOLatin1Encoding
  255. } ifelse
  256. EOT
  257.     print <<"EOT" if ($norsk_ascii || $sw_fi_ascii);
  258. %%BeginProcSet: reencode 1.0 0
  259. /RE { %def
  260.    findfont begin
  261.    currentdict dup length dict begin
  262.       { %forall
  263.          1 index/FID ne {def} {pop pop} ifelse
  264.       } forall
  265.       /FontName exch def
  266.       dup length 0 ne { %if
  267.          /Encoding Encoding 256 array copy def
  268.          0 exch { %forall
  269.             dup type /nametype eq { %ifelse
  270.                Encoding 2 index 2 index put
  271.                pop 1 add
  272.             }{%else
  273.                exch pop
  274.             } ifelse
  275.          } forall
  276.       } if pop
  277.       currentdict dup
  278.    end
  279.    end
  280.    /FontName get exch definefont pop
  281. } bind def
  282. %%EndProcSet: reencode 1.0 0
  283. EOT
  284.    print <<"EOT" if (!($norsk_ascii || $sw_fi_ascii));
  285. %%BeginProcSet: newencode 1.0 0
  286. /NE { %def
  287.    findfont begin
  288.       currentdict dup length dict begin
  289.          { %forall
  290.             1 index/FID ne {def} {pop pop} ifelse
  291.          } forall
  292.          /FontName exch def
  293.          /Encoding exch def
  294.          currentdict dup
  295.       end
  296.    end
  297.    /FontName get exch definefont pop
  298. } bind def
  299. %%EndProcSet: newencode 1.0 0
  300. EOT
  301.    print "%%EndProlog\n%%BeginSetup\n";
  302.    if ($norsk_ascii || $sw_fi_ascii) {
  303.       print "[8#133 /AE/Oslash/Aring 8#173 /ae/oslash/aring] dup\n"
  304.     if ($norsk_ascii);
  305.       print "[8#133 /Adieresis/Odieresis/Aring" .
  306.             " 8#173 /adieresis/odieresis/aring] dup\n"
  307.     if ($sw_fi_ascii);
  308.       print "/$font-ISO/$font RE\n";
  309.       print "/$header_font-ISO/$header_font RE\n" if ($show_header);
  310.    } else {
  311.       print "ISOLatin1Encoding /$font-ISO/$font NE\n";
  312.       print "ISOLatin1Encoding /$header_font-ISO/$header_font NE\n"
  313.          if ($show_header);
  314.    }
  315.    printf "/F1/$font-ISO findfont %.2g scalefont def\n", $font_size;
  316.    print "/F2/$line_number_font findfont $line_number_size scalefont def\n"
  317.         if ($opt_l);
  318.    print "/F3/$header_font-ISO findfont $header_font_size scalefont def\n"
  319.         if ($show_header);
  320.    print "F1 SF\n";
  321.    print "%%EndSetup\n";
  322. }
  323.  
  324.  
  325.  
  326. sub new_page {
  327.    &end_page unless ($page_no == 0);
  328.    $page_no++;
  329.    print "%%Page: $page_no $page_no\n";
  330.    print "%%BeginPageSetup\n";
  331.    print "/page_save save def\n";
  332.    printf "90 rotate 0 -%d translate %% landscape mode\n",&page_right_edge
  333.       if ($landscape);
  334.    print "0.15 setlinewidth\n" if ($show_header);
  335.    print "%%EndPageSetup\n";
  336.    if ($show_header) {
  337.       # First print a box
  338.       local($llx,$lly,$urx,$ury) = ($left_margin - 10,
  339.             $top - $tb_margin - $header_font_size * 1.3,
  340.             $right_edge - $right_margin + 10, $top - $tb_margin);
  341.       printf "%.1f %.1f M %.1f %.1f L %.1f %.1f L ",
  342.              $llx,$lly, $urx,$lly, $urx, $ury;
  343.       printf "%.1f %.1f L closepath \n",$llx,$ury;
  344.       print  "gsave .95 setgray fill grestore stroke\n";
  345.       # Then the banner or the filename
  346.       print "F3 SF\n";
  347.       if ($opt_b) {
  348.          printf "($opt_b)%.1f %.1f S\n",
  349.                 $left_margin,$top - $tb_margin - $header_font_size;
  350.       }
  351.       elsif ($file_name) {
  352.          printf "(%s)%.1f %.1f S\n", $file_name, 
  353.                       $left_margin,
  354.                       $top - $tb_margin - $header_font_size;
  355.       }
  356.       # Then print page number
  357.       printf "%.1f %.1f M($page_no)dup stringwidth pop neg 0 rmoveto show\n",
  358.                  $right_edge - $right_margin, 
  359.                  $top - $tb_margin - $header_font_size;
  360.       print  "F1 SF\n";
  361.    }
  362.    if ($sep_bars) {
  363.       print "% Some postscript code to draw horizontal bars.\n";
  364.       print "% Not implemented yet\n";
  365.    }
  366. }
  367.  
  368. sub end_page {
  369.    unless ($page_no == 0) {
  370.       print "page_save restore\n";
  371.       print "showpage\n";
  372.    }
  373. }
  374.  
  375. sub ps_string
  376. {
  377.    # Prepare text for printing
  378.    local($_) = shift;
  379.    s/[\\\(\)]/\\$&/g;
  380.    s/[\001-\037\177-\377]/sprintf("\\%03o",ord($&))/ge;
  381.    $_;    # return string
  382. }
  383.  
  384.  
  385. ###########################################################################
  386.     # These next few lines are legal in both Perl and nroff.
  387.  
  388. .00;            # finish .ig
  389.  
  390. 'di            \" finish diversion--previous line must be blank
  391. .nr nl 0-1        \" fake up transition to first page again
  392. .nr % 0            \" start at page 1
  393. ';<<'.ex'; #__END__ #### From here on it's a standard manual page #########
  394. .TH I2PS 1 "October 1990"
  395. .SH NAME
  396. i2ps \- convert ISO Latin1 text to PostScript
  397. .SH SYNOPSIS
  398. .B i2ps
  399. [
  400. .B \-nflrth23g
  401. ] [
  402. .B \-b
  403. .I "text"
  404. ] [
  405. .B \-s
  406. .I size
  407. ] [
  408. .B \-w
  409. .I width
  410. ] [
  411. .I filename
  412. \&.\|.\|.
  413. ]
  414. .SH DESCRIPTION
  415. The
  416. .B i2ps
  417. program is used to print simple
  418. text files (e.g. program listings) on a PostScript\*R device. 
  419. The name
  420. .B i2ps
  421. stands for iso-to-postscript.  The program handles the whole
  422. ISO Latin1 (ISO 8859/1) character set. 
  423. Efforts have been made to ensure that 
  424. .B i2ps
  425. produces good looking and effective PostScript code.
  426. The output conforms to Adobe's
  427. document structuring conventions (version 2.1). The 
  428. .B i2ps 
  429. program
  430. assumes that the page format on the output device is A4. 
  431. (Change the definitions of &page_top and &page_right_edge if you
  432. want something else.)
  433. The meaning of form feed (^L) characters in the input stream is understood.
  434. .PP
  435. The
  436. .B i2ps
  437. program is written in
  438. .I perl.
  439. So if there is something you don't like about how
  440. .B i2ps
  441. works, you can "easily" fix it yourself.
  442. .SH OPTIONS
  443. .TP 5
  444. .B \-n
  445. use the norwegian version of ISO 646 (7-bit ascii) to encode the text.
  446. Norwegian letters will replace the left/right braces, left/right
  447. brackets, backslash and horizontal bar characters.
  448. .TP 5
  449. .B \-f
  450. use the finnish/swedish version of ISO 646.  Like
  451. .BR \-n ,
  452. but instead of the AE ligature and slashed-O you get a and o with two dots.
  453. .TP 5
  454. .B \-l
  455. produces line numbers on each 5'th and the last line.
  456. Nice for program listings.
  457. .TP 5
  458. .B \-t
  459. truncate lines that are to long. The default is to wrap
  460. long lines so that they continue on the next line on the printed output.
  461. .TP 5
  462. .B \-r
  463. rotate the output page 90 degrees. This is called
  464. .I landscape
  465. mode by some people.
  466. .TP 5
  467. .B \-h
  468. suppress generation of page headers.
  469. .TP 5
  470. .B \-2
  471. use two column format.
  472. .TP 5
  473. .B \-3
  474. use three column format.
  475. .TP 5
  476. .BI \-b " text"
  477. the 
  478. .I text
  479. parameter replaces the default text in the header of the pages.
  480. The default text is the filename of the file to be printed. There is no
  481. default if the text comes from standard input.
  482. .TP 5
  483. .BI \-s " size"
  484. specifies a new font size for the body text. The default is 10 point.
  485. .TP 5
  486. .BI \-w " width"
  487. specifies the number of characters per line. This is just another way
  488. of specifying the font size for the body text.  
  489. The w-option takes precedence over the
  490. s-option if both are present.
  491. .TP 5
  492. .B \-g
  493. eat garbage.  The
  494. .B i2ps 
  495. program normally skips binary files. This option means "print it anyway".
  496. .SH ENVIRONMENT
  497. .IP \fBI2PS\fP 10
  498. Options may also be specified with the environment variable "I2PS".
  499. The environment variable is parsed before the command line, so
  500. command line options override the environment variable.
  501. .SH EXAMPLES
  502. To print files on a PostScript printer:
  503. .nf
  504.     i2ps -l *.[ch] | lpr
  505. .fi
  506. .PP
  507. To find out how many pages i2ps will produce for a given file:
  508. .nf
  509.     i2ps file.txt | tail -1
  510. .fi
  511. .PP
  512. Our printer stacks the pages the wrong way. To fix it try:
  513. .nf
  514.     i2ps -2r -w80 file.txt | psrev | lpr
  515. .fi
  516. .SH SEE ALSO
  517. .BR perl (1),
  518. .BR enscript (1),
  519. .BR psrev (1),
  520. .BR ISO8859 (7),
  521. .BR PostScript (7)
  522. .SH BUGS
  523. There is no easy way to change the margins or the fonts that
  524. .B i2ps
  525. insists on using.
  526. The
  527. .B i2ps
  528. filter ought to understand the meaning of the backspace character. It is used
  529. to produce boldfaced and underlined text by programs like 
  530. .BR nroff (1).
  531. .PP
  532. If the you change the name of the file where
  533. .B i2ps
  534. lives, then you must change the name of the I2PS environment variable likewise.
  535. .SH AUTHOR
  536. Gisle Aas, Norwegian Computing Center (NR), Oslo, Norway.
  537. <Gisle.Aas@nr.no>
  538. .ex
  539.