Foomatic 1.1 beta release
Grant Taylor <gtaylor@picante.com>
http://www.linuxprinting.org/

With contributions from Till Kamppeter <till.kamppeter@gmx.net>

This README contains mainly info for developers. See the file USAGE if
you want to know how to use foomatic.

Copying
-------

This is under the GPL, except for MyXMLGrovePath.pm, which was Perl
Artistic and still is.  See http://www.gnu.org/.

If you spot a data error, send mail describing the bug to
foomatic-devel@linuxprinting.org

General discussion happens in the foomatic-devel forum/list thing at
www.linuxprinting.org.

Intro
-----

Roadmap: 
http://www.linuxprinting.org/pipermail/foomatic-devel/2001q1/000073.html

This version implements nearly all of what's necessary for Phase 2.  In
particular:

 - The whole thing is fully internationalized, with complete support
   for...  well, English.  The backends only accept English, because
   it's nonobvious how to find out the user's locale.  I think it's
   best to have the user tools accept locale-specific options but
   actually submit them in <en>.

 - There is code to manipulate those files.  You can load them, putz
   around with the data, and save them.  It's a little more awkward
   than pure Perl, but not horribly so.

 - There is code to take the data and produce the new XML version of
   what was once the .foo data files.  This is the magic!

 - There is temporary code to convert the new XML combo data into the
   old .foo style (this makes all the old backends and the spooler
   specific datafile generation functions work).

 - The API has been significantly cleaned up.

 - A program foomatic-configure is provided which implements complete
   printer configuration for the common spoolers. It is designed to
   support CUPS, PPR, PDQ, LPRng, LPD, GNUlpr, and direct spooler-less
   printing and it is designed to make it easy to write GUI or automagic
   printer configuration tools. It also transfers queues between different
   spoolers and generates Perl data structures so that frontends can build
   menues.

 - Printing and managing print jobs is done by foomatic-printjob,
   you supply exactly the same command line options for doing the same
   tasks on every supported spooler.

 - PJL (Printing Job Language) options can be read from the printer and
   added into the local Foomatic database. This allows access to many
   functions of the printer which are not supported by the driver, as
   paper tray selection, toner saving, toner density, ... This is done
   with foomatic-getpjloptions and foomatic-addpjloptions. Usually,
   PJL is only supported by PCL or PostScript laser printers.

 - Getting a list of all registered printers and with which drivers they
   work (overview XML file) and setting up the datafile for a given 
   printer/driver combo (combo XML file) works in a reasonable time and
   with a reasonable amount of memory. So computing of data can be done
   when the data is needed. Shipping big pre-built data collections is
   not necessary any more.

 - One can produce PPD files for PPD-aware applications as Star Office,
   Open Office, the GIMP (for printers not supported by GIMP-Print), GPR,
   Windows/Mac clients using their PostScript driver (and the Linux/Unix
   server using the Linux driver for the printer). They give access to
   all the driver's options in the printing dialogs of said
   appllications. This works for all spoolers.

The upshot of all this is that you can now make changes easily and run
the scripts to calculate out whatever your backend needs directly.

Programs
--------

Makefile

  A makefile with an install target.

foomatic-gswrapper

  This is a wrapper around Ghostscript.  It regularizes options if
  they differ between gs flavors.  The backends invoke
  foomatic-gswrapper automatically if present.

foomatic-datafile

  This program will compute the spooler-specific datafile for any
  spooler/printer/driver tuple, or a spooler-independent PPD file for
  applications/clients being able to access the printer's options. There
  is a flag to force recompiling of the combo data, or it can come from
  the precomputed cached results. Use the -f flag if you change any
  source/ data files.

