#!/usr/bin/perl

# All information about the command line options of the proprietary Lexmark
# filters (/usr/local/lexmark/<model>/<model>, e. g.:
# /usr/local/lexmark/z52/z52) are obtained calling the filter with the
# "--help" option.

# === ADAPT THIS TO FIT TO YOUR ENVIRONMENT ===============================

# The name of the GhostScript executable, add the path if it is not in the
# standard path for executables
my $ghostscript = "gs";

# The path where your Lexmark printer driver is installed
my $lexmarkpath = "/usr/local/lexmark";

# =========================================================================

# Read in all command line options

use Getopt::Std;
# Model, media Type, Resolution, Image type, Cartridge, Dithering, Port
# alignA, alignB, alignC, alignD, alignE, alignF
getopts("m:t:r:i:c:d:p:A:B:C:D:E:F:");

# Read the "-m" option to get the model

my $model = $opt_m;
if (!defined($model)) {die "Printer model not specified, use \"-m z13\", \"-m z22\", \"-m z23\", \"-m z32\", \"-m z33\", \"-m z52\", or \"-m z53\".\n"};

if (!($model =~ m/^[zZ]([235][23]|13)$/)) {die "Chosen model does not exist, use \"-m z13\", \"-m z22\", \"-m z23\", \"-m z32\", \"-m z33\", \"-m z52\", or \"-m z53\".\n"};

$model =~ tr/Z/z/;
$model =~ s/z22/z32/; # The Z22 and Z32 are compatible to each other
$model =~ s/z23/z33/; # The Z22 and Z32 use also the same driver

my $lexmarkfilter = $lexmarkpath . "/$model/$model";
my $lexmarkconfig;
if ($model eq "z32") {
    $lexmarkconfig = "z22-z32.conf";
} elsif ($model eq "z33") {
    $lexmarkconfig = "z23-z33.conf";
} else {
    $lexmarkconfig = "$model.conf";
}

# The paper size is stuffed into the PostScript file (it must be given
# this way for foomatic producing correct PPD files).

# Read out the paper size here

my $maxlines = 1000;            # how many lines to examine?
my $more_stuff = 1;             # there is more stuff in stdin.
my $linect = 0;                 # how many lines have we examined?
my $papersizex= "612";	        # The default size is "Letter".
my $papersizey= "792";

do {
    my $line;
    if ($line=<STDIN>) {
        #if ($linect == 0) {
        #    # Line zero should be postscript leader
        #    die 'job does not start with Postscript %! thing.\n'
        #        if $line !~ m/^.?%!/;
        #} else {
            if ($line =~ m!^\s*<<\s*/PageSize\s*\[\s*([0-9]*)\s*([0-9]*)\s*\]\s*/ImagingBBox\s*null\s*>>\s*setpagedevice\s*$!) {
        	$papersizex = $1;
        	$papersizey = $2;
	    }
        #}
        # Push the line onto the stack for later spitting up...
        push (@examined_stuff, $line);
        $linect++;
    } else {
        # EOF!
        $more_stuff = 0;
    }
} while (($linect < $maxlines) and $more_stuff);

# Get the number of the page size for the command line of the Lexmark driver

my @papersizes = ();
if (($model eq "z13") || ($model eq "z23") || ($model eq "z33")) {
    @papersizes = ( ( 612, 792 ),   #Letter
		    ( 595, 842 ),   #A4
		    ( 396, 612 ),   #Statement
		    ( 612, 1008 ),  #Legal
		    ( 516, 729 ),   #B5
		    ( 522, 756 ),   #Executive
		    ( 421, 595 ),   #A5
		    ( 297, 420 ),   #A6
		    ( 216, 360 ),   #Index card
		    ( 0, 0 ),       #Banner A4
		    ( 0, 0 ),       #Banner Letter
		    ( 288, 432 ),   #Post card
		    ( 283, 420 ),   #Hagaki
		    ( 261, 468 ),   #Envelope 6 3/4
		    ( 279, 639 ),   #Envelope 9
		    ( 297, 684 ),   #Envelope 10
		    ( 312, 624 ),   #Envelope DL
		    ( 459, 649 ),   #Envelope C5
		    ( 323, 459 ),   #Envelope C6
		    ( 499, 709 ),   #Envelope B5
		    ( 279, 540 ),   #Envelope 7 3/4
		    ( 315, 413 ),   #A2 Baronial
		    ( 340, 729 ),   #Chokei 3
		    ( 255, 581 ),   #Chokei 4
		    ( 227, 581 ),   #Chokei 40
		    ( 612, 785 ),   #Kakugata 3
		    ( 558, 757 ),   #Kakugata 4
		    ( 539, 680 ),   #Kakugata 5
		    ( 459, 649 ),   #Kakugata 6
		    ( 0, 0 ),       #Custom
		    ( 0, 0 ),       #EK-PH-001 (not retreivable)
		    ( 414, 612 ) ); #EK-PH-011
} else {
    @papersizes = ( ( 612, 792 ),   #Letter
		    ( 612, 1008 ),  #Legal
		    ( 516, 729 ),   #B5
		    ( 595, 842 ),   #A4
		    ( 522, 756 ),   #Executive
		    ( 421, 595 ),   #A5
		    ( 0, 0 ),       #Custom Banner
		    ( 420, 567 ),   #Ohfhagaki
		    ( 283, 420 ),   #Hagaki
		    ( 279, 540 ),   #Envelope Monarch
		    ( 279, 639 ),   #Envelope 9
		    ( 297, 684 ),   #Envelope 10
		    ( 312, 624 ),   #Envelope DL
		    ( 459, 649 ),   #Envelope C5
		    ( 323, 459 ),   #Envelope C6
		    ( 499, 709 ),   #Envelope B5
		    ( 0, 0 ),       #Envelope D5 (not retrivable)
		    ( 0, 0 ),       #Envelope 7 5 (not retrivable)
		    ( 288, 432 ),   #Index 4X6
		    ( 216, 360 ),   #Index 3X5
		    ( 0, 0 ),       #Banner A4
		    ( 0, 0 ) );     #Banner Letter
}

