#!/usr/bin/perl
# Require Perl5
#
# txt2pdf -- Text to PDF
#
# by SANFACE Software <sanface@sanface.com> 25 March 2002
#
# txt2pdf 5.x is shareware: its cost is $99. 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=6347
# or contact SANFACE Software sanface@sanface.com
#
# This is version 5.6
#
use strict;
use Getopt::Long;
use File::Basename;
use File::Find;
use File::DosGlob 'glob';

my $version="5.6";
my $fpos=0;
my $producer="txt2pdf";
my $pageNO;
my $lineNO;
# Default paper is Letter size
my $pageHeight=792;
my $pageWidth=612;
my @location;
my @pageObj;
my $lines=0; my $bflines=0;
my $buf="";
my $input=""; my $output=""; my $saveinput;
my $elem="";
my $configure="txt2pdf.cfg";
my $help=0; my $default=0; my $verbose=0; my $Version; my $border=0; my $paper="";
my $landscape=0; my $list=0;
my $npage=0; my $stdin=0;
my $transition=""; my $motion=""; my $direction=0; my $dimension=""; my $rotate=0;
my $bgdesign=""; my $fgdesign=""; my $epdi=0; my $epdn=0; my @epd;
my (@color,@fontmark);
my $colori=0; my $fontmarki=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 $pdfdir=""; my $txtdir=""; my $newoutput; my $newinput;
my $txt2pdfHome="http://www.sanface.com/$producer.html";
my $Unregistered="Generated by unregistered $producer v.$version \251 $companyname 2002\nAvailable at $txt2pdfHome \n";
my $SANFACEmail="mailto:sanface\@sanface.com";
my $SECURESERVER="http://www.regsoft.net/purchase.php3?productid=6347";
my $font; my $times = 0; my $timef = 0; my $loop=1;

$configure = $ENV{'TXT2PDFCFG'} if (! -e "$configure");

&GetOptions("configure=s"  => \$configure,
            "help"         => \$help,
            "default"      => \$default,
            "landscape"    => \$landscape,
	    "list=s"       => \$list,
            "paper=s"      => \$paper,
            "npage"        => \$npage,
            "recursive=s"  => \$recursive,
            "match=s"      => \$match,
            "border"       => \$border,
            "pdfdir=s"     => \$pdfdir,
            "txtdir=s"     => \$txtdir,
            ""             => \$stdin,
            "current"      => \$Version,
            "verbose"      => \$verbose) || printusage() ;
my @elem=("tmpdir","author","creator","keywords","subject","title","landscape",
          "paper","font","lines","tab","pointSize","vertSpace","transition",
          "npage","colour","fontmark","beginfile","endfile","border","bgdesign","fgdesign",
          "pagemode","pagelayout","rotate","typeencoding","withextension",
          "sleep","pdfdir","txtdir","viewerpreferences","fit","list");
my %option=(tmpdir             => './',
            author             => '',
            creator            => '',
            keywords           => '',
            subject            => '',
            title              => '',
            landscape          => '0',
            paper              => 'letter',
            font               => 'Courier',
            npage              => '0',
            lines              => '',
            pointSize          => '10',
            vertSpace          => '12',
            transition         => '',
            tab                => '8',
            colour             => '',
            fontmark           => '',
            beginfile          => '',
            endfile            => '',
            border             => '0',
            bgdesign           => '',
            fgdesign           => '',
            pagemode           => '',
            pagelayout         => '',
            typeencoding       => 'default',
            rotate             => '0',
            withextension      => '0',
            sleep              => '0',
            pdfdir             => '',
            txtdir             => '',
	    viewerpreferences  => '',
            fit                => '0',
            list               => '');