foomatic-configure

  See USAGE for more info.

  This is the great-grandady of printer configuration programs.
  You can invoke this to configure a printer
  and driver under any spooler with any sort of printer connection.
  It includes methods to summarize the current configurations, to add
  new queues, reconfigure existing queues, enumerate the printers
  known to the world, and return xml data objects describing
  individual printers and drivers.

  It should be very straightforward to write interactive printer
  configuration tools around this script:

  1. foomatic-configure -O prints the XML db overview on stdout
  2. foomatic-configure -Q prints an XML summary of printer queues
  3. foomatic-configure -X prints the XML for a database object
  4. foomatic-configure with various options does the actual setup
  5. foomatic-configure -P prints Perl structures for frontends
  6. foomatic-configure -C copies queues, also to other spoolers
  7. foomatic-configure -D sets a queue as the default queue
  8. foomatic-configure -R removes a queue
	
  foomatic-configure supports CUPS, PPR, PDQ, LPD, LPRng, GNUlpr, and
  direct spooler-less printing nearly completely. The program is 
  structured with a dispatch table; for the cost of a few Perl 
  functions it can support even more spoolers. If not told, it attempts
  to guess which spooler to use, or asks.

  Regarding item (2), the summary of current config.  It shows each
  queue, giving attributes for spooler, and various settings.  Queues
  with the foomatic attribute set to zero are not foomatic-configure
  configured queues (or raw queues). Trying to modify them with
  foomatic-configure would turn them into raw queues. The summary shows
  also which is the default queue, if a default queue is defined for the
  current spooler. The $PRINTER environment variable is not taken into
  account here.

  For all spoolers, f-c fully groks the configuration format. It rewrites
  the whole thing, preserving ordering, comments, etc, and regularizing the
  syntax on each rewrite.  So it can change entries that are clearly
  lpdomatic ones, and leave others alone. Also changes of the option
  default settings done manually (or with KUPS, XPP, XPDQ, KDEPrint,
  ...) are preserved when modifying a queue.

  It is wrong to store configuration in a weird place just because foomatic 
  is used: the user should be able to edit the config by hand the
  old-fashioned way...

  When configuring printers, the spooler-specific datafile is put into
  /etc/foomatic/<spooler>/ (and if needed symlinked to from
  elsewhere).  The corresponding XML combo file and a PPD file (to be
  symlinked/used by applications or clients) is put in
  /etc/foomatic/. They all get a basename taken from the queue name.

  For printer configuration frontends it is necessary to get all info
  about the queue configuration, the options, possible settings, and
  default settings. This info can be retrived as a Perl data
  structure. The structure produced by

     foomatic-configure -q -P > testfile.pl

  can be read by the following Perl script example.pl

     #!/usr/bin/perl
     my @QUEUES;

     eval (join('',(<STDIN>)));

     my $i;
     my $N = $#QUEUES + 1;
     print "$N Queues\n";
     for ($i = 0;  $i < $N; $i++) {
         my $n = $i + 1;
         print "$n : $QUEUES[$i]->{'queuedata'}{'queue'}\n";
     }

  with

     cat testfile.pl | ./example.pl

  Queue copying especially allows to switch between spoolers overtaking
  ones queues with all settings and adjustments.

foomatic-ppdload

  This program takes a ppd filename and a printer id as arguments.  It
  parses a PPD file and writes option data into the foomatic database
  for use with the foomatic "ppd" driver and that printer.  There are
  several limitations, but it's an interesting experiment.

  Right now, it will handle Boolean and PickOne options that go in the
  Prolog, DocumentSetup, or PageSetup spots.  Also, PPD interoption
  constraints (not to be confused with foomatic option to printer and
  driver mapping constraints) are not supported by foomatic.  And of
  course, the interesting color and font information from the PPD has
  no place in the current foomatic schema.  All this will change over
  time.

foomatic-getpjloptions

  Reads the PJL options from local (parallel, USB. serial, ...) or remote
  (only socket, LPD is not bi-directional) printers to standard output. They
  can be piped into foomatic-addpjloptions to add them to the database. Call
  the program without arguments for help.

