#!/usr/bin/perl
#
# hpijs-generator - A generator for the foomatic XML files for HP's "hpijs"
#                   inkjet printer driver (http://hpinkjet.sourceforge.net/)
#
# Copyright 2001 Till Kamppeter <till.kamppeter@gmx.net>
#
#   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 Free
#   Software Foundation; either version 2 of the License, or (at your option)
#   any later version.
#
#   This program is distributed in the hope that it will be useful, but
#   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
#   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
#   for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

# File and path definitions
my $mapfile = "./hpijs-printermap";
my $kitdir = "./foomatic-db";

# XML file templates
my $hpijs_driver_xml =
"<driver id=\"driver/hpijs\">
 <name>hpijs</name>
 <url>http://hpinkjet.sourceforge.net/</url>
 <execution>
  <filter />
  <nopjl />
  <prototype>gs -q -dBATCH -dSAFER -dQUIET -dNOPAUSE -sDEVICE=ijs -sIjsServer=hpijs%A -dIjsUseOutputFD%Z -sOutputFile=- -</prototype>
 </execution>
 <comments>
  <en>

  This driver is the first free driver issued by HP for their DeskJet
  and LaserJet printers. Since version 1.0.1 HP has put it under a
  BSD-like license without the restriction that it is only allowed to
  use the driver with HP printers, as it was the case for HPIJS 1.0
  and earlier. So this driver is really free software now.&lt;P&gt;

  Since version 1.0 the driver uses the new IJS interface to plug in
  drivers into GhostScript without needing to recompile GhostScript,
  the driver is provided by an extra executable invoked by GhostScript
  which gets the raster data from GhostScript via shared memory, which
  is much faster than piping bitmap output into the standard input of
  the driver, in addition GhostScript can ask the driver for the
  capabilities of the printer/driver pair.&lt;P&gt;

  The quality of colour printing is much higher than the quality of
  the other drivers.&lt;P&gt;

  The quality on photo papers (in photo mode) is very high, especially
  for the newer models (beginning from the HP DeskJet 990C) which
  auto-detect the paper type by a hardware facility and so
  automatically switch between the normal colour mode and the photo
  mode. On the HP DeskJet 990C and newer there is also a 1200 dpi high
  resolution mode available, which gives excellent photo quality. This
  driver is the only free one which supports more than 600 dpi on HP
  inkjet printers.&lt;P&gt;

  This driver supports also monochrome laser printers in PCL 5 up to
  600 dpi. Most laser printers with 1200 dpi understand usually PCL 6
  or PostScript, so use the &quot;pxlmono&quot;, &quot;lj5gray&quot;,
  or &quot;Postscript&quot; then. For Brother laser printers use the
  &quot;hl1240&quot;/&quot;hl1250&quot; drivers.&lt;P&gt;

  The driver execution data currently available on this site is for
  version 1.2 (or newer) of HPIJS and IJS 0.33 (available in GNU
  GhostScript 6.53 and APFL GhostScript 7.04). It does not work with
  older versions of HPIJS and IJS.&lt;P&gt;
  </en>
 </comments>
 <printers>
\@\@PRINTERENTRIES\@\@ </printers>
</driver>
";

my $printerlist_xml = 
"  <printer>
   <id>printer/\@\@PRINTERID\@\@</id>\@\@COMMENT\@\@
  </printer>
";

my $hpijs_model_xml =
"<option type=\"enum\" id=\"opt/hpijs-Model\">
  <!-- A multilingual <comments> block can appear here, too;
       it should be treated as documentation for the user. -->
  <arg_longname>
   <en>Model</en>
  </arg_longname>
  <arg_shortname>
   <en>Model</en><!-- backends only know <en> shortnames! -->
  </arg_shortname>
  <arg_execution>
   <arg_order>100</arg_order>
   <arg_spot>A</arg_spot>
   <arg_required />
   <arg_substitution />
   <arg_proto> %s</arg_proto>
  </arg_execution>
  <constraints>
\@\@MODELCONSTRAINTS\@\@  </constraints>
  <enum_vals>
\@\@MODELENUMVALS\@\@  </enum_vals>
</option>
";

my $hpijs_pagesize_xml = 
"<option type=\"enum\" id=\"opt/hpijs-PageSize\">
  <!-- A multilingual <comments> block can appear here, too;
       it should be treated as documentation for the user. -->
  <arg_longname>
   <en>Page Size</en>
  </arg_longname>
  <arg_shortname>
   <en>PageSize</en><!-- backends only know <en> shortnames! -->
  </arg_shortname>
  <arg_execution>
   <arg_order>105</arg_order>
   <arg_spot>A</arg_spot>
   <arg_substitution />
   <arg_proto>%s</arg_proto>
  </arg_execution>
  <constraints>
