#!/usr/bin/perl
#
# txt2pdf.pl from mcollins@fcnetwork.com
#
# MC's Q&D text to PDF converter.
#
# FYI,
#
# I wrote a simple text file to PDF converter that uses PDF::API2::Lite.
# It isn't full-featured by any stretch but it does illustrate one of the
# many uses of this cool module.  I'm submitting it here for your perusal.
# If you think of any useful things to add to it please let me know.
# Fredo, please feel free to include it in the contributed items if you
# would like.
#
# Thanks!  (Sorry about the long comments that wrap around to the next
# line...)
# 
# -MC
#
use strict;
use warnings;
use PDF::API2::Lite;
use Getopt::Long;
use File::Basename;

$|++;                   # turn off buffering

my $pdf;              	# main PDF document object
my $page;             	# current page being processed
my $text;             	# current page's text object
my $font;             	# current font being used

# variables from the command line
my $left;             	# left margin/starting point; default = 36pts from page
my $top;              	# top margin/starting point; default = 36pts from page
my $infile;           	# input path & file (from cmd line arg - could be glob)
my $lpp;              	# lines per page
my $layout;           	# portrait or landscape; default = portrait
my $landscape;          # landscape cmd line flag
my $fontsize;           # font size; default = 7.25
my $bold;             	# set to 1 for bold on; default = 0;
my $spacing;          	# text spacing ($pdf->textlead); default = 8

# other variables
my @FILES;            	# list of input files, in case of glob
my $file;             	# Current file being converted
my $destpath;           # destination path
my $outfile;          	# output path & file
my $linecount;        	# how many lines have been processed on this page
my $arg;              	# command line argument being processed
my $help;               # Flag for displaying help

$fontsize = 7.25;     	# unless otherwise specified, font size is 7.25
$spacing  = 8;        	# unless otherwise specified, spacing is 8

$layout = "Portrait"; 	# default page layout


if ($#ARGV < 0) {
  print "Usage:\n";
  print "txt2pdf <options> <textfilename>\n";
  exit(1);
}
# get those cmd line args!
my $opts_okay = GetOptions(
	'h'             => \$help,
	'help'          => \$help,		# Can use -h or --help
	'lpp=i'         => \$lpp,
	'left=f'        => \$left,
	'top=f'         => \$top,
	'fontsize=f'    => \$fontsize,
	'spacing=f'     => \$spacing,
	'b'             => \$bold,
	'l'             => \$landscape,
	'in=s'          => \$infile,
	'dir=s'         => \$destpath,
);

# if help, then display usage
if ( $help ) { &usage; exit(0); }

# Check filename
if ( ! $infile ) {
	die "Please specify a file name or glob with --in=<filename>\n";
	exit(1);
}

# Check path
if ( ! $destpath ) { $destpath = '/default/path/'; }