if($Version) {print "$producer $version\n";exit;}
$help and printusage();
$default and defaultparams();
my $tmpelem; my $var;
if (-e $configure) {
  open (CNF, "$configure");
  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) {
        $tmpelem=$1;
        if ($tmpelem=~/#!ENV#(.*)#!\/ENV#/) {
          $var=$ENV{$1};
          $tmpelem=~s/#!ENV#(.*)#!\/ENV#/$var/;
          }
        $option{$elem}=$tmpelem;
        }
      }
    }
  close(CNF);
  } else {
  &Warning("to set your txt2pdf configuration file you can use:\ntxt2pdf.cfg or -configure your_txt2pdf.cfg or TXT2PDFCFG\nElse the program will use the default parameters\n-default to see the default parameters\n")
  }
$list and $option{'list'}=$list;
if ($option{'list'}) {
open (LIST, "$option{'list'}") ||
     die "txt2pdf: couldn't open list file $option{'list'}\n";
  while (<LIST>) {
    s/\t/ /g;        #replace tabs by space
    next if /^ *\#/; #ignore comment lines
    next if /^ *$/;  #ignore empty lines
    push @ARGV,$_;
    }
close(LIST);
  }
$paper and $option{'paper'}=$paper;
$landscape and $option{'landscape'}=$landscape;
$npage and $option{'npage'}=$npage;
$border and $option{'border'}=$border;
$pdfdir and $option{'pdfdir'}=$pdfdir;
$txtdir and $option{'txtdir'}=$txtdir;

print <<FEE;

This is an UNREGISTERED version of $producer.
Registration fee is \$99.
Register NOW via a SECURE SERVER at
$SECURESERVER
or contact $companyname $SANFACEmail


FEE

if ($stdin) {push @ARGV,"-";}
if (uc($option{'paper'}) =~ /A3/)           {$pageWidth=842;  $pageHeight=1190;}
elsif (uc($option{'paper'}) =~ /A4/)        {$pageWidth=595;  $pageHeight=842; }
elsif (uc($option{'paper'}) =~ /A5/)        {$pageWidth=421;  $pageHeight=595; }
elsif (uc($option{'paper'}) =~ /TABLOID/)   {$pageWidth=792;  $pageHeight=1224;}
elsif (uc($option{'paper'}) =~ /LEDGER/)    {$pageWidth=1224; $pageHeight=792; }
elsif (uc($option{'paper'}) =~ /LEGAL/)     {$pageWidth=612;  $pageHeight=1008;}
elsif (uc($option{'paper'}) =~ /STATEMENT/) {$pageWidth=396;  $pageHeight=612; }
elsif (uc($option{'paper'}) =~ /EXECUTIVE/) {$pageWidth=540;  $pageHeight=720; }
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'}) && (uc($option{'paper'}) !~ /LETTER/))
    {&Warning("the set paper $option{'paper'} isn't supported\n$producer will use the default paper (letter)")}
  }

if ($option{'landscape'}) {
  my $tmp=$pageHeight;
  $pageHeight=$pageWidth;
  $pageWidth=$tmp;
  }
my $npagex=$pageWidth/2;
my $npagey=20;
my $typeencoding=$option{'typeencoding'};
if (($typeencoding !~ /MacRomanEncoding/) && ($typeencoding !~ /MacExpertEncoding/) && ($typeencoding !~ /WinAnsiEncoding/) && ($typeencoding !~ /default/))
  {&Warning("the set encoding $typeencoding isn't MacRomanEncoding or MacExpertEncoding or WinAnsiEncoding or default\n$producer will use the default encoding (ISOLatin1Encoding)")}

if ($option{'transition'} =~ /replace/) {$transition=""}
elsif ($option{'transition'} =~ /dissolve/) {$transition="Dissolve"}
elsif ($option{'transition'}=~/box!(.*)!/)
  {
  $transition="Box";
  if ($1 eq "I" || $1 eq "O") {$motion=$1}
  else     {
    &Warning("the set motion $1 with $transition transition isn't supported\n$producer will use the $transition I (Input) motion");
    $motion="I";
    }
  }
elsif ($option{'transition'}=~/glitter!(.*)!/)
  {
  $transition="Glitter";
  if ($1 == 0 || $1 == 270 || $1 == 315) {$direction=$1}
  else
    {&Warning("the set direction $1 with $transition transition isn't supported\n$producer will use the $transition 0 direction")}
  }