\@\@PAGESIZECONSTRAINTS\@\@  </constraints>
  <enum_vals>
\@\@PAGESIZEENUMVALS\@\@  </enum_vals>
</option>
";

my $hpijs_quality_xml = 
"<option type=\"enum\" id=\"opt/hpijs-Quality\">
  <!-- A multilingual <comments> block can appear here, too;
       it should be treated as documentation for the user. -->
  <arg_longname>
   <en>Quality, Ink Type, Media Type</en>
  </arg_longname>
  <arg_shortname>
   <en>Quality</en><!-- backends only know <en> shortnames! -->
  </arg_shortname>
  <arg_execution>
   <arg_order>110</arg_order>
   <arg_spot>A</arg_spot>
   <arg_substitution />
   <arg_proto> -sIjsParams=%s</arg_proto>
  </arg_execution>
  <constraints>
\@\@QUALITYCONSTRAINTS\@\@  </constraints>
  <enum_vals>
\@\@QUALITYENUMVALS\@\@  </enum_vals>
</option>
";

my $hpijs_duplex_xml = 
"<option type=\"enum\" id=\"opt/hpijs-Duplex\">
  <!-- A multilingual <comments> block can appear here, too;
       it should be treated as documentation for the user. -->
  <arg_longname>
   <en>Double-Sided Printing</en>
  </arg_longname>
  <arg_shortname>
   <en>Duplex</en><!-- backends only know <en> shortnames! -->
  </arg_shortname>
  <arg_execution>
   <arg_order>120</arg_order>
   <arg_spot>A</arg_spot>
   <arg_substitution />
   <arg_proto> -dDuplex=%s</arg_proto>
  </arg_execution>
  <constraints>
\@\@DUPLEXCONSTRAINTS\@\@  </constraints>
  <enum_vals>
   <enum_val id=\"ev/hpijs-Duplex-None\">
    <ev_longname>
     <en>Off</en>
    </ev_longname>
    <!-- A multilingual <comments> block can appear here, too;
         it should be treated as documentation for the user. -->
    <ev_shortname>
     <en>None</en>
     <!-- Until someone tells me how to learn the user locale in
          backends, the shortname must be monolingual in <en>! -->
    </ev_shortname>
    <ev_driverval>false</ev_driverval>
   </enum_val>
   <enum_val id=\"ev/hpijs-Duplex-DuplexNoTumble\">
    <ev_longname>
     <en>Long Edge (Standard)</en>
    </ev_longname>
    <!-- A multilingual <comments> block can appear here, too;
         it should be treated as documentation for the user. -->
    <ev_shortname>
     <en>DuplexNoTumble</en>
     <!-- Until someone tells me how to learn the user locale in
          backends, the shortname must be monolingual in <en>! -->
    </ev_shortname>
    <ev_driverval>true -dTumble=false</ev_driverval>
   </enum_val>
   <enum_val id=\"ev/hpijs-Duplex-DuplexTumble\">
    <ev_longname>
     <en>Short Edge (Flip)</en>
    </ev_longname>
    <!-- A multilingual <comments> block can appear here, too;
         it should be treated as documentation for the user. -->
    <ev_shortname>
     <en>DuplexTumble</en>
     <!-- Until someone tells me how to learn the user locale in
          backends, the shortname must be monolingual in <en>! -->
    </ev_shortname>
    <ev_driverval>true -dTumble=true</ev_driverval>
   </enum_val>
  </enum_vals>
</option>
";

my $hpijs_option_constraint_xml =
"     <constraint sense='true'>
      <driver>hpijs</driver>
      <printer>printer/\@\@PRINTERID\@\@</printer>\@\@COMMENT\@\@
      <arg_defval>ev/\@\@DEFAULTENUMVALID\@\@</arg_defval>
     </constraint>
";

my $hpijs_enum_val_xml =
"   <enum_val id=\"ev/\@\@ENUMVALID\@\@\">
    <ev_longname>
     <en>\@\@LONGNAME\@\@</en>
    </ev_longname>
    <!-- A multilingual <comments> block can appear here, too;
         it should be treated as documentation for the user. -->
    <ev_shortname>
     <en>\@\@SHORTNAME\@\@</en>
     <!-- Until someone tells me how to learn the user locale in
          backends, the shortname must be monolingual in <en>! -->
    </ev_shortname>
    <ev_driverval>\@\@DRIVERVALUE\@\@</ev_driverval>
    <constraints>
     <!-- Assume the choice doesn't apply... -->
     <constraint sense='false'>
      <driver>hpijs</driver>
     </constraint>
     <!-- ...except to these: -->
\@\@ENUMVALCONSTRAINTS\@\@    </constraints>
   </enum_val>
";

