diff options
-rw-r--r-- | ChangeLog | 109 | ||||
-rw-r--r-- | README | 32 | ||||
-rw-r--r-- | USAGE | 32 | ||||
-rw-r--r-- | beh.in | 4 | ||||
-rwxr-xr-x | configure | 13 | ||||
-rw-r--r-- | debian/README.Debian | 2 | ||||
-rw-r--r-- | debian/control | 4 | ||||
-rw-r--r-- | debian/copyright | 6 | ||||
-rw-r--r-- | foomatic-gswrapper.1.in | 4 | ||||
-rw-r--r-- | foomatic-gswrapper.in | 21 | ||||
-rw-r--r-- | foomatic-rip.1.in | 12 | ||||
-rw-r--r-- | foomatic-rip.in | 1156 |
12 files changed, 794 insertions, 601 deletions
@@ -1,3 +1,110 @@ +2007-12-04 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-gswrapper.in: Let Ghostscript always use buffered + input. This works around a Ghostscript bug which prevents + printing encrypted PDF files with Adobe Reader 8.1.1 and + Ghostscript built as shared library (Ghostscript bug #689577, + Ubuntu bug #172264). + +2007-11-30 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-rip.in: More bug fixes: + o If the CUPS-style duples option + "-o sides={one|two}-sided[-{long|short}-edge]" was supplied, + the "Duplex" option could be set to "0", "LongEdge", or + "ShortEdge", which do not exist in the "Duplex" options in + PPD files (Thanks to Ricoh Japan for reporting this bug). + o Now all of "LongEdge", "DuplexNoTumble", or "ShortEdge", + "DuplexTumble", are converted to each other if supplied as + value to an enumerated choice option (usually "Duplex") and + this value is not in the list of choices. + o Removed the unused variable "$rangeend" from the + parsepageranges() function. + o Reset the best score for finding the narrowest page range + before treating each option, not only before the first + option. Now jobs with page overrides on more than one + option are executed correctly. + +2007-11-23 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-rip.in: Several fixes for bugs found while developing + the foomatic-rip test suite for the LSB 3.2: + o If an option had the default value "0" (enumerated choice, + numerical, string) in the PPD file, the first choice from + the list was set as default and not "0". + o When assigning a non-integer number to an integer option, + the "%%BeginFeature: ..." line of the option inserted into + the PostScript data stream still contained the non-integer + value. Only the value in the code piece was converted to + integer. + o If a non-integer "*FoomaticRIPDefault..." was given for an + integer option it was not converted to integer. + o Boolean options had "0" and "1" as values in the + "%%BeginFeature: ..." lines and not "False" and "True". + o PPD-supplied JCL/PJL options did not get merged with + driver-generated JCL/PJL options when there were spaces + between the JCL command and the "=" (ex: "@PJL SET TRAY = 1"). + o Now all of "0", "No", "Off", "False" or "1", "Yes", "On", + "True" are converted to each other if supplied as value to + an enumerated choice option and this value is not in the + list of choices. + +2007-10-11 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-rip.in: Allow the parameters of the "*Foomatic..." + lines which formerly had to be given without quotes also to be + given with double quotes. This is to support generation and + manipulation of Foomatic PPDs with the CUPS DDK. The PPD + generator of the CUPS DDK ("ppdc") can create these lines only + with quoted parameters (See http://www.cups.org/str.php?L2551). + +2007-07-18 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-rip.in: Added support for suppressing page accounting + on a per-driver basis. Page accounting is deactivated if a line + "*FoomaticNoPageAccounting: True" is found in the PPD file. + +2007-03-20 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-rip.in: Performance improvement: Do not match all forms + of DSC comments against every line. Check whether the line is a + DSC comment at all and pass it quickly through if not (Thanks to + Andreas Bolsch, Andreas dot Bolsch at alumni dot TU-Berlin dot + DE, for this patch). Will probably fix Ubuntu bug LP#78781 + (https://launchpad.net/bugs/78781). + + Fixed bug of custom page sizes not read from the PostScript code + when the size values are in more than one line (as the + "imagetops" CUPS filter outputs them when adapting a + user-supplied custom page size to the aspect ratio of the image, + to not waste roll paper). This fixes CUPS STR #1722 + (http://www.cups.org/str.php?L1722), Ubuntu bug LP#42234 + (https://launchpad.net/bugs/42234). + + Let data structure get written to debug log also if foomatic-rip + exits with an error (only in debug mode). + +2007-03-10 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-rip.in: Replaced sysread() and syswrite() by read() and + print() as sysread() and syswrite() is not compatible with the + read() and print() of the other operations. See Ubuntu bug #87597 + (https://launchpad.net/bugs/87597). + +2007-02-20 Till Kamppeter <till.kamppeter@gmail.com> + + * foomatic-rip.in: Fixed problem of too high memory consumption + when binary output data of GhostScript is read line-wise and + does not contain line feeds (Ubuntu bug #85569 with driver + "eplaser", Red Hat bug #221194 with driver "lx5000"). Applied + same fix also to binary non-PostScript input data (only relevant + for non-CUPS printing systems). + + * README, USAGE, foomatic-rip.in, foomatic-rip.1.in, beh.in, + foomatic-gswrapper.1.in, debian/copyright, debian/control, + debian/README.Debian: Replaced "linuxprinting.org" by + "openprinting.org" or "OpenPrinting". + 2006-10-03 Till Kamppeter <till.kamppeter@gmail.com> * foomatic-rip.in: Fixed bashism. @@ -7,7 +114,7 @@ * foomatic-gswrapper.in: Support for built-in redirection of standard output of PostScript programs ("-sstdout=%stderr") in newer GhostScript versions. More reliable then using /dev/fd/3 - (not always available difficult to check presence) or '|cat >3' + (not always available, difficult to check presence) or '|cat >3' (not seekable and some GhostScript output devices require seekability of the output file), @@ -10,11 +10,9 @@ Filter scripts used by the printer spoolers to convert the incoming PostScript data into the printer's native format using a printer/driver specific, but spooler-independent PPD file. +Till Kamppeter <till.kamppeter@gmail.com> -Grant Taylor <gtaylor@picante.com> -Till Kamppeter <till.kamppeter@gmx.net> - -http://www.linuxprinting.org/ +http://www.openprinting.org/ This README contains mainly info for developers. See the file USAGE if you want to know how to use Foomatic. @@ -26,11 +24,18 @@ Copying This package and also the other Foomatic packages are under the GPL. See http://www.gnu.org/. -If you spot a data error or any other bug, send mail describing the bug to -foomatic-devel@linuxprinting.org -General discussion happens in the foomatic-devel forum/list thing at -www.linuxprinting.org. +Bugs +---- + +If you spot a data error or any other bug, either post on the Foomatic +developer mailing list + +http://lists.freestandards.org/mailman/listinfo/printing-foomatic + +or post on the OpenPrinting site support forum + +http://forums.openprinting.org/list.php?34 Intro @@ -38,20 +43,17 @@ Intro This is the stable version of Foomatic. See -http://www.linuxprinting.org/contribute.html#programming -http://www.linuxprinting.org/pipermail/foomatic-devel/2002q3/thread.html -http://www.linuxprinting.org/pipermail/foomatic-devel/2002q4/thread.html -http://www.linuxprinting.org/kpfeifle/LinuxKongress2002/Tutorial/IV.Foomatic-Developer/IV.tutorial-handout-foomatic-development.html +http://www.freestandards.org/en/OpenPrinting/Database/HowToContribute#programming to know more about its development. Your suggestions, bug reports, patches, ... are welcome on -http://www.linuxprinting.org/newsportal/thread.php3?name=linuxprinting.foomatic.devel +http://forums.openprinting.org/list.php?34 For getting Foomatic PPD files for this version, go to -http://www.linuxprinting.org/ +http://www.openprinting.org/ See the README file of "foomatic-db-engine" for a (more or less) complete overview of Foomatic. @@ -68,7 +70,7 @@ GNUlpr - An enhanced LPD (http://sf.net/projects/lpr, development stopped) PPR - Page PRinter spooler (http://ppr.sourceforge.net/) PDQ - Print, Don't Queue (http://pdq.sf.net/, development stopped) CPS - Coherent Printing System (http://www.tww.cx/cps.php) ---- - Direct, spooler-less printing (http://www.linuxprinting.org/) +--- - Direct, spooler-less printing (http://www.openprinting.org/) Programs and important files from this package @@ -9,10 +9,9 @@ Filter scripts used by the printer spoolers to convert the incoming PostScript data into the printer's native format using a printer/driver specific, but spooler-independent PPD file. +Till Kamppeter <till.kamppeter@gmail.com> -Grant Taylor <gtaylor@picante.com> -Till Kamppeter <till.kamppeter@gmx.net> -http://www.linuxprinting.org/ +http://www.openprinting.org/ This usage documentation file is written by Till Kamppeter @@ -94,26 +93,23 @@ the scripts when they are installed. Download sources: rlpr: http://freshmeat.net/projects/rlpr/ or - http://www.linuxprinting.org/download/printing/ + http://www.openprinting.org/download/printing/ netcat: http://freshmeat.net/projects/netcat/ This package does not require any other Foomatic package. it can be -used with PPD files downloaded from linuxprinting.org, with +used with PPD files downloaded from the OpenPrinting site, with manufacturer-supplied PPDs for PostScript printers, and probably with other PPD files. -Note: PPD files for native CUPS drivers, as the ones shipping with -CUPS or Gimp-Print cannot be used with other spoolers than CUPS. - For non-PostScript printers one also needs GhostScript (5.50 or newer, ESP GhostScript 7.05.4 or newer highly recommended) and the appropriate printer driver. For drivers which have to be compiled into GhostScript ("Execution -style: GhostScript" on the driver pages on linuxprinting.org) check -with "gs -h" whether the driver is in your GhostScript. If not you -need to compile the driver into your GhostScript or use a GhostScript -version which already contains it. +style: GhostScript" on the driver pages on the OpenPrinting site) +check with "gs -h" whether the driver is in your GhostScript. If not +you need to compile the driver into your GhostScript or use a +GhostScript version which already contains it. If the driver page says "Execution style: Uniprint", it is much easier, check whether the appropriate ".upp" file is in one of the @@ -215,19 +211,19 @@ If not, see, depending on your spooler: CUPS: - http://www.linuxprinting.org/cups-doc.html + http://www.openprinting.org/cups-doc.html LPD, LPRng, GNUlpr: - http://www.linuxprinting.org/lpd-doc.html + http://www.openprinting.org/lpd-doc.html PPR: - http://www.linuxprinting.org/ppr-doc.html + http://www.openprinting.org/ppr-doc.html PDQ: - http://www.linuxprinting.org/pdq-doc.html + http://www.openprinting.org/pdq-doc.html CPS: @@ -235,11 +231,11 @@ CPS: Direct, spooler-less printing: - http://www.linuxprinting.org/direct-doc.html + http://www.openprinting.org/direct-doc.html Usage of PPD files (for all spoolers): - http://www.linuxprinting.org/ppd-doc.html + http://www.openprinting.org/ppd-doc.html @@ -40,12 +40,12 @@ # Mark this filter world-readable and world-executable. Restart CUPS to # make the new backend known to the spooler. # -# See http://www.linuxprinting.org/cups-doc.html and the additional +# See http://www.openprinting.org/cups-doc.html and the additional # instructions below. # beh - Backend Error Handler # -# Copyright 2005 Till Kamppeter <till.kamppeter@gmx.net> +# Copyright 2005 Till Kamppeter <till.kamppeter@gmail.com> # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -883,7 +883,7 @@ esac else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi - cd $ac_popdir + cd "$ac_popdir" done fi @@ -2748,11 +2748,6 @@ esac *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ @@ -2791,6 +2786,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;} fi;; esac done` || { (exit 1); exit 1; } + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub diff --git a/debian/README.Debian b/debian/README.Debian index f8b3c74..b867d92 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -1,7 +1,7 @@ foomatic-filters for Debian --------------------------- -Note that the structure of the LinuxPrinting.org (foomatic) printer +Note that the structure of the OpenPrinting (foomatic) printer configuration system in Debian (and upstream) has changed from the 2.0 series. There are now 3 core packages: diff --git a/debian/control b/debian/control index d4263cc..112dc18 100644 --- a/debian/control +++ b/debian/control @@ -13,7 +13,7 @@ Depends: ${perl:Depends}, ${misc:Depends}, ucf (>= 0.30) Recommends: cupsys-client | lpr | lprng | pdq | rlpr, gs-esp | gs, cupsys | enscript | a2ps | mpage, foomatic-db-engine Conflicts: foomatic-bin (<< 2.9), cupsomatic-ppd (<< 20030507), gs (<< 8.0), gs-aladdin (<< 8.0) Replaces: foomatic-bin (<< 2.9), cupsomatic-ppd -Description: linuxprinting.org printer support - filters +Description: OpenPrinting printer support - filters Foomatic is a printer database designed to make it easier to set up common printers for use with Debian (and other operating systems). It provides the "glue" between a print spooler (like CUPS or lpr) and @@ -29,4 +29,4 @@ Description: linuxprinting.org printer support - filters For use with CUPS, you will need both the cupsys and cupsys-client packages installed on your system. . - Home Page: http://www.linuxprinting.org/ + Home Page: http://www.openprinting.org/ diff --git a/debian/copyright b/debian/copyright index 18a63f7..4c6c8ae 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,11 +1,11 @@ This package was debianized by Chris Lawrence <lawrencc@debian.org> on Sun, 13 Apr 2003 20:44:09 -0500. -It was downloaded from http://www.linuxprinting.org/download/foomatic/ +It was downloaded from http://www.openprinting.org/download/foomatic/ Upstream Authors: - Grant Taylor <gtaylor@picante.com> - Till Kamppeter <till.kamppeter@gmx.net> + Original founder: Grant Taylor <gtaylor@picante.com> + Current maintainer: Till Kamppeter <till.kamppeter@gmail.com> Copyright: diff --git a/foomatic-gswrapper.1.in b/foomatic-gswrapper.1.in index 38e7640..fd95941 100644 --- a/foomatic-gswrapper.1.in +++ b/foomatic-gswrapper.1.in @@ -26,4 +26,6 @@ project using output from the associated binary. .SH BUGS None so far. -Please send bug reports to foomatic-devel@linuxprinting.org. +Please send bug reports to the Foomatic mailing list: + +http://lists.freestandards.org/mailman/listinfo/printing-foomatic diff --git a/foomatic-gswrapper.in b/foomatic-gswrapper.in index e6b1049..d314c6a 100644 --- a/foomatic-gswrapper.in +++ b/foomatic-gswrapper.in @@ -17,7 +17,7 @@ my $configpath = "@sysconfdir@/foomatic"; # Read config file if present %conf = readConfFile("$configpath/filter.conf"); -# Set GhostScript path +# Set Ghostscript path my $gspath = "gs"; $gspath = $conf{gspath} if defined(%conf) and defined $conf{gspath}; my $execpath = "@EXECPATH@"; @@ -25,7 +25,7 @@ my $execpath = "@EXECPATH@"; $execpath = $conf{execpath} if defined(%conf) and defined $conf{execpath}; $ENV{'PATH'} = $execpath; -# Check whether we have a GhostScript version with redirection of the +# Check whether we have a Ghostscript version with redirection of the # standard output of the PostScript programs via '-sstdout=%stderr' my $gswithstdoutredirection = 0; if (`$gspath -dQUIET -dPARANOIDSAFER -dNOPAUSE -dBATCH -dNOMEDIAATTRS -sDEVICE=pswrite -sstdout=%stderr -sOutputFile=/dev/null -c '(hello\n) print flush' 2>&1` =~ /hello/) { @@ -34,7 +34,7 @@ if (`$gspath -dQUIET -dPARANOIDSAFER -dNOPAUSE -dBATCH -dNOMEDIAATTRS -sDEVICE=p grep (m!\-sOutputFile=\-! && do { - # If GhostScript does not support redirecting the standard output + # If Ghostscript does not support redirecting the standard output # of the PostScript program to standard error with # '-sstdout=%stderr', sen the job output data to fd 3; errors # will be on 2(stderr) and job ps program interpreter output on @@ -44,13 +44,14 @@ grep (m!\-sOutputFile=\-! # quoted properly below... }, @ARGV); -if (!$gswithstdoutredirection) { - grep (((m!^\-$!) || (m!^\-_$!)) - && do { - # Get the input from fd 0. - $_ = "/dev/fd/0"; - }, @ARGV); -} +grep (((m!^\-$!) || (m!^\-_$!) || (m!^/dev/fd/0$!)) + && do { + # Use always buffered input. This works around a Ghostscript + # bug which prevents printing encrypted PDF files with Adobe + # Reader 8.1.1 and Ghostscript built as shared library + # (Ghostscript bug #689577, Ubuntu bug #172264) + $_ = "-_"; + }, @ARGV); # Turn *off* -q (quiet!); now that stderr is useful! :) my @myargs = grep (! m!^\-q$!, @ARGV); diff --git a/foomatic-rip.1.in b/foomatic-rip.1.in index 698d022..7c86fd6 100644 --- a/foomatic-rip.1.in +++ b/foomatic-rip.1.in @@ -190,13 +190,13 @@ immediately after the data is transferred to the printer. directs your jobs to the LPD printer queue \fBlp\fR on the machine named \fBprintserver\fR. -See also http://www.linuxprinting.org/direct-doc.html +See also http://www.openprinting.org/direct-doc.html .SH "PRINTING WITH SPOOLER" -See the documentation on the Linux Printing Web site: +See the documentation on the OpenPrinting Web site: .ft CW -http://www.linuxprinting.org +http://www.openprinting.org/ \fR .SH FILES @@ -223,11 +223,13 @@ The PPD files of the currently defined printers returns 0 unless something unexpected happens. .SH AUTHOR -Till Kamppeter <\fItill.kamppeter@gmx.net\fR> with parts of Manfred +Till Kamppeter <\fItill.kamppeter@gmail.com\fR> with parts of Manfred Wassmanns's <\fImanolo@NCC-1701.B.Shuttle.de\fR> man pages for the Foomatic 2.0.x filters. .SH BUGS None so far. -Please send bug reports to foomatic-devel@linuxprinting.org. +Please send bug reports to the Foomatic mailing list: + +http://lists.freestandards.org/mailman/listinfo/printing-foomatic diff --git a/foomatic-rip.in b/foomatic-rip.in index a681753..18b06a0 100644 --- a/foomatic-rip.in +++ b/foomatic-rip.in @@ -26,12 +26,12 @@ my $ripversion='$Revision$'; # spoolers run the print filters as a special user, as "lp", not as # "root" or as the user who sent the job). -# See http://www.linuxprinting.org/cups-doc.html -# http://www.linuxprinting.org/lpd-doc.html -# http://www.linuxprinting.org/ppr-doc.html -# http://www.linuxprinting.org/pdq-doc.html -# http://www.linuxprinting.org/direct-doc.html -# http://www.linuxprinting.org/ppd-doc.html +# See http://www.openprinting.org/cups-doc.html +# http://www.openprinting.org/lpd-doc.html +# http://www.openprinting.org/ppr-doc.html +# http://www.openprinting.org/pdq-doc.html +# http://www.openprinting.org/direct-doc.html +# http://www.openprinting.org/ppd-doc.html # ========================================================================== # @@ -114,8 +114,8 @@ my $logfile = "/tmp/foomatic-rip"; # # foomatic-rip spooler-independent PS->Printer filter (RIP) of Foomatic # -# Copyright 2002 - 2004 Grant Taylor <gtaylor@picante.com> -# & Till Kamppeter <till.kamppeter@gmx.net> +# Copyright 2002 - 2007 Grant Taylor <gtaylor@picante.com> +# & Till Kamppeter <till.kamppeter@gmail.com> # & Helge Blischke <h.blischke@srz.de> # # This program is free software; you can redistribute it and/or modify it @@ -1132,7 +1132,7 @@ while(<PPD>) { $line =~ m!^([^\"]*)\"!; $cmd .= $1; $model = unhtmlify($cmd); - } elsif (m!^\*FoomaticIDs:\s*(\S+)\s+(\S+)\s*$!) { + } elsif (m!^\*FoomaticIDs:\s*\"?\s*(\S+?)\s+(\S+?)\s*\"?\s*$!) { # "*FoomaticIDs: <printer ID> <driver ID>" my $id = $1; my $driver = $2; @@ -1181,6 +1181,17 @@ while(<PPD>) { $line =~ m!^([^\"]*)\"!; $cmd .= $1; $dat->{'cmd'} = unhtmlify($cmd); + } elsif (m!^\*FoomaticNoPageAccounting:\s*\"?\s*(\S+?)\s*\"?\s*$!) { + # "*FoomaticRIPNoPageAccounting: <boolean value>" + my $value = $1; + # Apply the value + if ($value =~ /^True$/i) { + # Driver is not compatible with page accounting according to the + # Foomatic database, so turn it off for this driver + $ps_accounting = 0; + $accounting_prolog = ''; + print $logh "CUPS page accounting disabled by driver.\n"; + } } elsif (m!^\*cupsFilter:\s*\"(.*)$!) { # "*cupsFilter: <code>" my $line = $1; @@ -1277,8 +1288,8 @@ while(<PPD>) { # Unmark the current argument to do not mis-interpret any keywords # as choices $currentargument = ""; - } elsif ((m!^\*FoomaticRIPOption ([^/:\s]+):\s*(\S+)\s+(\S+)\s+(\S)\s*$!) || - (m!^\*FoomaticRIPOption ([^/:\s]+):\s*(\S+)\s+(\S+)\s+(\S)\s+(\S+)\s*$!)){ + } elsif ((m!^\*FoomaticRIPOption ([^/:\s]+):\s*\"?\s*(\S+?)\s+(\S+)\s+(\S)\s*\"?\s*$!) || + (m!^\*FoomaticRIPOption ([^/:\s]+):\s*\"?\s*(\S+?)\s+(\S+)\s+(\S)\s+(\S+?)\s*\"?\s*$!)){ # "*FoomaticRIPOption <option>: <type> <style> <spot> [<order>]" # <order> only used for 1-choice enum options my $argname = $1; @@ -1330,7 +1341,7 @@ while(<PPD>) { $line =~ m!^([^\"]*)\"!; $proto .= $1; $dat->{'args_byname'}{$argname}{'proto'} = unhtmlify($proto); - } elsif (m!^\*FoomaticRIPOptionRange\s+([^/:\s]+):\s*(\S+)\s+(\S+)\s*$!) { + } elsif (m!^\*FoomaticRIPOptionRange\s+([^/:\s]+):\s*\"?\s*(\S+?)\s+(\S+?)\s*\"?\s*$!) { # "*FoomaticRIPOptionRange <option>: <min> <max>" # Used for numerical options only my $argname = $1; @@ -1341,7 +1352,7 @@ while(<PPD>) { # Store the values $dat->{'args_byname'}{$argname}{'min'} = $min; $dat->{'args_byname'}{$argname}{'max'} = $max; - } elsif (m!^\*FoomaticRIPOptionMaxLength\s+([^/:\s]+):\s*(\S+)\s*$!) { + } elsif (m!^\*FoomaticRIPOptionMaxLength\s+([^/:\s]+):\s*\"?\s*(\S+?)\s*\"?\s*$!) { # "*FoomaticRIPOptionMaxLength <option>: <length>" # Used for string options only my $argname = $1; @@ -1421,7 +1432,7 @@ while(<PPD>) { checkarg ($dat, $argname); # Store the value $dat->{'args_byname'}{$argname}{'default'} = $default; - } elsif (m!^\*FoomaticRIPDefault([^/:\s]+):\s*([^/:\s]+)\s*$!) { + } elsif (m!^\*FoomaticRIPDefault([^/:\s]+):\s*\"?\s*([^/:\s]+?)\s*\"?\s*$!) { # "*FoomaticRIPDefault<option>: <value>" # Used for numerical options only my $argname = $1; @@ -1463,7 +1474,7 @@ while(<PPD>) { checksetting ($dat, $currentargument, $setting); # Make sure that this argument has a default setting, even if # none is defined in this PPD file - if (!$dat->{'args_byname'}{$currentargument}{'default'}) { + if (!defined ($dat->{'args_byname'}{$currentargument}{'default'})) { $dat->{'args_byname'}{$currentargument}{'default'} = $setting; } $dat->{'args_byname'}{$currentargument}{'vals_byname'}{$setting}{'comment'} = $translation; @@ -1515,7 +1526,7 @@ while(<PPD>) { checksetting ($dat, $argname, $setting); # Make sure that this argument has a default setting, even if # none is defined in this PPD file - if (!$dat->{'args_byname'}{$argname}{'default'}) { + if (!defined ($dat->{'args_byname'}{$argname}{'default'})) { $dat->{'args_byname'}{$argname}{'default'} = $setting; } } @@ -1652,6 +1663,9 @@ if ((!defined(@{$dat->{'args'}})) || if ($arg->{'fdefault'} > $arg->{'max'}) { $arg->{'fdefault'} = $arg->{'max'}; } + if ($arg->{'type'} eq 'int') { + $arg->{'fdefault'} = POSIX::floor($arg->{'fdefault'}); + } my $mindiff = abs($arg->{'max'} - $arg->{'min'}); my $closestvalue; for my $val (@{$arg->{'vals'}}) { @@ -1936,9 +1950,10 @@ for (@opts) { # Handle the standard duplex option, mostly if ($avalue =~ m!^two-sided!i) { if (defined($dat->{'args_byname'}{'Duplex'})) { - # We set "Duplex" to '1' here, the real argument setting - # will be done later - $dat->{'args_byname'}{'Duplex'}{$optionset} = '1'; + # Default to long-edge binding here, for the case that + # there is no binding setting + $dat->{'args_byname'}{'Duplex'}{$optionset} = + 'DuplexNoTumble'; # Check the binding: "long edge" or "short edge" if ($avalue =~ m!long-edge!i) { if (defined($dat->{'args_byname'}{'Binding'})) { @@ -1946,7 +1961,7 @@ for (@opts) { $dat->{'args_byname'}{'Binding'}{'vals_byname'}{'LongEdge'}{'value'}; } else { $dat->{'args_byname'}{'Duplex'}{$optionset} = - 'LongEdge'; + 'DuplexNoTumble'; } } elsif ($avalue =~ m!short-edge!i) { if (defined($dat->{'args_byname'}{'Binding'})) { @@ -1954,15 +1969,13 @@ for (@opts) { $dat->{'args_byname'}{'Binding'}{'vals_byname'}{'ShortEdge'}{'value'}; } else { $dat->{'args_byname'}{'Duplex'}{$optionset} = - 'ShortEdge'; + 'DuplexTumble'; } } } } elsif ($avalue =~ m!^one-sided!i) { if (defined($dat->{'args_byname'}{'Duplex'})) { - # We set "Duplex" to '0' here, the real argument setting - # will be done later - $dat->{'args_byname'}{'Duplex'}{$optionset} = '0'; + $dat->{'args_byname'}{'Duplex'}{$optionset} = 'None'; } } @@ -2332,6 +2345,9 @@ for $file (@filelist) { my $twolinesbefore = ""; # The line two lines before the current # line (Non-DSC comments are ignored) + my $linesafterlastbeginfeature = ""; # All code lines after the last + # "%%BeginFeature:" + my @psheader = (); # The header of the PostScript file, # to be sent after each start of the # renderer @@ -2452,6 +2468,8 @@ for $file (@filelist) { my $ooo110 = 0; # Flag to work around an application # bug. + my $saved = 0; # DSC line not processed yet + if ($dontparse) { # We do not parse the PostScript to find Foomatic options, we check # only whether we have PostScript. @@ -2466,7 +2484,8 @@ for $file (@filelist) { # determining the last active line # and the one before the last - if (($printprevpage) || ($line=<STDIN>)) { + if (($printprevpage) || ($saved) || ($line=<STDIN>)) { + $saved = 0; if ($linect == $nonpslines) { # In the beginning should be the postscript leader, @@ -2554,537 +2573,571 @@ for $file (@filelist) { } } } else { - if ($line =~ m/^\s*\%\%BeginDocument[: ]/) { - # Beginning of an embedded document - # Note that Adobe Acrobat has a bug and so uses - # "%%BeginDocument " instead of "%%BeginDocument:" - $nestinglevel ++; - print $logh "Embedded document, " . - "nesting level now: $nestinglevel\n"; - } elsif (($line =~ m/^\s*\%\%EndDocument/) && - ($nestinglevel > 0)) { - # End of an embedded document - $nestinglevel --; - print $logh "End of Embedded document, " . - "nesting level now: $nestinglevel\n"; - } elsif (($line =~ m/^\s*\%\%Creator[: ](.*)$/) && - ($nestinglevel == 0)) { - # Here we set flags to treat particular bugs of the - # PostScript produced by certain applications - my $creator = $1; - if ($creator =~ /^\s*OpenOffice.org\s+1.1.\d+\s*$/) { - # OpenOffice.org 1.1.x - # The option settings supposed to affect the - # whole document are put into the "%%PageSetup" - # section of the first page - print $logh "Document created with " . - "OpenOffice.org 1.1.x\n"; - $ooo110 = 1; - } - } elsif (($line =~ m/^\%\%BeginProlog/) && - ($nestinglevel == 0)) { - # Note: Below is another place where a "Prolog" - # section start will be considered. There we assume - # start of the "Prolog" if the job is DSC-Conformimg, - # but an arbitrary comment starting with "%%Begin", but - # not a comment explicitly treated here, is found. This - # is done because many "dvips" (TeX/LaTeX) files miss - # the "%%BeginProlog" comment. - # Beginning of Prolog - print $logh "${added_lf}-----------\nFound: \%\%BeginProlog\n"; - $inprolog = 1; - $postscriptsection = 'prolog' if $inheader; - $nondsclines = 0; - # Insert options for "Prolog" - if (!$prologfound) { - $line .= makeprologsection($dat, $optionset, 0); - } - $prologfound = 1; - } elsif (($line =~ m/^\%\%EndProlog/) && - ($nestinglevel == 0)) { - # End of Prolog - print $logh "Found: \%\%EndProlog\n"; - $inprolog = 0; - $insertoptions = $linect + 1; - } elsif (($line =~ m/^\%\%BeginSetup/) && - ($nestinglevel == 0)) { - # Beginning of Setup - print $logh "${added_lf}-----------\nFound: \%\%BeginSetup\n"; - $insetup = 1; - # We need to distinguish with the $inheader variable - # here whether we are in the header or on a page, as - # OpenOffice.org inserts a "%%BeginSetup...%%EndSetup" - # section after the first "%%Page:..." line and assumes - # this section to be valid for all pages. - $postscriptsection = 'setup' if $inheader; - $nondsclines = 0; - if ($inheader) { - # If there was no "Prolog" but there are - # options for the "Prolog", push a "Prolog" - # with these options onto the @psfifo here - if (!$prologfound) { - # "Prolog" missing, insert it here - $line = makeprologsection($dat, $optionset, 1) . - $line; - # Now we have a "Prolog" - $prologfound = 1; + if ($line =~ /^\%\%/) { + if ($line =~ m/^\s*\%\%BeginDocument[: ]/) { + # Beginning of an embedded document + # Note that Adobe Acrobat has a bug and so uses + # "%%BeginDocument " instead of "%%BeginDocument:" + $nestinglevel ++; + print $logh "Embedded document, " . + "nesting level now: $nestinglevel\n"; + } elsif (($line =~ m/^\s*\%\%EndDocument/) && + ($nestinglevel > 0)) { + # End of an embedded document + $nestinglevel --; + print $logh "End of Embedded document, " . + "nesting level now: $nestinglevel\n"; + } elsif (($line =~ m/^\s*\%\%Creator[: ](.*)$/) && + ($nestinglevel == 0)) { + # Here we set flags to treat particular bugs of the + # PostScript produced by certain applications + my $creator = $1; + if ($creator =~ /^\s*OpenOffice.org\s+1.1.\d+\s*$/) { + # OpenOffice.org 1.1.x + # The option settings supposed to affect the + # whole document are put into the "%%PageSetup" + # section of the first page + print $logh "Document created with " . + "OpenOffice.org 1.1.x\n"; + $ooo110 = 1; } - # Insert options for "DocumentSetup" or "AnySetup" - if ($spooler ne 'cups') { - # For non-CUPS spoolers or no spooler at all, we leave - # everything as it is. - if (!$setupfound) { - $line .= makesetupsection($dat, $optionset, 0); - } - $setupfound = 1; + } elsif (($line =~ m/^\%\%BeginProlog/) && + ($nestinglevel == 0)) { + # Note: Below is another place where a "Prolog" + # section start will be considered. There we assume + # start of the "Prolog" if the job is DSC-Conformimg, + # but an arbitrary comment starting with "%%Begin", but + # not a comment explicitly treated here, is found. This + # is done because many "dvips" (TeX/LaTeX) files miss + # the "%%BeginProlog" comment. + # Beginning of Prolog + print $logh "${added_lf}-----------\nFound: \%\%BeginProlog\n"; + $inprolog = 1; + $postscriptsection = 'prolog' if $inheader; + $nondsclines = 0; + # Insert options for "Prolog" + if (!$prologfound) { + $line .= makeprologsection($dat, $optionset, 0); } - } else { - # Found option settings must be stuffed into both - # the header and the currrent page now. They will - # be written into both the "header" and the - # "currentpage" optionsets and the PostScript code - # lines of this section will not only go into the - # output stream, but also added to the end of the - # @psheader, so that they get repeated (to preserve - # the embedded PostScript option settings) on a - # restart of the renderer due to command line - # option changes - $optionsalsointoheader = 1; - print $logh "\"%%BeginSetup\" in page header\n"; - } - } elsif (($line =~ m/^\%\%EndSetup/) && - ($nestinglevel == 0)) { - # End of Setup - print $logh "Found: \%\%EndSetup\n"; - $insetup = 0; - if ($inheader) { - if ($spooler eq 'cups') { - # In case of CUPS, we must insert the - # accounting stuff just before the - # %%EndSetup comment in order to leave any - # EndPage procedures that have been - # defined by either the pstops filter or - # the PostScript job itself fully - # functional. - if (!$setupfound) { - $line = makesetupsection($dat, - $optionset, 0) . - $line; - } - $setupfound = 1; - } + $prologfound = 1; + } elsif (($line =~ m/^\%\%EndProlog/) && + ($nestinglevel == 0)) { + # End of Prolog + print $logh "Found: \%\%EndProlog\n"; + $inprolog = 0; $insertoptions = $linect + 1; - } else { - # The "%%BeginSetup...%%EndSetup" which - # OpenOffice.org has inserted after the first - # "%%Page:..." line ends here, so the following - # options go only onto the current page again - $optionsalsointoheader = 0; - } - } elsif (($line =~ m/^\%\%Page:(.*)$/) && - ($nestinglevel == 0)) { - if ((!$lastpassthru) && (!$inheader)) { - # In the last line we were not in passthru mode, - # so the last page is not printed. Prepare to do - # it now. - $printprevpage = 1; - # Print the previous page - $passthru = 1; - print $logh "New page found but previous not " . - "printed, print it now.\n"; - } else { - # The previous page is printed, so we can prepare - # the current one - $printprevpage = 0; - print $logh "${added_lf}-----------\nNew page: $1\n"; - # Count pages - $currentpage ++; - # We consider the beginning of the page already as - # page setup section, as some apps do not use - # "%%PageSetup" tags. - $postscriptsection = 'pagesetup'; - # Save PostScript state before beginning the page - #$line .= "/foomatic-saved-state save def\n"; - # Here begins a new page + } elsif (($line =~ m/^\%\%BeginSetup/) && + ($nestinglevel == 0)) { + # Beginning of Setup + print $logh "${added_lf}-----------\nFound: \%\%BeginSetup\n"; + $insetup = 1; + # We need to distinguish with the $inheader variable + # here whether we are in the header or on a page, as + # OpenOffice.org inserts a "%%BeginSetup...%%EndSetup" + # section after the first "%%Page:..." line and assumes + # this section to be valid for all pages. + $postscriptsection = 'setup' if $inheader; + $nondsclines = 0; if ($inheader) { - # Here we add some stuff which still belongs - # into the header - my $stillforheader; - # If there was no "Setup" but there are - # options for the "Setup", push a "Setup" - # with these options onto the @psfifo here - if (!$setupfound) { - # "Setup" missing, insert it here - $stillforheader = - makesetupsection($dat, $optionset, 1) . - $stillforheader; - # Now we have a "Setup" - $setupfound = 1; - } # If there was no "Prolog" but there are # options for the "Prolog", push a "Prolog" # with these options onto the @psfifo here if (!$prologfound) { # "Prolog" missing, insert it here - $stillforheader = + $line = makeprologsection($dat, $optionset, 1) . - $stillforheader; + $line; # Now we have a "Prolog" $prologfound = 1; } - # Now we push this onto the header - push (@psheader, $stillforheader); - # The first page starts, so the header ends - $inheader = 0; - $nondsclines = 0; - # Option setting should go into the - # page-specific option set now - $optionset = 'currentpage'; + # Insert options for "DocumentSetup" or "AnySetup" + if ($spooler ne 'cups') { + # For non-CUPS spoolers or no spooler at all, + # we leave everything as it is. + if (!$setupfound) { + $line .= + makesetupsection($dat, $optionset, 0); + } + $setupfound = 1; + } } else { - # Restore PostScript state after completing the - # previous page: - # - # foomatic-saved-state restore - # %%Page: ... - # /foomatic-saved-state save def - # - # Print this directly, so that if we need to - # restart the renderer for this page due to - # a command line change this is done under the - # old instance of the renderer - #print $rendererhandle - # "foomatic-saved-state restore\n"; - - # Save the option settings of the previous page - copyoptions($dat, 'currentpage', - 'previouspage'); - deleteoptions($dat, 'currentpage'); + # Found option settings must be stuffed into both + # the header and the currrent page now. They will + # be written into both the "header" and the + # "currentpage" optionsets and the PostScript code + # lines of this section will not only go into the + # output stream, but also added to the end of the + # @psheader, so that they get repeated (to preserve + # the embedded PostScript option settings) on a + # restart of the renderer due to command line + # option changes + $optionsalsointoheader = 1; + print $logh "\"%%BeginSetup\" in page header\n"; } - # Initialize the option set - copyoptions($dat, 'header', 'currentpage'); - # Set command line options which apply only - # given pages - setoptionsforpage($dat, 'currentpage', $currentpage); - $pagesetupfound = 0; - if ($spooler eq 'cups') { - # Remove the "notfirst" flag from all options - # forseen for the "PageSetup" section, because - # when these are numerical options for CUPS. - # they have to be set to the correct value - # for every page - for my $arg (@{$dat->{'args'}}) { - if (($arg->{'section'} eq 'PageSetup') && - (defined($arg->{'notfirst'}))) { - delete($arg->{'notfirst'}); + } elsif (($line =~ m/^\%\%EndSetup/) && + ($nestinglevel == 0)) { + # End of Setup + print $logh "Found: \%\%EndSetup\n"; + $insetup = 0; + if ($inheader) { + if ($spooler eq 'cups') { + # In case of CUPS, we must insert the + # accounting stuff just before the + # %%EndSetup comment in order to leave any + # EndPage procedures that have been + # defined by either the pstops filter or + # the PostScript job itself fully + # functional. + if (!$setupfound) { + $line = makesetupsection($dat, + $optionset, 0) . + $line; } + $setupfound = 1; } + $insertoptions = $linect + 1; + } else { + # The "%%BeginSetup...%%EndSetup" which + # OpenOffice.org has inserted after the first + # "%%Page:..." line ends here, so the following + # options go only onto the current page again + $optionsalsointoheader = 0; } - # Insert PostScript option settings - # (options for section "PageSetup". - if ($isdscjob) { - $line .= - makepagesetupsection($dat, $optionset, - 0); - $pagesetupfound = 1; + } elsif (($line =~ m/^\%\%Page:(.*)$/) && + ($nestinglevel == 0)) { + if ((!$lastpassthru) && (!$inheader)) { + # In the last line we were not in passthru mode, + # so the last page is not printed. Prepare to do + # it now. + $printprevpage = 1; + # Print the previous page + $passthru = 1; + print $logh "New page found but previous not " . + "printed, print it now.\n"; + } else { + # The previous page is printed, so we can prepare + # the current one + $printprevpage = 0; + print $logh "${added_lf}-----------\nNew page: $1\n"; + # Count pages + $currentpage ++; + # We consider the beginning of the page already as + # page setup section, as some apps do not use + # "%%PageSetup" tags. + $postscriptsection = 'pagesetup'; + # Save PostScript state before beginning the page + #$line .= "/foomatic-saved-state save def\n"; + # Here begins a new page + if ($inheader) { + # Here we add some stuff which still belongs + # into the header + my $stillforheader; + # If there was no "Setup" but there are + # options for the "Setup", push a "Setup" + # with these options onto the @psfifo here + if (!$setupfound) { + # "Setup" missing, insert it here + $stillforheader = + makesetupsection($dat, $optionset, 1) . + $stillforheader; + # Now we have a "Setup" + $setupfound = 1; + } + # If there was no "Prolog" but there are + # options for the "Prolog", push a "Prolog" + # with these options onto the @psfifo here + if (!$prologfound) { + # "Prolog" missing, insert it here + $stillforheader = + makeprologsection($dat, $optionset, + 1) . + $stillforheader; + # Now we have a "Prolog" + $prologfound = 1; + } + # Now we push this onto the header + push (@psheader, $stillforheader); + # The first page starts, so the header ends + $inheader = 0; + $nondsclines = 0; + # Option setting should go into the + # page-specific option set now + $optionset = 'currentpage'; + } else { + # Restore PostScript state after completing the + # previous page: + # + # foomatic-saved-state restore + # %%Page: ... + # /foomatic-saved-state save def + # + # Print this directly, so that if we need to + # restart the renderer for this page due to + # a command line change this is done under the + # old instance of the renderer + #print $rendererhandle + # "foomatic-saved-state restore\n"; + + # Save the option settings of the previous page + copyoptions($dat, 'currentpage', + 'previouspage'); + deleteoptions($dat, 'currentpage'); + } + # Initialize the option set + copyoptions($dat, 'header', 'currentpage'); + # Set command line options which apply only + # given pages + setoptionsforpage($dat, 'currentpage', $currentpage); + $pagesetupfound = 0; + if ($spooler eq 'cups') { + # Remove the "notfirst" flag from all options + # forseen for the "PageSetup" section, because + # when these are numerical options for CUPS. + # they have to be set to the correct value + # for every page + for my $arg (@{$dat->{'args'}}) { + if (($arg->{'section'} eq 'PageSetup') && + (defined($arg->{'notfirst'}))) { + delete($arg->{'notfirst'}); + } + } + } + # Insert PostScript option settings + # (options for section "PageSetup". + if ($isdscjob) { + $line .= + makepagesetupsection($dat, $optionset, + 0); + $pagesetupfound = 1; + } + # Now the page header comes, so buffer the data, + # because we must perhaps shut down and restart + # the renderer + $passthru = 0; + $ignorepageheader = 0; + $optionsalsointoheader = 0; } - # Now the page header comes, so buffer the data, - # because we must perhaps shut down and restart - # the renderer + } elsif (($line =~ m/^\%\%BeginPageSetup/) && + ($nestinglevel == 0) && + (!$ignorepageheader)) { + # Start of the page header, up to %%EndPageSetup + # nothing of the page will be drawn, page-specific + # option settngs (as letter-head paper for page 1) + # go here + print $logh "${added_lf}Found: \%\%BeginPageSetup\n"; $passthru = 0; - $ignorepageheader = 0; - $optionsalsointoheader = 0; - } - } elsif (($line =~ m/^\%\%BeginPageSetup/) && - ($nestinglevel == 0) && - (!$ignorepageheader)) { - # Start of the page header, up to %%EndPageSetup - # nothing of the page will be drawn, page-specific - # option settngs (as letter-head paper for page 1) - # go here - print $logh "${added_lf}Found: \%\%BeginPageSetup\n"; - $passthru = 0; - $inpageheader = 1; - $postscriptsection = 'pagesetup'; - if (($ooo110) && ($currentpage == 1)) { - $optionsalsointoheader = 1; - } else { + $inpageheader = 1; + $postscriptsection = 'pagesetup'; + if (($ooo110) && ($currentpage == 1)) { + $optionsalsointoheader = 1; + } else { + $optionsalsointoheader = 0; + } + } elsif (($line =~ m/^\%\%EndPageSetup/) && + ($nestinglevel == 0) && + (!$ignorepageheader)) { + # End of the page header, the page is ready to be + # printed + print $logh "Found: \%\%EndPageSetup\n"; + print $logh "End of page header\n"; + # We cannot for sure say that the page header ends here + # OpenOffice.org puts (due to a bug) a "%%BeginSetup... + # %%EndSetup" section after the first "%%Page:...". It + # is possible that CUPS inserts a "%%BeginPageSetup... + # %%EndPageSetup" before this section, which means that + # the options in the "%%BeginSetup...%%EndSetup" + # section are after the "%%EndPageSetup", so we + # continue for searching options up to the buffer size + # limit $maxlinesforpageoptions. + $passthru = 0; + $inpageheader = 0; $optionsalsointoheader = 0; - } - } elsif (($line =~ m/^\%\%EndPageSetup/) && - ($nestinglevel == 0) && - (!$ignorepageheader)) { - # End of the page header, the page is ready to be - # printed - print $logh "Found: \%\%EndPageSetup\n"; - print $logh "End of page header\n"; - # We cannot for sure say that the page header ends here - # OpenOffice.org puts (due to a bug) a "%%BeginSetup... - # %%EndSetup" section after the first "%%Page:...". It - # is possible that CUPS inserts a "%%BeginPageSetup... - # %%EndPageSetup" before this section, which means that - # the options in the "%%BeginSetup...%%EndSetup" section - # are after the "%%EndPageSetup", so we continue for - # searching options up to the buffer size limit - # $maxlinesforpageoptions. - $passthru = 0; - $inpageheader = 0; - $optionsalsointoheader = 0; - } elsif ((($line =~ m/^\%\%(BeginFeature):\s*\*?([^\*\s=]+)\s+()(\S[^\r\n]*)\r?\n?$/) || - ($line =~ m/^\s*\%\%\s*(FoomaticRIPOptionSetting):\s*([^\*\s=]+)\s*=\s*(\@?)([^\@\s][^\r\n]*)\r?\n?$/)) && - ($nestinglevel == 0) && - (!$optionreplaced) && - ((!$passthru) || (!$isdscjob))) { - my ($linetype, $option, $fromcomposite, $value) = - ($1, $2, $3, $4); - - # Mark that we are in a "Feature" section - if ($linetype eq 'BeginFeature') { - $infeature = 1; - } - - # OK, we have an option. If it's not a - # *ostscript-style option (ie, it's command-line or - # JCL) then we should note that fact, since the - # attribute-to-filter option passing in CUPS is kind of - # funky, especially wrt boolean options. - - print $logh "Found: $line"; - if (my $arg=argbyname($option)) { - print $logh " Option: $option=" . - ($fromcomposite ? "From" : "") . $value; - if (($spooler eq 'cups') && - ($linetype eq 'BeginFeature') && - (!defined($arg->{'notfirst'})) && - ($arg->{$optionset} ne $value) && - (($inheader) || - ($arg->{section} eq 'PageSetup'))) { - # We have the first occurence of an - # option setting and the spooler is CUPS, - # so this setting is inserted by "pstops". - # The value from the command line was not - # inserted by "pstops" so it seems to be - # not under the choices in the PPD. - # Possible reasons: - # - # - "pstops" ignores settings of numerical - # or string options which are not one of - # the choices in the PPD file, and inserts - # the default value instead. - # - # - On the command line an option was applied - # only to selected pages: - # "-o <page ranges>:<option>=<values> - # This is not supported by CUPS, so not - # taken care of by "pstops". - # - # We must fix this here by replacing the setting - # inserted by "pstops" with the exact setting - # given on the command line. - - # $arg->{$optionset} is already - # range-checked, so do not check again here - # Insert DSC comment - my $dest = ((($inheader) && ($isdscjob)) ? - \@psheader : \@psfifo); - push(@{$dest}, - "%%BeginFeature: " . - "*$option $arg->{$optionset}\n"); - my $val; - if ($arg->{'style'} eq 'G') { - # PostScript option, insert the code - if ($arg->{'type'} eq 'bool') { - # Boolean option - if (defined($arg->{$optionset}) && - $arg->{$optionset} == 1) { - push(@{$dest}, $arg->{'proto'} . "\n"); - } elsif ($arg->{'protof'}) { - push(@{$dest}, $arg->{'protof'}. "\n"); + } elsif ((($line =~ m/^\%\%(BeginFeature):\s*\*?([^\*\s=]+)\s+()(\S[^\r\n]*)\r?\n?$/) || + ($line =~ m/^\s*\%\%\s*(FoomaticRIPOptionSetting):\s*([^\*\s=]+)\s*=\s*(\@?)([^\@\s][^\r\n]*)\r?\n?$/)) && + ($nestinglevel == 0) && + (!$optionreplaced) && + ((!$passthru) || (!$isdscjob))) { + my ($linetype, $option, $fromcomposite, $value) = + ($1, $2, $3, $4); + + # Mark that we are in a "Feature" section + if ($linetype eq 'BeginFeature') { + $infeature = 1; + $linesafterlastbeginfeature = ""; + } + + # OK, we have an option. If it's not a + # *ostscript-style option (ie, it's command-line or + # JCL) then we should note that fact, since the + # attribute-to-filter option passing in CUPS is kind of + # funky, especially wrt boolean options. + + print $logh "Found: $line"; + if (my $arg=argbyname($option)) { + print $logh " Option: $option=" . + ($fromcomposite ? "From" : "") . $value; + if (($spooler eq 'cups') && + ($linetype eq 'BeginFeature') && + (!defined($arg->{'notfirst'})) && + ($arg->{$optionset} ne $value) && + (($inheader) || + ($arg->{section} eq 'PageSetup'))) { + + # We have the first occurence of an option + # setting and the spooler is CUPS, so this + # setting is inserted by "pstops" or + # "imagetops". The value from the command + # line was not inserted by "pstops" or + # "imagetops" so it seems to be not under + # the choices in the PPD. Possible + # reasons: + # + # - "pstops" and "imagetops" ignore settings + # of numerical or string options which are + # not one of the choices in the PPD file, + # and inserts the default value instead. + # + # - On the command line an option was applied + # only to selected pages: + # "-o <page ranges>:<option>=<values> + # This is not supported by CUPS, so not + # taken care of by "pstops". + # + # We must fix this here by replacing the + # setting inserted by "pstops" or "imagetops" + # with the exact setting given on the command + # line. + + # $arg->{$optionset} is already + # range-checked, so do not check again here + # Insert DSC comment + my $dest = ((($inheader) && ($isdscjob)) ? + \@psheader : \@psfifo); + my $val; + if ($arg->{'style'} eq 'G') { + # PostScript option, insert the code + if ($arg->{'type'} eq 'bool') { + # Boolean option + push(@{$dest}, + "%%BeginFeature: *$option " . + ($arg->{$optionset} == 1 ? + "True" : "False") . "\n"); + if (defined($arg->{$optionset}) && + $arg->{$optionset} == 1) { + push(@{$dest}, $arg->{'proto'} . + "\n"); + } elsif ($arg->{'protof'}) { + push(@{$dest}, $arg->{'protof'} . + "\n"); + } + } elsif ((($arg->{'type'} eq 'enum') || + ($arg->{'type'} eq 'string') || + ($arg->{'type'} eq + 'password')) && + (defined($val = + $arg->{'vals_byname'}{$arg->{$optionset}}))) { + # Enumerated choice of string or enum + # option + push(@{$dest}, + "%%BeginFeature: " . + "*$option $arg->{$optionset}\n"); + push(@{$dest}, $val->{'driverval'} . "\n"); + } elsif ((($arg->{'type'} eq 'string') || + ($arg->{'type'} eq + 'password')) && + ($arg->{$optionset} eq 'None')) { + # 'None' is mapped to the empty string + # in string options + push(@{$dest}, + "%%BeginFeature: " . + "*$option $arg->{$optionset}\n"); + my $driverval = $arg->{'proto'}; + $driverval =~ s/\%s//g; + push(@{$dest}, $driverval . "\n"); + } else { + # Setting for numerical or string + # option which is not under the + # enumerated choices + push(@{$dest}, + "%%BeginFeature: " . + "*$option $arg->{$optionset}\n"); + my $sprintfproto = $arg->{'proto'}; + $sprintfproto =~ s/\%(?!s)/\%\%/g; + push(@{$dest}, + sprintf($sprintfproto, + $arg->{$optionset}) . + "\n"); } - } elsif ((($arg->{'type'} eq 'enum') || - ($arg->{'type'} eq 'string') || - ($arg->{'type'} eq 'password')) && - (defined($val = - $arg->{'vals_byname'}{$arg->{$optionset}}))) { - # Enumerated choice of string or enum - # option - push(@{$dest}, $val->{'driverval'} . "\n"); - } elsif ((($arg->{'type'} eq 'string') || - ($arg->{'type'} eq 'password')) && - ($arg->{$optionset} eq 'None')) { - # 'None' is mapped to the empty string in - # string options - my $driverval = $arg->{'proto'}; - $driverval =~ s/\%s//g; - push(@{$dest}, $driverval . "\n"); } else { - # Setting for numerical or string option - # which is not under the enumerated choices - my $sprintfproto = $arg->{'proto'}; - $sprintfproto =~ s/\%(?!s)/\%\%/g; + # Command line or JCL option push(@{$dest}, - sprintf($sprintfproto, - $arg->{$optionset}) . - "\n"); + "%% FoomaticRIPOptionSetting: " . + "$option=$arg->{$optionset}\n"); } - } else { - # Command line or JCL option - push(@{$dest}, - "%% FoomaticRIPOptionSetting: " . - "$option=$arg->{$optionset}\n"); + print $logh " --> Correcting numerical/string " . + "option to $option=$arg->{$optionset}" . + " (Command line argument)\n"; + # We have replaced this option on the + # FIFO + $optionreplaced = 1; } - print $logh " --> Correcting numerical/string " . - "option to $option=$arg->{$optionset}" . - " (Command line argument)\n"; - # We have replaced this option on the - # FIFO - $optionreplaced = 1; - } - # Mark that we have already found this option - $arg->{'notfirst'} = 1; - if (!$optionreplaced) { - if ($arg->{'style'} ne 'G') { - # "Controlled by '<Composite>'" setting of - # a member option of a composite option - if ($fromcomposite) { - $value = "From$value"; - } - # Non-PostScript option - # Check whether it is valid - if (defined(my $newvalue = - checkoptionvalue($dat, $option, - $value, 0))) { - print $logh " --> Setting option\n"; - # Valid choice, set it. - $arg->{$optionset} = $newvalue; - if ($optionsalsointoheader) { - $arg->{'header'} = $newvalue; + # Mark that we have already found this option + $arg->{'notfirst'} = 1; + if (!$optionreplaced) { + if ($arg->{'style'} ne 'G') { + # "Controlled by '<Composite>'" setting of + # a member option of a composite option + if ($fromcomposite) { + $value = "From$value"; } - if (($arg->{'type'} eq 'enum') && - (($option eq 'PageSize') || - ($option eq 'PageRegion')) && - ($newvalue =~ /^Custom/) && - ($linetype eq - 'FoomaticRIPOptionSetting')) { - # Custom page size - $twolinesbefore =~ - /^\s*([\d\.]+)\s+([\d\.]+)\s+([\d\.]+)\s+([\d\.]+)\s+([\d\.]+)\s*$/; - my ($w, $h) = ($1, $2); - if (($w) && ($h) && - ($w != 0) && ($h != 0)) { - $newvalue = "$newvalue.${w}x$h"; - $arg->{$optionset} = $newvalue; - if ($optionsalsointoheader) { - $arg->{'header'} = - $newvalue; + # Non-PostScript option + # Check whether it is valid + if (defined(my $newvalue = + checkoptionvalue($dat, $option, + $value, 0))) { + print $logh " --> Setting option\n"; + # Valid choice, set it. + $arg->{$optionset} = $newvalue; + if ($optionsalsointoheader) { + $arg->{'header'} = $newvalue; + } + if (($arg->{'type'} eq 'enum') && + (($option eq 'PageSize') || + ($option eq 'PageRegion')) && + ($newvalue =~ /^Custom/) && + ($linetype eq + 'FoomaticRIPOptionSetting')) { + # Custom page size + $linesafterlastbeginfeature =~ + /^[\s\r\n]*([\d\.]+)[\s\r\n]+([\d\.]+)[\s\r\n]+/s; + my ($w, $h) = ($1, $2); + if (($w) && ($h) && + ($w != 0) && ($h != 0)) { + $newvalue = + "$newvalue.${w}x$h"; + $arg->{$optionset} = $newvalue; + if ($optionsalsointoheader) { + $arg->{'header'} = + $newvalue; + } } } + # For a composite option insert the + # code from the member options with + # current setting "From<composite>" + # The code from the member options + # is chosen according to the setting + # of the composite option. + if (($arg->{'style'} eq 'X') && + ($linetype eq + 'FoomaticRIPOptionSetting')) { + buildcommandline($dat, $optionset); + $line .= + $arg->{$postscriptsection}; + } + # If this argument is PageSize or + # PageRegion, also set the other + syncpagesize($dat, $option, $newvalue, + $optionset); + if ($optionsalsointoheader) { + syncpagesize($dat, $option, + $newvalue, 'header'); + } + } else { + # Invalid option, log it. + print $logh " --> Invalid option " . + "setting found in job\n"; } - # For a composite option insert the - # code from the member options with - # current setting "From<composite>" - # The code from the member options - # is chosen according to the setting - # of the composite option. - if (($arg->{'style'} eq 'X') && - ($linetype eq - 'FoomaticRIPOptionSetting')) { + } elsif ($fromcomposite) { + # PostScript option, but we have to look up + # the PostScript code to be inserted from + # the setting of a composite option, as + # this option is set to "Controlled by + # '<Composite>'". + # Set the option + if (defined(my $newvalue = + checkoptionvalue + ($dat, $option, + "From$value", 0))) { + print $logh " --> Looking up setting " . + "in composite option '$value'\n"; + # Valid choice, set it. + $arg->{$optionset} = $newvalue; + if ($optionsalsointoheader) { + $arg->{'header'} = $newvalue; + } + # Update composite options buildcommandline($dat, $optionset); - $line .= $arg->{$postscriptsection}; + # Substitute PostScript comment by + # the real code + $line = $arg->{'compositesubst'}; + } else { + # Invalid option, log it. + print $logh " --> Invalid option " . + "setting found in job\n"; } - # If this argument is PageSize or - # PageRegion, also set the other - syncpagesize($dat, $option, $newvalue, - $optionset); - if ($optionsalsointoheader) { - syncpagesize($dat, $option, - $newvalue, 'header'); - } - } else { - # Invalid option, log it. - print $logh " --> Invalid option " . - "setting found in job\n"; - } - } elsif ($fromcomposite) { - # PostScript option, but we have to look up - # the PostScript code to be inserted from - # the setting of a composite option, as this - # option is set to "Controlled by - # '<Composite>'". - # Set the option - if (defined(my $newvalue = - checkoptionvalue - ($dat, $option, - "From$value", 0))) { - print $logh " --> Looking up setting " . - "in composite option '$value'\n"; - # Valid choice, set it. - $arg->{$optionset} = $newvalue; - if ($optionsalsointoheader) { - $arg->{'header'} = $newvalue; - } - # Update composite options - buildcommandline($dat, $optionset); - # Substitute PostScript comment by - # the real code - $line = $arg->{'compositesubst'}; } else { - # Invalid option, log it. - print $logh " --> Invalid option " . - "setting found in job\n"; + # it is a PostScript style option with + # the code readily inserted, no option + # for the renderer command line/JCL to set, + # no lookup of a composite option needed, + # so nothing to do here... + print $logh + " --> Option will be set by " . + "PostScript interpreter\n"; } - } else { - # it is a PostScript style option with - # the code readily inserted, no option - # for the renderer command line/JCL to set, - # no lookup of a composite option needed, - # so nothing to do here... - print $logh - " --> Option will be set by " . - "PostScript interpreter\n"; } + } else { + # This option is unknown to us. WTF? + print $logh "Unknown option $option=$value found " . + "in the job\n"; } - } else { - # This option is unknown to us. WTF? - print $logh "Unknown option $option=$value found " . - "in the job\n"; - } - } elsif (($line =~ m/^\%\%EndFeature/) && - ($nestinglevel == 0)) { - # End of Feature - $infeature = 0; - # If the option setting was replaced, it ends here, too, - # end the next option is not necessarily also replaced. - $optionreplaced = 0; - } elsif (($line =~ m/^\%\%Begin/) && - ($isdscjob) && - (!$prologfound) && - ($nestinglevel == 0)) { - # In some PostScript files (especially when generated - # by "dvips" of TeX/LaTeX) the "%%BeginProlog" is - # missing, so assume that it was before the current - # line (the first line starting with "%%Begin". - print $logh "Job claims to be DSC-conforming, but " . - "\"%%BeginProlog\" was missing before first " . - "line with another \"%%Begin...\" comment " . - "(is this a TeX/LaTeX/dvips-generated PostScript " . - "file?). Assuming start of \"Prolog\" here.\n"; - # Beginning of Prolog - $inprolog = 1; - $nondsclines = 0; - # Insert options for "Prolog" before the current line - if (!$prologfound) { - $line = - "%%BeginProlog\n" . - makeprologsection($dat, $optionset, 0) . - $line; + } elsif (($line =~ m/^\%\%EndFeature/) && + ($nestinglevel == 0)) { + # End of Feature + $infeature = 0; + # If the option setting was replaced, it ends here, + # too, and the next option is not necessarily also + # replaced. + $optionreplaced = 0; + $linesafterlastbeginfeature = ""; + } elsif (($line =~ m/^\%\%Begin/) && + ($isdscjob) && + (!$prologfound) && + ($nestinglevel == 0)) { + # In some PostScript files (especially when generated + # by "dvips" of TeX/LaTeX) the "%%BeginProlog" is + # missing, so assume that it was before the current + # line (the first line starting with "%%Begin". + print $logh "Job claims to be DSC-conforming, but " . + "\"%%BeginProlog\" was missing before first " . + "line with another \"%%Begin...\" comment " . + "(is this a TeX/LaTeX/dvips-generated PostScript " . + "file?). Assuming start of \"Prolog\" here.\n"; + # Beginning of Prolog + $inprolog = 1; + $nondsclines = 0; + # Insert options for "Prolog" before the current line + if (!$prologfound) { + $line = + "%%BeginProlog\n" . + makeprologsection($dat, $optionset, 0) . + $line; + } + $prologfound = 1; + } elsif (($line =~ m/^\s*\%/) || ($line =~ m/^\s*$/)) { + # This is an unknown PostScript comment or a blank + # line, no active code + $ignoreline = 1; } - $prologfound = 1; - } elsif (($line =~ m/^\s*\%/) || ($line =~ m/^\s*$/)) { - # This is an unknown PostScript comment or a blank line, - # no active code - $ignoreline = 1; } else { # This line is active PostScript code + if ($infeature) { + # Collect coe in a "%%BeginFeature: ... %%EndFeature" + # section, to get the values for a custom option + # setting + $linesafterlastbeginfeature .= $line; + } if ($inheader) { if ((!$inprolog) && (!$insetup)) { # Outside the "Prolog" and "Setup" section @@ -3151,10 +3204,10 @@ for $file (@filelist) { # Debug info if ($lastpassthru != $passthru) { if ($passthru) { - print $logh "Found:\n $line" . + print $logh "Found: $line" . " --> Output goes directly to the renderer now.\n${added_lf}"; } else { - print $logh "Found:\n $line" . + print $logh "Found: $line" . " --> Output goes to the FIFO buffer now.${added_lf}\n"; } } @@ -3221,6 +3274,19 @@ for $file (@filelist) { # Send line to renderer if (!$printprevpage) { print $rendererhandle $line; + + while ($line=<STDIN>) + { + if ($line =~ /^\%\%[A-Za-z\s]{3,}/) { + print $logh "Found: $line" . + " --> Continue DSC parsing now.${added_lf}\n"; + $saved = 1; + last; + } else { + print $rendererhandle $line; + $linect++; + } + } } } else { # Push the line onto the stack for later spitting up... @@ -3773,6 +3839,7 @@ sub getrendererhandle { # value $line =~ /^([^=]+)/; my $cmd = $1; + $cmd =~ s/^\s*(.*?)\s*$/$1/; my $cmdfound = 0; for (@jclheader) { # If the command is there, replace it @@ -3824,8 +3891,9 @@ sub getrendererhandle { } # The rest of the job data - while (<KID4_IN>) { - print $fileh $_; + my $buf; + while (read(KID4_IN, $buf, 1024)) { + print $fileh $buf; } # A JCL trailer @@ -4005,7 +4073,7 @@ sub getfileconverterhandle { # CUPS can stuff the default settings into the PostScript output # of the file converter (so all CUPS settings get also applied when # one prints the documentation pages (all other files we get - # already converted to PostScript by CUPS. + # already converted to PostScript by CUPS). if ($spooler eq 'cups') { $fileconverter .= " | ${programdir}pstops '$rargs[0]' '$rargs[1]' '$rargs[2]' " . @@ -4195,8 +4263,9 @@ sub getfileconverterhandle { # filter print KID2 $alreadyread; # Then read the rest from standard input - while (<STDIN>) { - print KID2 $_; + my $buf; + while (read(STDIN, $buf, 1024)) { + print KID2 $buf; } if (!close STDIN && $! != $ESPIPE) { @@ -4847,6 +4916,12 @@ sub rip_die { } else { print STDERR $message . "\n"; } + if ($debug) { + use Data::Dumper; + local $Data::Dumper::Purity=1; + local $Data::Dumper::Indent=1; + print $logh Dumper($dat); + } exit $exitstat; } @@ -5116,7 +5191,11 @@ sub checkoptionvalue { ($arg->{'type'} eq 'float')) { if (($value <= $arg->{'max'}) && ($value >= $arg->{'min'})) { + if ($arg->{'type'} eq 'int') { + return POSIX::floor($value); + } else { return $value; + } } elsif ($forcevalue) { my $name = $arg->{'name'}; my $newvalue; @@ -5462,8 +5541,6 @@ sub parsepageranges { my $currentnumber = 0; my $rangestart = 0; -####### Question: is rangeend ever used? - my $rangeend = 0; my $currentkeyword = ''; my $invalidrange = 0; my $totalscore = 0; @@ -5537,8 +5614,7 @@ sub parsepageranges { } } elsif ($c =~ /[a-z_]/i) { # Letter or underscore - if (($rangestart > 0) || ($rangeend > 0) || - ($currentnumber > 0)) { + if (($rangestart > 0) || ($currentnumber > 0)) { # Keyword not allowed after a page number or a # page range $invalidrange = 1; @@ -5587,10 +5663,10 @@ sub setoptionsforpage { # number of the page my ($dat, $optionset, $page) = @_; - my $bestscore = 10000000; my $value; for my $arg (@{$dat->{'args'}}) { $value = ''; + my $bestscore = 10000000; for my $key (keys %{$arg}) { next if $key !~ /^pages:(.*)$/; my $pageranges = $1; @@ -5754,8 +5830,8 @@ sub buildcommandline { # Custom paper size $val = valbyname($arg,"Custom"); $found = 1; - } elsif ($userval eq '0') { - foreach (qw(No Off False None)) { + } elsif ($userval =~ /^(0|No|Off|False)$/i) { + foreach (qw(0 No Off False None)) { if ($val=valbyname($arg,$_)) { $userval = $_; $arg->{$optionset} = $userval; @@ -5763,8 +5839,8 @@ sub buildcommandline { last; } } - } elsif ($userval eq '1') { - foreach (qw(Yes On True)) { + } elsif ($userval =~ /^(1|Yes|On|True)$/i) { + foreach (qw(1 Yes On True)) { if ($val=valbyname($arg,$_)) { $userval = $_; $arg->{$optionset} = $userval; @@ -5772,7 +5848,7 @@ sub buildcommandline { last; } } - } elsif ($userval eq 'LongEdge') { + } elsif ($userval =~ /^(LongEdge|DuplexNoTumble)$/i) { # Handle different names for the choices of the # "Duplex" option foreach (qw(LongEdge DuplexNoTumble)) { @@ -5783,7 +5859,7 @@ sub buildcommandline { last; } } - } elsif ($userval eq 'ShortEdge') { + } elsif ($userval =~ /^(ShortEdge|DuplexTumble)$/i) { foreach (qw(ShortEdge DuplexTumble)) { if ($val=valbyname($arg,$_)) { $userval = $_; @@ -5826,7 +5902,8 @@ sub buildcommandline { # Custom page size for PostScript printers $cmdvar = "$width $height 0 0 0\n$cmdvar"; } else { - # Custom page size for Foomatic/Gimp-Print + # Custom page size for Foomatic/Gutenprint/ + # Gimp-Print $cmdvar =~ s/\%0/$width/ or $cmdvar =~ s/(\W)0(\W)/$1$width$2/ or $cmdvar =~ s/^0(\W)/$width$1/m or @@ -5876,7 +5953,12 @@ sub buildcommandline { # Place this Postscript command onto the prepend queue # for the appropriate section. if ($cmdvar) { - my $open = "[{\n%%BeginFeature: *$name $userval\n"; + my $open = "[{\n%%BeginFeature: *$name "; + if ($type eq 'bool') { + $open .= ($userval == 1 ? "True" : "False") . "\n"; + } else { + $open .= "$userval\n"; + } my $close = "\n%%EndFeature\n} stopped cleartomark\n"; if ($section eq "Prolog") { push (@prologprepend, "$open$cmdvar$close"); |