elsif ($option{'transition'}=~/wipe!(.*)!/)
  {
  $transition="Wipe";
  if ($1 == 0 || $1 == 90 || $1 == 180 || $1 == 270) {$direction=$1}
  else
    {&Warning("the set direction $1 with $transition transition isn't supported\n$producer will use the $transition 0 direction")}
  }
elsif ($option{'transition'}=~/blinds!(.*)!/)
  {
  $transition="Blinds";
  if ($1 eq "H" || $1 eq "V") {$dimension=$1}
  else     {
    &Warning("the set dimension $1 with $transition transition isn't supported\n$producer will use the $transition H dimension");
    $dimension="H";
    }
  }
elsif ($option{'transition'}=~/split!(.*)!(.*)!/)
  {
  $transition="Split";
  if ($1 eq "H" || $1 eq "V") {$dimension=$1}
  else     {
    &Warning("the set dimension $1 with $transition transition isn't supported\n$producer will use the $transition H dimension");
    $dimension="H";
    }
  if ($2 eq "I" || $2 eq "O") {$motion=$2}
  else     {
    &Warning("the set motion $1 with $transition transition isn't supported\n$producer will use the $transition I (Input) motion");
    $motion="I";
    }
  }
else { 
  if ($option{'transition'})
    {
    &Warning("the set transition $option{'transition'} isn't supported\n$producer will use the default transition (replace)");
    $option{'transition'}="";
    }
  }

  if (($option{'pagemode'} !~ /FullScreen/) && ($option{'pagemode'} ne "")){
    &Warning("the set page mode $option{'pagemode'} isn't supported\n$producer will use the default page mode (UseNone)");
    $option{'pagemode'}="";
    }

  if (($option{'pagelayout'} !~ /OneColumn/) && ($option{'pagelayout'} !~ /TwoColumnRight/) && ($option{'pagelayout'} !~ /TwoColumnLeft/) && ($option{'pagelayout'} ne "")) {
    &Warning("the set page layout $option{'pagelayout'} isn't supported\n$producer will use the default page layout (SinglePage)");
    $option{'pagelayout'}="";
    }

if ($option{'lines'}) {$lines = $option{'lines'}}
else {$lines = ($pageHeight - 72) / $option{'vertSpace'}}
$lines = int $lines;
if (($option{'font'} !~ /Courier/) && ($option{'font'} !~ /Helvetica/) && ($option{'font'} !~ /Times/)) {
  &Warning("the set font $option{'font'} isn't Courier or Helvetica or Times\n$producer will use the default font (Courier)");
  $option{'font'}="Courier";
  }
if (($option{'rotate'} == 0) || ($option{'rotate'} == 90) || ($option{'rotate'} == 180) || ($option{'rotate'} == 270))
  {$rotate=$option{'rotate'}}
else {
   &Warning("the set rotate $option{'rotate'} isn't supported\n$producer will use the default rotate (0)");
   $rotate=0;
   }
if ($option{'colour'})
  {
  open (COLOUR, "$option{'colour'}") ||
     die "txt2pdf: couldn't open colour file $option{'colour'}\n";
  while (<COLOUR>) {
    if (/^(.*);(.*)$/) {
      $color[$colori*4]=$1;
      ($color[$colori*4+1],$color[$colori*4+2],$color[$colori*4+3])=split(/:/,$2);
#      if($color[$colori*4+1] > 1.0 || $color[$colori*4+2] > 1.0 || $color[$colori*4+3] > 1.0) {
#        # Use 255 based color scheme
#        my($i);
#        for($i=1;$i<4;$i++){$color[$colori*4+$i] = sprintf("%4f",$color[$colori*4+$i]/255.0)}
#        }
      $colori++;
      }
    }
  close(COLOUR);
  }