my $i;
my $papersizeindex = 0; # Default is "Letter"
for ($i = 0; $i < $#papersizes; $i += 2) {
    if (($papersizex > $papersizes[$i]-3) &&
        ($papersizex < $papersizes[$i]+3) &&
        ($papersizey > $papersizes[$i+1]-3) &&
        ($papersizey < $papersizes[$i+1]+3)) {
	$papersizeindex = $i / 2;
	last;
    }
}

# Add the options to the command line

# Page size
my $driveroptions = "--mediasize $papersizeindex";

# Media Type
my $mediatype = $opt_t;
if ((defined($mediatype)) && ($mediatype ne "default")) 
    {$driveroptions = "$driveroptions --mediatype $mediatype"};

# Resolution
my @resolutions = ( (  300, "Quick Print" ), #  300 dpi
		    (  600, "Normal" ),      #  600 dpi
		    ( 1200, "Better" ),      # 1200 dpi
		    ( 2400, "Best" ) );      # 2400 dpi
my $resolution = $opt_r;
my $gsres;
if ((defined($resolution)) && ($resolution ne "default")) {
    my $resolution_name;
    if (($model eq "z13") || ($model eq "z23") || ($model eq "z33")) {
        # The Z13/Z23/Z33 needs a verbose description instead of numbers
        for ($i = 0; $i < 8; $i += 2) {
            if ($resolution eq $resolutions[$i]) {
	        $resolution_name = $resolutions[$i+1];
	        break;
	    }
	}
	$gsres = "600";
    } else {
        # All other printers take just the dpi value
        $resolution_name = $resolution;
	if ($resolution eq "300") {
	    $gsres = "300";
	} else {
	    $gsres = "600";
	}
    }
    
    {$driveroptions = "$driveroptions --resolution $resolution_name"};
}

# Image Type
my $imagetype = $opt_i;
if ((defined($imagetype)) && ($imagetype ne "default")) 
    {$driveroptions = "$driveroptions --intent $imagetype"};

# Ink Type
my $inktype = $opt_c;
if ((defined($inktype)) && ($inktype ne "default")) 
    {$driveroptions = "$driveroptions --output $inktype"};

# Dithering
my $dither = $opt_d;
if ((defined($dither)) && ($dither ne "default")) 
    {$driveroptions = "$driveroptions --halftone $dither"};

# Port
my $port = $opt_p;
if (!(defined($port))) {die "Specification of the port where the printer is connected needed.\n"};

# Head Alignment
my $align_a = $opt_A;
my $align_b = $opt_B;
my $align_c = $opt_C;
my $align_d = $opt_D;
my $align_e = $opt_E;
my $align_f = $opt_F;

if ((defined($align_a)) && (defined($align_b))) {
    $driveroptions = "$driveroptions --align $align_a,$align_b";
    if ((defined($align_c)) && (defined($align_d))) {
	$driveroptions = "$driveroptions,$align_c,$align_d";
	if ((defined($align_e)) && (defined($align_f))) {
	    $driveroptions = "$driveroptions,$align_e,$align_f";
	}
    }
}

# Try to find foomatic-gswrapper, use it if it is available
for (split(':', $ENV{'PATH'})) {
    if (-x "$_/foomatic-gswrapper") {
	$ghostscript="$_/foomatic-gswrapper";
	last;
    }
}

my $cmdline = "| $ghostscript -q -dBATCH -dNOPAUSE -dSAFER -r$gsres -sDEVICE=ppmraw -sOutputFile=- - | $lexmarkfilter --config $lexmarkconfig $driveroptions --dotcounts > $port";

# Print the job

open PRINTER, $cmdline or die "Could not run printing command line.\n";
print PRINTER @examined_stuff; # first 100 lines or so
if ($more_stuff) {
    while (<STDIN>) {
	print PRINTER $_;
    }
}
close PRINTER or die "error closing printing command line.\n";

exit 0;
