#!/usr/bin/perl
# Require Perl5
#
# txt2pdf -- Text to PDF
#
# by SANFACE Software <sanface@sanface.com> 13 December 1999
#
# This is shareware (only $25)... Try it for 30 days.
# If you decide to continue using it, register NOW via a SECURE SERVER at
# http://www.regsoft.net/purchase.php3?productid=11906
# or contact SANFACE Software sanface@sanface.com
#
# This is version 2.5
#
use strict;
use Getopt::Long;
use File::Basename;
use File::Find;
# use File::DosGlob 'glob';

my $version="2.5";
my $fpos=0;
my $producer="txt2pdf";
my $line_end="\015";
my $pageNO;
my $lineNO;
# Default paper is Letter size
my $pageHeight=792;
my $pageWidth=612;
my @location;
my @pageObj;
my $lines=0;
my $buf="";
my $col2=0;
my $input=""; my $output="";
my $elem="";
my $configure="txt2pdf.cfg";
my $help=0; my $verbose=0; my $border=0; my $paper=""; my $landscape=0;
my $columns2=0; my $npage=0; my $allowinparse=0;
my $obj=0;
my $Tpages=0; my $resources=0; my $root=0; my $info=0;
my $BF; my $EF;
my @annots; my $LLx=48;
my $title="";
my $counter;
my $recursive=""; my $match="";
my $line; my $page;
my $companyname="SANFACE Software";
my $Unregistered="Generated by unregistered txt2pdf v.$version \251 $companyname 1999\n";
my $txt2pdfHome="http://www.sanface.com/txt2pdf.html";
my $ANFACEmail="mailto:sanface\@sanface.com";
my $SECURESERVER="http://www.regsoft.net/purchase.php3?productid=11906";
my $SECURESERVER2="http://www.pdfstore.com/mainpage.asp?webpageid=231&ProductID=1040&Action=BUY";
my @colours=("yellow","red","green","blue");
my %pscolours=(yellow => '1 1 0',
               red    => '1 0 0',
               green  => '0 1 0',
               blue   => '0 0 1');
my @fonts=("bo_it","bold","italic");
my %psfonts=(bo_it  => 'F4',
             bold   => 'F3',
             italic => 'F2');
my @coloursdata; my @fontsdata;
my $colour; my $font;
my $flagcolour=0; my $flagfont=0;

&GetOptions("configure=s"  => \$configure,
            "help"         => \$help,
            "landscape"    => \$landscape,
            "paper=s"      => \$paper,
            "2"            => \$columns2,
            "npage"        => \$npage,
            "recursive=s"  => \$recursive,
            "match=s"      => \$match,
            "border"       => \$border,
            "allowinparse" => \$allowinparse,
            "verbose"      => \$verbose) || printusage() ;
my @elem=("lf_extra","tmpdir","author","creator","keywords","subject","title",
          "landscape","paper","font","cols","lines","tab","pointSize","vertSpace",
          "columns2","npage","yellow","red","green","blue","bold","italic",
          "bo_it","beginfile","endfile","allowinparse","border");
my %option=(lf_extra           => '0',
            tmpdir             => './',
            author             => '',
            creator            => '',
            keywords           => '',
            subject            => '',
            title              => '',
            landscape          => '0',
            paper              => 'letter',
            font               => 'Courier',
            columns2           => '0',
            npage              => '0',
            cols               => '80',
            lines              => '',
            pointSize          => '10',
            vertSpace          => '12',
            tab                => '8',
            yellow             => '',
            red                => '',
            green              => '',
            blue               => '',
            bo_it              => '',
            bold               => '',
            italic             => '',
            beginfile          => '',
            endfile            => '',
            allowinparse       => '0',
            border             => '0');

$help and printusage();

open (CNF, "$configure") || die "txt2pdf: couldn't open configuration file $configure\n";
while (<CNF>) {
  s/\t/ /g;        #replace tabs by space
  next if /^ *\#/; #ignore comment lines
  next if /^ *$/;  #ignore empty lines
  foreach $elem (@elem) {if (/ *$elem *: *(.*)/i) {$option{$elem}=$1;}}
  }
close(CNF);
$paper and $option{'paper'}=$paper;
$landscape and $option{'landscape'}=$landscape;
$columns2 and $option{'columns2'}=$columns2;
$npage and $option{'npage'}=$npage;
$border and $option{'border'}=$border;
$allowinparse and $option{'allowinparse'}=$allowinparse;

print <<FEE;

This is an UNREGISTERED version of txt2pdf.
Registration fee is only \$25.
Register NOW via a SECURE SERVER at
$SECURESERVER
or at
$SECURESERVER2
or contact $companyname $ANFACEmail


FEE

if (uc($option{'paper'}) eq "A3") {
   $pageWidth=842;
   $pageHeight=1190;
   }