if ($option{'fontmark'})
  {
  open (FONTMARK, "$option{'fontmark'}") ||
     die "txt2pdf: couldn't open fontmark file $option{'fontmark'}\n";
  while (<FONTMARK>) {
    if (/^(.*);(.*)$/) {
      $fontmark[$fontmarki*2]=$1;
      $fontmark[$fontmarki*2+1]=$2;
      if    ($fontmark[$fontmarki*2+1] eq "bold") {$fontmark[$fontmarki*2+1]="/F3"}
      elsif ($fontmark[$fontmarki*2+1] eq "italic") {$fontmark[$fontmarki*2+1]="/F2"}
      elsif ($fontmark[$fontmarki*2+1] eq "bolditalic") {$fontmark[$fontmarki*2+1]="/F4"}
      else {$fontmark[$fontmarki*2+1]="/F1"}
      $fontmarki++;
      }
    }
  close(FONTMARK);
  }
if ($option{'bgdesign'})
  {
  open (BGDESIGN, "$option{'bgdesign'}") ||
     die "$producer: couldn't open background design file $option{'bgdesign'}\n";
  while (<BGDESIGN>) {
    s/\015$//;
    if (/^#!epd#(.*);(.*);(.*);(.*);(.*);(.*);(.*)#!\/epd#$/) {
      $epd[$epdi*9]=$1;
      $epd[$epdi*9+2]=0;
      $epd[$epdi*9+3]=$2;
      $epd[$epdi*9+4]=$3;
      $epd[$epdi*9+5]=$4;
      $epd[$epdi*9+6]=$5;
      $epd[$epdi*9+7]=$6;
      $epd[$epdi*9+8]=$7;
      $epdi++;
      next;
      }
    $bgdesign.=$_;
    }
  close(BGDESIGN);
  }
if ($option{'fgdesign'})
  {
  open (FGDESIGN, "$option{'fgdesign'}") ||
     die "$producer: couldn't open foreground design file $option{'fgdesign'}\n";
  while (<FGDESIGN>) {s/\015$//;$fgdesign.=$_;}
  close(FGDESIGN);
  }

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;
   }

SLEEP:
if ($recursive) {
  if($loop == 1) {
    $match=~s/\./\\./g;
    $match=~s/\*/.*/g;
    $match=~s/\?/./g;
    $match=~s/$/\$/;
    }
  @ARGV=();
  find (\&wanted,"$recursive");
  }

my $URy=$pageHeight - 42;
my $tmpfile = $option{'tmpdir'} . "txt2pdf$$";

  if ($option{'beginfile'}) {
    open (BEGINFILE,$option{'beginfile'}) ||
      die qq!$producer: couldn't open input file $option{'beginfile'}\n!;
    binmode BEGINFILE;
    while(<BEGINFILE>) {
      s/\r?\n$/\n/;
      s/\r/\n/g;
      $bflines++;
      $_=&TAB($_);
      $BF.=$_;
      }
    close(BEGINFILE);
    }
  if ($option{'endfile'}) {
    open (ENDFILE,$option{'endfile'}) ||
      die qq!$producer: couldn't open input file $option{'endfile'}\n!;
    binmode ENDFILE;
    while(<ENDFILE>) {
      s/\r?\n$/\n/;
      s/\r/\n/g;
      $_=&TAB($_);
      $EF.=$_;
      }
    close(ENDFILE);
    }