foomatic-addpjloptions

  Add the PJL options listed by a printer to the Foomatic database. The
  option list is read from a file or from standard input. The ID of the
  printer for which the options are has to be provided (option -p). You can 
  add all PJL options or only the most important ones (-i). When you are
  adding the options from a file, you are asked whether the printer ID is
  correct, but you can turn this off if you want (-f). Call the program with
  the -h option to get help.

  Note: The program needs the three files foomatic-templates/pjl*.xml

  Example for making available the PJL options of the networked HP LaserJet
  4050 (Foomatic ID: 62304), hostname printer6, port 9100 with CUPS:

  # Remove the "native" PJL options from the database
  rm -f `grep -li "pjl" db/source/opt/*.xml`
  # Remove the options from a former PJL option poll on the same printer
  rm -f foomatic-db/opt/pjl-62304-*
  # Get the PJL options from the printer
  ./foomatic-getpjloptions printer6 9100 | ./foomatic-addpjloptions -p 62304
  # Move the XML files into the database
  ./foomatic-kitload -k foomatic-db/
  # Make a PPD file and recompile all needed Foomatic files
  ./foomatic-datafile -f -t cups -d lj5gray -p 62304 > lj4050.ppd
  # Set up printer queue
  lpadmin -p LaserJet4050 -E -v socket://printer6:9100/ -P lj4050.ppd

foomatic-kitload

  This program installs a foomatic data kit into the local data
  library.  It takes a -k <dirname> option, where <dirname> is the
  toplevel directory of a foomatic driver "kit".  A "kit" is a
  selection of XML source files arranged exactly as in the source/
  section of the master database (ie, opt/ driver/ printer/ subdirs).
  The gimp-print's foomatic-generator produces exactly such a kit.

  Foomatic-kitload is moderately paranoid about kits: the kit must
  contain at least one of printer/ driver/ and opt/; the kit must
  contain only files ending in .xml, the kit cannot be the local
  library itself, etc.  But it does not inspect the contents of the
  kit files in any way.

foomatic-printjob

  See USAGE for more info.

  This program implements all the logic for controlling the dynamic 
  elements of queues.  In other words, jobs. It'll submit them, provide
  status on them, cancel them, etc. This provides an easy way for
  application authors to print in a spooler and driver neutral way.

foomatic-ipp

  This program (not yet written) provides basic IPP export for queues
  accessible to foomatic-printjob and foomatic-configure.  Whee!

foomatic-compiledb

  This program will run around and generate combo data for all valid
  printer/driver combinations.  It takes about two hours (without 
  foomatic-combo-xml) on a 256M/750MHz x86 machine.  There's a -f flag
  to force a recompile by erasing the whole combo and pcache subtrees.

  compile_db also now takes a -j# flag: it will run that many compute
  processes in parallel.  You should run compile_db with both -f,
  which will clear the results area, and a -j flag to specify how may
  processes to run concurrently.  (Gratuitous feature: you can add
  more processes in the middle without conflict!  Just don't run
  another with -f until they all finish).  Alas, compile_db seems to
  be memory bandwidth-bound (without foomatic-combo-xml), so the nifty
  parallelization has no effect on execution time.  Drat.

  Generally, compile_db should just not be necessary except for people
  who modify option and driver data.  Foomatic-datafile and especially
  foomatic-configure will automagically compute just what they need at
  runtime, and cache the results.