elsif (uc($option{'paper'}) eq "A4") {
   $pageWidth=595;
   $pageHeight=842;
   }
elsif (uc($option{'paper'}) eq "A5") {
   $pageWidth=421;
   $pageHeight=595;
   }
elsif ($option{'paper'}=~/(\d+)x(\d+)/) {
   if ($1<72) {$pageWidth=72;}
   else {$pageWidth=$1}
   if ($2<72) {$pageHeight=72;}
   else {$pageHeight=$2}
   }
else {
   if (($option{'paper'}) && ($option{'paper'} ne "letter")) {
     print <<PAPER;
Warning: the set paper $option{'paper'} isn't supported
         txt2pdf will use the default paper (letter)

PAPER
       }
     }

if ($option{'landscape'}) {
  my $tmp=$pageHeight;
  $pageHeight=$pageWidth;
  $pageWidth=$tmp;
  }
if ($option{'columns2'}) {$option{'cols'} /= 2}
my $blanknpage=($option{'cols'} / 2) - 1;
my $blank=" ";
my $blanks;
for (1 .. $blanknpage) {$blanks .= $blank}
if ($option{'lines'}) {$lines = $option{'lines'}}
else {$lines = ($pageHeight - 72) / $option{'vertSpace'}}
$lines = int $lines;
if (($option{'font'} ne "Courier") && ($option{'font'} ne "Helvetica") && ($option{'font'} ne "Times")) {
  print <<FONT;
Warning: the set font $option{'font'} isn't Courier or Helvetica or Times
         txt2pdf will use the default font (Courier)

FONT
  $option{'font'}="Courier";
  }

sub wanted {
  if ($File::Find::name=~/$match/) {
    push @ARGV,$File::Find::name;
    }
  }

if ($match && !$recursive) {
   print "You can use -match option only with -recursive option\n";
   exit;
   }

if ($recursive) {
  $match=~s/\./\\./g;
  $match=~s/\*/.*/g;
  $match=~s/\?/./g;
  $match=~s/$/\$/;
  find (\&wanted,"$recursive");
  }

# Manca la dimensione della fonte

my $URy=$pageHeight - 42;
my $tmpfile = $option{'tmpdir'} . "txt2pdf$$"; 
my $z=0;
# Generalization: simple add new colours
foreach $colour (@colours) {
  if ($option{$colour}) {
    $flagcolour=1;
    open (COLOUR,$option{$colour}) ||
      die qq!txt2pdf: couldn't open input file $option{$colour}\n!;
    while(<COLOUR>) {
      chop;
      s/\t/ /g;        #replace tabs by space
      next if /^ *\#/; #ignore comment lines
      next if /^ *$/;  #ignore empty lines
      push @{$coloursdata[$z]},$_;
      }
    close(COLOUR);
    }
  else {push @{$coloursdata[$z]},"";}
  $z++;
  }
$z=0;
foreach $font (@fonts) {
  if ($option{$font}) {
    $flagfont=1;
    open (FONT,$option{$font}) ||
      die qq!txt2pdf: couldn't open input file $option{$font}\n!;
    while(<FONT>) {
      chop;
      s/\t/ /g;        #replace tabs by space
      next if /^ *\#/; #ignore comment lines
      next if /^ *$/;  #ignore empty lines
      push @{$fontsdata[$z]},$_;
      }
    close(FONT);
    }
  else {push @{$fontsdata[$z]},"";}
  $z++;
  }
  if ($option{'beginfile'}) {
    open (BEGINFILE,$option{'beginfile'}) ||
      die qq!txt2pdf: couldn't open input file $option{'beginfile'}\n!;
    while(<BEGINFILE>) {
      $_=&TAB($_);
      $BF.=$_;
      }
    close(BEGINFILE);
    }
  if ($option{'endfile'}) {
    open (ENDFILE,$option{'endfile'}) ||
      die qq!txt2pdf: couldn't open input file $option{'endfile'}\n!;
    while(<ENDFILE>) {
      $_=&TAB($_);
      $EF.=$_;
      }
    close(ENDFILE);
    }