my $hpijs_enum_val_constraint_xml =
"     <constraint sense='true'>
      <driver>hpijs</driver>
      <printer>printer/\@\@PRINTERID\@\@</printer>\@\@COMMENT\@\@
     </constraint>
";

# Available paper size values (the "constraints" fields will be filled
# in with the appropriate printers when the printer list is parsed

my @pagesize_order = qw/Letter Legal Ledger Executive 
                        A3 A4 A5 A6
                        Photo 
                        B4JIS B5JIS
                        Oufuku Hagaki
                        SuperB FLSA/;
my @pagesize_size_order = qw/SuperB A3 Ledger B4JIS Legal FLSA Letter A4
                             Executive B5JIS A5 Oufuku A6 Photo Hagaki/;
my $pagesize_vals = { 
    'Letter' => { 
	'longname' => 'Letter',
	'driverval' => ' -dDEVICEWIDTHPOINTS=612 -dDEVICEHEIGHTPOINTS=792',
	'constraints' => ""
    },
    'Legal' => { 
	'longname' => 'Legal',
	'driverval' => ' -dDEVICEWIDTHPOINTS=612 -dDEVICEHEIGHTPOINTS=1008',
	'constraints' => ""
    },
    'Ledger' => { 
	'longname' => 'Ledger',
	'driverval' => ' -dDEVICEWIDTHPOINTS=792 -dDEVICEHEIGHTPOINTS=1224',
	'constraints' => ""
    },
    'Executive' => { 
	'longname' => 'Executive',
	'driverval' => ' -dDEVICEWIDTHPOINTS=522 -dDEVICEHEIGHTPOINTS=756',
	'constraints' => ""
    },
    'A3' => { 
	'longname' => 'A3',
	'driverval' => ' -dDEVICEWIDTHPOINTS=842 -dDEVICEHEIGHTPOINTS=1190',
	'constraints' => ""
    },
    'A4' => { 
	'longname' => 'A4',
	'driverval' => ' -dDEVICEWIDTHPOINTS=595 -dDEVICEHEIGHTPOINTS=842',
	'constraints' => ""
    },
    'A5' => { 
	'longname' => 'A5',
	'driverval' => ' -dDEVICEWIDTHPOINTS=420 -dDEVICEHEIGHTPOINTS=595',
	'constraints' => ""
    },
    'A6' => { 
	'longname' => 'A6',
	'driverval' => ' -dDEVICEWIDTHPOINTS=297 -dDEVICEHEIGHTPOINTS=420',
	'constraints' => ""
    },
    'Photo' => { 
	'longname' => 'Photo',
	'driverval' => ' -dDEVICEWIDTHPOINTS=288 -dDEVICEHEIGHTPOINTS=432',
	'constraints' => ""
    },
    'B4JIS' => { 
	'longname' => 'B4 (JIS)',
	'driverval' => ' -dDEVICEWIDTHPOINTS=729 -dDEVICEHEIGHTPOINTS=1033',
	'constraints' => ""
    },
    'B5JIS' => { 
	'longname' => 'B5 (JIS)',
	'driverval' => ' -dDEVICEWIDTHPOINTS=516 -dDEVICEHEIGHTPOINTS=729',
	'constraints' => ""
    },
    'Oufuku' => { 
	'longname' => 'Oufuku-Hagaki',
	'driverval' => ' -dDEVICEWIDTHPOINTS=420 -dDEVICEHEIGHTPOINTS=567',
	'constraints' => ""
    },
    'Hagaki' => { 
	'longname' => 'Hagaki',
	'driverval' => ' -dDEVICEWIDTHPOINTS=283 -dDEVICEHEIGHTPOINTS=420',
	'constraints' => ""
    },
    'SuperB' => { 
	'longname' => 'Super B',
	'driverval' => ' -dDEVICEWIDTHPOINTS=936 -dDEVICEHEIGHTPOINTS=1368',
	'constraints' => ""
    },
    'FLSA' => { 
	'longname' => 'American Foolscap',
	'driverval' => ' -dDEVICEWIDTHPOINTS=612 -dDEVICEHEIGHTPOINTS=936',
	'constraints' => ""
    }
};

# Available quality values (the "constraints" fields will be filled in with
# the appropriate printers when the printer list is parsed

my @quality_order = qw/300DraftGrayscaleK
                       300DraftGrayscaleCMYK
                       300DraftColorCMY 300DraftColorCMYK
                       300GrayscaleK 300GrayscaleCMYK
                       300ColorCMY 300ColorCMYFullBleed 300ColorCMYK
                       300PhotoCMY 300PhotoCMYK
                       300PhotoCMYcmK
                       300BestGrayscaleK 300BestGrayscaleCMYK
                       600GrayscaleK 600GrayscaleCMYK
                       600ColorCMY 600ColorCMYFullBleed 600ColorCMYK
                       600PhotoCMY 600PhotoCMYK
                       600BestGrayscaleK 600BestGrayscaleCMYK
                       1200PhotoCMY 1200PhotoCMYFullBleed 1200PhotoCMYK/;