foomatic-combo-xml

  The Foomatic accelaration engine written in C (by Till), it computes
  printer/driver combo XML files or the printer overview XML file in less
  then two seconds (on a crappy 128MB/350MHz machine). foomatic-compiledb
  needs less than three minutes for its job on a two-processor 1GB/1GHz 
  machine. The printer/driver combo XML files are computed around 600 times
  faster than with the pure Perl programs. In addition, foomatic-combo-xml
  does not need more than 10 MB of memory.

  The program is called by the Foomatic Perl library, but can also be
  called stand-alone, call the program without command line options to
  know how to use it.

  foomatic-combo-xml does not need any XML parsing libraries, to make it
  faster and less memory-consuming, the XML files are somehow "manually"
  parsed.

  Without foomatic-combo-xml the following problems appeared:

  - The thing was *at least* an order of magnitude slower than life
    under Postgres and Perl was.  It took hours to run compile_db, and
    up to some minutes (at least a few seconds) to compile one combo.
    The first one took more time as the option cache loaded.  (The
    new overview and pcache mechanisms mitigated this a bit, but not
    much for compile_db).

  - Memory: compiledb compute processes peaked at about 150MB RAM.  You
    could turn down the number of computations per process, but it
    never got much below 130MB.

etc/printcap

  My testing printcap and etcdir for foomatic-configure.


Backends
--------

lpdomatic

  Runs under LPD, VA's GNUlpr LPD variant, LPRng, and probably others.
  Currently uses a plain Perl dump of the old-style combo data as
  input.

cupsomatic

  Runs under CUPS.  The datafile is a Perl dump of the old-style combo
  data embedded as comments at the end of an automatically generated
  PPD.  The PPD reflects all the options, numerical options are mapped to
  enumerated options. Some GUIs (KDE 3.x, XPP 1.1 and newer) show the
  numerical options as numerical options anyway.

ppromatic

  Runs under PPR.  The datafile is a Perl dump of the old-style combo
  data embedded as comments at the end of an automatically generated
  PPD.  The PPD reflects all the options, numerical options are mapped to
  enumerated options.

pdqomatic

  Not actually a standalone program at this time.  Rather, the
  Foomatic::DB code directly generates PDQ driver declaration with
  embedded shell script code to implement everything needed.

mfomatic

  Runs under magicfilter, mainly for LPRng use.  A derivative of this
  is used by Red Hat (?).  Takes the old-style Perl dump as input.
  Works together with a slightly modified magicfilter; code here
  generates magicfilter definitions that process ascii properly and
  pipe Postgres into mfomatic.  mfomatic is probably broken.

directomatic

  Filter for printing directly to the printer, without any spooler,
  uses the same plain Perl dump as lpdomatic as input.