# Check for filename vs. filespec(glob)
if ( $infile =~ m/\*|\?/ ) {
	print "Found glob spec, checking...\n";
	@FILES = glob($infile);
	if ( ! @FILES ) {
		die "No files match spec: '$infile', exiting...\n";
	} # if no files match
	print "Found file";
	if ( $#FILES > 0 ) { print "s"; }               # Be nice, use plural
	print ":\n";
	foreach ( @FILES ) {
		print "$_\n";
	} # foreach @FILES

} else {
	if ( ! -f $infile ) {
		die "Could not locate file '$infile', exiting...\n";
	} # if $infile not found
	@FILES = ( $infile );
} # if $infile contains wildcards

# Validate remaining cmd line args

if ( $landscape ) {
	## Set up landscape defaults and maxima
	$layout = 'landscape';

	## Set default lines per page if necessary
	if ( ! $lpp	) { $lpp 	= 45; }     # Landscape default lines per page

	## If left margin not specified, default to 1/2" or 36 points
	if ( ! $left 	) { $left 	= 36; }   # Default left margin

	## Left margin shouldn't be more than 10.5" (756 points) from left edge of page
	if ( ! $left > 756 ) {
		$left = 756;            # Landscape max left margin (in points)
	} # if $left greater than 756 points

	## For top margin, need to calculate number of points from top of page
	## Example, 1/2" margin is 36 points from top of page
	## Top of page is 612 points, 1/2" down is 576 points (612 - 36 = 576)
	if ( ! $top  ) {
		$top = 612 - 36;      # Calculate 36 pts (1/2") from top of page
	} else {
		$top = 612 - $top;    # Calculate $top pts from top of page
	} # if top margin not specified

} else {
	## Set up portrait defaults and maxima

	## Set default lines per page if necessary
	if ( ! $lpp      ) { $lpp 	= 60; }         # Landscape default lines per page

	## If left margin not specified, default to 1/2" or 36 points
	if ( ! $left     ) { $left 	= 36; }         # Default left margin

	## Left margin shouldn't be more than 8" (576 points) from left edge of page
	if ( ! $left > 576 ) {
		$left = 576;                            # Landscape max left margin (in points)
	} # if $left greater than 576 points

	## For top margin, need to calculate number of points from top of page
	## Example, 1/2" margin is 36 points from top of page
	## Top of page is 792 points, 1/2" down is 756 points (792 - 36 = 756)
	if ( ! $top  ) {
		$top = 792 - 36;                        # Calculate 36pts (1/2") from top of page
	} else {
		$top = 792 - $top;                      # Calculate $top pts from top of page
	} # if top margin not specified

} # if landscape or portrait

# Set max, min spacing
if ( $spacing > 720 ) { $spacing = 720;	}         # why would anyone want this much spacing?
if ( $spacing < 1   ) { $spacing = 1; 	}         # That's awfully crammed together...

foreach $file ( @FILES ) {
  	print "Processing $file...\n";
  	my ($name,$dir,$suf) = fileparse($file,qr/\.[^.]*/);

  	if ( $suf =~ m/txt2pdf|txt/) {
  		# replace .txt or .txt2pdf with .pdf
    	$outfile = $destpath . $name . '.pdf';
  	} else {
  		# just append .pdf to end of filename
  		$outfile = $destpath . $name . $suf . '.pdf';
  	} # if suffix is '.txt' or '.txt2pdf'

	$pdf = PDF::API2::Lite->new;

  	&newpage;      # create first page in PDF document

  	open (FILEIN,"$file") or die "$file - $!\n";
  	while(<FILEIN>) {
    	#chomp;
	# chomp is insufficient when dealing with EOL from different systems
    	# this little regex will make things a bit easier
    	s/(\r)|(\n)//g;

    	if (m/\x0C/ || $linecount >= $lpp) {    # found page break
          &newpage;
	    next;
    	} # if
    	$pdf->text($_);
    	$pdf->nl;
    	$linecount++;

  	} # while(<FILEIN>)
  	$pdf->textend;
  	close(FILEIN);
  	$pdf->saveas($outfile);
} # foreach $file (@FILES)

sub newpage() {
  	if ($layout =~ m/l/i) { $pdf->page(792,612);}
  	else { $pdf->page(612,792); }

  	if ( $bold ) { $font = $pdf->corefont('CourierBold');}
  	else {$font = $pdf->corefont('Courier');}

  	$pdf->textstart;
  	$pdf->textlead($spacing);
  	$pdf->transform(-translate => [$left,$top]);
  	$pdf->textfont($font,$fontsize);
  	$linecount = 1;
}

sub usage() {
print << 'END_OF_USAGE'

MC's Text to PDF converter (very cheesy, but useful nonetheless)

Usage:
txt2pdf [options] <source file name>

Options:

  --lpp=##    specify number of lines per page
              Note: portrait/landscape, margins and font size all affect the
              placement of text on a page.  You may need to experiment

  --left=##   specify left margin in points. 72 points = 1 inch

  --top=##    specify top margin in points. 36 points = .5 inch

  -h, --help  This help page

  --size=##   Set font size; default is 7.25

  --spacing=# Set the spacing between lines; default is 8

  -b, -B      Set bold type to on; default is not bold

  -l, -L      Set doc to landscape; default is portrait


  Special thanks to Alfred Reibenschuh for such a cool Perl module!
  Also, many thanks to the PDF::API2 community for such great ideas.

END_OF_USAGE
}

__END__