diff options
author | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2008-02-16 00:27:39 +0000 |
---|---|---|
committer | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2008-02-16 00:27:39 +0000 |
commit | ac884b6a1c1c3dfe73ef7e770d91ea225002a2c3 (patch) | |
tree | 09fb84a85bf308c6a6dd45f7293c64c40fe5acdc /ppdc/ppdc-source.cxx | |
parent | 5a738aeaea5c4dd9384a8601cc5c99be683b69ca (diff) | |
download | cups-ac884b6a1c1c3dfe73ef7e770d91ea225002a2c3.tar.gz |
Merge CUPS 1.4svn-r7319.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@624 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'ppdc/ppdc-source.cxx')
-rw-r--r-- | ppdc/ppdc-source.cxx | 3241 |
1 files changed, 3241 insertions, 0 deletions
diff --git a/ppdc/ppdc-source.cxx b/ppdc/ppdc-source.cxx new file mode 100644 index 000000000..c85dd6c60 --- /dev/null +++ b/ppdc/ppdc-source.cxx @@ -0,0 +1,3241 @@ +// +// "$Id$" +// +// Source class for the CUPS PPD Compiler. +// +// Copyright 2007-2008 by Apple Inc. +// Copyright 2002-2007 by Easy Software Products. +// +// These coded instructions, statements, and computer programs are the +// property of Apple Inc. and are protected by Federal copyright +// law. Distribution and use rights are outlined in the file "LICENSE.txt" +// which should have been included with this file. If this file is +// file is missing or damaged, see the license at "http://www.cups.org/". +// +// Contents: +// +// ppdcSource::ppdcSource() - Load a driver source file. +// ppdcSource::~ppdcSource() - Free a driver source file. +// ppdcSource::add_include() - Add an include directory. +// ppdcSource::find_driver() - Find a driver. +// ppdcSource::find_include() - Find an include file. +// ppdcSource::find_size() - Find a media size. +// ppdcSource::find_variable() - Find a variable. +// ppdcSource::get_attr() - Get an attribute. +// ppdcSource::get_boolean() - Get a boolean value. +// ppdcSource::get_choice() - Get a choice. +// ppdcSource::get_color_model() - Get an old-style color model option. +// ppdcSource::get_color_order() - Get an old-style color order value. +// ppdcSource::get_color_profile() - Get a color profile definition. +// ppdcSource::get_color_space() - Get an old-style colorspace value. +// ppdcSource::get_constraint() - Get a constraint. +// ppdcSource::get_custom_size() - Get a custom media size definition +// from a file. +// ppdcSource::get_filter() - Get a filter. +// ppdcSource::get_float() - Get a single floating-point number. +// ppdcSource::get_font() - Get a font definition. +// ppdcSource::get_generic() - Get a generic old-style option. +// ppdcSource::get_group() - Get an option group. +// ppdcSource::get_installable() - Get an installable option. +// ppdcSource::get_integer() - Get an integer value from a string. +// ppdcSource::get_integer() - Get an integer value from a file. +// ppdcSource::get_measurement() - Get a measurement value. +// ppdcSource::get_option() - Get an option definition. +// ppdcSource::get_resolution() - Get an old-style resolution option. +// ppdcSource::get_simple_profile() - Get a simple color profile definition. +// ppdcSource::get_size() - Get a media size definition from a file. +// ppdcSource::get_token() - Get a token from a file. +// ppdcSource::get_variable() - Get a variable definition. +// ppdcSource::quotef() - Write a formatted, quoted string... +// ppdcSource::read_file() - Read a driver source file. +// ppdcSource::scan_file() - Scan a driver source file. +// ppdcSource::set_variable() - Set a variable. +// ppdcSource::write_file() - Write the current source data to a file. +// + +// +// Include necessary headers... +// + +#include "ppdc.h" +#include <cups/globals.h> +#include <limits.h> +#include <math.h> +#include <unistd.h> +#include <cups/raster.h> +#include "data/epson.h" +#include "data/escp.h" +#include "data/hp.h" +#include "data/label.h" +#include "data/pcl.h" + + +// +// Class globals... +// + +ppdcArray *ppdcSource::includes = 0; +const char *ppdcSource::driver_types[] = + { + "custom", + "ps", + "escp", + "pcl", + "label", + "epson", + "hp" + }; + + +// +// 'ppdcSource::ppdcSource()' - Load a driver source file. +// + +ppdcSource::ppdcSource(const char *f) // I - File to read +{ + filename = new ppdcString(f); + base_fonts = new ppdcArray(); + drivers = new ppdcArray(); + po_files = new ppdcArray(); + sizes = new ppdcArray(); + vars = new ppdcArray(); + + if (f) + read_file(f); +} + + +// +// 'ppdcSource::~ppdcSource()' - Free a driver source file. +// + +ppdcSource::~ppdcSource() +{ + delete filename; + delete base_fonts; + delete drivers; + delete po_files; + delete sizes; + delete vars; +} + + +// +// 'ppdcSource::add_include()' - Add an include directory. +// + +void +ppdcSource::add_include(const char *d) // I - Include directory +{ + if (!d) + return; + + if (!includes) + includes = new ppdcArray(); + + includes->add(new ppdcString(d)); +} + + +// +// 'ppdcSource::find_driver()' - Find a driver. +// + +ppdcDriver * // O - Driver +ppdcSource::find_driver(const char *f) // I - Driver file name +{ + ppdcDriver *d; // Current driver + + + for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next()) + if (!strcasecmp(f, d->pc_file_name->value)) + return (d); + + return (NULL); +} + + +// +// 'ppdcSource::find_include()' - Find an include file. +// + +char * // O - Found path or NULL +ppdcSource::find_include( + const char *f, // I - Include filename + const char *base, // I - Current directory + char *n, // I - Path buffer + int nlen) // I - Path buffer length +{ + ppdcString *dir; // Include directory + char temp[1024], // Temporary path + *ptr; // Pointer to end of path + + + // Range check input... + if (!f || !*f || !n || nlen < 2) + return (0); + + // Check the first character to see if we have <name> or "name"... + if (*f == '<') + { + // Remove the surrounding <> from the name... + strlcpy(temp, f + 1, sizeof(temp)); + ptr = temp + strlen(temp) - 1; + + if (*ptr != '>') + { + fprintf(stderr, "ppdc: Invalid #include/#po filename \"%s\"!\n", n); + return (0); + } + + *ptr = '\0'; + f = temp; + } + else + { + // Check for the local file relative to the current directory... + if (base && *base && f[0] != '/') + snprintf(n, nlen, "%s/%s", base, f); + else + strlcpy(n, f, nlen); + + if (!access(n, 0)) + return (n); + else if (*f == '/') + { + // Absolute path that doesn't exist... + return (0); + } + } + + // Search the include directories, if any... + if (includes) + { + for (dir = (ppdcString *)includes->first(); dir; dir = (ppdcString *)includes->next()) + { + snprintf(n, nlen, "%s/%s", dir->value, f); + if (!access(n, 0)) + return (n); + } + } + + // Search the standard include directories... + _cups_globals_t *cg = _cupsGlobals(); // Global data + + snprintf(n, nlen, "%s/ppdc/%s", cg->cups_datadir, f); + if (!access(n, 0)) + return (n); + + snprintf(n, nlen, "%s/po/%s", cg->cups_datadir, f); + if (!access(n, 0)) + return (n); + else + return (0); +} + + +// +// 'ppdcSource::find_po()' - Find a message catalog for the given locale... +// + +ppdcCatalog * // O - Message catalog or NULL +ppdcSource::find_po(const char *l) // I - Locale name +{ + ppdcCatalog *cat; // Current message catalog + + + for (cat = (ppdcCatalog *)po_files->first(); + cat; + cat = (ppdcCatalog *)po_files->next()) + if (!strcasecmp(l, cat->locale->value)) + return (cat); + + return (NULL); +} + + +// +// 'ppdcSource::find_size()' - Find a media size. +// + +ppdcMediaSize * // O - Size +ppdcSource::find_size(const char *s) // I - Size name +{ + ppdcMediaSize *m; // Current media size + + + for (m = (ppdcMediaSize *)sizes->first(); m; m = (ppdcMediaSize *)sizes->next()) + if (!strcasecmp(s, m->name->value)) + return (m); + + return (NULL); +} + + +// +// 'ppdcSource::find_variable()' - Find a variable. +// + +ppdcVariable * // O - Variable +ppdcSource::find_variable(const char *n)// I - Variable name +{ + ppdcVariable *v; // Current variable + + + for (v = (ppdcVariable *)vars->first(); v; v = (ppdcVariable *)vars->next()) + if (!strcasecmp(n, v->name->value)) + return (v); + + return (NULL); +} + + +// +// 'ppdcSource::get_attr()' - Get an attribute. +// + +ppdcAttr * // O - Attribute +ppdcSource::get_attr(ppdcFile *fp) // I - File to read +{ + char name[1024], // Name string + selector[1024], // Selector string + *text, // Text string + value[1024]; // Value string + + + // Get the attribute parameters: + // + // Attribute name selector value + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name after Attribute on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + + if (!get_token(fp, selector, sizeof(selector))) + { + fprintf(stderr, "ppdc: Expected selector after Attribute on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + + if ((text = strchr(selector, '/')) != NULL) + *text++ = '\0'; + + if (!get_token(fp, value, sizeof(value))) + { + fprintf(stderr, "ppdc: Expected value after Attribute on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + +// printf("name=\"%s\", selector=\"%s\", value=\"%s\"\n", name, selector, value); + + return (new ppdcAttr(name, selector, text, value)); +} + + +// +// 'ppdcSource::get_boolean()' - Get a boolean value. +// + +int // O - Boolean value +ppdcSource::get_boolean(ppdcFile *fp) // I - File to read +{ + char buffer[256]; // String buffer + + + if (!get_token(fp, buffer, sizeof(buffer))) + { + fprintf(stderr, "ppdc: Expected boolean value on line %d of %s.\n", + fp->line, fp->filename); + return (-1); + } + + if (!strcasecmp(buffer, "on") || + !strcasecmp(buffer, "yes") || + !strcasecmp(buffer, "true")) + return (1); + else if (!strcasecmp(buffer, "off") || + !strcasecmp(buffer, "no") || + !strcasecmp(buffer, "false")) + return (0); + else + { + fprintf(stderr, "ppdc: Bad boolean value (%s) on line %d of %s.\n", + buffer, fp->line, fp->filename); + return (-1); + } +} + + +// +// 'ppdcSource::get_choice()' - Get a choice. +// + +ppdcChoice * // O - Choice data +ppdcSource::get_choice(ppdcFile *fp) // I - File to read +{ + char name[1024], // Name + *text, // Text + code[10240]; // Code + + + // Read a choice from the file: + // + // Choice name/text code + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected choice name/text on line %d of %s.\n", + fp->line, fp->filename); + return (NULL); + } + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + if (!get_token(fp, code, sizeof(code))) + { + fprintf(stderr, "ppdc: Expected choice code on line %d of %s.\n", + fp->line, fp->filename); + return (NULL); + } + + // Return the new choice + return (new ppdcChoice(name, text, code)); +} + + +// +// 'ppdcSource::get_color_model()' - Get an old-style color model option. +// + +ppdcChoice * // O - Choice data +ppdcSource::get_color_model(ppdcFile *fp) + // I - File to read +{ + char name[1024], // Option name + *text, // Text option + temp[256]; // Temporary string + int color_space, // Colorspace + color_order, // Color order + compression; // Compression mode + + + // Get the ColorModel parameters: + // + // ColorModel name/text colorspace colororder compression + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, + "ppdc: Expected name/text combination for ColorModel on line " + "%d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, + "ppdc: Expected colorspace for ColorModel on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((color_space = get_color_space(temp)) < 0) + color_space = get_integer(temp); + + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, + "ppdc: Expected color order for ColorModel on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((color_order = get_color_order(temp)) < 0) + color_order = get_integer(temp); + + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, + "ppdc: Expected compression for ColorModel on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + compression = get_integer(temp); + + snprintf(temp, sizeof(temp), + "<</cupsColorSpace %d/cupsColorOrder %d/cupsCompression %d>>" + "setpagedevice", + color_space, color_order, compression); + + return (new ppdcChoice(name, text, temp)); +} + + +// +// 'ppdcSource::get_color_order()' - Get an old-style color order value. +// + +int // O - Color order value +ppdcSource::get_color_order( + const char *co) // I - Color order string +{ + if (!strcasecmp(co, "chunked") || + !strcasecmp(co, "chunky")) + return (CUPS_ORDER_CHUNKED); + else if (!strcasecmp(co, "banded")) + return (CUPS_ORDER_BANDED); + else if (!strcasecmp(co, "planar")) + return (CUPS_ORDER_PLANAR); + else + return (-1); +} + + +// +// 'ppdcSource::get_color_profile()' - Get a color profile definition. +// + +ppdcProfile * // O - Color profile +ppdcSource::get_color_profile( + ppdcFile *fp) // I - File to read +{ + char resolution[1024], // Resolution/media type + *media_type; // Media type + int i; // Looping var + float g, // Gamma value + d, // Density value + m[9]; // Transform matrix + + + // Get the ColorProfile parameters: + // + // ColorProfile resolution/mediatype gamma density m00 m01 m02 ... m22 + if (!get_token(fp, resolution, sizeof(resolution))) + { + fprintf(stderr, "ppdc: Expected resolution/mediatype following ColorProfile on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((media_type = strchr(resolution, '/')) != NULL) + *media_type++ = '\0'; + else + media_type = resolution; + + g = get_float(fp); + d = get_float(fp); + for (i = 0; i < 9; i ++) + m[i] = get_float(fp); + + return (new ppdcProfile(resolution, media_type, g, d, m)); +} + + +// +// 'ppdcSource::get_color_space()' - Get an old-style colorspace value. +// + +int // O - Colorspace value +ppdcSource::get_color_space( + const char *cs) // I - Colorspace string +{ + if (!strcasecmp(cs, "w")) + return (CUPS_CSPACE_W); + else if (!strcasecmp(cs, "rgb")) + return (CUPS_CSPACE_RGB); + else if (!strcasecmp(cs, "rgba")) + return (CUPS_CSPACE_RGBA); + else if (!strcasecmp(cs, "k")) + return (CUPS_CSPACE_K); + else if (!strcasecmp(cs, "cmy")) + return (CUPS_CSPACE_CMY); + else if (!strcasecmp(cs, "ymc")) + return (CUPS_CSPACE_YMC); + else if (!strcasecmp(cs, "cmyk")) + return (CUPS_CSPACE_CMYK); + else if (!strcasecmp(cs, "ymck")) + return (CUPS_CSPACE_YMCK); + else if (!strcasecmp(cs, "kcmy")) + return (CUPS_CSPACE_KCMY); + else if (!strcasecmp(cs, "kcmycm")) + return (CUPS_CSPACE_KCMYcm); + else if (!strcasecmp(cs, "gmck")) + return (CUPS_CSPACE_GMCK); + else if (!strcasecmp(cs, "gmcs")) + return (CUPS_CSPACE_GMCS); + else if (!strcasecmp(cs, "white")) + return (CUPS_CSPACE_WHITE); + else if (!strcasecmp(cs, "gold")) + return (CUPS_CSPACE_GOLD); + else if (!strcasecmp(cs, "silver")) + return (CUPS_CSPACE_SILVER); + else if (!strcasecmp(cs, "CIEXYZ")) + return (CUPS_CSPACE_CIEXYZ); + else if (!strcasecmp(cs, "CIELab")) + return (CUPS_CSPACE_CIELab); + else if (!strcasecmp(cs, "RGBW")) + return (CUPS_CSPACE_RGBW); + else if (!strcasecmp(cs, "ICC1")) + return (CUPS_CSPACE_ICC1); + else if (!strcasecmp(cs, "ICC2")) + return (CUPS_CSPACE_ICC2); + else if (!strcasecmp(cs, "ICC3")) + return (CUPS_CSPACE_ICC3); + else if (!strcasecmp(cs, "ICC4")) + return (CUPS_CSPACE_ICC4); + else if (!strcasecmp(cs, "ICC5")) + return (CUPS_CSPACE_ICC5); + else if (!strcasecmp(cs, "ICC6")) + return (CUPS_CSPACE_ICC6); + else if (!strcasecmp(cs, "ICC7")) + return (CUPS_CSPACE_ICC7); + else if (!strcasecmp(cs, "ICC8")) + return (CUPS_CSPACE_ICC8); + else if (!strcasecmp(cs, "ICC9")) + return (CUPS_CSPACE_ICC9); + else if (!strcasecmp(cs, "ICCA")) + return (CUPS_CSPACE_ICCA); + else if (!strcasecmp(cs, "ICCB")) + return (CUPS_CSPACE_ICCB); + else if (!strcasecmp(cs, "ICCC")) + return (CUPS_CSPACE_ICCC); + else if (!strcasecmp(cs, "ICCD")) + return (CUPS_CSPACE_ICCD); + else if (!strcasecmp(cs, "ICCE")) + return (CUPS_CSPACE_ICCE); + else if (!strcasecmp(cs, "ICCF")) + return (CUPS_CSPACE_ICCF); + else + return (-1); +} + + +// +// 'ppdcSource::get_constraint()' - Get a constraint. +// + +ppdcConstraint * // O - Constraint +ppdcSource::get_constraint(ppdcFile *fp)// I - File to read +{ + char temp[1024], // One string to rule them all + *ptr, // Pointer into string + *option1, // Constraint option 1 + *choice1, // Constraint choice 1 + *option2, // Constraint option 2 + *choice2; // Constraint choice 2 + + + // Read the UIConstaints parameter in one of the following forms: + // + // UIConstraints "*Option1 *Option2" + // UIConstraints "*Option1 Choice1 *Option2" + // UIConstraints "*Option1 *Option2 Choice2" + // UIConstraints "*Option1 Choice1 *Option2 Choice2" + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, "ppdc: Expected constraints string for UIConstraints on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + for (ptr = temp; isspace(*ptr); ptr ++); + + if (*ptr != '*') + { + fprintf(stderr, "ppdc: Option constraint must *name on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + option1 = ptr; + + for (; *ptr && !isspace(*ptr); ptr ++); + for (; isspace(*ptr); *ptr++ = '\0'); + + if (*ptr != '*') + { + choice1 = ptr; + + for (; *ptr && !isspace(*ptr); ptr ++); + for (; isspace(*ptr); *ptr++ = '\0'); + } + else + choice1 = NULL; + + if (*ptr != '*') + { + fprintf(stderr, "ppdc: Expected two option names on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + option2 = ptr; + + for (; *ptr && !isspace(*ptr); ptr ++); + for (; isspace(*ptr); *ptr++ = '\0'); + + if (*ptr) + choice2 = ptr; + else + choice2 = NULL; + + return (new ppdcConstraint(option1, choice1, option2, choice2)); +} + + +// +// 'ppdcSource::get_custom_size()' - Get a custom media size definition from a file. +// + +ppdcMediaSize * // O - Media size +ppdcSource::get_custom_size(ppdcFile *fp) + // I - File to read +{ + char name[1024], // Name + *text, // Text + size_code[10240], // PageSize code + region_code[10240]; // PageRegion + float width, // Width + length, // Length + left, // Left margin + bottom, // Bottom margin + right, // Right margin + top; // Top margin + + + // Get the name, text, width, length, margins, and code: + // + // CustomMedia name/text width length left bottom right top size-code region-code + if (!get_token(fp, name, sizeof(name))) + return (NULL); + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + if ((width = get_measurement(fp)) < 0.0f) + return (NULL); + + if ((length = get_measurement(fp)) < 0.0f) + return (NULL); + + if ((left = get_measurement(fp)) < 0.0f) + return (NULL); + + if ((bottom = get_measurement(fp)) < 0.0f) + return (NULL); + + if ((right = get_measurement(fp)) < 0.0f) + return (NULL); + + if ((top = get_measurement(fp)) < 0.0f) + return (NULL); + + if (!get_token(fp, size_code, sizeof(size_code))) + return (NULL); + + if (!get_token(fp, region_code, sizeof(region_code))) + return (NULL); + + // Return the new media size... + return (new ppdcMediaSize(name, text, width, length, left, bottom, + right, top, size_code, region_code)); +} + + +// +// 'ppdcSource::get_duplex()' - Get a duplex option. +// + +void +ppdcSource::get_duplex(ppdcFile *fp, // I - File to read from + ppdcDriver *d) // I - Current driver +{ + char temp[256]; // Duplex keyword + ppdcAttr *attr; // cupsFlipDuplex attribute + ppdcGroup *g; // Current group + ppdcOption *o; // Duplex option + + + // Duplex {boolean|none|normal|flip} + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, "ppdc: Expected duplex type after Duplex on line %d of %s!\n", + fp->line, fp->filename); + return; + } + + if (!strcasecmp(temp, "none") || !strcasecmp(temp, "false") || + !strcasecmp(temp, "no") || !strcasecmp(temp, "off")) + { + g = d->find_group("General"); + if ((o = g->find_option("Duplex")) != NULL) + g->options->remove(o); + + for (attr = (ppdcAttr *)d->attrs->first(); + attr; + attr = (ppdcAttr *)d->attrs->next()) + if (!strcmp(attr->name->value, "cupsFlipDuplex")) + { + d->attrs->remove(attr); + break; + } + } + else if (!strcasecmp(temp, "normal") || !strcasecmp(temp, "true") || + !strcasecmp(temp, "yes") || !strcasecmp(temp, "on") || + !strcasecmp(temp, "flip")) + { + g = d->find_group("General"); + o = g->find_option("Duplex"); + + if (!o) + { + o = new ppdcOption(PPDC_PICKONE, "Duplex", "2-Sided Printing", + !strcasecmp(temp, "flip") ? PPDC_SECTION_PAGE : + PPDC_SECTION_ANY, 10.0f); + o->add_choice(new ppdcChoice("None", "Off (1-Sided)", + "<</Duplex false>>setpagedevice")); + o->add_choice(new ppdcChoice("DuplexNoTumble", "Long-Edge (Portrait)", + "<</Duplex true/Tumble false>>setpagedevice")); + o->add_choice(new ppdcChoice("DuplexTumble", "Short-Edge (Landscape)", + "<</Duplex true/Tumble true>>setpagedevice")); + + g->add_option(o); + } + + for (attr = (ppdcAttr *)d->attrs->first(); + attr; + attr = (ppdcAttr *)d->attrs->next()) + if (!strcmp(attr->name->value, "cupsFlipDuplex")) + { + if (strcasecmp(temp, "flip")) + d->attrs->remove(attr); + break; + } + + if (!strcasecmp(temp, "flip") && !attr) + d->add_attr(new ppdcAttr("cupsFlipDuplex", NULL, NULL, "true")); + } + else + fprintf(stderr, "ppdc: Unknown duplex type \"%s\" on line %d of %s!\n", + temp, fp->line, fp->filename); +} + + +// +// 'ppdcSource::get_filter()' - Get a filter. +// + +ppdcFilter * // O - Filter +ppdcSource::get_filter(ppdcFile *fp) // I - File to read +{ + char type[1024], // MIME type + program[1024], // Filter program + *ptr; // Pointer into MIME type + int cost; // Relative cost + + + // Read filter parameters in one of the following formats: + // + // Filter "type cost program" + // Filter type cost program + + if (!get_token(fp, type, sizeof(type))) + { + fprintf(stderr, "ppdc: Expected a filter definition on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((ptr = strchr(type, ' ')) != NULL) + { + // Old-style filter definition in one string... + *ptr++ = '\0'; + cost = strtol(ptr, &ptr, 10); + + while (isspace(*ptr)) + ptr ++; + + strcpy(program, ptr); + } + else + { + cost = get_integer(fp); + + if (!get_token(fp, program, sizeof(program))) + { + fprintf(stderr, "ppdc: Expected a program name on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + } + + if (!type[0]) + { + fprintf(stderr, "ppdc: Invalid empty MIME type for filter on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if (cost < 0 || cost > 200) + { + fprintf(stderr, "ppdc: Invalid cost for filter on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if (!program[0]) + { + fprintf(stderr, "ppdc: Invalid empty program name for filter on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + return (new ppdcFilter(type, program, cost)); +} + + +// +// 'ppdcSource::get_float()' - Get a single floating-point number. +// + +float // O - Number +ppdcSource::get_float(ppdcFile *fp) // I - File to read +{ + char temp[256], // String buffer + *ptr; // Pointer into buffer + float val; // Floating point value + + + // Get the number from the file and range-check... + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, "ppdc: Expected real number on line %d of %s!\n", + fp->line, fp->filename); + return (-1.0f); + } + + val = (float)strtod(temp, &ptr); + + if (*ptr) + { + fprintf(stderr, "ppdc: Unknown trailing characters in real number \"%s\" on line %d of %s!\n", + temp, fp->line, fp->filename); + return (-1.0f); + } + else + return (val); +} + + +// +// 'ppdcSource::get_font()' - Get a font definition. +// + +ppdcFont * // O - Font data +ppdcSource::get_font(ppdcFile *fp) // I - File to read +{ + char name[256], // Font name + encoding[256], // Font encoding + version[256], // Font version + charset[256], // Font charset + temp[256]; // Font status string + ppdcFontStatus status; // Font status enumeration + + + // Read font parameters as follows: + // + // Font * + // Font name encoding version charset status + // %font name encoding version charset status + // + // "Name" is the PostScript font name. + // + // "Encoding" is the default encoding of the font: Standard, ISOLatin1, + // Special, Expert, ExpertSubset, etc. + // + // "Version" is the version number string. + // + // "Charset" specifies the characters that are included in the font: + // Standard, Special, Expert, Adobe-Identity, etc. + // + // "Status" is the keyword ROM or Disk. + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name after Font on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + + if (!strcmp(name, "*")) + { + // Include all base fonts... + encoding[0] = '\0'; + version[0] = '\0'; + charset[0] = '\0'; + status = PPDC_FONT_ROM; + } + else + { + // Load a full font definition... + if (!get_token(fp, encoding, sizeof(encoding))) + { + fprintf(stderr, "ppdc: Expected encoding after Font on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + + if (!get_token(fp, version, sizeof(version))) + { + fprintf(stderr, "ppdc: Expected version after Font on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + + if (!get_token(fp, charset, sizeof(charset))) + { + fprintf(stderr, "ppdc: Expected charset after Font on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, "ppdc: Expected status after Font on line %d of %s!\n", + fp->line, fp->filename); + return (0); + } + + if (!strcasecmp(temp, "ROM")) + status = PPDC_FONT_ROM; + else if (!strcasecmp(temp, "Disk")) + status = PPDC_FONT_DISK; + else + { + fprintf(stderr, "ppdc: Bad status keyword %s on line %d of %s!\n", + temp, fp->line, fp->filename); + return (0); + } + } + +// printf("Font %s %s %s %s %s\n", name, encoding, version, charset, temp); + + return (new ppdcFont(name, encoding, version, charset, status)); +} + + +// +// 'ppdcSource::get_generic()' - Get a generic old-style option. +// + +ppdcChoice * // O - Choice data +ppdcSource::get_generic(ppdcFile *fp, // I - File to read + const char *keyword, + // I - Keyword name + const char *tattr, + // I - Text attribute + const char *nattr) + // I - Numeric attribute +{ + char name[1024], // Name + *text, // Text + command[256]; // Command string + int val; // Numeric value + + + // Read one of the following parameters: + // + // Foo name/text + // Foo integer name/text + if (nattr) + val = get_integer(fp); + else + val = 0; + + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name/text after %s on line %d of %s!\n", + keyword, fp->line, fp->filename); + return (NULL); + } + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + if (nattr) + { + if (tattr) + snprintf(command, sizeof(command), + "<</%s(%s)/%s %d>>setpagedevice", + tattr, name, nattr, val); + else + snprintf(command, sizeof(command), + "<</%s %d>>setpagedevice", + nattr, val); + } + else + snprintf(command, sizeof(command), + "<</%s(%s)>>setpagedevice", + tattr, name); + + return (new ppdcChoice(name, text, command)); +} + + +// +// 'ppdcSource::get_group()' - Get an option group. +// + +ppdcGroup * // O - Group +ppdcSource::get_group(ppdcFile *fp, // I - File to read + ppdcDriver *d) // I - Printer driver +{ + char name[1024], // UI name + *text; // UI text + ppdcGroup *g; // Group + + + // Read the Group parameters: + // + // Group name/text + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected group name/text on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + // See if the group already exists... + if ((g = d->find_group(name)) == NULL) + { + // Nope, add a new one... + g = new ppdcGroup(name, text); + d->add_group(g); + } + + return (g); +} + + +// +// 'ppdcSource::get_installable()' - Get an installable option. +// + +ppdcOption * // O - Option +ppdcSource::get_installable(ppdcFile *fp) + // I - File to read +{ + char name[1024], // Name for installable option + *text; // Text for installable option + ppdcOption *o; // Option + + + // Read the parameter for an installable option: + // + // Installable name/text + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name/text after Installable on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + // Create the option... + o = new ppdcOption(PPDC_BOOLEAN, name, text, PPDC_SECTION_ANY, 10.0f); + + // Add the false and true choices... + o->add_choice(new ppdcChoice("False", "Not Installed", "")); + o->add_choice(new ppdcChoice("True", "Installed", "")); + + return (o); +} + + +// +// 'ppdcSource::get_integer()' - Get an integer value from a string. +// + +int // O - Integer value +ppdcSource::get_integer(const char *v) // I - Value string +{ + int val; // Value + int temp; // Temporary value + char *newv; // New value string pointer + + + // Parse the value string... + if (!v) + return (-1); + + if (isdigit(*v) || *v == '-' || *v == '+') + { + // Return a simple integer value + val = strtol(v, (char **)&v, 0); + if (*v || val == LONG_MIN) + return (-1); + else + return (val); + } + else if (*v == '(') + { + // Return the bitwise OR of each integer in parenthesis... + v ++; + val = 0; + + while (*v && *v != ')') + { + temp = strtol(v, &newv, 0); + + if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') || + temp == LONG_MIN) + return (-1); + + val |= temp; + v = newv; + } + + if (*v == ')') + return (val); + else + return (-1); + } + else + return (-1); +} + + +// +// 'ppdcSource::get_integer()' - Get an integer value from a file. +// + +int // O - Integer value +ppdcSource::get_integer(ppdcFile *fp) // I - File to read +{ + char temp[1024]; // String buffer + + + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, "ppdc: Expected integer on line %d of %s!\n", + fp->line, fp->filename); + return (-1); + } + else + return (get_integer(temp)); +} + + +// +// 'ppdcSource::get_measurement()' - Get a measurement value. +// + +float // O - Measurement value in points +ppdcSource::get_measurement(ppdcFile *fp) + // I - File to read +{ + char buffer[256], // Number buffer + *ptr; // Pointer into buffer + float val; // Measurement value + + + // Grab a token from the file... + if (!get_token(fp, buffer, sizeof(buffer))) + return (-1.0f); + + // Get the floating point value of "s" and skip all digits and decimal points. + val = (float)strtod(buffer, &ptr); + + // Check for a trailing unit specifier... + if (!strcasecmp(ptr, "mm")) + val *= 72.0f / 25.4f; + else if (!strcasecmp(ptr, "cm")) + val *= 72.0f / 2.54f; + else if (!strcasecmp(ptr, "m")) + val *= 72.0f / 0.0254f; + else if (!strcasecmp(ptr, "in")) + val *= 72.0f; + else if (!strcasecmp(ptr, "ft")) + val *= 72.0f * 12.0f; + else if (strcasecmp(ptr, "pt") && *ptr) + return (-1.0f); + + return (val); +} + + +// +// 'ppdcSource::get_option()' - Get an option definition. +// + +ppdcOption * // O - Option +ppdcSource::get_option(ppdcFile *fp, // I - File to read + ppdcDriver *d, // I - Printer driver + ppdcGroup *g) // I - Current group +{ + char name[1024], // UI name + *text, // UI text + type[256]; // UI type string + ppdcOptType ot; // Option type value + ppdcOptSection section; // Option section + float order; // Option order + ppdcOption *o; // Option + + + // Read the Option parameters: + // + // Option name/text type section order + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected option name/text on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + if (!get_token(fp, type, sizeof(type))) + { + fprintf(stderr, "ppdc: Expected option type on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if (!strcasecmp(type, "boolean")) + ot = PPDC_BOOLEAN; + else if (!strcasecmp(type, "pickone")) + ot = PPDC_PICKONE; + else if (!strcasecmp(type, "pickmany")) + ot = PPDC_PICKMANY; + else + { + fprintf(stderr, "ppdc: Invalid option type \"%s\" on line %d of %s!\n", + type, fp->line, fp->filename); + return (NULL); + } + + if (!get_token(fp, type, sizeof(type))) + { + fprintf(stderr, "ppdc: Expected option section on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if (!strcasecmp(type, "AnySetup")) + section = PPDC_SECTION_ANY; + else if (!strcasecmp(type, "DocumentSetup")) + section = PPDC_SECTION_DOCUMENT; + else if (!strcasecmp(type, "ExitServer")) + section = PPDC_SECTION_EXIT; + else if (!strcasecmp(type, "JCLSetup")) + section = PPDC_SECTION_JCL; + else if (!strcasecmp(type, "PageSetup")) + section = PPDC_SECTION_PAGE; + else if (!strcasecmp(type, "Prolog")) + section = PPDC_SECTION_PROLOG; + else + { + fprintf(stderr, "ppdc: Invalid option section \"%s\" on line %d of %s!\n", + type, fp->line, fp->filename); + return (NULL); + } + + order = get_float(fp); + + // See if the option already exists... + if ((o = d->find_option(name)) == NULL) + { + // Nope, add a new one... + o = new ppdcOption(ot, name, text, section, order); + g->add_option(o); + } + else if (o->type != ot) + { +// printf("o=%p, o->type=%d, o->name=%s, ot=%d, name=%s\n", +// o, o->type, o->name->value, ot, name); + fprintf(stderr, "ppdc: Option already defined with a different type on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + return (o); +} + + +// +// 'ppdcSource::get_po()' - Get a message catalog. +// + +ppdcCatalog * // O - Message catalog +ppdcSource::get_po(ppdcFile *fp) // I - File to read +{ + char locale[32], // Locale name + poname[1024], // Message catalog filename + basedir[1024], // Base directory + *baseptr, // Pointer into directory + pofilename[1024]; // Full filename of message catalog + ppdcCatalog *cat; // Message catalog + + + // Read the #po parameters: + // + // #po locale "filename.po" + if (!get_token(fp, locale, sizeof(locale))) + { + fprintf(stderr, "ppdc: Expected locale after #po on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if (!get_token(fp, poname, sizeof(poname))) + { + fprintf(stderr, "ppdc: Expected filename after #po %s on line %d of %s!\n", + locale, fp->line, fp->filename); + return (NULL); + } + + // See if the locale is already loaded... + if (find_po(locale)) + { + fprintf(stderr, "ppdc: Duplicate #po for locale %s on line %d of %s!\n", + locale, fp->line, fp->filename); + return (NULL); + } + + // Figure out the current directory... + strlcpy(basedir, fp->filename, sizeof(basedir)); + + if ((baseptr = strrchr(basedir, '/')) != NULL) + *baseptr = '\0'; + else + strcpy(basedir, "."); + + // Find the po file... + if (find_include(poname, basedir, pofilename, sizeof(pofilename))) + { + // Found it, so load it... + cat = new ppdcCatalog(locale, pofilename); + + // Reset the filename to the name supplied by the user... + delete cat->filename; + cat->filename = new ppdcString(poname); + + // Return the catalog... + return (cat); + } + else + { + fprintf(stderr, "ppdc: Unable to find #po file %s on line %d of %s!\n", + poname, fp->line, fp->filename); + return (NULL); + } +} + + +// +// 'ppdcSource::get_resolution()' - Get an old-style resolution option. +// + +ppdcChoice * // O - Choice data +ppdcSource::get_resolution(ppdcFile *fp)// I - File to read +{ + char name[1024], // Name + *text, // Text + temp[256], // Temporary string + command[256], // Command string + *commptr; // Pointer into command + int xdpi, ydpi, // X + Y resolution + color_order, // Color order + color_space, // Colorspace + compression, // Compression mode + depth, // Bits per color + row_count, // Row count + row_feed, // Row feed + row_step; // Row step/interval + + + // Read the resolution parameters: + // + // Resolution colorspace bits row-count row-feed row-step name/text + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, "ppdc: Expected override field after Resolution on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + color_order = get_color_order(temp); + color_space = get_color_space(temp); + compression = get_integer(temp); + + depth = get_integer(fp); + row_count = get_integer(fp); + row_feed = get_integer(fp); + row_step = get_integer(fp); + + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name/text after Resolution on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + switch (sscanf(name, "%dx%d", &xdpi, &ydpi)) + { + case 0 : + fprintf(stderr, "ppdc: Bad resolution name \"%s\" on line %d of %s!\n", + name, fp->line, fp->filename); + break; + case 1 : + ydpi = xdpi; + break; + } + + // Create the necessary PS commands... + snprintf(command, sizeof(command), + "<</HWResolution[%d %d]/cupsBitsPerColor %d/cupsRowCount %d" + "/cupsRowFeed %d/cupsRowStep %d", + xdpi, ydpi, depth, row_count, row_feed, row_step); + commptr = command + strlen(command); + + if (color_order >= 0) + { + snprintf(commptr, sizeof(command) - (commptr - command), + "/cupsColorOrder %d", color_order); + commptr += strlen(commptr); + } + + if (color_space >= 0) + { + snprintf(commptr, sizeof(command) - (commptr - command), + "/cupsColorSpace %d", color_space); + commptr += strlen(commptr); + } + + if (compression >= 0) + { + snprintf(commptr, sizeof(command) - (commptr - command), + "/cupsCompression %d", compression); + commptr += strlen(commptr); + } + + snprintf(commptr, sizeof(command) - (commptr - command), ">>setpagedevice"); + + // Return the new choice... + return (new ppdcChoice(name, text, command)); +} + + +// +// 'ppdcSource::get_simple_profile()' - Get a simple color profile definition. +// + +ppdcProfile * // O - Color profile +ppdcSource::get_simple_profile(ppdcFile *fp) + // I - File to read +{ + char resolution[1024], // Resolution/media type + *media_type; // Media type + float m[9]; // Transform matrix + float kd, rd, g; // Densities and gamma + float red, green, blue; // RGB adjustments + float yellow; // Yellow density + float color; // Color density values + + + // Get the SimpleColorProfile parameters: + // + // SimpleColorProfile resolution/mediatype black-density yellow-density + // red-density gamma red-adjust green-adjust blue-adjust + if (!get_token(fp, resolution, sizeof(resolution))) + { + fprintf(stderr, "ppdc: Expected resolution/mediatype following SimpleColorProfile on line %d of %s!\n", + fp->line, fp->filename); + return (NULL); + } + + if ((media_type = strchr(resolution, '/')) != NULL) + *media_type++ = '\0'; + else + media_type = resolution; + + // Collect the profile parameters... + kd = get_float(fp); + yellow = get_float(fp); + rd = get_float(fp); + g = get_float(fp); + red = get_float(fp); + green = get_float(fp); + blue = get_float(fp); + + // Build the color profile... + color = 0.5f * rd / kd - kd; + m[0] = 1.0f; // C + m[1] = color + blue; // C + M (blue) + m[2] = color - green; // C + Y (green) + m[3] = color - blue; // M + C (blue) + m[4] = 1.0f; // M + m[5] = color + red; // M + Y (red) + m[6] = yellow * (color + green); // Y + C (green) + m[7] = yellow * (color - red); // Y + M (red) + m[8] = yellow; // Y + + if (m[1] > 0.0f) + { + m[3] -= m[1]; + m[1] = 0.0f; + } + else if (m[3] > 0.0f) + { + m[1] -= m[3]; + m[3] = 0.0f; + } + + if (m[2] > 0.0f) + { + m[6] -= m[2]; + m[2] = 0.0f; + } + else if (m[6] > 0.0f) + { + m[2] -= m[6]; + m[6] = 0.0f; + } + + if (m[5] > 0.0f) + { + m[7] -= m[5]; + m[5] = 0.0f; + } + else if (m[7] > 0.0f) + { + m[5] -= m[7]; + m[7] = 0.0f; + } + + // Return the new profile... + return (new ppdcProfile(resolution, media_type, g, kd, m)); +} + + +// +// 'ppdcSource::get_size()' - Get a media size definition from a file. +// + +ppdcMediaSize * // O - Media size +ppdcSource::get_size(ppdcFile *fp) // I - File to read +{ + char name[1024], // Name + *text; // Text + float width, // Width + length; // Length + + + // Get the name, text, width, and length: + // + // #media name/text width length + if (!get_token(fp, name, sizeof(name))) + return (NULL); + + if ((text = strchr(name, '/')) != NULL) + *text++ = '\0'; + else + text = name; + + if ((width = get_measurement(fp)) < 0.0f) + return (NULL); + + if ((length = get_measurement(fp)) < 0.0f) + return (NULL); + + // Return the new media size... + return (new ppdcMediaSize(name, text, width, length, 0.0f, 0.0f, 0.0f, 0.0f)); +} + + +// +// 'ppdcSource::get_token()' - Get a token from a file. +// + +char * // O - Token string or NULL +ppdcSource::get_token(ppdcFile *fp, // I - File to read + char *buffer, // I - Buffer + int buflen) // I - Length of buffer +{ + char *bufptr, // Pointer into string buffer + *bufend; // End of string buffer + int ch, // Character from file + nextch, // Next char in file + quote, // Quote character used... + empty, // Empty input? + startline; // Start line for quote + char name[256], // Name string + *nameptr; // Name pointer + ppdcVariable *var; // Variable pointer + + + // Mark the beginning and end of the buffer... + bufptr = buffer; + bufend = buffer + buflen - 1; + + // Loop intil we've read a token... + quote = 0; + startline = 0; + empty = 1; + + while ((ch = fp->get()) != EOF) + { + if (isspace(ch) && !quote) + { + if (empty) + continue; + else + break; + } + else if (ch == '$') + { + // Variable substitution + empty = 0; + + for (nameptr = name; (ch = fp->peek()) != EOF;) + { + if (!isalnum(ch) && ch != '_') + break; + else if (nameptr < (name + sizeof(name) - 1)) + *nameptr++ = fp->get(); + } + + if (nameptr == name) + { + // Just substitute this character... + if (ch == '$') + { + // $$ = $ + if (bufptr < bufend) + *bufptr++ = fp->get(); + } + else + { + // $ch = $ch + fprintf(stderr, "ppdc: Bad variable substitution ($%c) on line %d of %s.\n", + ch, fp->line, fp->filename); + + if (bufptr < bufend) + *bufptr++ = '$'; + } + } + else + { + // Substitute the variable value... + *nameptr = '\0'; + var = find_variable(name); + if (var) + { + strncpy(bufptr, var->value->value, bufend - bufptr); + bufptr += strlen(var->value->value); + } + else + { + fprintf(stderr, "ppdc: Undefined variable (%s) on line %d of %s.\n", + name, fp->line, fp->filename); + snprintf(bufptr, bufend - bufptr + 1, "$%s", name); + bufptr += strlen(name) + 1; + } + } + } + else if (ch == '/' && !quote) + { + // Possibly a comment... + nextch = fp->peek(); + + if (nextch == '*') + { + // C comment... + fp->get(); + ch = fp->get(); + while ((nextch = fp->get()) != EOF) + { + if (ch == '*' && nextch == '/') + break; + + ch = nextch; + } + + if (nextch == EOF) + break; + } + else if (nextch == '/') + { + // C++ comment... + while ((nextch = fp->get()) != EOF) + if (nextch == '\n') + break; + + if (nextch == EOF) + break; + } + else + { + // Not a comment... + empty = 0; + + if (bufptr < bufend) + *bufptr++ = ch; + } + } + else if (ch == '\'' || ch == '\"') + { + empty = 0; + + if (quote == ch) + { + // Ending the current quoted string... + quote = 0; + } + else if (quote) + { + // Insert the opposing quote char... + if (bufptr < bufend) + *bufptr++ = ch; + } + else + { + // Start a new quoted string... + startline = fp->line; + quote = ch; + } + } + else if ((ch == '(' || ch == '<') && !quote) + { + empty = 0; + quote = ch; + startline = fp->line; + + if (bufptr < bufend) + *bufptr++ = ch; + } + else if ((ch == ')' && quote == '(') || (ch == '>' && quote == '<')) + { + quote = 0; + + if (bufptr < bufend) + *bufptr++ = ch; + } + else if (ch == '\\') + { + empty = 0; + + if ((ch = fp->get()) == EOF) + break; + + if (bufptr < bufend) + *bufptr++ = ch; + } + else if (bufptr < bufend) + { + empty = 0; + + *bufptr++ = ch; + + if ((ch == '{' || ch == '}') && !quote) + break; + } + } + + if (quote) + { + fprintf(stderr, "ppdc: Unterminated string starting with %c on line %d of %s!\n", + quote, startline, fp->filename); + return (NULL); + } + + if (empty) + return (NULL); + else + { + *bufptr = '\0'; +// puts(buffer); + return (buffer); + } +} + + +// +// 'ppdcSource::get_variable()' - Get a variable definition. +// + +ppdcVariable * // O - Variable +ppdcSource::get_variable(ppdcFile *fp) // I - File to read +{ + char name[1024], // Name + value[1024]; // Value + + + // Get the name and value: + // + // #define name value + if (!get_token(fp, name, sizeof(name))) + return (NULL); + + if (!get_token(fp, value, sizeof(value))) + return (NULL); + + // Set the variable... + return (set_variable(name, value)); +} + + +// +// 'ppdcSource::quotef()' - Write a formatted, quoted string... +// + +int // O - Number bytes on success, -1 on failure +ppdcSource::quotef(cups_file_t *fp, // I - File to write to + const char *format, // I - Printf-style format string + ...) // I - Additional args as needed +{ + va_list ap; // Pointer to additional arguments + int bytes; // Bytes written + char sign, // Sign of format width + size, // Size character (h, l, L) + type; // Format type character + const char *bufformat; // Start of format + int width, // Width of field + prec; // Number of characters of precision + char tformat[100]; // Temporary format string for fprintf() + char *s; // Pointer to string + int slen; // Length of string + int i; // Looping var + + + // Range check input... + if (!fp || !format) + return (-1); + + // Loop through the format string, formatting as needed... + va_start(ap, format); + + bytes = 0; + + while (*format) + { + if (*format == '%') + { + bufformat = format; + format ++; + + if (*format == '%') + { + cupsFilePutChar(fp, *format++); + bytes ++; + continue; + } + else if (strchr(" -+#\'", *format)) + sign = *format++; + else + sign = 0; + + width = 0; + while (isdigit(*format)) + width = width * 10 + *format++ - '0'; + + if (*format == '.') + { + format ++; + prec = 0; + + while (isdigit(*format)) + prec = prec * 10 + *format++ - '0'; + } + else + prec = -1; + + if (*format == 'l' && format[1] == 'l') + { + size = 'L'; + format += 2; + } + else if (*format == 'h' || *format == 'l' || *format == 'L') + size = *format++; + + if (!*format) + break; + + type = *format++; + + switch (type) + { + case 'E' : // Floating point formats + case 'G' : + case 'e' : + case 'f' : + case 'g' : + if ((format - bufformat + 1) > (int)sizeof(tformat)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + bytes += cupsFilePrintf(fp, tformat, va_arg(ap, double)); + break; + + case 'B' : // Integer formats + case 'X' : + case 'b' : + case 'd' : + case 'i' : + case 'o' : + case 'u' : + case 'x' : + if ((format - bufformat + 1) > (int)sizeof(tformat)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int)); + break; + + case 'p' : // Pointer value + if ((format - bufformat + 1) > (int)sizeof(tformat)) + break; + + strncpy(tformat, bufformat, format - bufformat); + tformat[format - bufformat] = '\0'; + + bytes += cupsFilePrintf(fp, tformat, va_arg(ap, void *)); + break; + + case 'c' : // Character or character array + if (width <= 1) + { + bytes ++; + cupsFilePutChar(fp, va_arg(ap, int)); + } + else + { + cupsFileWrite(fp, va_arg(ap, char *), width); + bytes += width; + } + break; + + case 's' : // String + if ((s = va_arg(ap, char *)) == NULL) + s = (char *)"(nil)"; + + slen = strlen(s); + if (slen > width && prec != width) + width = slen; + + if (slen > width) + slen = width; + + if (sign != '-') + { + for (i = width - slen; i > 0; i --, bytes ++) + cupsFilePutChar(fp, ' '); + } + + for (i = slen; i > 0; i --, s ++, bytes ++) + { + if (*s == '\\' || *s == '\"') + { + cupsFilePutChar(fp, '\\'); + bytes ++; + } + + cupsFilePutChar(fp, *s); + } + + if (sign == '-') + { + for (i = width - slen; i > 0; i --, bytes ++) + cupsFilePutChar(fp, ' '); + } + break; + } + } + else + { + cupsFilePutChar(fp, *format++); + bytes ++; + } + } + + va_end(ap); + + // Return the number of characters written. + return (bytes); +} + + +// +// 'ppdcSource::read_file()' - Read a driver source file. +// + +void +ppdcSource::read_file(const char *f) // I - File to read +{ + ppdcFile *fp = new ppdcFile(f); + scan_file(fp); + delete fp; +} + + +// +// 'ppdcSource::scan_file()' - Scan a driver source file. +// + +void +ppdcSource::scan_file(ppdcFile *fp, // I - File to read + ppdcDriver *td, // I - Driver template + bool inc) // I - Including? +{ + ppdcDriver *d; // Current driver + ppdcGroup *g, // Current group + *general, // General options group + *install; // Installable options group + ppdcOption *o; // Current option + ppdcChoice *c; // Current choice + char temp[256], // Token from file... + *ptr; // Pointer into token + int isdefault; // Default option? + + + // Initialize things as needed... + if (inc && td) + d = td; + else + d = new ppdcDriver(td); + + if ((general = d->find_group("General")) == NULL) + { + general = new ppdcGroup("General", NULL); + d->add_group(general); + } + + if ((install = d->find_group("InstallableOptions")) == NULL) + { + install = new ppdcGroup("InstallableOptions", "Installable Options"); + d->add_group(install); + } + + // Loop until EOF or } + o = 0; + g = general; + while (get_token(fp, temp, sizeof(temp))) + { + if (temp[0] == '*') + { + // Mark the next choice as the default + isdefault = 1; + + for (ptr = temp; ptr[1]; ptr ++) + *ptr = ptr[1]; + + *ptr = '\0'; + } + else + { + // Don't mark the next choice as the default + isdefault = 0; + } + + if (!strcasecmp(temp, "}")) + { + // Close this one out... + break; + } + else if (!strcasecmp(temp, "{")) + { + // Open a new child... + scan_file(fp, d); + } + else if (!strcasecmp(temp, "#define")) + { + // Get the variable... + get_variable(fp); + } + else if (!strcasecmp(temp, "#include")) + { + // #include filename + char basedir[1024], // Base directory + *baseptr, // Pointer into directory + inctemp[1024], // Initial filename + incname[1024]; // Include filename + ppdcFile *incfile; // Include file + + + // Get the include name... + if (!get_token(fp, inctemp, sizeof(inctemp))) + { + fprintf(stderr, "ppdc: Expected include filename on line %d of %s!\n", + fp->line, fp->filename); + break; + } + + // Figure out the current directory... + strlcpy(basedir, fp->filename, sizeof(basedir)); + + if ((baseptr = strrchr(basedir, '/')) != NULL) + *baseptr = '\0'; + else + strcpy(basedir, "."); + + // Find the include file... + if (find_include(inctemp, basedir, incname, sizeof(incname))) + { + // Open the include file, scan it, and then close it... + incfile = new ppdcFile(incname); + scan_file(incfile, d, true); + delete incfile; + } + else + { + // Can't find it! + fprintf(stderr, + "ppdc: Unable to find include file \"%s\" on line %d of %s!\n", + inctemp, fp->line, fp->filename); + break; + } + } + else if (!strcasecmp(temp, "#media")) + { + ppdcMediaSize *m; // Media size + + + // Get a media size... + m = get_size(fp); + if (m) + sizes->add(m); + } + else if (!strcasecmp(temp, "#po")) + { + ppdcCatalog *cat; // Message catalog + + + // Get a message catalog... + cat = get_po(fp); + if (cat) + po_files->add(cat); + } + else if (!strcasecmp(temp, "Attribute")) + { + ppdcAttr *a; // Attribute + + + // Get an attribute... + a = get_attr(fp); + if (a) + d->add_attr(a); + } + else if (!strcasecmp(temp, "Choice")) + { + // Get a choice... + if (!o) + { + fprintf(stderr, "ppdc: Choice found on line %d of %s with no Option!\n", + fp->line, fp->filename); + break; + } + + c = get_choice(fp); + if (!c) + break; + + // Add it to the current option... + o->add_choice(c); + + if (isdefault) + o->set_defchoice(c); + } + else if (!strcasecmp(temp, "ColorDevice")) + { + // ColorDevice boolean + d->color_device = get_boolean(fp); + } + else if (!strcasecmp(temp, "ColorModel")) + { + // Get the color model + c = get_color_model(fp); + if (!c) + continue; + + // Add the choice to the ColorModel option... + if ((o = d->find_option("ColorModel")) == NULL) + { + // Create the ColorModel option... + o = new ppdcOption(PPDC_PICKONE, "ColorModel", "Color Mode", PPDC_SECTION_ANY, 10.0f); + g = general; + g->add_option(o); + } + + o->add_choice(c); + + if (isdefault) + o->set_defchoice(c); + + o = NULL; + } + else if (!strcasecmp(temp, "ColorProfile")) + { + ppdcProfile *p; // Color profile + + + // Get the color profile... + p = get_color_profile(fp); + + if (p) + d->profiles->add(p); + } + else if (!strcasecmp(temp, "Copyright")) + { + // Copyright string + char copytemp[8192], // Copyright string + *copyptr, // Pointer into string + *copyend; // Pointer to end of string + + + // Get the copyright string... + if (!get_token(fp, copytemp, sizeof(temp))) + { + fprintf(stderr, + "ppdc: Expected string after Copyright on line %d of %s!\n", + fp->line, fp->filename); + break; + } + + // Break it up into individual lines... + for (copyptr = copytemp; copyptr; copyptr = copyend) + { + if ((copyend = strchr(copyptr, '\n')) != NULL) + *copyend++ = '\0'; + + d->copyright->add(new ppdcString(copyptr)); + } + } + else if (!strcasecmp(temp, "CustomMedia")) + { + ppdcMediaSize *m; // Media size + + + // Get a custom media size... + m = get_custom_size(fp); + if (m) + d->sizes->add(m); + + if (isdefault) + d->set_default_size(m); + } + else if (!strcasecmp(temp, "Cutter")) + { + // Cutter boolean + int have_cutter; // Have a paper cutter? + + + have_cutter = get_boolean(fp); + if (have_cutter <= 0) + continue; + + if ((o = d->find_option("CutMedia")) == NULL) + { + o = new ppdcOption(PPDC_BOOLEAN, "CutMedia", "Cut Media", PPDC_SECTION_ANY, 10.0f); + + g = general; + g->add_option(o); + + c = new ppdcChoice("False", NULL, "<</CutMedia 0>>setpagedevice"); + o->add_choice(c); + o->set_defchoice(c); + + c = new ppdcChoice("True", NULL, "<</CutMedia 4>>setpagedevice"); + o->add_choice(c); + } + + o = NULL; + } + else if (!strcasecmp(temp, "Darkness")) + { + // Get the darkness choice... + c = get_generic(fp, "Darkness", NULL, "cupsCompression"); + if (!c) + continue; + + // Add the choice to the cupsDarkness option... + if ((o = d->find_option("cupsDarkness")) == NULL) + { + // Create the cupsDarkness option... + o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f); + g = general; + g->add_option(o); + } + + o->add_choice(c); + + if (isdefault) + o->set_defchoice(c); + + o = NULL; + } + else if (!strcasecmp(temp, "DriverType")) + { + int i; // Looping var + + + // DriverType keyword + if (!get_token(fp, temp, sizeof(temp))) + { + fprintf(stderr, "ppdc: Expected driver type keyword following DriverType on line %d of %s!\n", + fp->line, fp->filename); + continue; + } + + for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++) + if (!strcasecmp(temp, driver_types[i])) + break; + + if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0]))) + d->type = (ppdcDrvType)i; + else if (!strcasecmp(temp, "dymo")) + d->type = PPDC_DRIVER_LABEL; + else + fprintf(stderr, "ppdc: Unknown driver type %s on line %d of %s!\n", + temp, fp->line, fp->filename); + } + else if (!strcasecmp(temp, "Duplex")) + get_duplex(fp, d); + else if (!strcasecmp(temp, "Filter")) + { + ppdcFilter *f; // Filter + + + // Get the filter value... + f = get_filter(fp); + if (f) + d->filters->add(f); + } + else if (!strcasecmp(temp, "Finishing")) + { + // Get the finishing choice... + c = get_generic(fp, "Finishing", "OutputType", NULL); + if (!c) + continue; + + // Add the choice to the cupsFinishing option... + if ((o = d->find_option("cupsFinishing")) == NULL) + { + // Create the cupsFinishing option... + o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f); + g = general; + g->add_option(o); + } + + o->add_choice(c); + + if (isdefault) + o->set_defchoice(c); + + o = NULL; + } + else if (!strcasecmp(temp, "Font") || + !strcasecmp(temp, "#font")) + { + ppdcFont *f; // Font + + + // Get a font... + f = get_font(fp); + if (f) + { + if (!strcasecmp(temp, "#font")) + base_fonts->add(f); + else + d->add_font(f); + + if (isdefault) + d->set_default_font(f); + } + } + else if (!strcasecmp(temp, "Group")) + { + // Get a group... + g = get_group(fp, d); + if (!g) + break; + } + else if (!strcasecmp(temp, "HWMargins")) + { + // HWMargins left bottom right top + d->left_margin = get_measurement(fp); + d->bottom_margin = get_measurement(fp); + d->right_margin = get_measurement(fp); + d->top_margin = get_measurement(fp); + } + else if (!strcasecmp(temp, "InputSlot")) + { + // Get the input slot choice... + c = get_generic(fp, "InputSlot", NULL, "MediaPosition"); + if (!c) + continue; + + // Add the choice to the InputSlot option... + if ((o = d->find_option("InputSlot")) == NULL) + { + // Create the InputSlot option... + o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source", + PPDC_SECTION_ANY, 10.0f); + g = general; + g->add_option(o); + } + + o->add_choice(c); + + if (isdefault) + o->set_defchoice(c); + + o = NULL; + } + else if (!strcasecmp(temp, "Installable")) + { + // Get the installable option... + o = get_installable(fp); + + // Add it as needed... + if (o) + { + install->add_option(o); + o = NULL; + } + } + else if (!strcasecmp(temp, "ManualCopies")) + { + // ManualCopies boolean + d->manual_copies = get_boolean(fp); + } + else if (!strcasecmp(temp, "Manufacturer")) + { + // Manufacturer name + char name[256]; // Model name string + + + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name after Manufacturer on line %d of %s!\n", + fp->line, fp->filename); + break; + } + + d->set_manufacturer(name); + } + else if (!strcasecmp(temp, "MaxSize")) + { + // MaxSize width length + d->max_width = get_measurement(fp); + d->max_length = get_measurement(fp); + } + else if (!strcasecmp(temp, "MediaSize")) + { + // MediaSize keyword + char name[41]; // Media size name + ppdcMediaSize *m, // Matching media size... + *dm; // Driver media size... + + + if (get_token(fp, name, sizeof(name)) == NULL) + { + fprintf(stderr, "ppdc: Expected name after MediaSize on line %d of %s!\n", + fp->line, fp->filename); + break; + } + + m = find_size(name); + + if (!m) + { + fprintf(stderr, "ppdc: Unknown media size \"%s\" on line %d of %s!\n", + name, fp->line, fp->filename); + break; + } + + // Add this size to the driver... + dm = new ppdcMediaSize(m->name->value, m->text->value, + m->width, m->length, d->left_margin, + d->bottom_margin, d->right_margin, + d->top_margin); + d->sizes->add(dm); + + if (isdefault) + d->set_default_size(dm); + } + else if (!strcasecmp(temp, "MediaType")) + { + // Get the media type choice... + c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType"); + if (!c) + continue; + + // Add the choice to the MediaType option... + if ((o = d->find_option("MediaType")) == NULL) + { + // Create the MediaType option... + o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type", + PPDC_SECTION_ANY, 10.0f); + g = general; + g->add_option(o); + } + + o->add_choice(c); + + if (isdefault) + o->set_defchoice(c); + + o = NULL; + } + else if (!strcasecmp(temp, "MinSize")) + { + // MinSize width length + d->min_width = get_measurement(fp); + d->min_length = get_measurement(fp); + } + else if (!strcasecmp(temp, "ModelName")) + { + // ModelName name + char name[256]; // Model name string + + + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name after ModelName on line %d of %s!\n", + fp->line, fp->filename); + break; + } + + d->set_model_name(name); + } + else if (!strcasecmp(temp, "ModelNumber")) + { + // ModelNumber number + d->model_number = get_integer(fp); + } + else if (!strcasecmp(temp, "Option")) + { + // Get an option... + o = get_option(fp, d, g); + if (!o) + break; + } + else if (!strcasecmp(temp, "PCFileName")) + { + // PCFileName name + char name[256]; // Model name string + + + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected name after PCFileName on line %d of %s!\n", + fp->line, fp->filename); + break; + } + + d->set_pc_file_name(name); + } + else if (!strcasecmp(temp, "Resolution")) + { + // Get the resolution choice... + c = get_resolution(fp); + if (!c) + continue; + + // Add the choice to the Resolution option... + if ((o = d->find_option("Resolution")) == NULL) + { + // Create the Resolution option... + o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY, 10.0f); + g = general; + g->add_option(o); + } + + o->add_choice(c); + + if (isdefault) + o->set_defchoice(c); + + o = NULL; + } + else if (!strcasecmp(temp, "SimpleColorProfile")) + { + ppdcProfile *p; // Color profile + + + // Get the color profile... + p = get_simple_profile(fp); + + if (p) + d->profiles->add(p); + } + else if (!strcasecmp(temp, "Throughput")) + { + // Throughput number + d->throughput = get_integer(fp); + } + else if (!strcasecmp(temp, "UIConstraints")) + { + ppdcConstraint *con; // Constraint + + + con = get_constraint(fp); + + if (con) + d->constraints->add(con); + } + else if (!strcasecmp(temp, "VariablePaperSize")) + { + // VariablePaperSize boolean + d->variable_paper_size = get_boolean(fp); + } + else if (!strcasecmp(temp, "Version")) + { + // Version string + char name[256]; // Model name string + + + if (!get_token(fp, name, sizeof(name))) + { + fprintf(stderr, "ppdc: Expected string after Version on line %d of %s!\n", + fp->line, fp->filename); + break; + } + + d->set_version(name); + } + else + { + fprintf(stderr, "ppdc: Unknown token \"%s\" seen on line %d of %s!\n", + temp, fp->line, fp->filename); + break; + } + } + + // Done processing this block, is there anything to save? + if (!inc) + { + if (!d->pc_file_name || !d->model_name || !d->manufacturer || !d->version || + !d->sizes->count) + { + // Nothing to save... + d->release(); + } + else + { + // Got a driver, save it... + drivers->add(d); + } + } +} + + +// +// 'ppdcSource::set_variable()' - Set a variable. +// + +ppdcVariable * // O - Variable +ppdcSource::set_variable( + const char *name, // I - Name + const char *value) // I - Value +{ + ppdcVariable *v; // Variable + + + // See if the variable exists already... + v = find_variable(name); + if (v) + { + // Change the variable value... + v->set_value(value); + } + else + { + // Create a new variable and add it... + v = new ppdcVariable(name, value); + vars->add(v); + } + + return (v); +} + + +// +// 'ppdcSource::write_file()' - Write the current source data to a file. +// + +int // O - 0 on success, -1 on error +ppdcSource::write_file(const char *f) // I - File to write +{ + cups_file_t *fp; // Output file + char bckname[1024]; // Backup file + ppdcDriver *d; // Current driver + ppdcString *st; // Current string + ppdcAttr *a; // Current attribute + ppdcConstraint *co; // Current constraint + ppdcFilter *fi; // Current filter + ppdcFont *fo; // Current font + ppdcGroup *g; // Current group + ppdcOption *o; // Current option + ppdcChoice *ch; // Current choice + ppdcProfile *p; // Current color profile + ppdcMediaSize *si; // Current media size + float left, // Current left margin + bottom, // Current bottom margin + right, // Current right margin + top; // Current top margin + int dtused[PPDC_DRIVER_MAX];// Driver type usage... + + + // Rename the current file, if any, to .bck... + snprintf(bckname, sizeof(bckname), "%s.bck", f); + rename(f, bckname); + + // Open the output file... + fp = cupsFileOpen(f, "w"); + + if (!fp) + { + // Can't create file; restore backup and return... + rename(bckname, f); + return (-1); + } + + cupsFilePuts(fp, "// CUPS PPD Compiler " CUPS_SVERSION "\n\n"); + + // Include standard files... + cupsFilePuts(fp, "// Include necessary files...\n"); + cupsFilePuts(fp, "#include <font.defs>\n"); + cupsFilePuts(fp, "#include <media.defs>\n"); + + memset(dtused, 0, sizeof(dtused)); + + for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next()) + if (d->type > PPDC_DRIVER_PS && !dtused[d->type]) + { + cupsFilePrintf(fp, "#include <%s.h>\n", driver_types[d->type]); + dtused[d->type] = 1; + } + + // Output each driver... + for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next()) + { + // Start the driver... + cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value, d->model_name->value); + cupsFilePuts(fp, "{\n"); + + // Write the copyright stings... + for (st = (ppdcString *)d->copyright->first(); + st; + st = (ppdcString *)d->copyright->next()) + quotef(fp, " Copyright \"%s\"\n", st->value); + + // Write other strings and values... + if (d->manufacturer->value) + quotef(fp, " Manufacturer \"%s\"\n", d->manufacturer->value); + if (d->model_name->value) + quotef(fp, " ModelName \"%s\"\n", d->model_name->value); + if (d->pc_file_name->value) + quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value); + if (d->version->value) + quotef(fp, " Version \"%s\"\n", d->version->value); + + cupsFilePrintf(fp, " DriverType %s\n", driver_types[d->type]); + + if (d->model_number) + { + switch (d->type) + { + case PPDC_DRIVER_ESCP : + cupsFilePuts(fp, " ModelNumber ("); + + if (d->model_number & ESCP_DOTMATRIX) + cupsFilePuts(fp, " $ESCP_DOTMATRIX"); + if (d->model_number & ESCP_MICROWEAVE) + cupsFilePuts(fp, " $ESCP_MICROWEAVE"); + if (d->model_number & ESCP_STAGGER) + cupsFilePuts(fp, " $ESCP_STAGGER"); + if (d->model_number & ESCP_ESCK) + cupsFilePuts(fp, " $ESCP_ESCK"); + if (d->model_number & ESCP_EXT_UNITS) + cupsFilePuts(fp, " $ESCP_EXT_UNITS"); + if (d->model_number & ESCP_EXT_MARGINS) + cupsFilePuts(fp, " $ESCP_EXT_MARGINS"); + if (d->model_number & ESCP_USB) + cupsFilePuts(fp, " $ESCP_USB"); + if (d->model_number & ESCP_PAGE_SIZE) + cupsFilePuts(fp, " $ESCP_PAGE_SIZE"); + if (d->model_number & ESCP_RASTER_ESCI) + cupsFilePuts(fp, " $ESCP_RASTER_ESCI"); + if (d->model_number & ESCP_REMOTE) + cupsFilePuts(fp, " $ESCP_REMOTE"); + + cupsFilePuts(fp, ")\n"); + break; + + case PPDC_DRIVER_PCL : + cupsFilePuts(fp, " ModelNumber ("); + + if (d->model_number & PCL_PAPER_SIZE) + cupsFilePuts(fp, " $PCL_PAPER_SIZE"); + if (d->model_number & PCL_INKJET) + cupsFilePuts(fp, " $PCL_INKJET"); + if (d->model_number & PCL_RASTER_END_COLOR) + cupsFilePuts(fp, " $PCL_RASTER_END_COLOR"); + if (d->model_number & PCL_RASTER_CID) + cupsFilePuts(fp, " $PCL_RASTER_CID"); + if (d->model_number & PCL_RASTER_CRD) + cupsFilePuts(fp, " $PCL_RASTER_CRD"); + if (d->model_number & PCL_RASTER_SIMPLE) + cupsFilePuts(fp, " $PCL_RASTER_SIMPLE"); + if (d->model_number & PCL_RASTER_RGB24) + cupsFilePuts(fp, " $PCL_RASTER_RGB24"); + if (d->model_number & PCL_PJL) + cupsFilePuts(fp, " $PCL_PJL"); + if (d->model_number & PCL_PJL_PAPERWIDTH) + cupsFilePuts(fp, " $PCL_PJL_PAPERWIDTH"); + if (d->model_number & PCL_PJL_HPGL2) + cupsFilePuts(fp, " $PCL_PJL_HPGL2"); + if (d->model_number & PCL_PJL_PCL3GUI) + cupsFilePuts(fp, " $PCL_PJL_PCL3GUI"); + if (d->model_number & PCL_PJL_RESOLUTION) + cupsFilePuts(fp, " $PCL_PJL_RESOLUTION"); + + cupsFilePuts(fp, ")\n"); + break; + + case PPDC_DRIVER_LABEL : + cupsFilePuts(fp, " ModelNumber "); + + switch (d->model_number) + { + case DYMO_3x0 : + cupsFilePuts(fp, "$DYMO_3x0\n"); + break; + + case ZEBRA_EPL_LINE : + cupsFilePuts(fp, "$ZEBRA_EPL_LINE\n"); + break; + + case ZEBRA_EPL_PAGE : + cupsFilePuts(fp, "$ZEBRA_EPL_PAGE\n"); + break; + + case ZEBRA_ZPL : + cupsFilePuts(fp, "$ZEBRA_ZPL\n"); + break; + + case ZEBRA_CPCL : + cupsFilePuts(fp, "$ZEBRA_CPCL\n"); + break; + + case INTELLITECH_PCL : + cupsFilePuts(fp, "$INTELLITECH_PCL\n"); + break; + + default : + cupsFilePrintf(fp, "%d\n", d->model_number); + break; + } + break; + + case PPDC_DRIVER_EPSON : + cupsFilePuts(fp, " ModelNumber "); + + switch (d->model_number) + { + case EPSON_9PIN : + cupsFilePuts(fp, "$EPSON_9PIN\n"); + break; + + case EPSON_24PIN : + cupsFilePuts(fp, "$EPSON_24PIN\n"); + break; + + case EPSON_COLOR : + cupsFilePuts(fp, "$EPSON_COLOR\n"); + break; + + case EPSON_PHOTO : + cupsFilePuts(fp, "$EPSON_PHOTO\n"); + break; + + case EPSON_ICOLOR : + cupsFilePuts(fp, "$EPSON_ICOLOR\n"); + break; + + case EPSON_IPHOTO : + cupsFilePuts(fp, "$EPSON_IPHOTO\n"); + break; + + default : + cupsFilePrintf(fp, "%d\n", d->model_number); + break; + } + break; + + case PPDC_DRIVER_HP : + cupsFilePuts(fp, " ModelNumber "); + switch (d->model_number) + { + case HP_LASERJET : + cupsFilePuts(fp, "$HP_LASERJET\n"); + break; + + case HP_DESKJET : + cupsFilePuts(fp, "$HP_DESKJET\n"); + break; + + case HP_DESKJET2 : + cupsFilePuts(fp, "$HP_DESKJET2\n"); + break; + + default : + cupsFilePrintf(fp, "%d\n", d->model_number); + break; + } + + cupsFilePuts(fp, ")\n"); + break; + + default : + cupsFilePrintf(fp, " ModelNumber %d\n", d->model_number); + break; + } + } + + if (d->manual_copies) + cupsFilePuts(fp, " ManualCopies Yes\n"); + + if (d->color_device) + cupsFilePuts(fp, " ColorDevice Yes\n"); + + if (d->throughput) + cupsFilePrintf(fp, " Throughput %d\n", d->throughput); + + // Output all of the attributes... + for (a = (ppdcAttr *)d->attrs->first(); + a; + a = (ppdcAttr *)d->attrs->next()) + if (a->text->value && a->text->value[0]) + quotef(fp, " Attribute \"%s\" \"%s/%s\" \"%s\"\n", + a->name->value, a->selector->value ? a->selector->value : "", + a->text->value, a->value->value ? a->value->value : ""); + else + quotef(fp, " Attribute \"%s\" \"%s\" \"%s\"\n", + a->name->value, a->selector->value ? a->selector->value : "", + a->value->value ? a->value->value : ""); + + // Output all of the constraints... + for (co = (ppdcConstraint *)d->constraints->first(); + co; + co = (ppdcConstraint *)d->constraints->next()) + { + if (co->option1->value[0] == '*') + cupsFilePrintf(fp, " UIConstraints \"%s %s", co->option1->value, + co->choice1->value ? co->choice1->value : ""); + else + cupsFilePrintf(fp, " UIConstraints \"*%s %s", co->option1->value, + co->choice1->value ? co->choice1->value : ""); + + if (co->option2->value[0] == '*') + cupsFilePrintf(fp, " %s %s\"\n", co->option2->value, + co->choice2->value ? co->choice2->value : ""); + else + cupsFilePrintf(fp, " *%s %s\"\n", co->option2->value, + co->choice2->value ? co->choice2->value : ""); + } + + // Output all of the filters... + for (fi = (ppdcFilter *)d->filters->first(); + fi; + fi = (ppdcFilter *)d->filters->next()) + cupsFilePrintf(fp, " Filter \"%s %d %s\"\n", + fi->mime_type->value, fi->cost, fi->program->value); + + // Output all of the fonts... + for (fo = (ppdcFont *)d->fonts->first(); + fo; + fo = (ppdcFont *)d->fonts->next()) + if (!strcmp(fo->name->value, "*")) + cupsFilePuts(fp, " Font *\n"); + else + cupsFilePrintf(fp, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n", + fo->name->value, fo->encoding->value, + fo->version->value, fo->charset->value, + fo->status == PPDC_FONT_ROM ? "ROM" : "Disk"); + + // Output all options... + for (g = (ppdcGroup *)d->groups->first(); + g; + g = (ppdcGroup *)d->groups->next()) + { + if (g->options->count == 0) + continue; + + if (g->text->value && g->text->value[0]) + quotef(fp, " Group \"%s/%s\"\n", g->name->value, g->text->value); + else + cupsFilePrintf(fp, " Group \"%s\"\n", g->name->value); + + for (o = (ppdcOption *)g->options->first(); + o; + o = (ppdcOption *)g->options->next()) + { + if (o->choices->count == 0) + continue; + + if (o->text->value && o->text->value[0]) + quotef(fp, " Option \"%s/%s\"", o->name->value, o->text->value); + else + cupsFilePrintf(fp, " Option \"%s\"", o->name->value); + + cupsFilePrintf(fp, " %s %s %.1f\n", + o->type == PPDC_BOOLEAN ? "Boolean" : + o->type == PPDC_PICKONE ? "PickOne" : "PickMany", + o->section == PPDC_SECTION_ANY ? "AnySetup" : + o->section == PPDC_SECTION_DOCUMENT ? "DocumentSetup" : + o->section == PPDC_SECTION_EXIT ? "ExitServer" : + o->section == PPDC_SECTION_JCL ? "JCLSetup" : + o->section == PPDC_SECTION_PAGE ? "PageSetup" : + "Prolog", + o->order); + + for (ch = (ppdcChoice *)o->choices->first(); + ch; + ch = (ppdcChoice *)o->choices->next()) + { + if (ch->text->value && ch->text->value[0]) + quotef(fp, " %sChoice \"%s/%s\" \"%s\"\n", + o->defchoice == ch->name ? "*" : "", + ch->name->value, ch->text->value, + ch->code->value ? ch->code->value : ""); + else + quotef(fp, " %sChoice \"%s\" \"%s\"\n", + o->defchoice == ch->name ? "*" : "", + ch->name->value, + ch->code->value ? ch->code->value : ""); + } + } + } + + // Output all of the color profiles... + for (p = (ppdcProfile *)d->profiles->first(); + p; + p = (ppdcProfile *)d->profiles->next()) + cupsFilePrintf(fp, " ColorProfile \"%s/%s\" %.3f %.3f " + "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n", + p->resolution->value, p->media_type->value, + p->density, p->gamma, + p->profile[0], p->profile[1], p->profile[2], + p->profile[3], p->profile[4], p->profile[5], + p->profile[6], p->profile[7], p->profile[8]); + + // Output all of the media sizes... + left = 0.0; + bottom = 0.0; + right = 0.0; + top = 0.0; + + for (si = (ppdcMediaSize *)d->sizes->first(); + si; + si = (ppdcMediaSize *)d->sizes->next()) + if (si->size_code->value && si->region_code->value) + { + // Output a custom media size... + quotef(fp, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n", + si->name == d->default_size ? "*" : "", si->name->value, + si->text->value, si->width, si->length, si->left, si->bottom, + si->right, si->top, si->size_code->value, + si->region_code->value); + } + else + { + // Output a standard media size... + if (fabs(left - si->left) > 0.1 || + fabs(bottom - si->bottom) > 0.1 || + fabs(right - si->right) > 0.1 || + fabs(top - si->top) > 0.1) + { + cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n", + si->left, si->bottom, si->right, si->top); + + left = si->left; + bottom = si->bottom; + right = si->right; + top = si->top; + } + + cupsFilePrintf(fp, " %sMediaSize %s\n", + si->name == d->default_size ? "*" : "", + si->name->value); + } + + if (d->variable_paper_size) + { + cupsFilePuts(fp, " VariablePaperSize Yes\n"); + + if (fabs(left - d->left_margin) > 0.1 || + fabs(bottom - d->bottom_margin) > 0.1 || + fabs(right - d->right_margin) > 0.1 || + fabs(top - d->top_margin) > 0.1) + { + cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n", + d->left_margin, d->bottom_margin, d->right_margin, + d->top_margin); + } + + cupsFilePrintf(fp, " MinSize %.2f %.2f\n", d->min_width, d->min_length); + cupsFilePrintf(fp, " MaxSize %.2f %.2f\n", d->max_width, d->max_length); + } + + // End the driver... + cupsFilePuts(fp, "}\n"); + } + + // Close the file and return... + cupsFileClose(fp); + + return (0); +} + + +// +// End of "$Id$". +// |