my $quality_vals = { 
    '300GrayscaleK' => { 
	'longname' => '300 dpi, Grayscale, Black Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=0&quot; -r300',
	'constraints' => ""
    },
    '300DraftGrayscaleK' => { 
	'longname' => '300 dpi, Draft, Grayscale, Black Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=1,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=0&quot; -r300',
	'constraints' => ""
    },
    '300BestGrayscaleK' => { 
	'longname' => '300 dpi, Best, Grayscale, Black Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=0&quot; -r300',
	'constraints' => ""
    },
    '600GrayscaleK' => { 
	'longname' => '600 dpi, Grayscale, Black Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=0&quot; -r600',
	'constraints' => ""
    },
    '600BestGrayscaleK' => { 
	'longname' => '600 dpi, Best, Grayscale, Black Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=0&quot; -r600',
	'constraints' => ""
    },
    '300GrayscaleCMYK' => { 
	'longname' => '300 dpi, Grayscale, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=2&quot; -r300',
	'constraints' => ""
    },
    '300DraftGrayscaleCMYK' => { 
	'longname' => '300 dpi, Draft, Grayscale, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=1,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=2&quot; -r300',
	'constraints' => ""
    },
    '300BestGrayscaleCMYK' => { 
	'longname' => '300 dpi, Best, Grayscale, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=2&quot; -r300',
	'constraints' => ""
    },
    '600GrayscaleCMYK' => { 
	'longname' => '600 dpi, Grayscale, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=2&quot; -r600',
	'constraints' => ""
    },
    '600BestGrayscaleCMYK' => { 
	'longname' => '600 dpi, Best, Grayscale, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=0,Quality:MediaType=0,Quality:PenSet=2&quot; -r600',
	'constraints' => ""
    },
    '300ColorCMY' => {
	'longname' => '300 dpi, Color, Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=1&quot; -r300',
	'constraints' => ""
    },
    '300DraftColorCMY' => {
	'longname' => '300 dpi, Draft, Color, Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=1,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=1&quot; -r300',
	'constraints' => ""
    },
    '600ColorCMY' => {
	'longname' => '600 dpi, Color, Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=1&quot; -r600',
	'constraints' => ""
    },
    '1200PhotoCMY' => {
	'longname' => '1200 dpi, Color, Color Cartr., Photo Paper',
	'driverval' => 
	    '&quot;Quality:Quality=3,Quality:ColorMode=2,Quality:MediaType=2,Quality:PenSet=1&quot; -r1200',
	'constraints' => ""
    },
    '300ColorCMYK' => {
	'longname' => '300 dpi, Color, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=2&quot; -r300',
	'constraints' => ""
    },
    '300DraftColorCMYK' => {
	'longname' => '300 dpi, Draft, Color, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=1,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=2&quot; -r300',
	'constraints' => ""
    },
    '600ColorCMYK' => {
	'longname' => '600 dpi, Color, Black &amp; Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=2&quot; -r600',
	'constraints' => ""
    },
    '300PhotoCMYcmK' => {
	'longname' => '300 dpi, Photo, Photo &amp; Color Cartr., Premium Paper',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=2,Quality:MediaType=1,Quality:PenSet=4&quot; -r300',
	'constraints' => ""
    },
    '300PhotoCMYK' => {
	'longname' => '300 dpi, Photo, Black &amp; Color Cartr., Photo Paper',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=2,Quality:MediaType=2,Quality:PenSet=2&quot; -r300',
	'constraints' => ""
    },
    '600PhotoCMYK' => {
	'longname' => '600 dpi, Photo, Black &amp; Color Cartr., Photo Paper',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=2,Quality:MediaType=2,Quality:PenSet=2&quot; -r600',
	'constraints' => ""
    },
    '300PhotoCMY' => {
	'longname' => '300 dpi, Photo, Color Cartr., Photo Paper',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=2,Quality:MediaType=2,Quality:PenSet=1&quot; -r300',
	'constraints' => ""
    },
    '600PhotoCMY' => {
	'longname' => '600 dpi, Photo, Color Cartr., Photo Paper',
	'driverval' => 
	    '&quot;Quality:Quality=2,Quality:ColorMode=2,Quality:MediaType=2,Quality:PenSet=1&quot; -r600',
	'constraints' => ""
    },
    '1200PhotoCMYK' => {
	'longname' => '1200 dpi, Photo, Black &amp; Color Cartr., Photo Paper',
	'driverval' => 
	    '&quot;Quality:Quality=3,Quality:ColorMode=2,Quality:MediaType=2,Quality:PenSet=2&quot; -r1200',
	'constraints' => ""
    },
    '300ColorCMYFullBleed' => {
	'longname' => '300 dpi, Color, Full Bleed, Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=1,Quality:FullBleed=1&quot; -r300',
	'constraints' => ""
    },
    '600ColorCMYFullBleed' => {
	'longname' => '600 dpi, Color, Full Bleed, Color Cartr.',
	'driverval' => 
	    '&quot;Quality:Quality=0,Quality:ColorMode=2,Quality:MediaType=0,Quality:PenSet=1,Quality:FullBleed=1&quot; -r600',
	'constraints' => ""
    },
    '1200PhotoCMYFullBleed' => {
	'longname' => '1200 dpi, Color, Full Bleed, Color Cartr., Photo Paper',
	'driverval' => 
	    '&quot;Quality:Quality=3,Quality:ColorMode=2,Quality:MediaType=2,Quality:PenSet=1,Quality:FullBleed=1&quot; -r1200',
	'constraints' => ""
    },
};