Things People Can Do
--------------------

 - Try it out!  In theory, foomatic-datafile output should be
   basically identical to whatever it was before.  Make sure your
   printer still works, and that there are no buglets.  (There's
   thousands of lines of new code changed between then and now, so
   there will certainly be glitches; just post on the 
   linuxprinting.foomatic.devel forum and we'll fix them).

 - Now is a good time to examine the file formats and ponder the
   implementation of automagical driver info and opt info generation.
   (Done for stp/gimp-print; see that implementation for inspriation)

 - Also, the XML combo files are what user GUI tools should be able to
   deal with.  For a given queue, the file can be found in
   /etc/foomatic/queuename.xml.  For a given system, the available
   queues can be found by examining the output of foomatic-configure
   -Q.  To actually configure queues, tools should invoke f-c.


About the database
------------------

There is a $libdir, somewhere.  Underneath $libdir there are:

 db/                             - the database
 db/kitload.log                  - list of third-party "kit" files
 db/source/                      - "source" data, provided by humans, etc
 db/source/printer/<poid>.xml    - printer-specific data, one per printer id
 db/source/driver/<driver>.xml   - driver-specific data, one per driver name
 db/source/opt/<idx>.xml         - option data, one file per option
 cache/                          - "compiled" data, and xml parse cache
 cache/compiled/                 - "compiled" data, computed by PHTDBPUB code
 cache/compiled/overview.xml     - summary thing to speed certain operations
 cache/compiled/<driver>/        - directories named by driver
 cache/compiled/<drv>/<id>.xml   - printers that work for this driver
 cache/pcache/*.perl             - machine-independent binary cached data

The whole cache/compiled/ tree can be computed anytime again from the
source/ tree by running the script ./compile_db.  This should be
mostly unnecessary.

You can also force a recompile with the -f flag to foomatic-datafile.

Finally, if a compiled file turns up missing whenever PHTDBPUB wants
it, it'll be recomputed and saved then.


Foomatic::DB API
----------------

This API isn't required, now that the data is an an easy-to-process
format (nevermind the foomatic-configure language independent "api")
for heathen users of non-Perl languages, but even for such dogs it's
instructive to poke at how certain things are done:

get_driverlist
get_printerlist
get_printers_for_driver
get_drivers_for_printer

  These all return lists of printer id's or driver names.  The
  get_foo_for_bar methods accept a printer id or driver name as
  appropriate; the frst two just return all and take no arguments.

get_overview
get_overview_xml
get_overview_grove

  This returns an overview listing of all printers, with ids, makes,
  models, functionaliy, drivers, etc.  The various flavors return a
  Perl data structure, or XML or a Grove.

get_makes
get_models_by_make

  These return makes and models lists.

get_javascript2

  This returns a JavaScript function that accepts two widget element
  names.  If the first one is set to a value that euqals a known make,
  then the second one's choices are replaced with a set of models
  valued with printer IDs.  I use this to make a "nested menu" out of
  two menu controls on a web page.

get_printer_from_make_model

  This returns a printer id from a make and model

normalize

  This is used in sorts to sort printer model names properly.  You
  can't sort a printer model as a word, because the number messes it
  up, and you can't sort by number, because that doesn't work either.
  You can sort characterwise on a normalized() name.

get_combo_data_xml
get_combo_data_grove

  This returns the combined printer/driver data for a particular
  combination.  Arguments are driver, printer id, force; where force
  is 1 to recompile for sure and not included or zero to take from the
  cache.

  The _xml form returns pretty-printed XML.  The _grove form returns a
  Perl XML::Grove structure.

  The "combo" operation is less trival than it looks; be careful when
  messing with it.  It took me hours to get right...

get_printer_grove
get_driver_grove
get_printer_xml
get_driver_xml

  These return the information in the printer info or driver info
  database files.  See get_combo_data_* for _xml vs _grove
  differences.

getdat

  This returns an old-style "dat" structure, useful for all the old
  backends and spooler data functions.  It takes driver, poid [,force]
  arguments; just like get_combo_data_*

getmfdata
getpdqdata
getlpddata
getcupsppd
getgenericppd

  These return the spooler-specific data file for various spoolers and
  backends, and also the spooler-independent PPDs for applications and 
  clients. They take no arguments; instead you must call getdat
  first, and they'll then magically find that result. For CUPS you should
  use "getgenericppd", it produces PPD files closer to the Adobe standards,
  "getcupsppd" is only there for compatibility with KDE 2.x and XPP
  1.0 and earlier.

getdocs
getexecdocs
get_summarydocs

  For some reason there are three functions which return documentation
  about job options for particular printer/driver pairs.  For that
  matter, there's a fourth one in the various backends.

  These work the same way as get*data; you call getdat first.

  Once, these worked if you called getdat with only a driver; in that
  case it sort of documented it for all printers at once.  This is
  sort of incomplete, especially what with PJL arguments in the world.
  I also probably broke it in the xml rewrite.

get_libdir

  Returns the library directory.

grove_*
pretty_xml

  Various utility functions for XML and Grove data manipulation.  I'll
  probably rearrange and derive a personal flavour of Grove so that
  these will be methods on Groves instead of random utility functions
  like this.


Foomatic::GrovePath
-------------------

This is a slightly modified version of the standard XML::Grove::Path,
which kept blowing up on me.  The silly thing die'd for XML paths that
don't exist.  This one doesn't.


Dependencies
------------
use Storable;              # Already in Debian libstorable-perl
use XML::Grove;            # Already in Debian
use XML::Grove::Builder;
use XML::Grove::AsString;
use XML::Parser::PerlSAX;
use XML::Grove::Factory;
use XML::Grove::AsCanonXML;
use XML::Twig;

These came in, and required beyond Debian potato stuff, the following
files from CPAN (Foomatic is the printer database for Mandrake 8.1 and
newer, so all these are already available):

Storable-1.0.12.tar.gz     # already in Debian
DateManip-5.39.tar.gz
Parse-Yapp-1.04.tar.gz
XML-Grove-0.46alpha.tar.gz # already in Debian
XML-Dumper-0.4.tar.gz
XML-Encoding-1.01.tar.gz
XML-Parser-2.29.tar.gz     # includes expat; easy to install
XML-Parser.2.30.tar.gz     # doesn't include expat; harder to install 
XML-Twig-2.02.tar.gz
libxml-enno-1.02.tar.gz
libxml-perl-0.07.tar.gz    # Debian has, but out of date?

I experimented with XML::DOM, but the API was created by lunatics or
something, and the resulting data structure is impossible to work with
sensibly in Perl: it's gratuitously self-referential and stores all
sorts of stuff in $i[0][1][3][5][2][9] array things for no good
reason.

I also experimented with several pretty-print methods for XML; the
current one works if there are no comments, and only mucks up slightly
on comments.  The current scheme involves comverting back and forth
from xml a few times to get it pretty.  This is better than
libxml-enno XML::Filter::Reindent, which reverses all the tags and
skips elements.  Argh!


Data
----

There are three main source datafiles; annotated examples:

source/opt/2.xml
================

Every option exists independently from printers or drivers, because
they might apply to arbitrary combinations of printers and/or drivers.
In practice, some drivers have wholly unique options (gimp-print/stp,
for example), while others (lots of generic basic Ghostscript drivers,
for example) share some options.

<option type="enum" id="opt/2">

# Options are of a type "enum", "bool", "int" or "float"
# options have an ID.  The id is also the filename.

# The shortname is a spaceless short name for the thing.
# It must not contain / or :
# It should be one of the standard Adobe PPD option names if apropriate

  <arg_shortname>

# Various things here, and all <comments>, are internationalized.
# They take the usual posix locale codes in the form xx[_YY], where xx
# is a two-letter iso language code, and YY is two-letter country code
# to distinguise differing national dialects.
#
# Generally the national dialects won't be very common or necessary
# here.  The backends currently require that <en> content be provided.

   <en>PageSize</en><!-- backends only know <en> shortnames! -->
  </arg_shortname>

# The longname is a short phrase describing the thing in more detail
# GUI tools usually show longnames

  <arg_longname>
   <en>Page Size</en>
  </arg_longname>

# The comments are used to form documentation.  In theory these can
# become man pages or the like.

  <!-- A multilingual <comments> block can appear here, too;
       it should be treated as documentation for the user. -->

# The execution section describe how the backend should execute this
# option.  The order and spot apply to the *driver*'s prototype for
# arg_substitution (once called commandline) style options, or just
# the order applies for arg_postscript and arg_pjl options.  The
# user's value gets put into the arg_proto's %s location.

  <arg_execution>
   <arg_order>100</arg_order>
   <arg_spot>Z</arg_spot>
   <arg_postscript />
   <arg_proto>&lt;&lt;/PageSize[%s]/ImagingBBox null&gt;&gt;setpagedevice</arg_proto>
  </arg_execution>

# The constraints define what printer/driver combinrations this option
# applies to.  The *most specific* constraint rules the day; it's
# "sense" says wether or not the option is "in".  The winning
# constraint also provides the default value used when this option
# applies to that printer and driver.

# Constraint elements are: driver, make, model.  The driver is the
# driver name, or not present to apply to any driver.  The make is the
# printer make, or not present to apply to any printer make.  The
# model is the driver model, or not present to apply to any printer.
# Instead of make/model, you can also specify <printer>id</printer>.

# IMPORTANT: The make and model must match the one in the printer xml
# definition, and everywhere else in the other options.  I need to
# write a utility to change printer names sensibly.
#
# You can also use <printer>printer-id</printer> instead of make/model.

# It is illegal to have a model with no make.

# It is illegal to have none of make/model/driver.

# It is illegal to have *no* constraints, or at least such options are
# never used.

# For enum options, the defval is the id of the enum_val that is the
# default.  For other option types, it is the actual default value
# (ie, a number, or 1 or 0 for boolean, etc).

  <constraints>
     <constraint sense="true">
      <driver>sj48</driver>
      <arg_defval>ev/1</arg_defval>
     </constraint>
     <constraint sense="true">
      <driver>r4081</driver>
      <arg_defval>ev/1</arg_defval>
     </constraint>
# A gajillion constraings deleted
  </constraints>
  <enum_vals>
   <enum_val id="ev/1">
    <ev_longname>
     <en>US Letter</en>
    </ev_longname>
    <!-- A multilingual <comments> block can appear here, too;
         it should be treated as documentation for the user. -->
    <ev_shortname>
     <en>Letter</en>
     <!-- Until someone tells me how to learn the user locale in 
          backends, the shortname must be monolingual in <en>! -->
    </ev_shortname>

# If present, the driverval is what gets substituted in for the %s in
# the option's prototype.  This way the user-visible stuff can be
# anything.

    <ev_driverval>612 792</ev_driverval>

# This enum_val has no constraints.  It *is* OK for enum_vals to
# have no constraints; they are assumed to apply unless
# constrained otherwise.

   </enum_val>
   <enum_val id="ev/115">
    <ev_longname>
     <en>A3</en>
    </ev_longname>
    <!-- A multilingual <comments> block can appear here, too;
         it should be treated as documentation for the user. -->
    <ev_shortname>
     <en>A3</en>
     <!-- Until someone tells me how to learn the user locale in 
          backends, the shortname must be monolingual in <en>! -->
    </ev_shortname>
    <ev_driverval>842 1191</ev_driverval>

# Here are some example constraints for an enum_val.  The A3 size
# paper doesn't fit on lots of printers, so there are various
# constraints to make the right thing happen.

    <constraints>
     <constraint sense="true">
      <driver>ml85p</driver>
      <arg_defval>na</arg_defval>
     </constraint>
     <constraint sense="true">
      <make>HP</make>
      <model>DeskJet 1000C</model>
      <driver>pnm2ppa</driver>
      <arg_defval>na</arg_defval>
     </constraint>
     <constraint sense="false">
      <make>HP</make>
      <model>DeskJet 820C</model>
      <driver>pnm2ppa</driver>
      <arg_defval>na</arg_defval>
     </constraint>

     # lots more...

    </constraints>
   </enum_val>
  </enum_vals>
</option>



printer/100576
==============

# The printer file contains information specific to a particular
# printer.

<printer id="printer/100576">

# Make and model are not internationalized.  There will eventually be
# an "alias" mechanism, but the need is different.

  <make>HP</make>
  <model>LaserJet 4000</model>

# Various stuff about the machine

  <mechanism>
    <laser/>

# At some point we can make color be less of a boolean flag and more
# of a section full of goodies.

    <!--not "color"-->
    <resolution>

# In theory this is a list.  In practice I've only got one per
# printer, and the Resolution argument sort of replaces this
# information.

      <dpi>
        <x>1200</x>
        <y>1200</y>
      </dpi>
    </resolution>

    <consumables>

# Information about ink, drums, etc.
# The comments are supposed to be qualitative ("it costs a ton to
# run!")

      <comments>
        <en>toner</en>
      </comments>

# There should be <partno>12A1975</partno> elements with manufacturer
# part numbers for the various carts, etc it takes.  I'll track them
# all down someday, and have a price watcher thingy like I do now for
# the printers.

      <!--one or more "partno" elements.-->
    </consumables>
  </mechanism>

  <url>http://www.pandi.hp.com/pandi-db/prod_info.show?model=C4118A&amp;name=LaserJet4000</url>

# The lang section.  In practice this will be only minimally useful;
# 
#  - Backends can pstops the ps down a level if needed
#  - Backends can know if pjl options apply
#  - Backends can know if "quick text" will work

  <lang>
    <postscript level="2">
    <!--unknown ppd filename "ppd"--></postscript>
    <pjl/>
    <text>
      <charset>us-ascii</charset>
    </text>
  </lang>

# The autodetection stuff

  <autodetect>

# There are normally <parallel>four elements inside</parallel>
# Plus we can figure out what to put for other types like usb.

    <!--no known parport probe information-->
  </autodetect>

# My grading system.  It's US-style letter grades A, B, D, and F,
# which the website shows as perfect through paperweight.
# THERE IS NO `C'!!!

  <functionality>A</functionality>

# There's a spot for the "best" driver.  Arguably, the scores should
# live with the printer/driver association and not on the printer, but
# then it's a big hassle to figure out if a printer works...

  <!--unknown preferred "driver"-->

  <!--not "unverified"-->
  <!--no "contrib_url"-->

# The regular notes section.
# The allowed tags are: <p>, <a href="foobar"> </a> and nothing else.

  <comments>
    <en>I don&apos;t believe this:&lt;p&gt;

&lt;i&gt;1200x1200 dpi only possible with Windows drivers,
600x600 can be reached w/o particular software.
The difference is visible, but only slightly, so
the Functionality got &quot;Mostly&quot;&lt;p&gt;&lt;/i&gt;

Do the following:&lt;p&gt;

Set the resolution on the front panel to &quot;Prores 1200&quot;, not to &quot;Fastres 1200&quot;.
When you use CUPS with HPs PPD file, turn off &quot;Fastres 1200&quot; in the
printer configuration options.&lt;p&gt;

Try the generic PostScript PPD file which comes with KUPS 1.0 or newer.</en>
  </comments>
</printer>


driver/md2k
===========

The driver files contain information about drivers.  There are a few
things, but the two biggies are the prototype and the printers list

<driver id="driver/md2k">
 <name>md2k</name>
 <url>http://plaza26.mbn.or.jp/~higamasa/gdevmd2k/</url>
 <execution>
  <ghostscript />

# The prototype defines what command the backends run to drive this
# printer.  It must take postscript on stdin and generate "printer
# stuff" on stdout.  Various %A, %B, etc substitution "spots" are
# specified; this is where substition options will be placed.

  <prototype>gs -q -dBATCH -dSAFER -dQUIET -dNOPAUSE -sDEVICE=md2k%A%Z -sOutputFile=- -</prototype>
 </execution>
 <comments>
  <en>Part of the gdevmd2k-0.2a package by Shinya Umino.  The web page and 
documentation are in Japanese.  
&lt;a href="/clippings/MD5000-translation.txt"&gt;Here&lt;/a&gt;
is an English translation of the driver's web page, and &lt;a 
href="/clippings/alpsmd.txt"&gt;here&lt;/a&gt; is the README from the driver package.</en>
 </comments>

# The printer list is a simple list of printers that this driver works
# with.  Historically, these "bits" were on the printer cgi form page,
# but now I've put them here.

 <printers>
  <printer>
   <id>printer/240137</id><!-- Alps MD-1000 -->
  </printer>
  <printer>
   <id>printer/240169</id><!-- Alps MD-1300 -->
  </printer>
  <printer>
   <id>printer/240105</id><!-- Alps MD-2000 -->
  </printer>
  <printer>
   <id>printer/240073</id><!-- Alps MD-4000 -->
  </printer>
 </printers>
</driver>