if (@ARGV) {
  my @files;
  if ($^O =~ /^MSWin32$/i && !$recursive) {@files = glob($ARGV[0])}
  else {@files = @ARGV}
  foreach $input (@files) {
    $obj=0;
    $pageNO=0;
    $fpos=0;
    @pageObj='';
    if(!$option{'title'}) {$title=basename($input,"");}
    else {$title=$option{'title'};}
    $verbose and print "Processing $input file\n";
    $output=$input;
    my $out=basename($output,"");
    if ($out=~/(.*)\..*/) {$out=~s/(.*)\..*/$1\.pdf/;}
      else {$out.=".pdf";}
    $output=dirname($output,"");

    if ($^O =~ /VMS/ ) {
# On OpenVMS: Also don't add '/' if dir ends in ']' or ':'
#    e.g. VMS filepecs look like
      $output.="/" if ($output !~ /(\/|\\|]|:)$/ );
    } elsif ($^O eq 'MacOS') {
      $output.=":" if ($output !~ /:$/ ); # macs are a bit different...
    } else {
# concat '/' only if dir doesn't already end in a '/' or '\\'
      $output.="/" if ($output !~ /(\/|\\)$/ );
    }
    $output.=$out;
    open (OUT, ">$output") || die "txt2pdf: couldn't open output file $output\n";
    &ReorganizeFile($input);
    &WriteLink($tmpfile);
    &WriteHeader();
    &WritePages($tmpfile);
    &WriteOutlines($tmpfile);
    &WriteRest();
    close(OUT);
    # a simple user-interface enhancement
    # make a MacOS double-clickable file
    if ($^O eq 'MacOS') {MacPerl::SetFileInfo('CARO','PDF ', $output)}
    $verbose and print "Writing $output file\n";
    }
    if ($^O =~ /VMS/ ) {
# On OpenVMS, need While to delete all versions of tmpfile
      while ( unlink($tmpfile) ) {};
    } else {
      unlink($tmpfile);
    }
  } else {printusage();}

sub ReorganizeFile {
  my $file=shift(@_);

  my $i;
  my $temporary;
  open (IN, "$file") || die "txt2pdf: couldn't open input file $file\n";
  open (TEMP, ">$tmpfile") || die "txt2pdf: couldn't open temporary file $tmpfile\n";
  if($BF) 
    {
    my @BeginFile = split (/\n/,$BF);
    foreach $temporary (@BeginFile) {print TEMP &Columns($temporary)}
    print TEMP "+-EndBeginFile-+\n";
    }
  while (<IN>) {
    chop;
    $_ = &TAB($_);
    print TEMP &Columns($_);
    }
  if($EF) {
    my @EndFile = split (/\n/,$EF);
    foreach $temporary (@EndFile) {print TEMP &Columns($temporary)}
    }
  print TEMP "\n";
  print TEMP &Columns($Unregistered);
  close(IN);
  close(TEMP);
  }

sub Columns {
  my $Line=shift(@_);

  my $countLine=$Line;
  if ($option{'allowinparse'}) {
    $countLine=~s/\[!\w*\]//g;
    $countLine=~s/\[!\/\w*\]//g;
    }
# subtract number of '^]H' occurrences from line length
# as these will be substituted by special formatting
  my $columns=(length $countLine) - ($Line =~ tr/\010/\010/);  
  my $tmpbuf="";
  if ( $columns == 0 ) {return ("\n")}
  if ( $Line =~/^ *$/ ) {return ("\n")}
  while ($columns > $option{'cols'}) {
    my $line1=substr $Line,0,$option{'cols'};
    my $line2=substr $Line,$option{'cols'};
    my $char1=substr $Line,$option{'cols'},1;
    my $char2=substr $Line,$option{'cols'}-1,1;
# If a line is longer than 80 chars some words go to the next line
    if(($char1 ne " ") && ($char2 ne " ")) {
      if($line1=~/(.*)( )+([^ ]+)/) {$tmpbuf.="$1$2\n";}
      else {$tmpbuf.="$line1\n";}
      $line2=$3.$line2;
      } else {
      $tmpbuf.="$line1\n";
      if($char1 eq " ") {$line2=substr $Line,$option{'cols'}+1;}
      }
    $Line=$line2;
    $columns=(length $Line) - ($Line =~ tr/\010/\010/);
    }
  $tmpbuf .= "$Line\n";
  return ($tmpbuf);
  }

sub WriteOutlines {
  my $file=shift(@_);

  my $line=0;
  open (IN, "$file") || die "txt2pdf: couldn't open input file $file\n";
  while (<IN>) {
    $line++;
    if ($line == $lines) {
      if ($option{'columns2'} && !$col2) {
        $col2=1;
        $line=1;
        $LLx= ($pageWidth/2) + 25 - 2;
        } else {
        $line=1;
        if ($option{'columns2'} eq 1) {$col2 = 0}
        }
      }
    }
  close(IN);
  }

