diff options
Diffstat (limited to 'src/cups/genppd.c')
-rw-r--r-- | src/cups/genppd.c | 1573 |
1 files changed, 1117 insertions, 456 deletions
diff --git a/src/cups/genppd.c b/src/cups/genppd.c index 537bb26..f7f6e62 100644 --- a/src/cups/genppd.c +++ b/src/cups/genppd.c @@ -1,9 +1,9 @@ /* - * "$Id: genppd.c,v 1.36.2.15 2004/06/12 20:04:05 rlk Exp $" + * "$Id: genppd.c,v 1.107 2005/04/23 00:26:07 rlk Exp $" * * PPD file generation program for the CUPS drivers. * - * Copyright 1993-2003 by Easy Software Products. + * Copyright 1993-2005 by Easy Software Products and Robert Krawitz. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, @@ -32,7 +32,12 @@ * main() - Process files on the command-line... * initialize_stp_options() - Initialize the min/max values for * each STP numeric option. - * usage() - Show program usage... + * usage() - Show program usage. + * help() - Show detailed program usage. + * getlangs() - Get available translations. + * printlangs() - Show available translations. + * printmodels() - Show available printer models. + * checkcat() - Check message catalogue exists. * write_ppd() - Write a PPD file. */ @@ -45,6 +50,8 @@ #endif #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <dirent.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> @@ -59,13 +66,8 @@ #include <cups/cups.h> #include <cups/raster.h> -#ifdef INCLUDE_GIMP_PRINT_H -#include INCLUDE_GIMP_PRINT_H -#else -#include <gimp-print/gimp-print.h> -#endif -#include <gimp-print/gimp-print-intl.h> -#include "../../lib/libprintut.h" +#include <gutenprint/gutenprint.h> +#include <gutenprint/gutenprint-intl.h> /* * Note: @@ -74,19 +76,19 @@ * so we can report Level 3 support by default... */ -#ifndef CUPS_PPD_PS_LEVEL -# define CUPS_PPD_PS_LEVEL 3 -#endif +int cups_ppd_ps_level = CUPS_PPD_PS_LEVEL; +static const char *cups_modeldir = CUPS_MODELDIR; /* * File handling stuff... */ +static const char *ppdext = ".ppd"; #ifdef HAVE_LIBZ -# define PPDEXT ".ppd.gz" +static const char *gzext = ".gz"; #else -# define PPDEXT ".ppd" +static const char *gzext = ""; # define gzFile FILE * # define gzopen fopen # define gzclose fclose @@ -102,6 +104,7 @@ #define DEFAULT_SIZE "Letter" /*#define DEFAULT_SIZE "A4"*/ +#define CATALOG "LC_MESSAGES/gutenprint.mo" typedef struct /**** Media size values ****/ { @@ -115,56 +118,33 @@ typedef struct /**** Media size values ****/ top; /* Media top margin */ } paper_t; - -/* - * STP option data... - */ - -static struct /**** STP numeric options ****/ +const char *special_options[] = { - const char *name, /* Name of option */ - *text; /* Human-readable text */ - int low, /* Low value (thousandths) */ - high, /* High value (thousandths) */ - defval, /* Default value */ - step; /* Step (thousandths) */ -} stp_options[] = -{ - { "stpBrightness", "Brightness" }, - { "stpContrast", "Contrast" }, - { "stpGamma", "Gamma" }, - { "stpDensity", "Density" }, -#ifndef __APPLE__ - { "stpCyan", "Cyan" }, - { "stpMagenta", "Magenta" }, - { "stpYellow", "Yellow" }, - { "stpSaturation", "Saturation" } -#else - { "stpSaturation", "Saturation" }, - { "stpCyan", "Cyan" }, - { "stpMagenta", "Magenta" }, - { "stpYellow", "Yellow" } -#endif /* __APPLE__ */ + "PageSize", + "MediaType", + "InputSlot", + "Resolution", + "OutputOrder", + "Quality", + "ImageType", + "Duplex", + NULL }; -/* - * Mapping between manufacturer names embedded in the printer name and - * manufacturer names authorized in the PPD specification. - * If printers of other manufacturers are added, this table must - * be extended. - */ -static struct +const char *parameter_class_names[] = { - const char *manufacturer_embedded_name; - const char *manufacturer_real_name; -} stp_manufacturers[] = + N_("Printer Features"), + N_("Output Control") +}; + +const char *parameter_level_names[] = { - { "CANON", "Canon" }, - { "EPSON", "Epson" }, - { "HP", "HP" }, - { "LEXMARK", "Lexmark" }, - { "APPLE", "Apple" }, - { NULL, NULL } + N_("Common"), + N_("Extra 1"), + N_("Extra 2"), + N_("Extra 3"), + N_("Extra 4"), + N_("Extra 5") }; @@ -172,60 +152,96 @@ static struct * Local functions... */ -void initialize_stp_options(void); void usage(void); -int write_ppd(const stp_printer_t p, const char *prefix, - const char *language, int verbose); -const char *find_manufacturer_from_name(const char *name); +void help(void); +char ** getlangs(void); +static int stpi_scandir (const char *dir, + struct dirent ***namelist, + int (*sel) (const struct dirent *), + int (*cmp) (const void *, const void *)); +int checkcat (const struct dirent *localedir); +void printlangs(char** langs); +void printmodels(int verbose); +int write_ppd(const stp_printer_t *p, const char *prefix, + const char *language, int verbose); + +/* + * Global variables... + */ +const char *baselocaledir = PACKAGE_LOCALE_DIR; + +static int +is_special_option(const char *name) +{ + int i = 0; + while (special_options[i]) + { + if (strcmp(name, special_options[i]) == 0) + return 1; + i++; + } + return 0; +} + +static void +print_group_open(FILE *fp, stp_parameter_class_t p_class, + stp_parameter_level_t p_level) +{ + /* TRANSLATORS: "Gutenprint" is a proper name, not a description */ + gzprintf(fp, "*OpenGroup: %s %s %s\n\n", _("Gutenprint"), + _(parameter_class_names[p_class]), + _(parameter_level_names[p_level])); +} + +static void +print_group_close(FILE *fp, stp_parameter_class_t p_class, + stp_parameter_level_t p_level) +{ + gzprintf(fp, "*CloseGroup: %s %s %s\n\n", _("Gutenprint"), + _(parameter_class_names[p_class]), + _(parameter_level_names[p_level])); +} /* * 'main()' - Process files on the command-line... */ -int /* O - Exit status */ -main(int argc, /* I - Number of command-line arguments */ - char *argv[]) /* I - Command-line arguments */ +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ { - int i; /* Looping var */ - int option_index; /* Option index */ - const char *prefix; /* Directory prefix for output */ - const char *language; /* Language */ - const char *catalog = NULL;/* Catalog location */ - stp_printer_t printer; /* Pointer to printer driver */ - int verbose = 0; - static struct option long_options[] = - { /* Command-line options */ - /* name, has_arg, flag val */ - {"help", no_argument, 0, (int) 'h'}, - {"verbose", no_argument, 0, (int) 'v'}, - {"quiet", no_argument, 0, (int) 'q'}, - {"catalog", required_argument, 0, (int) 'c'}, - {"prefix", required_argument, 0, (int) 'p'}, - {0, 0, 0, 0} - }; + int i; /* Looping var */ + const char *prefix; /* Directory prefix for output */ + const char *language = NULL; /* Language */ + const stp_printer_t *printer; /* Pointer to printer driver */ + int verbose = 0; /* Verbose messages */ + char **langs = NULL; /* Available translations */ + char **models = NULL; /* Models to output, all if NULL */ + int opt_printlangs = 0; /* Print available translations */ + int opt_printmodels = 0;/* Print available models */ /* * Parse command-line args... */ - prefix = "ppd"; - language = "C"; - - initialize_stp_options(); - - option_index = 0; + prefix = CUPS_MODELDIR; for (;;) { - if ((i = getopt_long(argc, argv, "hvqc:p:", long_options, - &option_index)) == -1) + if ((i = getopt(argc, argv, "23hvqc:p:l:LMVd:")) == -1) break; switch (i) { + case '2': + cups_ppd_ps_level = 2; + break; + case '3': + cups_ppd_ps_level = 3; + break; case 'h': - usage(); + help(); break; case 'v': verbose = 1; @@ -234,9 +250,9 @@ main(int argc, /* I - Number of command-line arguments */ verbose = 0; break; case 'c': - catalog = optarg; + baselocaledir = optarg; #ifdef DEBUG - fprintf (stderr, "DEBUG: catalog: %s\n", catalog); + fprintf (stderr, "DEBUG: baselocaledir: %s\n", baselocaledir); #endif break; case 'p': @@ -245,14 +261,73 @@ main(int argc, /* I - Number of command-line arguments */ fprintf (stderr, "DEBUG: prefix: %s\n", prefix); #endif break; + case 'l': + language = optarg; + break; + case 'L': + opt_printlangs = 1; + break; + case 'M': + opt_printmodels = 1; + break; + case 'd': + cups_modeldir = optarg; + break; + case 'V': + printf("cups-genppd version %s, " + "Copyright (c) 1993-2005 by Easy Software Products and Robert Krawitz.\n\n", + VERSION); + printf("Default CUPS PPD PostScript Level: %d\n", cups_ppd_ps_level); + printf("Default PPD location (prefix): %s\n", CUPS_MODELDIR); + printf("Default base locale directory: %s\n\n", PACKAGE_LOCALE_DIR); + puts("This program is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU General Public License,\n" + "version 2, as published by the Free Software Foundation.\n" + "\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program; if not, please contact Easy Software\n" + "Products at:\n" + "\n" + " Attn: CUPS Licensing Information\n" + " Easy Software Products\n" + " 44141 Airport View Drive, Suite 204\n" + " Hollywood, Maryland 20636-3111 USA\n" + "\n" + " Voice: (301) 373-9603\n" + " EMail: cups-info@cups.org\n" + " WWW: http://www.cups.org\n"); + exit (EXIT_SUCCESS); + break; default: usage(); + exit (EXIT_FAILURE); break; } } + if (optind < argc) { + int n, numargs; + numargs = argc-optind; + models = stp_malloc((numargs+1) * sizeof(char*)); + for (n=0; n<numargs; n++) + { + models[n] = argv[optind+n]; + } + models[numargs] = (char*) NULL; + + n=0; + } + +#ifdef ENABLE_NLS + langs = getlangs(); +#endif /* - * Initialise libgimpprint + * Initialise libgutenprint */ stp_init(); @@ -261,7 +336,21 @@ main(int argc, /* I - Number of command-line arguments */ * Set the language... */ + if (language) + { + unsetenv("LC_CTYPE"); + unsetenv("LC_COLLATE"); + unsetenv("LC_TIME"); + unsetenv("LC_NUMERIC"); + unsetenv("LC_MONETARY"); + unsetenv("LC_MESSAGES"); + unsetenv("LC_ALL"); + unsetenv("LANG"); + setenv("LC_ALL", language, 1); + setenv("LANG", language, 1); + } setlocale(LC_ALL, ""); + #ifdef LC_NUMERIC setlocale(LC_NUMERIC, "C"); #endif /* LC_NUMERIC */ @@ -270,190 +359,423 @@ main(int argc, /* I - Number of command-line arguments */ * Set up the catalog */ - if (catalog) +#ifdef ENABLE_NLS + if (baselocaledir) { - if ((bindtextdomain(PACKAGE, catalog)) == NULL) + if ((bindtextdomain(PACKAGE, baselocaledir)) == NULL) { - fprintf(stderr, "genppd: cannot load message catalog %s: %s\n", catalog, - strerror(errno)); - exit(1); + fprintf(stderr, "cups-genppd: cannot load message catalog %s under %s: %s\n", + PACKAGE, baselocaledir, strerror(errno)); + exit(EXIT_FAILURE); } #ifdef DEBUG - fprintf (stderr, "DEBUG: bound textdomain: %s\n", catalog); + fprintf (stderr, "DEBUG: bound textdomain: %s under %s\n", + PACKAGE, baselocaledir); #endif if ((textdomain(PACKAGE)) == NULL) { - fprintf(stderr, "genppd: cannot select message catalog %s: %s\n", - catalog, strerror(errno)); - exit(1); + fprintf(stderr, "cups-genppd: cannot select message catalog %s under %s: %s\n", + PACKAGE, baselocaledir, strerror(errno)); + exit(EXIT_FAILURE); } #ifdef DEBUG fprintf (stderr, "DEBUG: textdomain set: %s\n", PACKAGE); #endif } +#endif + + /* + * Print lists + */ + + if (opt_printlangs) + { + printlangs(langs); + exit (EXIT_SUCCESS); + } + + if (opt_printmodels) + { + printmodels(verbose); + exit (EXIT_SUCCESS); + } /* * Write PPD files... */ - for (i = 0; i < stp_known_printers(); i++) - { - printer = stp_get_printer_by_index(i); - - if (printer && write_ppd(printer, prefix, language, verbose)) - return (1); - } + if (models) + { + int n; + for (n=0; models[n]; n++) + { + printer = stp_get_printer_by_driver(models[n]); + if (!printer) + printer = stp_get_printer_by_long_name(models[n]); + + if (printer) + { + if (write_ppd(printer, prefix, language, verbose)) + return 1; + } + else + { + printf("Driver not found: %s\n", models[n]); + return (1); + } + } + stp_free(models); + } + else + { + for (i = 0; i < stp_printer_model_count(); i++) + { + printer = stp_get_printer_by_index(i); + if (printer && write_ppd(printer, prefix, language, verbose)) + return (1); + } + } if (!verbose) - fprintf(stderr, "\n"); + fprintf(stderr, " done.\n"); + if (langs) + { + char **langs_tmp = langs; + while (*langs_tmp) + { + stp_free(*langs_tmp); + langs_tmp++; + } + stp_free(langs); + } return (0); } - /* - * 'initialize_stp_options()' - Initialize the min/max values for - * each STP numeric option. + * 'usage()' - Show program usage... */ void -initialize_stp_options(void) +usage(void) { - const stp_vars_t lower = stp_minimum_settings(); - const stp_vars_t upper = stp_maximum_settings(); - const stp_vars_t defvars = stp_default_settings(); - - - stp_options[0].low = 1000 * stp_get_brightness(lower); - stp_options[0].high = 1000 * stp_get_brightness(upper); - stp_options[0].defval = 1000 * stp_get_brightness(defvars); - stp_options[0].step = 50; - - stp_options[1].low = 1000 * stp_get_contrast(lower); - stp_options[1].high = 1000 * stp_get_contrast(upper); - stp_options[1].defval = 1000 * stp_get_contrast(defvars); - stp_options[1].step = 50; - - stp_options[2].low = 1000 * stp_get_gamma(lower); - stp_options[2].high = 1000 * stp_get_gamma(upper); - stp_options[2].defval = 1000 * stp_get_gamma(defvars); - stp_options[2].step = 50; - - stp_options[3].low = 1000 * stp_get_density(lower); - stp_options[3].high = 1000 * stp_get_density(upper); - stp_options[3].defval = 1000 * stp_get_density(defvars); - stp_options[3].step = 50; - -#ifndef __APPLE__ - stp_options[4].low = 1000 * stp_get_cyan(lower); - stp_options[4].high = 1000 * stp_get_cyan(upper); - stp_options[4].defval = 1000 * stp_get_cyan(defvars); - stp_options[4].step = 50; - - stp_options[5].low = 1000 * stp_get_magenta(lower); - stp_options[5].high = 1000 * stp_get_magenta(upper); - stp_options[5].defval = 1000 * stp_get_magenta(defvars); - stp_options[5].step = 50; - - stp_options[6].low = 1000 * stp_get_yellow(lower); - stp_options[6].high = 1000 * stp_get_yellow(upper); - stp_options[6].defval = 1000 * stp_get_yellow(defvars); - stp_options[6].step = 50; - - stp_options[7].low = 1000 * stp_get_saturation(lower); - stp_options[7].high = 1000 * stp_get_saturation(upper); - stp_options[7].defval = 1000 * stp_get_saturation(defvars); - stp_options[7].step = 50; -#else - stp_options[4].low = 1000 * stp_get_saturation(lower); - stp_options[4].high = 1000 * stp_get_saturation(upper); - stp_options[4].defval = 1000 * stp_get_saturation(defvars); - stp_options[4].step = 50; - - stp_options[5].low = 1000 * stp_get_cyan(lower); - stp_options[5].high = 1000 * stp_get_cyan(upper); - stp_options[5].defval = 1000 * stp_get_cyan(defvars); - stp_options[5].step = 50; - - stp_options[6].low = 1000 * stp_get_magenta(lower); - stp_options[6].high = 1000 * stp_get_magenta(upper); - stp_options[6].defval = 1000 * stp_get_magenta(defvars); - stp_options[6].step = 50; - - stp_options[7].low = 1000 * stp_get_yellow(lower); - stp_options[7].high = 1000 * stp_get_yellow(upper); - stp_options[7].defval = 1000 * stp_get_yellow(defvars); - stp_options[7].step = 50; -#endif /* __APPLE__ */ + puts("Usage: cups-genppd [-c localedir] " + "[-l locale] [-p prefix] [-q] [-v] models...\n" + " cups-genppd -L [-c localedir]\n" + " cups-genppd -M [-v]\n" + " cups-genppd -h\n" + " cups-genppd -V\n"); } +void +help(void) +{ + puts("Generate Gutenprint PPD files for use with CUPS\n\n"); + usage(); + puts("\nExamples: LANG=de_DE cups-genppd -p ppd -c /usr/share/locale\n" + " cups-genppd -L -c /usr/share/locale\n" + " cups-genppd -M -v\n\n" + "Commands:\n" + " -h Show this help message.\n" + " -L List available translations (message catalogs).\n" + " -M List available printer models.\n" + " -V Show version information and defaults.\n" + " The default is to output PPDs.\n" + "Options:\n" + " -c localedir Use localedir as the base directory for locale data.\n" + " -l locale Output PPDs translated with messages for locale.\n" + " -p prefix Output PPDs in directory prefix.\n" + " -d prefix Embed directory prefix in PPD file.\n" + " -q Quiet mode.\n" + " -v Verbose mode.\n" + "models:\n" + " A list of printer models, either the driver or quoted full name.\n"); +} /* - * 'usage()' - Show program usage... + * 'dirent_sort()' - sort directory entries */ +static int +dirent_sort(const void *a, + const void *b) +{ + return strcoll ((*(const struct dirent *const *) a)->d_name, + (*(const struct dirent *const *) b)->d_name); +} -void -usage(void) +/* + * 'getlangs()' - Get a list of available translations + */ + +char ** +getlangs(void) { - fputs("Usage: genppd [--help] [--catalog=domain] " - "[--language=locale] [--prefix=dir]\n", stderr); + struct dirent** langdirs; + int n; + char **langs; + + n = stpi_scandir (baselocaledir, &langdirs, checkcat, dirent_sort); + if (n >= 0) + { + int idx; + langs = stp_malloc((n+1) * sizeof(char*)); + for (idx = 0; idx < n; ++idx) + { + langs[idx] = (char*) stp_malloc((strlen(langdirs[idx]->d_name)+1) * sizeof(char)); + strcpy(langs[idx], langdirs[idx]->d_name); + free (langdirs[idx]); /* Must use plain free() */ + } + langs[n] = NULL; + free (langdirs); /* Must use plain free() */ + } + else + return NULL; - exit(EXIT_FAILURE); + return langs; } -const char * -find_manufacturer_from_name(const char *name) + +/* + * 'printlangs()' - Print list of available translations + */ + +void printlangs(char **langs) { - int i = 0; - while (stp_manufacturers[i].manufacturer_real_name) + if (langs) { - if (strncasecmp(name, stp_manufacturers[i].manufacturer_embedded_name, - strlen(stp_manufacturers[i].manufacturer_embedded_name)) == 0) - return stp_manufacturers[i].manufacturer_real_name; - i++; + int n = 0; + while (langs && langs[n]) + { + printf("%s\n", langs[n]); + n++; + } + } + exit (EXIT_SUCCESS); +} + + +/* + * 'printmodels' - Print a list of available models + */ + +void printmodels(int verbose) +{ + const stp_printer_t *p; + int i; + + for (i = 0; i < stp_printer_model_count(); i++) + { + p = stp_get_printer_by_index(i); + if (p && + strcmp(stp_printer_get_family(p), "ps") != 0 && + strcmp(stp_printer_get_family(p), "raw") != 0) + { + if(verbose) + printf("%-20s%s\n", stp_printer_get_driver(p), + stp_printer_get_long_name(p)); + else + printf("%s\n", stp_printer_get_driver(p)); + } + } + exit (EXIT_SUCCESS); +} + +/* Adapted from GNU libc <dirent.h> + These macros extract size information from a `struct dirent *'. + They may evaluate their argument multiple times, so it must not + have side effects. Each of these may involve a relatively costly + call to `strlen' on some systems, so these values should be cached. + + _D_EXACT_NAMLEN (DP) returns the length of DP->d_name, not including + its terminating null character. + + _D_ALLOC_NAMLEN (DP) returns a size at least (_D_EXACT_NAMLEN (DP) + 1); + that is, the allocation size needed to hold the DP->d_name string. + Use this macro when you don't need the exact length, just an upper bound. + This macro is less likely to require calling `strlen' than _D_EXACT_NAMLEN. + */ + +#ifdef _DIRENT_HAVE_D_NAMLEN +# ifndef _D_EXACT_NAMLEN +# define _D_EXACT_NAMLEN(d) ((d)->d_namlen) +# endif +# ifndef _D_ALLOC_NAMLEN +# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1) +# endif +#else +# ifndef _D_EXACT_NAMLEN +# define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name)) +# endif +# ifndef _D_ALLOC_NAMLEN +# ifdef _DIRENT_HAVE_D_RECLEN +# define _D_ALLOC_NAMLEN(d) (((char *) (d) + (d)->d_reclen) - &(d)->d_name[0]) +# else +# define _D_ALLOC_NAMLEN(d) (sizeof (d)->d_name > 1 ? sizeof (d)->d_name : \ + _D_EXACT_NAMLEN (d) + 1) +# endif +# endif +#endif + +/* + * 'stpi_scandir()' - BSD scandir() replacement. + */ + +static int +stpi_scandir (const char *dir, + struct dirent ***namelist, + int (*sel) (const struct dirent *), + int (*cmp) (const void *, const void *)) +{ + DIR *dp = opendir (dir); + struct dirent **v = NULL; + size_t vsize = 0, i; + struct dirent *d; + int save; + + if (dp == NULL) + return -1; + + save = errno; + errno = 0; + + i = 0; + while ((d = readdir (dp)) != NULL) + if (sel == NULL || (*sel) (d)) + { + struct dirent *vnew; + size_t dsize; + + /* Ignore errors from sel or readdir */ + errno = 0; + + if (i == vsize) + { + struct dirent **new; + if (vsize == 0) + vsize = 10; + else + vsize *= 2; + new = (struct dirent **) realloc (v, vsize * sizeof (*v)); + if (new == NULL) + break; + v = new; + } + + dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d; + vnew = (struct dirent *) malloc (dsize); + if (vnew == NULL) + break; + + v[i++] = (struct dirent *) memcpy (vnew, d, dsize); + } + + if (errno != 0) + { + save = errno; + + while (i > 0) + free (v[--i]); + free (v); + + i = -1; } - fprintf(stderr, "Cannot determine manufacturer of %s\n!", name); - abort(); - return NULL; + else + { + /* Sort the list if we have a comparison function to sort with. */ + if (cmp != NULL) + qsort (v, i, sizeof (*v), cmp); + + *namelist = v; + } + + (void) closedir (dp); + errno = save; + + return i; } +/* + * 'checkcat()' - A callback for stpi_scandir() to check + * if a message catalogue exists + */ + +int +checkcat (const struct dirent *localedir) +{ + char* catpath; + int catlen, status = 0, savederr; + struct stat catstat; + + savederr = errno; /* since we are a callback, preserve stpi_scandir() state */ + + /* LOCALEDIR / LANG / LC_MESSAGES/CATALOG */ + /* Add 3, for two '/' separators and '\0' */ + catlen = strlen(baselocaledir) + strlen(localedir->d_name) + strlen(CATALOG) + 3; + catpath = (char*) stp_malloc(catlen * sizeof(char)); + + strncpy (catpath, baselocaledir, strlen(baselocaledir)); + catlen = strlen(baselocaledir); + *(catpath+catlen) = '/'; + catlen++; + strncpy (catpath+catlen, localedir->d_name, strlen(localedir->d_name)); + catlen += strlen(localedir->d_name); + *(catpath+catlen) = '/'; + catlen++; + strncpy (catpath+catlen, CATALOG, strlen(CATALOG)); + catlen += strlen(CATALOG); + *(catpath+catlen) = '\0'; + + if (!stat (catpath, &catstat)) + { + if (S_ISREG(catstat.st_mode)) + { + status = 1; + } + } + + stp_free (catpath); + + errno = savederr; + return status; +} /* * 'write_ppd()' - Write a PPD file. */ int /* O - Exit status */ -write_ppd(const stp_printer_t p, /* I - Printer driver */ +write_ppd(const stp_printer_t *p, /* I - Printer driver */ const char *prefix, /* I - Prefix (directory) for PPD files */ - const char *language,/* I - Language/locale */ + const char *language, int verbose) { - int i, j; /* Looping vars */ + int i, j, k, l; /* Looping vars */ gzFile fp; /* File to write to */ char filename[1024]; /* Filename */ - const char *driverptr; /* Pointer into driver name */ - const char *manufacturer; /* Manufacturer name */ int num_opts; /* Number of printer options */ - stp_param_t *opts; /* Printer options */ - const char *defopt; /* Default printer option */ int xdpi, ydpi; /* Resolution info */ - stp_vars_t v; /* Variable info */ + stp_vars_t *v; /* Variable info */ int width, height, /* Page information */ bottom, left, top, right; const char *driver; /* Driver name */ const char *long_name; /* Driver long name */ - stp_vars_t printvars; /* Printer option names */ - int model; /* Driver model number */ - const stp_printfuncs_t *printfuncs; /* Driver functions */ + const char *manufacturer; /* Manufacturer of printer */ + const stp_vars_t *printvars; /* Printer option names */ paper_t *the_papers; /* Media sizes */ int cur_opt; /* Current option */ + struct stat dir; /* prefix dir status */ int variable_sizes; /* Does the driver support variable sizes? */ int min_width, /* Min/max custom size */ min_height, max_width, max_height; - + stp_parameter_t desc; + stp_parameter_list_t param_list; + const stp_param_string_t *opt; + int has_quality_parameter = 0; + int has_image_type_parameter = 0; + int printer_is_color = 0; /* * Initialize driver-specific variables... @@ -461,9 +783,8 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ driver = stp_printer_get_driver(p); long_name = stp_printer_get_long_name(p); - printvars = stp_printer_get_printvars(p); - model = stp_printer_get_model(p); - printfuncs = stp_printer_get_printfuncs(p); + manufacturer = stp_printer_get_manufacturer(p); + printvars = stp_printer_get_defaults(p); the_papers = NULL; cur_opt = 0; @@ -471,16 +792,37 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ * Skip the PostScript drivers... */ - if (strcmp(driver, "ps") == 0 || - strcmp(driver, "ps2") == 0) + if (strcmp(stp_printer_get_family(p), "ps") == 0 || + strcmp(stp_printer_get_family(p), "raw") == 0) return (0); /* * Make sure the destination directory exists... */ - mkdir(prefix, 0777); - sprintf(filename, "%s/%s" PPDEXT, prefix, driver); + + if (stat(prefix, &dir) && !S_ISDIR(dir.st_mode)) + { + if (mkdir(prefix, 0777)) + { + printf("cups-genppd: Cannot create directory %s: %s\n", + prefix, strerror(errno)); + exit (EXIT_FAILURE); + } + } + + /* + * The files will be named stp-<driver>.<major>.<minor>.ppd, for + * example: + * + * stp-escp2-ex.5.0.ppd + * + * or + * + * stp-escp2-ex.5.0.ppd.gz + */ + snprintf(filename, sizeof(filename) - 1, "%s/stp-%s.%s%s%s", + prefix, driver, GUTENPRINT_RELEASE_VERSION, ppdext, gzext); /* * Open the PPD file... @@ -488,7 +830,7 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ if ((fp = gzopen(filename, "wb")) == NULL) { - fprintf(stderr, "genppd: Unable to create file \"%s\" - %s.\n", + fprintf(stderr, "cups-genppd: Unable to create file \"%s\" - %s.\n", filename, strerror(errno)); return (2); } @@ -497,18 +839,27 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ * Write a standard header... */ - manufacturer = find_manufacturer_from_name(long_name); - if (verbose) fprintf(stderr, "Writing %s...\n", filename); else fprintf(stderr, "."); gzputs(fp, "*PPD-Adobe: \"4.3\"\n"); - gzputs(fp, "*%PPD file for CUPS/Gimp-Print.\n"); - gzputs(fp, "*%Copyright 1993-2001 by Easy Software Products, All Rights Reserved.\n"); - gzputs(fp, "*%This PPD file may be freely used and distributed under the terms of\n"); - gzputs(fp, "*%the GNU GPL.\n"); + gzputs(fp, "*%PPD file for CUPS/Gutenprint.\n"); + gzputs(fp, "*%Copyright 1993-2005 by Easy Software Products and Robert Krawitz.\n"); + gzputs(fp, "*%This program is free software; you can redistribute it and/or\n"); + gzputs(fp, "*%modify it under the terms of the GNU General Public License,\n"); + gzputs(fp, "*%version 2, as published by the Free Software Foundation.\n"); + gzputs(fp, "*%\n"); + gzputs(fp, "*%This program is distributed in the hope that it will be useful, but\n"); + gzputs(fp, "*%WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n"); + gzputs(fp, "*%or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n"); + gzputs(fp, "*%for more details.\n"); + gzputs(fp, "*%\n"); + gzputs(fp, "*%You should have received a copy of the GNU General Public License\n"); + gzputs(fp, "*%along with this program; if not, write to the Free Software\n"); + gzputs(fp, "*%Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"); + gzputs(fp, "*%\n"); gzputs(fp, "*FormatVersion: \"4.3\"\n"); gzputs(fp, "*FileVersion: \"" VERSION "\"\n"); /* Specify language of PPD translation */ @@ -526,10 +877,9 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ * The following code generates a (hopefully unique) 8.3 filename from * the driver name, and makes the filename all UPPERCASE as well... */ - + gzprintf(fp, "*PCFileName: \"STP%05d.PPD\"\n", stp_get_printer_index_by_driver(driver)); - gzprintf(fp, "*Manufacturer: \"%s\"\n", manufacturer); /* @@ -541,6 +891,7 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ gzputs(fp, "*Product: \"(AFPL Ghostscript)\"\n"); gzputs(fp, "*Product: \"(GNU Ghostscript)\"\n"); gzputs(fp, "*Product: \"(ESP Ghostscript)\"\n"); + gzputs(fp, "*Product: \"(GPL Ghostscript)\"\n"); /* * The ModelName attribute now provides the long name rather than the @@ -555,84 +906,128 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ * with commas. Now use a dash instead... */ - gzprintf(fp, "*NickName: \"%s - CUPS+Gimp-Print v" VERSION "\"\n", - long_name); -#if CUPS_PPD_PS_LEVEL == 2 - gzputs(fp, "*PSVersion: \"(2017.000) 550\"\n"); -#else - gzputs(fp, "*PSVersion: \"(3010.000) 705\"\n"); -#endif /* CUPS_PPD_PS_LEVEL == 2 */ - gzprintf(fp, "*LanguageLevel: \"%d\"\n", CUPS_PPD_PS_LEVEL); - - /* Assume that color printers are inkjets and should have pages reversed */ - if (stp_get_output_type(printvars) == OUTPUT_COLOR) + /* + * NOTE - code in rastertoprinter looks for this version string. + * If this is changed, the corresponding change must be made in + * rastertoprinter.c. Look for "ppd->nickname" + */ + gzprintf(fp, "*NickName: \"%s%s%s\"\n", + long_name, CUPS_PPD_NICKNAME_STRING, VERSION); + if (cups_ppd_ps_level == 2) + gzputs(fp, "*PSVersion: \"(2017.000) 550\"\n"); + else { - gzputs(fp, "*ColorDevice: True\n"); - gzputs(fp, "*DefaultColorSpace: RGB\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 550\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 651\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 652\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 653\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 704\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 705\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 707\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 800\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 815\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 850\"\n"); + gzputs(fp, "*PSVersion: \"(3010.000) 81501\"\n"); } - else + gzprintf(fp, "*LanguageLevel: \"%d\"\n", cups_ppd_ps_level); + + /* Set Job Mode to "Job" as this enables the Duplex option */ + v = stp_vars_create_copy(printvars); + stp_set_string_parameter(v, "JobMode", "Job"); + + /* Assume that color printers are inkjets and should have pages reversed */ + stp_describe_parameter(v, "PrintingMode", &desc); + if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) { - gzputs(fp, "*ColorDevice: False\n"); - gzputs(fp, "*DefaultColorSpace: Gray\n"); + if (stp_string_list_is_present(desc.bounds.str, "Color")) + { + printer_is_color = 1; + gzputs(fp, "*ColorDevice: True\n"); + } + else + { + printer_is_color = 0; + gzputs(fp, "*ColorDevice: False\n"); + } + if (strcmp(desc.deflt.str, "Color") == 0) + gzputs(fp, "*DefaultColorSpace: RGB\n"); + else + gzputs(fp, "*DefaultColorSpace: Gray\n"); } + stp_parameter_description_destroy(&desc); gzputs(fp, "*FileSystem: False\n"); gzputs(fp, "*LandscapeOrientation: Plus90\n"); gzputs(fp, "*TTRasterizer: Type42\n"); - gzputs(fp, "*RequiresPageRegion All: True\n"); gzputs(fp, "*cupsVersion: 1.1\n"); - gzprintf(fp, "*cupsModelNumber: \"%d\"\n", model); + gzprintf(fp, "*cupsModelNumber: \"0\"\n"); gzputs(fp, "*cupsManualCopies: True\n"); - gzputs(fp, "*cupsFilter: \"application/vnd.cups-raster 100 rastertoprinter\"\n"); + gzprintf(fp, "*cupsFilter: \"application/vnd.cups-raster 100 rastertogutenprint.%s\"\n", GUTENPRINT_RELEASE_VERSION); if (strcasecmp(manufacturer, "EPSON") == 0) gzputs(fp, "*cupsFilter: \"application/vnd.cups-command 33 commandtoepson\"\n"); gzputs(fp, "\n"); + gzprintf(fp, "*StpDriverName: \"%s\"\n", driver); + gzprintf(fp, "*StpPPDLocation: \"%s%s%s/stp-%s.%s%s%s\"\n", + cups_modeldir, + cups_modeldir[strlen(cups_modeldir) - 1] == '/' ? "" : "/", + language ? language : "C", + driver, + GUTENPRINT_RELEASE_VERSION, + ppdext, + gzext); + gzprintf(fp, "*StpLocale: \"%s\"\n", language ? language : "C"); /* * Get the page sizes from the driver... */ - v = stp_allocate_copy(printvars); + if (printer_is_color) + stp_set_string_parameter(v, "PrintingMode", "Color"); + else + stp_set_string_parameter(v, "PrintingMode", "BW"); + stp_set_string_parameter(v, "ChannelBitDepth", "8"); variable_sizes = 0; - opts = (*(printfuncs->parameters))(p, NULL, "PageSize", &num_opts); - defopt = (*(printfuncs->default_parameters))(p, NULL, "PageSize"); - the_papers = malloc(sizeof(paper_t) * num_opts); + stp_describe_parameter(v, "PageSize", &desc); + num_opts = stp_string_list_count(desc.bounds.str); + the_papers = stp_malloc(sizeof(paper_t) * num_opts); for (i = 0; i < num_opts; i++) { - const stp_papersize_t papersize = stp_get_papersize_by_name(opts[i].name); + const stp_papersize_t *papersize; + opt = stp_string_list_param(desc.bounds.str, i); + papersize = stp_get_papersize_by_name(opt->name); if (!papersize) { - printf("Unable to lookup size %s!\n", opts[i].name); + printf("Unable to lookup size %s!\n", opt->name); continue; } - if (strcmp(opts[i].name, "Custom") == 0) + if (strcmp(opt->name, "Custom") == 0) { variable_sizes = 1; continue; } - width = stp_papersize_get_width(papersize); - height = stp_papersize_get_height(papersize); + width = papersize->width; + height = papersize->height; if (width <= 0 || height <= 0) continue; - stp_set_media_size(v, opts[i].name); + stp_set_string_parameter(v, "PageSize", opt->name); - (*(printfuncs->media_size))(p, v, &width, &height); - (*(printfuncs->imageable_area))(p, v, &left, &right, &bottom, &top); + stp_get_media_size(v, &width, &height); + stp_get_imageable_area(v, &left, &right, &bottom, &top); - the_papers[cur_opt].name = opts[i].name; - the_papers[cur_opt].text = opts[i].text; + the_papers[cur_opt].name = opt->name; + the_papers[cur_opt].text = opt->text; the_papers[cur_opt].width = width; the_papers[cur_opt].height = height; the_papers[cur_opt].left = left; the_papers[cur_opt].right = right; - the_papers[cur_opt].bottom = bottom; - the_papers[cur_opt].top = top; + the_papers[cur_opt].bottom = height - bottom; + the_papers[cur_opt].top = height - top; cur_opt++; } @@ -646,7 +1041,7 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ gzputs(fp, "*OpenUI *PageSize: PickOne\n"); gzputs(fp, "*OrderDependency: 10 AnySetup *PageSize\n"); - gzprintf(fp, "*DefaultPageSize: %s\n", defopt); + gzprintf(fp, "*DefaultPageSize: %s\n", desc.deflt.str); for (i = 0; i < cur_opt; i ++) { gzprintf(fp, "*PageSize %s", the_papers[i].name); @@ -657,7 +1052,7 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ gzputs(fp, "*OpenUI *PageRegion: PickOne\n"); gzputs(fp, "*OrderDependency: 10 AnySetup *PageRegion\n"); - gzprintf(fp, "*DefaultPageRegion: %s\n", defopt); + gzprintf(fp, "*DefaultPageRegion: %s\n", desc.deflt.str); for (i = 0; i < cur_opt; i ++) { gzprintf(fp, "*PageRegion %s", the_papers[i].name); @@ -666,7 +1061,7 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ } gzputs(fp, "*CloseUI: *PageRegion\n\n"); - gzprintf(fp, "*DefaultImageableArea: %s\n", defopt); + gzprintf(fp, "*DefaultImageableArea: %s\n", desc.deflt.str); for (i = 0; i < cur_opt; i ++) { gzprintf(fp, "*ImageableArea %s", the_papers[i].name); @@ -676,7 +1071,7 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ } gzputs(fp, "\n"); - gzprintf(fp, "*DefaultPaperDimension: %s\n", defopt); + gzprintf(fp, "*DefaultPaperDimension: %s\n", desc.deflt.str); for (i = 0; i < cur_opt; i ++) { @@ -688,16 +1083,16 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ if (variable_sizes) { - (*(printfuncs->limit))(p, v, &max_width, &max_height, - &min_width, &min_height); - stp_set_media_size(v, "Custom"); - (*(printfuncs->media_size))(p, v, &width, &height); - (*(printfuncs->imageable_area))(p, v, &left, &right, &bottom, &top); + stp_get_size_limit(v, &max_width, &max_height, + &min_width, &min_height); + stp_set_string_parameter(v, "PageSize", "Custom"); + stp_get_media_size(v, &width, &height); + stp_get_imageable_area(v, &left, &right, &bottom, &top); gzprintf(fp, "*MaxMediaWidth: \"%d\"\n", max_width); gzprintf(fp, "*MaxMediaHeight: \"%d\"\n", max_height); gzprintf(fp, "*HWMargins: %d %d %d %d\n", - left, bottom, width - right, height - top); + left, height - bottom, width - right, top); gzputs(fp, "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\"\n"); gzprintf(fp, "*ParamCustomPageSize Width: 1 points %d %d\n", min_width, max_width); @@ -708,32 +1103,18 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ gzputs(fp, "*ParamCustomPageSize Orientation: 5 int 0 0\n\n"); } - if (opts) - { - for (i = 0; i < num_opts; i++) - { - free((void *)opts[i].name); - free((void *)opts[i].text); - } - - free(opts); - } - + stp_parameter_description_destroy(&desc); if (the_papers) - free(the_papers); - -#ifdef __APPLE__ - gzputs(fp, "*OpenGroup: MAIN/Basic settings\n"); -#endif + stp_free(the_papers); /* * Do we support color? */ - gzputs(fp, "*OpenUI *ColorModel: PickOne\n"); + gzputs(fp, "*OpenUI *ColorModel/Color Model: PickOne\n"); gzputs(fp, "*OrderDependency: 10 AnySetup *ColorModel\n"); - if (stp_get_output_type(printvars) == OUTPUT_COLOR) + if (printer_is_color) gzputs(fp, "*DefaultColorModel: RGB\n"); else gzputs(fp, "*DefaultColorModel: Gray\n"); @@ -741,100 +1122,176 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ gzprintf(fp, "*ColorModel Gray/Grayscale:\t\"<<" "/cupsColorSpace %d" "/cupsColorOrder %d" - "/cupsBitsPerColor 8>>setpagedevice\"\n", + ">>setpagedevice\"\n", CUPS_CSPACE_W, CUPS_ORDER_CHUNKED); - gzprintf(fp, "*ColorModel Black/Black & White:\t\"<<" + gzprintf(fp, "*ColorModel Black/Inverted Grayscale:\t\"<<" "/cupsColorSpace %d" "/cupsColorOrder %d" - "/cupsBitsPerColor 8>>setpagedevice\"\n", + ">>setpagedevice\"\n", CUPS_CSPACE_K, CUPS_ORDER_CHUNKED); - if (stp_get_output_type(printvars) == OUTPUT_COLOR) + if (printer_is_color) { - gzprintf(fp, "*ColorModel RGB/Color:\t\"<<" + gzprintf(fp, "*ColorModel RGB/RGB Color:\t\"<<" "/cupsColorSpace %d" "/cupsColorOrder %d" - "/cupsBitsPerColor 8>>setpagedevice\"\n", + ">>setpagedevice\"\n", CUPS_CSPACE_RGB, CUPS_ORDER_CHUNKED); - gzprintf(fp, "*ColorModel CMYK/Raw CMYK:\t\"<<" + gzprintf(fp, "*ColorModel CMY/CMY Color:\t\"<<" + "/cupsColorSpace %d" + "/cupsColorOrder %d" + ">>setpagedevice\"\n", + CUPS_CSPACE_CMY, CUPS_ORDER_CHUNKED); + gzprintf(fp, "*ColorModel CMYK/CMYK:\t\"<<" "/cupsColorSpace %d" "/cupsColorOrder %d" - "/cupsBitsPerColor 8>>setpagedevice\"\n", + ">>setpagedevice\"\n", CUPS_CSPACE_CMYK, CUPS_ORDER_CHUNKED); + gzprintf(fp, "*ColorModel KCMY/KCMY:\t\"<<" + "/cupsColorSpace %d" + "/cupsColorOrder %d" + ">>setpagedevice\"\n", + CUPS_CSPACE_KCMY, CUPS_ORDER_CHUNKED); } gzputs(fp, "*CloseUI: *ColorModel\n\n"); + /* + * 8 or 16 bit color (16 bit is slower) + */ + gzputs(fp, "*OpenUI *StpColorPrecision/Color Precision: PickOne\n"); + gzputs(fp, "*OrderDependency: 10 AnySetup *StpColorPrecision\n"); + gzputs(fp, "*DefaultStpColorPrecision: Normal\n"); + gzputs(fp, "*StpColorPrecision Normal/Normal:\t\"<<" + "/cupsBitsPerColor 8>>setpagedevice\"\n"); + gzputs(fp, "*StpColorPrecision Best/Best:\t\"<<" + "/cupsBitsPerColor 8" + "/cupsPreferredBitsPerColor 16>>setpagedevice\"\n"); + gzputs(fp, "*CloseUI: *StpColorPrecision\n\n"); + /* * Media types... */ - opts = (*(printfuncs->parameters))(p, NULL, "MediaType", &num_opts); - defopt = (*(printfuncs->default_parameters))(p, NULL, "MediaType"); + stp_describe_parameter(v, "MediaType", &desc); + num_opts = stp_string_list_count(desc.bounds.str); if (num_opts > 0) { gzprintf(fp, "*OpenUI *MediaType/%s: PickOne\n", _("Media Type")); gzputs(fp, "*OrderDependency: 10 AnySetup *MediaType\n"); - gzprintf(fp, "*DefaultMediaType: %s\n", defopt); + gzprintf(fp, "*DefaultMediaType: %s\n", desc.deflt.str); for (i = 0; i < num_opts; i ++) { + opt = stp_string_list_param(desc.bounds.str, i); gzprintf(fp, "*MediaType %s/%s:\t\"<</MediaType(%s)>>setpagedevice\"\n", - opts[i].name, opts[i].text, opts[i].name); - free((void *)opts[i].name); - free((void *)opts[i].text); + opt->name, opt->text, opt->name); } - free(opts); - gzputs(fp, "*CloseUI: *MediaType\n\n"); } + stp_parameter_description_destroy(&desc); /* * Input slots... */ - opts = (*(printfuncs->parameters))(p, NULL, "InputSlot", &num_opts); - defopt = (*(printfuncs->default_parameters))(p, NULL, "InputSlot"); + stp_describe_parameter(v, "InputSlot", &desc); + num_opts = stp_string_list_count(desc.bounds.str); if (num_opts > 0) { gzprintf(fp, "*OpenUI *InputSlot/%s: PickOne\n", _("Media Source")); gzputs(fp, "*OrderDependency: 10 AnySetup *InputSlot\n"); - gzprintf(fp, "*DefaultInputSlot: %s\n", defopt); + gzprintf(fp, "*DefaultInputSlot: %s\n", desc.deflt.str); for (i = 0; i < num_opts; i ++) { + opt = stp_string_list_param(desc.bounds.str, i); gzprintf(fp, "*InputSlot %s/%s:\t\"<</MediaClass(%s)>>setpagedevice\"\n", - opts[i].name, opts[i].text, opts[i].name); - free((void *)opts[i].name); - free((void *)opts[i].text); + opt->name, opt->text, opt->name); } - free(opts); - gzputs(fp, "*CloseUI: *InputSlot\n\n"); } + stp_parameter_description_destroy(&desc); + + /* + * Quality settings + */ + + stp_describe_parameter(v, "Quality", &desc); + if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST && desc.is_active) + { + stp_clear_string_parameter(v, "Resolution"); + has_quality_parameter = 1; + gzprintf(fp, "*OpenUI *StpQuality/%s: PickOne\n", _(desc.text)); + gzputs(fp, "*OrderDependency: 5 AnySetup *StpQuality\n"); + gzprintf(fp, "*DefaultStpQuality: %s\n", desc.deflt.str); + num_opts = stp_string_list_count(desc.bounds.str); + for (i = 0; i < num_opts; i++) + { + opt = stp_string_list_param(desc.bounds.str, i); + stp_set_string_parameter(v, "Quality", opt->name); + stp_describe_resolution(v, &xdpi, &ydpi); + if (xdpi == -1 || ydpi == -1) + gzprintf(fp, "*StpQuality %s/%s: \"\"\n", opt->name, opt->text); + else + gzprintf(fp, "*StpQuality %s/%s:\t\"<</HWResolution[%d %d]>>setpagedevice\"\n", + opt->name, opt->text, xdpi, ydpi); + } + gzputs(fp, "*CloseUI: *StpQuality\n\n"); + } + stp_parameter_description_destroy(&desc); + stp_clear_string_parameter(v, "Quality"); + + /* + * Image type + */ + + stp_describe_parameter(v, "ImageType", &desc); + if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST && desc.is_active) + { + has_image_type_parameter = 1; + gzprintf(fp, "*OpenUI *StpImageType/%s: PickOne\n", _(desc.text)); + gzputs(fp, "*OrderDependency: 5 AnySetup *StpImageType\n"); + gzprintf(fp, "*DefaultStpImageType: %s\n", desc.deflt.str); + num_opts = stp_string_list_count(desc.bounds.str); + for (i = 0; i < num_opts; i++) + { + opt = stp_string_list_param(desc.bounds.str, i); + gzprintf(fp, "*StpImageType %s/%s: \"\"\n", opt->name, opt->text); + } + gzputs(fp, "*CloseUI: *StpImageType\n\n"); + } + stp_parameter_description_destroy(&desc); /* * Resolutions... */ - opts = (*(printfuncs->parameters))(p, NULL, "Resolution", &num_opts); - defopt = (*(printfuncs->default_parameters))(p, NULL, "Resolution"); + stp_describe_parameter(v, "Resolution", &desc); + num_opts = stp_string_list_count(desc.bounds.str); gzprintf(fp, "*OpenUI *Resolution/%s: PickOne\n", _("Resolution")); gzputs(fp, "*OrderDependency: 20 AnySetup *Resolution\n"); - gzprintf(fp, "*DefaultResolution: %s\n", defopt); + if (has_quality_parameter) + gzprintf(fp, "*DefaultResolution: None\n"); + else + gzprintf(fp, "*DefaultResolution: %s\n", desc.deflt.str); + stp_clear_string_parameter(v, "Quality"); + if (has_quality_parameter) + gzprintf(fp, "*Resolution None/%s: \"\"\n", _("Automatic")); for (i = 0; i < num_opts; i ++) { /* * Strip resolution name to its essentials... */ - - (printfuncs->describe_resolution)(p, opts[i].name, &xdpi, &ydpi); + opt = stp_string_list_param(desc.bounds.str, i); + stp_set_string_parameter(v, "Resolution", opt->name); + stp_describe_resolution(v, &xdpi, &ydpi); /* This should not happen! */ if (xdpi == -1 || ydpi == -1) @@ -845,158 +1302,358 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ */ gzprintf(fp, "*Resolution %s/%s:\t\"<</HWResolution[%d %d]/cupsCompression %d>>setpagedevice\"\n", - opts[i].name, opts[i].text, xdpi, ydpi, i); - free((void *)opts[i].name); - free((void *)opts[i].text); + opt->name, opt->text, xdpi, ydpi, i); } - free(opts); + stp_parameter_description_destroy(&desc); gzputs(fp, "*CloseUI: *Resolution\n\n"); - /* - * STP option group... - */ - -#ifndef __APPLE__ - gzprintf(fp, "*OpenGroup: STP/%s\n", _("GIMP-print")); -#endif - - /* - * Image types... - */ - - gzprintf(fp, "*OpenUI *stpImageType/%s: PickOne\n", _("Image Type")); - gzputs(fp, "*OrderDependency: 10 AnySetup *stpImageType\n"); - gzputs(fp, "*DefaultstpImageType: LineArt\n"); - - gzprintf(fp, "*stpImageType LineArt/%s:\t\"<</cupsRowCount 0>>setpagedevice\"\n", - _("Line Art")); - gzprintf(fp, "*stpImageType SolidTone/%s:\t\"<</cupsRowCount 1>>setpagedevice\"\n", - _("Solid Colors")); - gzprintf(fp, "*stpImageType Continuous/%s:\t\"<</cupsRowCount 2>>setpagedevice\"\n", - _("Photograph")); - - gzputs(fp, "*CloseUI: *stpImageType\n\n"); - - /* - * Dithering algorithms... - */ - - gzprintf(fp, "*OpenUI *stpDither/%s: PickOne\n", _("Dither Algorithm")); - gzputs(fp, "*OrderDependency: 10 AnySetup *stpDither\n"); - gzprintf(fp, "*DefaultstpDither: %s\n", stp_default_dither_algorithm()); - - for (i = 0; i < stp_dither_algorithm_count(); i ++) - gzprintf(fp, "*stpDither %s/%s: \"<</cupsRowStep %d>>setpagedevice\"\n", - stp_dither_algorithm_name(i), stp_dither_algorithm_text(i), i); - - gzputs(fp, "*CloseUI: *stpDither\n\n"); - - /* - * InkTypes... - */ + stp_describe_parameter(v, "OutputOrder", &desc); + if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) + { + gzputs(fp, "*OpenUI *OutputOrder: PickOne\n"); + gzputs(fp, "*OrderDependency: 10 AnySetup *OutputOrder\n"); + gzprintf(fp, "*DefaultOutputOrder: %s\n", desc.deflt.str); + gzputs(fp, "*OutputOrder Normal/Normal: \"\"\n"); + gzputs(fp, "*OutputOrder Reverse/Reverse: \"\"\n"); + gzputs(fp, "*CloseUI: *OutputOrder\n\n"); + } + stp_parameter_description_destroy(&desc); - opts = (*(printfuncs->parameters))(p, NULL, "InkType", &num_opts); - defopt = (*(printfuncs->default_parameters))(p, NULL, "InkType"); + /* + * Duplex + * Note that the opt->name strings MUST match those in the printer driver(s) + * else the PPD files will not be generated correctly + */ - if (num_opts > 0) + stp_describe_parameter(v, "Duplex", &desc); + if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) { - gzprintf(fp, "*OpenUI *stpInkType/%s: PickOne\n", _("Ink Type")); - gzputs(fp, "*OrderDependency: 20 AnySetup *stpInkType\n"); - gzprintf(fp, "*DefaultstpInkType: %s\n", defopt); - - for (i = 0; i < num_opts; i ++) + num_opts = stp_string_list_count(desc.bounds.str); + if (num_opts > 0) { - /* - * Write the inktype option... - */ - - gzprintf(fp, "*stpInkType %s/%s:\t\"<</OutputType(%s)>>setpagedevice\"\n", - opts[i].name, opts[i].text, opts[i].name); - free((void *)opts[i].name); - free((void *)opts[i].text); + gzputs(fp, "*OpenUI *Duplex/Double-Sided Printing: PickOne\n"); + gzputs(fp, "*OrderDependency: 20 AnySetup *Duplex\n"); + gzprintf(fp, "*DefaultDuplex: %s\n", desc.deflt.str); + + for (i = 0; i < num_opts; i++) + { + opt = stp_string_list_param(desc.bounds.str, i); + if (strcmp(opt->name, "None") == 0) + gzprintf(fp, "*Duplex %s/%s: \"<</Duplex false>>setpagedevice\"\n", opt->name, opt->text); + else if (strcmp(opt->name, "DuplexNoTumble") == 0) + gzprintf(fp, "*Duplex %s/%s: \"<</Duplex true/Tumble false>>setpagedevice\"\n", opt->name, opt->text); + else if (strcmp(opt->name, "DuplexTumble") == 0) + gzprintf(fp, "*Duplex %s/%s: \"<</Duplex true/Tumble true>>setpagedevice\"\n", opt->name, opt->text); + } + gzputs(fp, "*CloseUI: *Duplex\n\n"); } - - free(opts); - - gzputs(fp, "*CloseUI: *stpInkType\n\n"); } - -#ifdef __APPLE__ - gzputs(fp, "*CloseGroup: MAIN\n\n"); - gzputs(fp, "*OpenGroup: STP/Expert adjustments\n"); -#endif /* __APPLE__ */ + stp_parameter_description_destroy(&desc); - /* - * Advanced STP options... - */ + param_list = stp_get_parameter_list(v); - if (stp_get_output_type(printvars) == OUTPUT_COLOR) -#ifndef __APPLE__ - num_opts = 8; - else - num_opts = 4; - - for (i = 0; i < num_opts; i ++) -#else + for (j = 0; j <= STP_PARAMETER_CLASS_OUTPUT; j++) { - num_opts = 8; - - for (i = 0; i < 5; i ++) -#endif /* __APPLE__ */ + for (k = 0; k <= STP_PARAMETER_LEVEL_ADVANCED4; k++) + { + int printed_open_group = 0; + size_t param_count = stp_parameter_list_count(param_list); + for (l = 0; l < param_count; l++) + { + int print_close_ui = 1; + const stp_parameter_t *lparam = + stp_parameter_list_param(param_list, l); + if (lparam->p_class != j || lparam->p_level != k || + is_special_option(lparam->name) || lparam->read_only || + (lparam->p_type != STP_PARAMETER_TYPE_STRING_LIST && + lparam->p_type != STP_PARAMETER_TYPE_BOOLEAN && + lparam->p_type != STP_PARAMETER_TYPE_DIMENSION && + lparam->p_type != STP_PARAMETER_TYPE_DOUBLE)) + continue; + stp_describe_parameter(v, lparam->name, &desc); + if (desc.is_active) + { + int printed_default_value = 0; + if (!printed_open_group) + { + print_group_open(fp, j, k); + printed_open_group = 1; + } + gzprintf(fp, "*OpenUI *Stp%s/%s: PickOne\n", + desc.name, _(desc.text)); +#if 0 + gzprintf(fp, "*OrderDependency: %d AnySetup *Stp%s\n", + (100 + l + (j * param_count) + + (k * STP_PARAMETER_LEVEL_INTERNAL * param_count)), + desc.name); +#endif + if (!desc.is_mandatory) + gzprintf(fp, "*DefaultStp%s: None\n", desc.name); + switch (desc.p_type) + { + case STP_PARAMETER_TYPE_STRING_LIST: + if (desc.is_mandatory) + gzprintf(fp, "*DefaultStp%s: %s\n", + desc.name, desc.deflt.str); + else + gzprintf(fp, "*Stp%s %s/%s: \"\"\n", desc.name, + "None", _("None")); + num_opts = stp_string_list_count(desc.bounds.str); + for (i = 0; i < num_opts; i++) + { + opt = stp_string_list_param(desc.bounds.str, i); + gzprintf(fp, "*Stp%s %s/%s: \"\"\n", + desc.name, opt->name, _(opt->text)); + } + break; + case STP_PARAMETER_TYPE_BOOLEAN: + if (desc.is_mandatory) + gzprintf(fp, "*DefaultStp%s: %s\n", desc.name, + desc.deflt.boolean ? "True" : "False"); + else + gzprintf(fp, "*Stp%s %s/%s: \"\"\n", desc.name, + "None", _("None")); + gzprintf(fp, "*Stp%s %s/%s: \"\"\n", + desc.name, "False", _("No")); + gzprintf(fp, "*Stp%s %s/%s: \"\"\n", + desc.name, "True", _("Yes")); + break; + case STP_PARAMETER_TYPE_DOUBLE: + if (desc.is_mandatory) + { + gzprintf(fp, "*DefaultStp%s: None\n", desc.name); + } + for (i = desc.bounds.dbl.lower * 1000; + i <= desc.bounds.dbl.upper * 1000 ; i += 100) + { + if (desc.deflt.dbl * 1000 == i && desc.is_mandatory) + { + gzprintf(fp, "*Stp%s None/%.3f: \"\"\n", + desc.name, ((double) i) * .001); + printed_default_value = 1; + } + else + gzprintf(fp, "*Stp%s %d/%.3f: \"\"\n", + desc.name, i, ((double) i) * .001); + } + if (!desc.is_mandatory) + gzprintf(fp, "*Stp%s None/None: \"\"\n", + desc.name, desc.deflt.dbl); + else if (! printed_default_value) + gzprintf(fp, "*Stp%s None/%.3f: \"\"\n", + desc.name, desc.deflt.dbl); + gzprintf(fp, "*CloseUI: *Stp%s\n\n", desc.name); + gzprintf(fp, "*OpenUI *StpFine%s/%s %s: PickOne\n", + desc.name, _(desc.text), _("Fine Adjustment")); + gzprintf(fp, "*DefaultStpFine%s:None\n", desc.name); + gzprintf(fp, "*StpFine%s None/0.000: \"\"\n", desc.name); + for (i = 0; i < 100; i += 5) + gzprintf(fp, "*StpFine%s %d/%.3f: \"\"\n", + desc.name, i, ((double) i) * .001); + gzprintf(fp, "*CloseUI: *StpFine%s\n\n", desc.name); + print_close_ui = 0; + + break; + case STP_PARAMETER_TYPE_DIMENSION: + if (desc.is_mandatory) + gzprintf(fp, "*DefaultStp%s: %d\n", + desc.name, desc.deflt.dimension); + else + gzprintf(fp, "*Stp%s %s/%s: \"\"\n", desc.name, + "None", _("None")); + for (i = desc.bounds.dimension.lower; + i <= desc.bounds.dimension.upper; i++) + { + /* FIXME + * For now, just use mm; we'll fix it later + * for the locale-appropriate setting. + * --rlk 20040818 + */ + gzprintf(fp, "*Stp%s %d/%.1f mm: \"\"\n", + desc.name, i, ((double) i) * 25.4 / 72); + } + gzprintf(fp, "*CloseUI: *Stp%s\n\n", desc.name); + print_close_ui = 0; + + break; + default: + break; + } + if (print_close_ui) + gzprintf(fp, "*CloseUI: *Stp%s\n\n", desc.name); + } + stp_parameter_description_destroy(&desc); + } + if (printed_open_group) + print_group_close(fp, j, k); + } + } + if (has_quality_parameter) { - gzprintf(fp, "*OpenUI *%s/%s: PickOne\n", stp_options[i].name, - stp_options[i].text); - gzprintf(fp, "*Default%s: 1000\n", stp_options[i].name); - for (j = stp_options[i].low; - j <= stp_options[i].high; - j += stp_options[i].step) - gzprintf(fp, "*%s %d/%.3f: \"\"\n", stp_options[i].name, j, j * 0.001); - gzprintf(fp, "*CloseUI: *%s\n\n", stp_options[i].name); + stp_parameter_t qdesc; + const char *tname = NULL; + stp_describe_parameter(v, "Quality", &qdesc); + if (qdesc.p_type == STP_PARAMETER_TYPE_STRING_LIST && + stp_string_list_count(qdesc.bounds.str) > 1) + { + for (l = 0; l < stp_string_list_count(qdesc.bounds.str); l++) + { + opt = stp_string_list_param(qdesc.bounds.str, l); + if (opt && strcmp(opt->name, "None") != 0) + { + tname = opt->name; + break; + } + } + } + for (l = 0; l < stp_parameter_list_count(param_list); l++) + { + const stp_parameter_t *lparam = + stp_parameter_list_param(param_list, l); + if (lparam->p_class > STP_PARAMETER_CLASS_OUTPUT || + lparam->p_level > STP_PARAMETER_LEVEL_ADVANCED4 || + strcmp(lparam->name, "Quality") == 0 || + (lparam->p_type != STP_PARAMETER_TYPE_STRING_LIST && + lparam->p_type != STP_PARAMETER_TYPE_BOOLEAN && + lparam->p_type != STP_PARAMETER_TYPE_DIMENSION && + lparam->p_type != STP_PARAMETER_TYPE_DOUBLE)) + continue; + stp_clear_string_parameter(v, "Quality"); + stp_describe_parameter(v, lparam->name, &desc); + if (desc.is_active) + { + stp_parameter_description_destroy(&desc); + stp_set_string_parameter(v, "Quality", tname); + stp_describe_parameter(v, lparam->name, &desc); + if (!desc.is_active) + { + gzprintf(fp, "*UIConstraints: *StpQuality *Stp%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *Stp%s *StpQuality\n\n", + lparam->name); + if (desc.p_type == STP_PARAMETER_TYPE_DOUBLE) + { + gzprintf(fp, "*UIConstraints: *StpQuality *StpFine%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *StpFine%s *StpQuality\n\n", + lparam->name); + } + } + } + stp_clear_string_parameter(v, "Quality"); + stp_parameter_description_destroy(&desc); + } + stp_parameter_description_destroy(&qdesc); } - - /* - * End of STP option group... - */ - - gzputs(fp, "*CloseGroup: STP\n\n"); -#ifdef __APPLE__ - gzputs(fp, "*OpenGroup: STPC/Expert color\n"); - - for (i = 5; i < num_opts; i ++) - { - gzprintf(fp, "*OpenUI *%s/%s: PickOne\n", stp_options[i].name, - stp_options[i].text); - gzprintf(fp, "*Default%s: 1000\n", stp_options[i].name); - for (j = stp_options[i].low; - j <= stp_options[i].high; - j += stp_options[i].step) - gzprintf(fp, "*%s %d/%.3f: \"\"\n", stp_options[i].name, j, j * 0.001); - gzprintf(fp, "*CloseUI: *%s\n", stp_options[i].name); - } - - gzputs(fp, "*CloseGroup: STPC\n\n"); + if (has_image_type_parameter) + { + stp_parameter_t qdesc; + const char *tname = NULL; + stp_describe_parameter(v, "ImageType", &qdesc); + if (qdesc.p_type == STP_PARAMETER_TYPE_STRING_LIST && + stp_string_list_count(qdesc.bounds.str) > 1) + { + for (l = 0; l < stp_string_list_count(qdesc.bounds.str); l++) + { + opt = stp_string_list_param(qdesc.bounds.str, l); + if (opt && strcmp(opt->name, "None") != 0) + { + tname = opt->name; + break; + } + } + } + for (l = 0; l < stp_parameter_list_count(param_list); l++) + { + const stp_parameter_t *lparam = + stp_parameter_list_param(param_list, l); + if (lparam->p_class > STP_PARAMETER_CLASS_OUTPUT || + lparam->p_level > STP_PARAMETER_LEVEL_ADVANCED4 || + strcmp(lparam->name, "ImageType") == 0 || + (lparam->p_type != STP_PARAMETER_TYPE_STRING_LIST && + lparam->p_type != STP_PARAMETER_TYPE_BOOLEAN && + lparam->p_type != STP_PARAMETER_TYPE_DIMENSION && + lparam->p_type != STP_PARAMETER_TYPE_DOUBLE)) + continue; + stp_clear_string_parameter(v, "ImageType"); + stp_describe_parameter(v, lparam->name, &desc); + if (desc.is_active) + { + stp_parameter_description_destroy(&desc); + stp_set_string_parameter(v, "ImageType", tname); + stp_describe_parameter(v, lparam->name, &desc); + if (!desc.is_active) + { + gzprintf(fp, "*UIConstraints: *StpImageType *Stp%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *Stp%s *StpImageType\n\n", + lparam->name); + if (desc.p_type == STP_PARAMETER_TYPE_DOUBLE) + { + gzprintf(fp, "*UIConstraints: *StpImageType *StpFine%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *StpFine%s *StpImageType\n\n", + lparam->name); + } + } + } + stp_clear_string_parameter(v, "ImageType"); + stp_parameter_description_destroy(&desc); + } + stp_parameter_description_destroy(&qdesc); } - else + if (printer_is_color) { - num_opts = 4; - - for (i = 0; i < num_opts; i ++) - { - gzprintf(fp, "*OpenUI *%s/%s: PickOne\n", stp_options[i].name, - stp_options[i].text); - gzprintf(fp, "*Default%s: 1000\n", stp_options[i].name); - for (j = stp_options[i].low; - j <= stp_options[i].high; - j += stp_options[i].step) - gzprintf(fp, "*%s %d/%.3f: \"\"\n", stp_options[i].name, j, j * 0.001); - gzprintf(fp, "*CloseUI: *%s\n", stp_options[i].name); - } - - gzputs(fp, "*CloseGroup: STP\n\n"); + for (l = 0; l < stp_parameter_list_count(param_list); l++) + { + const stp_parameter_t *lparam = + stp_parameter_list_param(param_list, l); + if (lparam->p_class > STP_PARAMETER_CLASS_OUTPUT || + lparam->p_level > STP_PARAMETER_LEVEL_ADVANCED4 || + strcmp(lparam->name, "Quality") == 0 || + is_special_option(lparam->name) || + (lparam->p_type != STP_PARAMETER_TYPE_STRING_LIST && + lparam->p_type != STP_PARAMETER_TYPE_BOOLEAN && + lparam->p_type != STP_PARAMETER_TYPE_DIMENSION && + lparam->p_type != STP_PARAMETER_TYPE_DOUBLE)) + continue; + stp_set_string_parameter(v, "PrintingMode", "Color"); + stp_describe_parameter(v, lparam->name, &desc); + if (desc.is_active) + { + stp_parameter_description_destroy(&desc); + stp_set_string_parameter(v, "PrintingMode", "BW"); + stp_describe_parameter(v, lparam->name, &desc); + if (!desc.is_active) + { + gzprintf(fp, "*UIConstraints: *ColorModel Gray *Stp%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *ColorModel Black *Stp%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *Stp%s *ColorModel Gray\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *Stp%s *ColorModel Black\n\n", + lparam->name); + if (desc.p_type == STP_PARAMETER_TYPE_DOUBLE) + { + gzprintf(fp, "*UIConstraints: *ColorModel Gray *StpFine%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *ColorModel Black *StpFine%s\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *StpFine%s *ColorModel Gray\n", + lparam->name); + gzprintf(fp, "*UIConstraints: *StpFine%s *ColorModel Black\n\n", + lparam->name); + } + } + } + stp_parameter_description_destroy(&desc); + } + stp_set_string_parameter(v, "PrintingMode", "Color"); } -#endif /* __APPLE__ */ + stp_parameter_list_destroy(param_list); /* * Fonts... @@ -1039,14 +1696,18 @@ write_ppd(const stp_printer_t p, /* I - Printer driver */ gzputs(fp, "*Font ZapfChancery-MediumItalic: Standard \"(001.007S)\" Standard ROM\n"); gzputs(fp, "*Font ZapfDingbats: Special \"(001.004S)\" Standard ROM\n"); - gzprintf(fp, "\n*%%End of %s.ppd\n", driver); + gzprintf(fp, "\n*%%End of stp-%s.%s%s\n", + driver, + GUTENPRINT_RELEASE_VERSION, + ppdext); gzclose(fp); - stp_free_vars(v); + stp_vars_destroy(v); return (0); } + /* - * End of "$Id: genppd.c,v 1.36.2.15 2004/06/12 20:04:05 rlk Exp $". + * End of "$Id: genppd.c,v 1.107 2005/04/23 00:26:07 rlk Exp $". */ |