# The HP inkjet printers can be classified in groups, where all printers in
# one group are compatible to each other and work with the same options.

my $printer_groups = {
    'DJ350' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300DraftGrayscaleK 300DraftColorCMY ' .
	                 '300GrayscaleK 300ColorCMY 300BestGrayscaleK ' .
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'DJ500' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300GrayscaleK',
	'QualityVals' => '300DraftGrayscaleK 300GrayscaleK',
	'Duplex' => 0
    },
    'DJ540' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300DraftGrayscaleK 300DraftColorCMY ' .
	                 '300GrayscaleK 300ColorCMY',
	'Duplex' => 0
    },
    'DJ630' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300DraftGrayscaleK 300DraftColorCMY ' .
	                 '300DraftColorCMYK ' .
	                 '300GrayscaleK 300ColorCMY 300ColorCMYK ' .
			 '300PhotoCMYcmK 300BestGrayscaleK ' .
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'DJ600' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' .
	                 '300GrayscaleCMYK 300ColorCMYK 300BestGrayscaleK '.
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'DJ6xx' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' .
	                 '300GrayscaleCMYK 300ColorCMYK 300BestGrayscaleK '.
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'DJ6xxPhoto' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' .
	                 '300GrayscaleCMYK 300ColorCMYK ' . 
			 '300PhotoCMYcmK 300BestGrayscaleK ' .
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'DJ8xx' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' . 
			 '300GrayscaleCMYK 600GrayscaleCMYK ' .
	                 '300ColorCMYK ' . 
			 '300PhotoCMYK 600PhotoCMYK',
	'Duplex' => 0
    },
    'DJ8x5' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300DraftGrayscaleK ' .
                         '300DraftColorCMY 300DraftColorCMYK ' .
                         '300GrayscaleK 600GrayscaleK ' .
                         '300ColorCMY 300ColorCMYK ' .
                         '300PhotoCMY 600PhotoCMY ' .
			 '300PhotoCMYK 600PhotoCMYK',
	'Duplex' => 0
    },
    'DJ850' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' . 
			 '300GrayscaleCMYK 600GrayscaleCMYK ' .
	                 '300ColorCMYK',
	'Duplex' => 0
    },
    'DJ890' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' . 
			 '300GrayscaleCMYK 600GrayscaleCMYK ' .
	                 '300ColorCMYK',
	'Duplex' => 0
    },
    'DJ9xx' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' . 
			 '300GrayscaleCMYK 600GrayscaleCMYK ' .
			 '300ColorCMYK ' . 
			 '300PhotoCMYK 600PhotoCMYK',
	'Duplex' => 1
    },
    'HP2xxx' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' . 
			 '300GrayscaleCMYK 600GrayscaleCMYK ' .
	                 '300ColorCMYK',
	'Duplex' => 1
    },
    'DJ9xxVIP' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' . 
			 '300GrayscaleCMYK 600GrayscaleCMYK ' .
			 '300ColorCMYK 600ColorCMYK 1200PhotoCMYK',
	'Duplex' => 1
    },
    'BI22xx' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMYK',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMYK ' . 
			 '300GrayscaleCMYK 600GrayscaleCMYK ' .
			 '300ColorCMYK 600ColorCMYK',
	'Duplex' => 1
    },
    'AP2xxx' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMY ' .
	                 '300DraftColorCMYK ' .
			 '300GrayscaleCMYK 300ColorCMY 300ColorCMYK ' .
			 '300PhotoCMYcmK 300BestGrayscaleK ' .
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'AP21xx' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMY ' .
	                 '300DraftColorCMYK ' .
			 '300GrayscaleCMYK 300ColorCMY 300ColorCMYK ' .
			 '300PhotoCMYcmK 300BestGrayscaleK ' .
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'AP2560' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300DraftGrayscaleCMYK 300DraftColorCMY ' .
	                 '300DraftColorCMYK ' .
			 '300GrayscaleCMYK 300ColorCMY 300ColorCMYK ' .
			 '300PhotoCMYcmK 300BestGrayscaleK ' .
	                 '600BestGrayscaleK',
	'Duplex' => 0
    },
    'PSP100' => {
	'PageSizeDefault' => 'Photo',
	'QualityDefault' => '300ColorCMY',
	'QualityVals' => '300ColorCMY 300ColorCMYFullBleed ' . 
                         '600ColorCMY 600ColorCMYFullBleed ' .
			 '1200PhotoCMY 1200PhotoCMYFullBleed',
	'Duplex' => 0
    },
    'LJMono' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '600GrayscaleK',
	'QualityVals' => '300DraftGrayscaleK 300GrayscaleK 600GrayscaleK',
	'Duplex' => 1
    },
    'LJMono300' => {
	'PageSizeDefault' => 'Letter',
	'QualityDefault' => '300GrayscaleK',
	'QualityVals' => '300DraftGrayscaleK 300GrayscaleK',
	'Duplex' => 1
    }
};