sub WriteLink {
  my $file=shift(@_);

  my $col2=0;
  # Start PDF
  &pos("%PDF-1.2\n");
  # It is recommended that the second line of a PDF file be a comment that
  # contains at least four characters with codes 128 or greater
  &pos("%\n");
  $line=0;
  $page=1;
  open (IN, "$file") || die "txt2pdf: couldn't open input file $file\n";
  my $linktemp;
  while (<IN>) {
    $line++;
    $linktemp=$_;
# algoritmo su come fare i link sulla seconda colonna
    if ($line == $lines) {
      if ($columns2 && !$col2) {
        $col2=1;
        $line=1;
        $LLx=($pageWidth/2)+25-2;
        } else {
        $line=1;
        $page++;
        if ($columns2) {$col2=0;$LLx=48;}
        }
      }
    while ($linktemp=~/(.*)((http|ftp|mailto|https|file|ldap|news):[^ \n]+)( +|$)/i) {
      $linktemp=$1;
      &Link(length $1,length $2,$2,"url");
      }
    ##  14May99 - Modified to handle the mime: marker.  It's just a
    ##            tweak of the original link test
    while ($linktemp=~/(.*)(mime:[^ \n]+)( +|$)/i) {
      $linktemp=$1;
      &Link(length $1,length $2,$2,"file");
      }
    if (/(.*)(txt2pdf v\.\d\.\d)/) {&Link(length $1,length $2,$txt2pdfHome,"url");}
    if (/(.*)(SANFACE Software)/) {&Link(length $1,length $2,$ANFACEmail,"url");}
    }
  close (IN);
  }