if (@ARGV) {
  my @files;
  my $i;

  if ($^O =~ /^MSWin32$/i && !$recursive) {
    foreach $i (@ARGV) {
      if($i=~/\*|\?/) {push @files,glob($i)}
      else {push @files,$i}
      }
    }
  else {@files = @ARGV}
  foreach $input (@files) {
    $obj=0;
    $pageNO=0;
    $fpos=0;
    @pageObj='';
    $verbose and $times = time;
    if(!$option{'title'}) {$title=basename($input,"")}
    else {$title=$option{'title'}}
    $verbose and print "Processing $input file\n";
    if ($stdin) {open (OUT, ">-") || die "$producer: couldn't open standard output\n"}
    else {
      $output=$input;
      $saveinput=$input;
      my $out=basename($output,"");
      if ($out=~/(.*)\..*/ and !$option{'withextension'}) {$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 "$producer: couldn't open output file $output\n";
    }
    binmode OUT;
    &ReorganizeFile($input);
    &WriteLink($tmpfile);
    &WriteHeader();
    &WritePages($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);
    }
  if($option{'txtdir'} ne "")
    {
    $newinput=$option{'txtdir'}.basename($saveinput);
    rename $saveinput,$newinput;
    $verbose and print "Moving $saveinput file in the $option{'txtdir'} directory\n";
    }
  if($option{'pdfdir'} ne "")
    {
    $newoutput=$option{'pdfdir'}.basename($output);
    rename $output,$newoutput;
    $verbose and print "Moving $output file in the $option{'pdfdir'} directory\n";
    }
  if ($verbose) {$timef = time; printf ("PDF generation time = %4.2f sec\n", $timef - $times );}
  if($option{'sleep'}) {
    sleep $option{'sleep'};
    $loop++;
    $verbose and print "\nLoop number $loop\n";
    goto SLEEP;
    }
  } else {
  print "$producer -help to read the online help\n";
  if($option{'sleep'}) {
    sleep $option{'sleep'};
    $loop++;
    $verbose and print "\nLoop number $loop\n";
    goto SLEEP;
    }
  }

sub ReorganizeFile {
  my $file=shift(@_);

  my $i;
  my $temporary;
  open (IN, "$file") || die "$producer: couldn't open input file $file\n";
  open (TEMP, ">$tmpfile") || die "$producer: couldn't open temporary file $tmpfile\n";
  binmode TEMP;
  if($BF) {print TEMP "$BF"}
  binmode IN;
  while (<IN>) {
    s/\r?\n$/\n/;
    s/\r/\n/g;
    $_ = &TAB($_);
    print TEMP "$_";
    }
  if($EF) {print TEMP "$EF"}
  print TEMP "\n";
  print TEMP $Unregistered;
  close(IN);
  close(TEMP);
  }

sub WriteLink {
  my $file=shift(@_);

  # 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 "$producer: couldn't open input file $file\n";
  my $linktemp;
  binmode IN;
  while (<IN>) {
    $line++;
    $linktemp=$_;
    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 ($line == $lines) {
        $line=0;
        $page++;
      }
    }
  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;
  my $gm = (gmtime(time))[2];
  my $local = (localtime(time))[2];
  my $diff = $local - $gm;
  if ($diff <= -12) { $diff += 24 }
  elsif ($diff > 12) { $diff -= 24 }
  my $zone = $diff;
  if ($zone =~ /-/) {$zone = sprintf "%.2d00", $zone}
  else  {$zone = sprintf "+%.2d00", $zone}
  $date=sprintf "D:$year%.2ld%.2ld%.2ld%.2ld%.2ld$zone",$mon,$mday,$hour,$min,$sec;
  $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 2002)\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;
  $epdn=($#epd+1)/9;
  my $i=0;
  my $epdbox="";
  for (1..$epdn) {
    open (EPD, $epd[$i*9]) || die "$producer: couldn't open image $epd[$i*9]\n";
    binmode EPD;
    while (<EPD>) {
      s/\r?\n$/\n/;
      s/\r/\n/g;
      /BBox\((.*)\)/ and $epdbox=join(' ',split(/,/,$1));
      }
    $location[++$obj]=$fpos;
    $epd[$i*9+2]=$obj;
    &pos("$obj 0 obj\n");
    &pos("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1 /Name /Fm$i\n/Matrix [ 1 0 0 1 0 0 ]\n/BBox [ $epdbox ]\n");
    $buf=sprintf "/Length %d 0 R ",$obj+1; &pos($buf);
    &pos("/Resources << >> >>\n");
    &pos("stream\n");
    my $streamStart=$fpos;
    open (EPD, $epd[$i*9]) || die "$producer: couldn't open image $epd[$i*9]\n";
    binmode EPD;
    while (<EPD>) {
      / *%(.*)/ and next;
      &pos("$_");
      }
    close(EPD);
    my $streamEnd=$fpos;
    &pos("\nendstream\n");
    &pos("endobj\n");
    $location[++$obj]=$fpos;
    &pos("$obj 0 obj\n");
    $buf=sprintf "%d\n",$streamEnd-$streamStart; &pos($buf);
    &pos("endobj\n");
    $i++;
    }
  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");
  if ($typeencoding eq "WinAnsiEncoding") {&pos("/BaseEncoding /WinAnsiEncoding\n")}
  elsif ($typeencoding eq "MacRomanEncoding") {&pos("/BaseEncoding /MacRomanEncoding\n")}
  elsif ($typeencoding eq "MacExpertEncoding") {&pos("/BaseEncoding /MacExpertEncoding\n")}
  else {
    &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("  /XObject << ");
  $i=0;
  for (1..$epdn) {
    &pos("/Fm$i $epd[$i*9+2] 0 R ");
    $i++;
    }
  &pos(">>\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 $converted=0;

  open (IN, "$file") || die "$producer: couldn't open input file $file\n";
  my $beginstream = &StartPage();
  $lineNO=-1;
  binmode IN;
  while (<IN>) {
    $temp=$_;
    $lineNO++;
    if ($lineNO eq $lines) {
      if ($option{'npage'}) {
        &pos("/F2 $option{'pointSize'} Tf\n");
        &pos("1 0 0 1 $npagex $npagey Tm\n($pageNO) Tj\n");
        &pos("/F1 $option{'pointSize'} Tf\n");
        }
      &EndPage($beginstream);
      $beginstream = &StartPage();
      }
    chop($temp);
    $temp=~s/\\/\\\\/g;
    $temp=~s/\(/\\(/g;
    $temp=~s/\)/\\)/g;
    &pos("T* (");
    my $color=($#color+1)/4;
    my $il=0;
    for (1..$color) {
      $temp=~s/($color[$il*4])/) Tj\n $color[$il*4+1] $color[$il*4+2] $color[$il*4+3] rg\n ($1) Tj\n 0 0 0 rg\n (/g;
      $il++;
      }
    my $fontmark=($#fontmark+1)/2;
    $il=0;
    for (1..$fontmark) {
      $temp=~s/($fontmark[$il*2])/) Tj\n $fontmark[$il*2+1] $option{'pointSize'} Tf\n ($1) Tj\n \/F1 $option{'pointSize'} Tf\n (/g;
      $il++;
      }
#    if ($temp=~/((http|ftp|mailto|mime|https|file|ldap|news):[^ \n]*) /i)
#      {
#      $substring=") Tj\n 0 0 1 rg\n ($1) Tj\n 0 0 0 rg (";
#      $temp=~s/$1/$substring/g;
#      }
    &pos("$temp");                                               
    &pos(") Tj\n");
    }
  close(IN);
  if ($option{'npage'}) {
    &pos("/F2 $option{'pointSize'} Tf\n");
    &pos("1 0 0 1 $npagex $npagey Tm\n($pageNO) Tj\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("/OpenAction << /Dest [ 1 /XYZ null null 5 ] >>\n");
  if ($option{'pagemode'}) {&pos("/PageMode /$option{'pagemode'}\n")};
  if ($option{'pagelayout'}) {&pos("/PageLayout /$option{'pagelayout'}\n")};
  if ($option{'viewerpreferences'}) {&pos("/ViewerPreferences <<$option{'viewerpreferences'}>>\n")}
  if ($option{'fit'}) {&pos("/OpenAction <</S /GoTo /D [0 /Fit]>>\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 \n");
  my $num="";
  for ($i=1;$i<=$obj;$i++) {
    $buf=sprintf "%.10ld 00000 n \n",$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);
  &pos("/Rotate $rotate\n");
  if ($transition eq "Dissolve") {&pos("/Trans << /Type /Trans /S /$transition >>\n")}
  if ($transition eq "Box") {&pos("/Trans << /Type /Trans /S /$transition /M /$motion >>\n")}
  if ($transition eq "Glitter") {&pos("/Trans << /Type /Trans /S /$transition /Di $direction >>\n")}
  if ($transition eq "Wipe") {&pos("/Trans << /Type /Trans /S /$transition /Di $direction >>\n")}
  if ($transition eq "Blinds") {&pos("/Trans << /Type /Trans /S /$transition /Dm /$dimension >>\n")}
  if ($transition eq "Split") {&pos("/Trans << /Type /Trans /S /$transition /Dm /$dimension /M /$motion >>\n")}
  $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;
  my $i=0;
  if ($epdn) {
    $i=0;
    for (1..$epdn) {
      &pos("q $epd[$i*9+3] $epd[$i*9+4] $epd[$i*9+5] $epd[$i*9+6] $epd[$i*9+7] $epd[$i*9+8] cm /Fm$i Do Q\n");
      $i++;
      }
    }
  my $default=15;
  my $Width=$pageWidth - $default;
  my $Height=$pageHeight - $default;
  if ($option{'border'}) {
    &pos("2 w\n");
    &pos("1 1 1 rg\n");
    &pos("$default $default m\n$Width $default l\n");
    &pos("$Width $default m\n$Width $Height l\n");
    &pos("$Width $Height m\n$default $Height l\n");
    &pos("$default $Height m\n$default $default l\n");
    &pos("B*\n");
    }
  if ($bgdesign) {&pos("$bgdesign")}
  &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;
  &pos("ET\n");
  if ($fgdesign) {&pos("$fgdesign")}
  $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=0;
  }

sub Link {
  my $linkbegin=shift(@_);
  my $linkend=shift(@_);
  my $link=shift(@_);
  my $type=shift(@_);

  my $tmpline=$line;
  $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");
# LLx LLy URx URy
  if ($option{'font'} eq "Courier") {
    $buf=sprintf "/Rect [%d %d %d %d]\n",
$LLx+$linkbegin*$option{'pointSize'}*0.6,
$URy-($tmpline)*($option{'vertSpace'}-$option{'pointSize'})-$tmpline*$option{'pointSize'},
$LLx+($linkbegin+$linkend)*$option{'pointSize'}*0.6+$option{'pointSize'}*0.3,
$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 [0 0 1]\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;
  print OUT "$string";
  }

sub Warning {
  my $string = shift(@_);
  print <<WARNING;
Warning: $string

WARNING
  }

sub printusage {
    print <<USAGEDESC;

usage:
        $producer [-options ...] list

where options include:
    -help                        print out this message
    -default                     print out the default parameters
    -configure file              default $producer.cfg
    -landscape
    -list file                   a list of textual input files
    -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
    -pdfdir directory            the directory where you want to put the PDFs
    -txtdir directory            the directory where you want to put the texts
    -current                     the program version
    -verbose                     verbose
    -                            use STDIN and STDOUT

list:
    with list you can use metacharacters and relative and absolute path name

example:
    $producer *.txt
    $producer -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 $producer!

Home: $txt2pdfHome

USAGEDESC
    exit(1);
}

sub defaultparams {
    print <<DEFAULTPARAMS;

tmpdir : ./
paper : letter
landscape : 0
font : Courier
npage : 0
lines : 60
tab : 8
pointSize : 10
vertSpace : 12
typeencoding : default

DEFAULTPARAMS
    exit(1);
}

exit 0;

# __END__

=head1 NAME

TXT2PDF - Version 5.6 25th March 2002

=head1 SYNOPSIS

Syntax : txt2pdf [-options] files

=head1 DESCRIPTION

TXT2PDF  is a very flexible and powerful PERL5 program.
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 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 background and foreground layers
 o every predefined encodings (WinAnsiEncoding, MacRomanEncoding,
   MacExpertEncoding) supported inside the PDF format is
   supported + the Unix default
 o STDIN and STDOUT support

=head1 Options

where options include:

    -help                        print out this message
    -default                     print out the default parameters
    -configure file              default txt2pdf.cfg
    -landscape
    -list file                   a list of textual input files
    -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
    -pdfdir directory            the directory where you want to put the PDFs
    -textdir directory           the directory where you want to put the texts
    -current                     the program version
    -verbose                     verbose
    -                            use STDIN and STDOUT

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.

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