# Variable to collect the printer entries for the driver XML file
my @printerlist = ();

# Variables to collect the constraint entries

my @model_constraints = ();
my @pagesize_constraints = ();
my @quality_constraints = ();
my @duplex_constraints = ();

# Variable to collect the model values

my @model_values = ();

# Read the printermap file and insert the printers into the appropriate 
# constraint lists

open PRINTERMAP, "< $mapfile" ||
    die "Printer map file $mapfile not found or not readable: $!\n";

print "Processing printer entries:\n\n";

while (my $line = <PRINTERMAP>) {
    chomp ($line);
    # Comment line or blank line
    next if (($line =~ /^\s*$/) || ($line =~ /^\s*\#/));
    # Extract the fields of the printer entry
    my ($id, $make, $model, $group, $maxpapersize, $comment) = 
	split(/\|/, $line);
    # Valid entry?
    next if (($id eq "") || ($make eq "") || 
	     ($model eq "") || ($group eq ""));
    # Is the contents of the group field valid?
    die "Printer $id: The group \"$group\" does not exist!\n" 
	if (!$printer_groups->{$group});
    # Is the maximum paper size valid?
    die "Printer $id: The paper size \"$maxpapersize\" does not exist!\n" 
	if (!$pagesize_vals->{$maxpapersize});
    # Set up comment
    if (($comment) && ($comment ne "")) {
	$comment = "<!-- $comment -->";
    }

    # Printer entry in driver XML file

    my $printer_entry = $printerlist_xml;
    $printer_entry =~ s/\@\@PRINTERID\@\@/$id/;
    $printer_entry =~ s/\@\@COMMENT\@\@/$comment/;
    push (@printerlist, $printer_entry);

    # Model option

    my $model_enum_val_id = "hpijs-Model-$id";
    my $model_option_constraint = $hpijs_option_constraint_xml;
    $model_option_constraint =~ s/\@\@PRINTERID\@\@/$id/;
    $model_option_constraint =~ s/\@\@COMMENT\@\@/$comment/;
    $model_option_constraint =~
	s/\@\@DEFAULTENUMVALID\@\@/$model_enum_val_id/;
    push (@model_constraints, $model_option_constraint);
    my $model_val_constraint = $hpijs_enum_val_constraint_xml;
    $model_val_constraint =~ s/\@\@PRINTERID\@\@/$id/;
    $model_val_constraint =~ s/\@\@COMMENT\@\@/$comment/;
    my $model_driverval = "-sDeviceManufacturer=&quot;$make&quot; -sDeviceModel=&quot;$model&quot;";
    my $model_longname = "";
    my $model_shortname = "";
    if ($id =~ /^\d+$/) { # Old numeric printer ID
	die "Printer $id: Comment field must be filled in when ID is numeric!\n"
	    if ((!$comment) || ($comment eq ""));
	$model_longname = $comment;
	$model_longname =~ s/<!-- //;
	$model_longname =~ s/ -->//;
	$model_shortname = $comment;
	$model_shortname =~ s/<!-- //;
	$model_shortname =~ s/ -->//;
	$model_shortname =~ s/ /-/;
	$model_shortname =~ s/ /_/g;
    } else { # New clear text printer ID
	$model_longname = $id;
	$model_longname =~ s/-/ /;
	$model_longname =~ s/_/ /g;
	$model_shortname = $id;
    }
    # Make use of $model_longname for progress reporting
    print "$model_longname\n";
    my $model_enum_val = $hpijs_enum_val_xml;
    $model_enum_val =~ s/\@\@ENUMVALID\@\@/$model_enum_val_id/;
    $model_enum_val =~ s/\@\@LONGNAME\@\@/$model_longname/;
    $model_enum_val =~ s/\@\@SHORTNAME\@\@/$model_shortname/;
    $model_enum_val =~ s/\@\@DRIVERVALUE\@\@/$model_driverval/;
    $model_enum_val =~ s/\@\@ENUMVALCONSTRAINTS\@\@/$model_val_constraint/;
    push (@model_values, $model_enum_val);

    # PageSize option
    
    my $pagesize_default = 
	"hpijs-PageSize-$printer_groups->{$group}{'PageSizeDefault'}";
    my $pagesize_option_constraint = $hpijs_option_constraint_xml;
    $pagesize_option_constraint =~ s/\@\@PRINTERID\@\@/$id/;
    $pagesize_option_constraint =~ s/\@\@COMMENT\@\@/$comment/;
    $pagesize_option_constraint =~
	s/\@\@DEFAULTENUMVALID\@\@/$pagesize_default/;
    push (@pagesize_constraints, $pagesize_option_constraint);
    $pagesize_val_constraint = $hpijs_enum_val_constraint_xml;
    $pagesize_val_constraint =~ s/\@\@PRINTERID\@\@/$id/;
    $pagesize_val_constraint =~ s/\@\@COMMENT\@\@/$comment/;
    my $maxsize_found = 0;
    for my $value (@pagesize_size_order) {
	if ($value eq $maxpapersize) {
	    $maxsize_found = 1;
	}
	if ($maxsize_found) {
	    $pagesize_vals->{$value}{'constraints'} .=
		$pagesize_val_constraint;
	}
    }

    # Quality option
    
    my $quality_default = 
	"hpijs-Quality-$printer_groups->{$group}{'QualityDefault'}";
    my $quality_option_constraint = $hpijs_option_constraint_xml;
    $quality_option_constraint =~ s/\@\@PRINTERID\@\@/$id/;
    $quality_option_constraint =~ s/\@\@COMMENT\@\@/$comment/;
    $quality_option_constraint =~
	s/\@\@DEFAULTENUMVALID\@\@/$quality_default/;
    push (@quality_constraints, $quality_option_constraint);
    $quality_val_constraint = $hpijs_enum_val_constraint_xml;
    $quality_val_constraint =~ s/\@\@PRINTERID\@\@/$id/;
    $quality_val_constraint =~ s/\@\@COMMENT\@\@/$comment/;
    for my $value (split(/ /, $printer_groups->{$group}{'QualityVals'})) {
	$quality_vals->{$value}{'constraints'} .=
	    $quality_val_constraint;
    }

    # Duplex option

    if ($printer_groups->{$group}{'Duplex'} == 1) {
	my $duplex_option_constraint = $hpijs_option_constraint_xml;
	$duplex_option_constraint =~ s/\@\@PRINTERID\@\@/$id/;
	$duplex_option_constraint =~ s/\@\@COMMENT\@\@/$comment/;
	$duplex_option_constraint =~
	s/\@\@DEFAULTENUMVALID\@\@/hpijs-Duplex-None/;
	push (@duplex_constraints, $duplex_option_constraint);
    }

}
close PRINTERMAP;

# Set up the directories for the XML files

mkdir 'foomatic-db', 0755 or die "Cannot create directory foomatic-db: $!\n"
    unless -d 'foomatic-db';
mkdir 'foomatic-db/opt', 0755 or die "Cannot create directory foomatic-db/opt: $!\n"
    unless -d 'foomatic-db/opt';
mkdir 'foomatic-db/driver', 0755 or die "Cannot create directory foomatic-db/driver: $!\n"
    unless -d 'foomatic-db/driver';

# Create the XML files

# foomatic-db/driver/hpijs.xml

print "\nCreating foomatic-db/driver/hpijs.xml ...\n";
my $printerentries = join('', @printerlist);
$hpijs_driver_xml =~ s/\@\@PRINTERENTRIES\@\@/$printerentries/;
open HPIJS_XML, "> foomatic-db/driver/hpijs.xml" ||
    die "Cannot write file foomatic-db/driver/hpijs.xml: $!\n";
print HPIJS_XML $hpijs_driver_xml;
close HPIJS_XML;

# foomatic-db/opt/hpijs-Model.xml

print "Creating foomatic-db/opt/hpijs-Model.xml ...\n";
my $modelconstraints = join('', @model_constraints);
my $modelenumvals = join('', @model_values);
$hpijs_model_xml =~ s/\@\@MODELCONSTRAINTS\@\@/$modelconstraints/;
$hpijs_model_xml =~ s/\@\@MODELENUMVALS\@\@/$modelenumvals/;
open HPIJS_MODEL_XML, "> foomatic-db/opt/hpijs-Model.xml" ||
    die "Cannot write file foomatic-db/opt/hpijs-Model.xml: $!\n";
print HPIJS_MODEL_XML $hpijs_model_xml;
close HPIJS_MODEL_XML;

# foomatic-db/opt/hpijs-PageSize.xml

print "Creating foomatic-db/opt/hpijs-PageSize.xml ...\n";
my $pagesize_values = ();
for my $value (@pagesize_order) {
    my $pagesize_val_constraints =
	$pagesize_vals->{$value}{'constraints'};
    my $pagesize_enum_val = $hpijs_enum_val_xml;
    $pagesize_enum_val =~ s/\@\@ENUMVALID\@\@/hpijs-PageSize-$value/;
    $pagesize_enum_val =~
	s/\@\@LONGNAME\@\@/$pagesize_vals->{$value}{'longname'}/;
    $pagesize_enum_val =~ s/\@\@SHORTNAME\@\@/$value/;
    $pagesize_enum_val =~
	s/\@\@DRIVERVALUE\@\@/$pagesize_vals->{$value}{'driverval'}/;
    $pagesize_enum_val =~
      s/\@\@ENUMVALCONSTRAINTS\@\@/$pagesize_val_constraints/;
    push (@pagesize_values, $pagesize_enum_val);
}
my $pagesizeconstraints = join('', @pagesize_constraints);
my $pagesizeenumvals = join('', @pagesize_values);
$hpijs_pagesize_xml =~ s/\@\@PAGESIZECONSTRAINTS\@\@/$pagesizeconstraints/;
$hpijs_pagesize_xml =~ s/\@\@PAGESIZEENUMVALS\@\@/$pagesizeenumvals/;
open HPIJS_PAGESIZE_XML, "> foomatic-db/opt/hpijs-PageSize.xml" ||
    die "Cannot write file foomatic-db/opt/hpijs-PageSize.xml: $!\n";
print HPIJS_PAGESIZE_XML $hpijs_pagesize_xml;
close HPIJS_PAGESIZE_XML;

# foomatic-db/opt/hpijs-Quality.xml

print "Creating foomatic-db/opt/hpijs-Quality.xml ...\n";
my $quality_values = ();
for my $value (@quality_order) {
    my $quality_val_constraints =
	$quality_vals->{$value}{'constraints'};
    my $quality_enum_val = $hpijs_enum_val_xml;
    $quality_enum_val =~ s/\@\@ENUMVALID\@\@/hpijs-Quality-$value/;
    $quality_enum_val =~
	s/\@\@LONGNAME\@\@/$quality_vals->{$value}{'longname'}/;
    $quality_enum_val =~ s/\@\@SHORTNAME\@\@/$value/;
    $quality_enum_val =~
	s/\@\@DRIVERVALUE\@\@/$quality_vals->{$value}{'driverval'}/;
    $quality_enum_val =~
      s/\@\@ENUMVALCONSTRAINTS\@\@/$quality_val_constraints/;
    push (@quality_values, $quality_enum_val);
}
my $qualityconstraints = join('', @quality_constraints);
my $qualityenumvals = join('', @quality_values);
$hpijs_quality_xml =~ s/\@\@QUALITYCONSTRAINTS\@\@/$qualityconstraints/;
$hpijs_quality_xml =~ s/\@\@QUALITYENUMVALS\@\@/$qualityenumvals/;
open HPIJS_QUALITY_XML, "> foomatic-db/opt/hpijs-Quality.xml" ||
    die "Cannot write file foomatic-db/opt/hpijs-Quality.xml: $!\n";
print HPIJS_QUALITY_XML $hpijs_quality_xml;
close HPIJS_QUALITY_XML;

# foomatic-db/opt/hpijs-Duplex.xml

print "Creating foomatic-db/opt/hpijs-Duplex.xml ...\n";
my $duplexconstraints = join('', @duplex_constraints);
$hpijs_duplex_xml =~ s/\@\@DUPLEXCONSTRAINTS\@\@/$duplexconstraints/;
open HPIJS_DUPLEX_XML, "> foomatic-db/opt/hpijs-Duplex.xml" ||
    die "Cannot write file foomatic-db/opt/hpijs-Duplex.xml: $!\n";
print HPIJS_DUPLEX_XML $hpijs_duplex_xml;
close HPIJS_DUPLEX_XML;

# Copying generated files into the database

if ( -d "../../db/source/driver/" ) { 
    print "\nMoving HPIJS Foomatic entries into the database ...\n";
    system "mv foomatic-db/driver/*.xml ../../db/source/driver/; mv foomatic-db/opt/*.xml ../../db/source/opt/; rm -rf foomatic-db" ||
	die "Cannot move the generated XML files into the Foomatic database!";
}

# Done

print "\nDone,\n\n";
exit 0;