sub WriteHeader {
  my $sec=0; my $min=0; my $hour=0; my $mday=0; my $mon=0; my $year=0;
  my $wday=0; my $yday=0; my $isdst=0; my $date="";
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  ++$mon;                              # $mon is 0..11
  $year += 1900;
  $date=sprintf "D:$year%.2ld%.2ld%.2ld%.2ld%.2ld",$mon,$mday,$hour,$min,$sec;
  # Start PDF
#  &pos("%PDF-1.2\n");
  # It is recommended that the second line of a PDF file be a comment that
  # contains at least four characters with codes 128 or greater
#  &pos("%\n");
  $location[++$obj]=$fpos;
  $info=$obj;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  $option{'author'} and &pos("/Author ($option{'author'})\n");
  &pos("/CreationDate ($date)\n");
  $option{'creator'} and &pos("/Creator ($option{'creator'})\n");
  &pos("/Producer ($producer v$version \\251 $companyname 1999)\n");
  &pos("/Title ($title)\n");
  $option{'subject'} and &pos("/Subject ($option{'subject'})\n");
  $option{'keywords'} and &pos("/Keywords ($option{'keywords'})\n");
  &pos(">>\n");
  &pos("endobj\n");
  $root=++$obj;
  $Tpages=++$obj;
  my $encoding=$obj+5;
  $resources=$obj+6;
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Font\n");
  &pos("/Subtype /Type1\n");
  &pos("/Name /F1\n");
  &pos("/Encoding $encoding 0 R\n");
  if ($option{'font'} eq "Times") {&pos("/BaseFont /$option{'font'}-Roman\n")}
  else {&pos("/BaseFont /$option{'font'}\n")}
  &pos(">>\n");
  &pos("endobj\n");
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Font\n");
  &pos("/Subtype /Type1\n");
  &pos("/Name /F2\n");
  &pos("/Encoding $encoding 0 R\n");
  if ($option{'font'} eq "Times") {&pos("/BaseFont /$option{'font'}-Italic\n")}
  else {&pos("/BaseFont /$option{'font'}-Oblique\n")}
  &pos(">>\n");
  &pos("endobj\n");
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Font\n");
  &pos("/Subtype /Type1\n");
  &pos("/Name /F3\n");
  &pos("/Encoding $encoding 0 R\n");
  &pos("/BaseFont /$option{'font'}-Bold\n");
  &pos(">>\n");
  &pos("endobj\n");
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Font\n");
  &pos("/Subtype /Type1\n");
  &pos("/Name /F4\n");
  &pos("/Encoding $encoding 0 R\n");
  if ($option{'font'} eq "Times") {&pos("/BaseFont /$option{'font'}-BoldItalic\n")}
  else {&pos("/BaseFont /$option{'font'}-BoldOblique\n")}
  &pos(">>\n");
  &pos("endobj\n");
# ISOLatin1Encoding
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Encoding\n");
  &pos("/Differences [ 0 /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/.notdef /.notdef /.notdef /.notdef /space /exclam\n");
  &pos("/quotedbl /numbersign /dollar /percent /ampersand\n");
  &pos("/quoteright /parenleft /parenright /asterisk /plus /comma\n");
  &pos("/hyphen /period /slash /zero /one /two /three /four /five\n");
  &pos("/six /seven /eight /nine /colon /semicolon /less /equal\n");
  &pos("/greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L\n");
  &pos("/M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n");
  &pos("/backslash /bracketright /asciicircum /underscore\n");
  &pos("/quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p\n");
  &pos("/q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright\n");
  &pos("/asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n");
  &pos("/dotlessi /grave /acute /circumflex /tilde /macron /breve\n");
  &pos("/dotaccent /dieresis /.notdef /ring /cedilla /.notdef\n");
  &pos("/hungarumlaut /ogonek /caron /space /exclamdown /cent\n");
  &pos("/sterling /currency /yen /brokenbar /section /dieresis\n");
  &pos("/copyright /ordfeminine /guillemotleft /logicalnot /hyphen\n");
  &pos("/registered /macron /degree /plusminus /twosuperior\n");
  &pos("/threesuperior /acute /mu /paragraph /periodcentered\n");
  &pos("/cedilla /onesuperior /ordmasculine /guillemotright\n");
  &pos("/onequarter /onehalf /threequarters /questiondown /Agrave\n");
  &pos("/Aacute /Acircumflex /Atilde /Adieresis /Aring /AE\n");
  &pos("/Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave\n");
  &pos("/Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve\n");
  &pos("/Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
  &pos("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n");
  &pos("/germandbls /agrave /aacute /acircumflex /atilde /adieresis\n");
  &pos("/aring /ae /ccedilla /egrave /eacute /ecircumflex\n");
  &pos("/edieresis /igrave /iacute /icircumflex /idieresis /eth\n");
  &pos("/ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
  &pos("/divide /oslash /ugrave /uacute /ucircumflex /udieresis\n");
  &pos("/yacute /thorn /ydieresis ]\n");
  &pos(">>\n");
  &pos("endobj\n");
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  $buf=sprintf "  /Font << /F1 %d 0 R /F2 %d 0 R /F3 %d 0 R /F4 %d 0 R >>\n",
       $obj-5, $obj-4, $obj-3, $obj-2;
  &pos($buf);
  &pos("  /ProcSet [ /PDF /Text ]\n");
  &pos(">>\n");
  &pos("endobj\n");
  }

sub WritePages {
  my $file=shift(@_);

  my $columns="";
  my $pageNO2=1;
  my $temp;
  my $i;
  my $parseword;
  my $thistest;
  my $testfont;
  my $testcolour;
  my $converted=0;

  open (IN, "$file") || die "txt2pdf: couldn't open input file $file\n";
  my $beginstream = &StartPage();
# Title
  if ($BF eq "") {
    &pos("/F3 $option{'pointSize'} Tf\n");
    &pos("T* ($title) Tj\n");
    &pos("/F1 $option{'pointSize'} Tf\n");
    }
  $lineNO=1;
  while (<IN>) {
    $temp=$_;
    if($temp=~/^\+-EndBeginFile-\+/){
      &pos("/F3 $option{'pointSize'} Tf\n");
      &pos("T* ($title) Tj\n");
      &pos("/F1 $option{'pointSize'} Tf\n");
      next;
      }
    $lineNO++;
    if ($lineNO == $lines) {
      if ($option{'columns2'} && !$col2) {
        if ($option{'npage'}) {
          &pos("/F2 $option{'pointSize'} Tf\n");
          &pos("($blanks$pageNO2)'\n"); $pageNO2++;
          &pos("/F1 $option{'pointSize'} Tf\n");
          }
        $buf=sprintf "1 0 0 1 %d %d Tm\n",($pageWidth/2)+25,$pageHeight-40;
        &pos($buf);
        $col2=1;
        $lineNO=1;
        } else {
        if ($option{'npage'}) {
          &pos("/F2 $option{'pointSize'} Tf\n");
          if ($option{'columns2'}) {&pos("($blanks$pageNO2)'\n"); $pageNO2++;}
          else {&pos("($blanks$pageNO)'\n")}
          &pos("/F1 $option{'pointSize'} Tf\n");
          }
        &EndPage($beginstream);
        $beginstream = &StartPage();
        $option{'columns2'} and $col2=0;
        }
      }
    if ($lineNO < $lines) {
      if (/^\n$/) {&pos("T* ")};
      chop($temp);
      $temp=~s/\\/\\\\/g;
      $temp=~s/\(/\\(/g;
      $temp=~s/\)/\\)/g;
      my $word;
      my $z;
      while ($temp) {
        $z=0;
        my @words='';
        @words=split(/ /,$temp);
        &pos("T* (");
        foreach $word (@words) {
          $z++;

# [Matt Johnson <matt@vadu.com>]: Extra condition to fix spacing probs.
# $converted gets set if a special word was parsed and 'eaten'. Ordinarily,
# without special words, spaces are fine, otherwise they introduce prespacing
# which looks weird.

          if (($z ne 1) && ($converted != 1)) {&pos(" ")}
          $converted = 0;

# '^]H' format conversion:
# substitute underlines by italics
# (don't know how to underline in pdf)
          if ($word=~/_\010/)
            {
            $word=~s/_\010//g;
            &pos(") Tj\n");
            &pos("/F2 $option{'pointSize'} Tf\n");
            &pos("($word) Tj\n");
            &pos("/F1 $option{'pointSize'} Tf\n");    
            &pos("(");
            $word = "";
            goto NEXT;
            }
          # substitute "bad" bold by "good" bold
          if ($word=~/\010/)
            {
            $word=~s/.\010//g;
            &pos(") Tj\n");
            &pos("/F3 $option{'pointSize'} Tf\n");
            &pos("($word) Tj\n");
            &pos("/F1 $option{'pointSize'} Tf\n");
            &pos("(");
            $word = "";
            goto NEXT;
            }
                                                 
          if ($word=~/^(http|ftp|mailto|mime|https|file|ldap|news):/i)
            {
            &pos(") Tj\n");
            &pos("$pscolours{blue} rg\n");
            &pos("($word) Tj\n");
            &pos("0 0 0 rg\n");
            &pos("(");
            $word = "";
            goto NEXT;
            }

# [Matt Johnson <matt@vadu.com>]: This is the parser code.
# It looks awful, all the repeated 'if ($converted != 1)... but it's the most
# efficient when it comes to runtime.

          if ($option{'allowinparse'} == 1) {
            if ($word=~/^\[!/) {
              $parseword = $word;
              $parseword =~ s/\[!//g;
              $parseword = substr($parseword, 0, -1);
              # above, to chop closing ). [UNSAFE!]
              # work on the principle that it's something we want to convert
              foreach $testcolour (keys %pscolours) {
                 if (lc($testcolour) eq $parseword) {
                    &pos(") Tj\n");
                    &pos("$pscolours{$testcolour} rg\n");
                    &pos("(");
                    $converted = 1;
                    $word = "";
                 }
              }
              if ($converted != 1) {
                 foreach $testfont (keys %psfonts) {
                    if (lc($testfont) eq $parseword) {
                       &pos(") Tj\n");
                       &pos("/$psfonts{$testfont} $option{'pointSize'} Tf\n");
                       &pos("(");
                       $converted = 1;
                       $word = "";
                    }
                 }
              }
              if ($converted != 1) {
                 foreach $testcolour (keys %pscolours) {
                    $thistest = '/' . $testcolour;
                    if (lc($thistest) eq $parseword) {
                       &pos(") Tj\n");
                       &pos("0 0 0 rg\n");
                       &pos("(");
                       $converted = 1;
                       $word = "";
                    }
                 }
              }
              if ($converted != 1) {
                 foreach $testfont (keys %psfonts) {
                    $thistest = '/' . $testfont;
                    if (lc($thistest) eq $parseword) {
                       &pos(") Tj\n");
                       &pos("/F1 $option{'pointSize'} Tf\n");
                       &pos("(");
                       $converted = 1;
                       $word = "";
                    }
                 }
              }
            }
          }
          if ($flagcolour) {
            my $imatch;
            for ($i=0;$i<=$#colours;$i++) {
              foreach $imatch (@{$coloursdata[$i]}) {
                !$imatch and next;
                if($word=~/$imatch/) {
                  &pos(") Tj\n");
                  &pos("$pscolours{$colours[$i]} rg\n");
                  &pos("($word) Tj\n");
                  &pos("0 0 0 rg\n");
                  &pos("(");
                  goto NEXT;
                  }
                }
              }
            }
          if ($flagfont) {
            my $imatch;
            for ($i=0;$i<=$#fonts;$i++) {
              foreach $imatch (@{$fontsdata[$i]}) {
                !$imatch and next;
                if($word=~/$imatch/) {
                  &pos(") Tj\n");
                  &pos("/$psfonts{$fonts[$i]} $option{'pointSize'} Tf\n");
                  &pos("($word) Tj\n");
                  &pos("/F1 $option{'pointSize'} Tf\n");
                  &pos("(");
                  goto NEXT;
                  }
                }
              }
            }
          &pos("$word");
NEXT:          }
        &pos(") Tj\n");
        $temp="";
        }
      }
    }
  close(IN);
  if ($option{'npage'}) {
    for ($lineNO..$lines-2) {&pos("T* ");} &pos("\n");
    &pos("/F2 $option{'pointSize'} Tf\n");
    if ($option{'columns2'}) {&pos("($blanks$pageNO2)'\n");}
    else {&pos("($blanks$pageNO)'\n");}
    &pos("/F1 $option{'pointSize'} Tf\n");
    }
  &EndPage($beginstream);
  }

# End PDF
sub WriteRest {
  my $i;
  $location[$root]=$fpos;
  &pos("$root 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Catalog\n");
  &pos("/Pages $Tpages 0 R\n");
  &pos(">>\n");
  &pos("endobj\n");
  $location[$Tpages]=$fpos;
  &pos("$Tpages 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Pages\n");
  &pos("/Count $pageNO\n");
  &pos("/MediaBox [ 0 0 $pageWidth $pageHeight ]\n");
  &pos("/Kids [ ");
  for ($i=1; $i<=$pageNO;$i++) {&pos("$pageObj[$i] 0 R ");}
  &pos("]\n");
  &pos(">>\n");
  &pos("endobj\n");
  my $xfer = $fpos;
  &pos("xref\n");
  $buf=sprintf "0 %d\n",$obj+1; &pos($buf);
  &pos("0000000000 65535 f $line_end");
  my $num="";
  for ($i=1;$i<=$obj;$i++) {
    $buf=sprintf "%.10ld 00000 n $line_end",$location[$i];
    &pos($buf);
    }
  &pos("trailer\n");
  &pos("<<\n");
  $buf=sprintf "/Size %d\n",$obj+1; &pos($buf);
  &pos("/Root $root 0 R\n");
  &pos("/Info $info 0 R\n");
  &pos(">>\n");
  &pos("startxref\n");
  &pos("$xfer\n");
  &pos("%%EOF\n");
  }

sub StartPage {

  $location[++$obj]=$fpos;
  $pageObj[++$pageNO]=$obj;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  &pos("/Type /Page\n");
  &pos("/Parent $Tpages 0 R\n");
  &pos("/Resources $resources 0 R\n");
  $buf=sprintf "/Contents %d 0 R\n",++$obj; &pos($buf);
  $annots[$pageNO] and &pos("/Annots [ $annots[$pageNO]]\n");
  &pos(">>\n");
  &pos("endobj\n");
  $location[$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  $buf=sprintf "/Length %d 0 R\n",$obj+1; &pos($buf);
  &pos(">>\n");
  &pos("stream\n");
  my $strmPos=$fpos;
  &pos("BT\n");
  &pos("/F1 $option{'pointSize'} Tf\n");
  $buf=sprintf "1 0 0 1 50 %d Tm\n",$pageHeight-40; &pos($buf);
  &pos("$option{'vertSpace'} TL\n");
  return ($strmPos);
  }

sub EndPage {
  my $streamStart=shift(@_);
  my $streamEnd=0;
  my $default=15;
  my $Width=$pageWidth - $default;
  my $Height=$pageHeight - $default;
  my $newline;
  if ($option{'border'}) {
    if ($option{'lf_extra'}) {$newline="\r\n"}
    else {$newline="\n"}
    &pos("2 w$newline");
    &pos("1 1 1 rg$newline");
    &pos("$default $default m$newline$Width $default l$newline");
    &pos("$Width $default m$newline$Width $Height l$newline");
    &pos("$Width $Height m$newline$default $Height l$newline");
    &pos("$default $Height m$newline$default $default l$newline");
    &pos("B*$newline");
    }
  &pos("ET\n");
  $streamEnd=$fpos;
  &pos("endstream\n");
  &pos("endobj\n");
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  $buf=sprintf "%d\n",$streamEnd-$streamStart; &pos($buf);
  &pos("endobj\n");
  $lineNO=1;
  }

sub Link {
  my $linkbegin=shift(@_);
  my $linkend=shift(@_);
  my $link=shift(@_);
  my $type=shift(@_);

  my $tmpline;
  $location[++$obj]=$fpos;
  &pos("$obj 0 obj\n");
  &pos("<<\n");
  &pos("/A <<\n");
  if ($type eq "url") {
    &pos("/S /URI\n");
    &pos("/URI ($link)\n");
    } else {
    &pos("/S /Launch\n");
    my $slink = substr($link, 5); ## Pull the file: from the front
    &pos("/F ($slink)\n");
    }
  &pos(">>\n");
  &pos("/Type /Annot\n");
  &pos("/Subtype /Link\n");
  if (!$option{'beginfile'}) {$tmpline=$line+1}
  else {$tmpline=$line}
# LLx LLy URx URy
  if ($option{'font'} eq "Courier") {
    $buf=sprintf "/Rect [%d %d %d %d]\n",
$LLx+$linkbegin*($option{'pointSize'}/2+1),
$URy-($tmpline)*($option{'vertSpace'}-$option{'pointSize'})-$tmpline*$option{'pointSize'},
$LLx+$linkbegin*($option{'pointSize'}/2+1)+($linkend+1)*($option{'pointSize'}/2+1),
$URy-($tmpline)*($option{'vertSpace'}-$option{'pointSize'})-($tmpline-1)*$option{'pointSize'};
    }
  elsif ($option{'font'} eq "Helvetica") {
    $buf=sprintf "/Rect [%d %d %d %d]\n",
$LLx+$linkbegin*($option{'pointSize'}/2-1),
$URy-($tmpline)*($option{'vertSpace'}-$option{'pointSize'})-$tmpline*$option{'pointSize'},
$LLx+$linkbegin*($option{'pointSize'}/2-1)+($linkend+1)*($option{'pointSize'}/2-1),
$URy-($tmpline)*($option{'vertSpace'}-$option{'pointSize'})-($tmpline-1)*$option{'pointSize'};
    }
  else {
    $buf=sprintf "/Rect [%d %d %d %d]\n",
$LLx+$linkbegin*($option{'pointSize'}/2-1),
$URy-($tmpline)*($option{'vertSpace'}-$option{'pointSize'})-$tmpline*$option{'pointSize'},
$LLx+$linkbegin*($option{'pointSize'}/2-1)+($linkend+1)*($option{'pointSize'}/2-1),
$URy-($tmpline)*($option{'vertSpace'}-$option{'pointSize'})-($tmpline-1)*$option{'pointSize'};
    }
  &pos($buf);
# Bordo azzurro
#  &pos("/C [$pscolours{blue}]\n");
# Rettangolo invisibile
  &pos("/Border [0 0 0]\n");
  &pos("/H /I\n");
  &pos(">>\n");
  &pos("endobj\n");
  $annots[$page].="$obj 0 R ";
  }

sub TAB {
  my $line=shift(@_);
  while($line=~/([^\t]*)\t/) {
    my $spaces="";
    my $spaceNO=$option{'tab'}-(length $1)%$option{'tab'};
    for(1..$spaceNO) {$spaces.=" ";}
    $line=~s/([^\t]*)\t/$1$spaces/;
    }
  return($line);
  }

sub pos {
  my $string = shift(@_);
  $fpos+=length $string;
  if($string=~/\n/) {$fpos += $option{'lf_extra'};}
  print OUT "$string";
  }

sub printusage {
    print <<USAGEDESC;

usage:
        txt2pdf [-options ...] list

where options include:
    -help                        print out this message
    -configure file              default txt2pdf.cfg
    -landscape
    -2                           format in 2 columns
    -paper format                default letter, valid formats: A3 (or a3),
                                 A4 (or a4), A5 (or a5), widthxheight
    -npage                       add page number
    -recursive directory         scan recursively the directory
    -match     files             match different files ex. *.pdf, a?.*
                                 (require -recursive option)
    -border                      border line
    -allowinparse                parser
    -verbose                     verbose

list:
    with list you can use metacharacters and relative and absolute path name

example:
    txt2pdf *.txt
    txt2pdf -m "a*.txt" -r my_directory


If you want to know more about this tool, you might want
to read the docs. They came together with txt2pdf!

Home: $txt2pdfHome

USAGEDESC
    exit(1);
}

=head1 NAME

TXT2PDF - Version 2.5 13th December 1999

=head1 SYNOPSIS

Syntax : txt2pdf [-options] files

=head1 DESCRIPTION

TXT2PDF  is a very flexible and powerful PERL5 program (5 penguin rate at
LinuxBerg).
It's a converter from text files to PDF format files.  

=head1 Features

TXT2PDF is a native converter,  you don't need to  pass through PostScript
format.  Some  feature  of TXT2PDF includes :

 o every   word  like  http://...   ftp://...   mailto:...   https://... 
   file:...  ldap:... news:...  will become an URL
 o every word like mime:... will become a link that launch the correct
   application and opens the file 
 o you can produce a 2-columns PDF o you can add page number in every page
 o you can add text at the beginning and at the end of every file
 o you can add a border to every page
 o you can use a few parse commands (e.g. [!blue]...[!/blue])

=head1 Options

where options include:

    -help                        print out this message
    -configure file              default txt2pdf.cfg
    -landscape
    -2                           format in 2 columns
    -paper format                default letter, valid formats: A3 (or a3),
                                 A4 (or a4), A5 (or a5), widthxheight
    -npage                       add page number
    -recursive directory         scan recursively the directory
    -match     files             match different files ex. *.pdf, a?.*
                                 (require -recursive option)
    -border                      border line
    -allowinparse                parser
    -verbose                     verbose

list:

   with list you can use metacharacters and relative and absolute path 
   name

-configure  filename:  with this option you can configure an alternate
configuration file (the default  configuration  file  is  txt2pdf.cfg,
located  in txt2pdf directory).  This option is very useful if you use
txt2pdf in a automatic task (e.g.  cron).  e.g.
 
  txt2pdf -c c.cfg *.c
  txt2pdf -m "a*.txt" -r my_directory

-match files -recursive directory: with  these option  you can convert 
all the files in the directory and in every its subdirectories
e.g
txt2pdf -m "a*.txt" -r .
to convert  every file  beginning with a and with txt extension to PDF
inside the . directory and in every its subdirectories 

Every file of the list is converted in a PDF file.  If the file has an
extension the extension is changed with .pdf extension,  if  the  file
doesn't have an extension the .pdf extension is added.
If  the  line  in  the  input file is longer than the cols number, the
words after are put in the next line.  The word on cols  number  isn't
divided and it is put in the next line.

ASCII 8 chars are converted using ISO Latin1 Encoding

CreationDate (The date the document was created) in Info dictionary is
automatically set.

The   automatic   convertion   of  words  like  http://...   ftp://...
mailto:...  https://...  file:...  ldap:...  news:...  to URLs.

=cut
