libcupsfilters.pc \
libppd.pc \
libfontembed.pc
+if ENABLE_LIBPPDC
+pkgconf_DATA += \
+ libppdc.pc
+endif
doc_DATA = \
ABOUT-NLS \
ln-srf \
libcupsfilters.pc.in \
libppd.pc.in \
+ libppdc.pc.in \
libfontembed.pc.in \
utils/cups-browsed.service \
utils/cups-browsed-upstart.conf \
data/unclassified.ps \
drv/custom-media-lines
+# =========
+# utilities
+# =========
+
+pkgutilsdir = $(bindir)
+pkgutils_PROGRAMS =
+
# ========
# Backends
# ========
ppd/test2.ppd \
ppd/README.md
+# ===========================
+# PPDC legacy support library
+# ===========================
+pkgppdcincludefiles = \
+ ppdc/ppdc.h
+
+pkgppdcdefsfiles = \
+ ppdc/epson.h \
+ ppdc/hp.h \
+ ppdc/label.h \
+ ppdc/font.defs \
+ ppdc/media.defs \
+ ppdc/raster.defs
+
+if ENABLE_LIBPPDC
+pkgppdcincludedir = $(includedir)/ppdc
+pkgppdcinclude_DATA = \
+ $(pkgppdcincludefiles)
+pkgppdcdefsdir = $(datadir)/ppdc
+pkgppdcdefs_DATA = \
+ $(pkgppdcdefsfiles)
+lib_LTLIBRARIES += libppdc.la
+endif
+
+libppdc_la_SOURCES = \
+ ppdc/ppdc-array.cxx \
+ ppdc/ppdc-attr.cxx \
+ ppdc/ppdc-catalog.cxx \
+ ppdc/ppdc-choice.cxx \
+ ppdc/ppdc-constraint.cxx \
+ ppdc/ppdc-driver.cxx \
+ ppdc/ppdc-file.cxx \
+ ppdc/ppdc-filter.cxx \
+ ppdc/ppdc-font.cxx \
+ ppdc/ppdc-group.cxx \
+ ppdc/ppdc-import.cxx \
+ ppdc/ppdc-mediasize.cxx \
+ ppdc/ppdc-message.cxx \
+ ppdc/ppdc-option.cxx \
+ ppdc/ppdc-private.h \
+ ppdc/ppdc-profile.cxx \
+ ppdc/ppdc-shared.cxx \
+ ppdc/ppdc-source.cxx \
+ ppdc/ppdc-string.cxx \
+ ppdc/ppdc-variable.cxx \
+ $(pkgppdcincludefiles) \
+ $(pkgppdcdefsfiles)
+libppdc_la_LIBADD = \
+ libcupsfilters.la \
+ libppd.la \
+ $(CUPS_LIBS)
+libppdc_la_CFLAGS = \
+ -I$(srcdir)/cupsfilters/ \
+ -I$(srcdir)/ppd/ \
+ $(CUPS_CFLAGS)
+libppdc_la_LDFLAGS = \
+ -no-undefined \
+ -version-info 1
+
+EXTRA_DIST += \
+ $(pkgppdcincludefiles) \
+ $(pkgppdcdefsfiles)
+
+if ENABLE_PPDC
+pkgutils_PROGRAMS += \
+ drv2ppd
+endif
+
+drv2ppd_SOURCES = \
+ ppdc/drv2ppd.cxx
+drv2ppd_LDADD = \
+ libppdc.la \
+ $(CUPS_LIBS)
+drv2ppd_CFLAGS = \
+ -I$(srcdir)/ppdc/ \
+ $(CUPS_CFLAGS)
+
# =================
# Fontembed library
# =================
$(LN_SRF) $(DESTDIR)$(pkgppdgendir)/driverless-fax $(DESTDIR)$(bindir)
$(LN_SRF) $(DESTDIR)$(pkgppdgendir)/driverless-fax $(DESTDIR)$(pkgbackenddir)
endif
+if ENABLE_LIBPPDC
+if ENABLE_PPDC
+ $(LN_SRF) $(DESTDIR)$(bindir)/drv2ppd $(DESTDIR)$(bindir)/ppdc
+endif
+endif
if ENABLE_BRAILLE
$(LN_S) -f imagetobrf $(DESTDIR)$(pkgfilterdir)/imagetoubrl
$(LN_S) -f vectortopdf $(DESTDIR)$(pkgfilterdir)/svgtopdf
$(RM) $(DESTDIR)$(bindir)/driverless-fax
$(RM) $(DESTDIR)$(pkgbackenddir)/driverless-fax
endif
+if ENABLE_LIBPPDC
+if ENABLE_PPDC
+ $(RM) $(DESTDIR)$(bindir)/ppdc
+endif
+endif
if ENABLE_BRAILLE
$(RM) $(DESTDIR)$(pkgfilterdir)/imagetoubrl
$(RM) $(DESTDIR)$(pkgfilterdir)/svgtopdf
fi
fi
+AC_ARG_ENABLE([libppdc], [AS_HELP_STRING([--enable-libppdc], [enable libppdc, to handle driver information files (*.drv).])],
+ [enable_libppdc="$enableval"],
+ [enable_libppdc=yes]
+)
+AM_CONDITIONAL([ENABLE_LIBPPDC],
+[test "x$enable_libppdc" != "xno"])
+
+# Do not overwrite a ppdc which is already there from CUPS, in this case
+# default to not include a ppdc utility
+if test ! -e "$bindir/ppdc" || test -h "$bindir/ppdc"; then
+ no_cups_ppdc=yes
+else
+ no_cups_ppdc=no
+fi
+AC_ARG_ENABLE([ppdc], [AS_HELP_STRING([--enable-ppdc], [enable ppdc utility, to build PPD files from driver information files (*.drv).])],
+ [enable_ppdc="$enableval"],
+ [enable_ppdc="$no_cups_ppdc"]
+)
+if test "x$enable_libppdc" = "xno"; then
+ enable_ppdc=no
+fi
+AM_CONDITIONAL([ENABLE_PPDC],
+[test "x$enable_ppdc" != "xno"])
+
+PPDC_DATADIR="$datadir/ppdc"
+AC_DEFINE_UNQUOTED(PPDC_DATADIR, "$PPDC_DATADIR", [ppdc include dir])
+AC_SUBST(PPDC_DATADIR)
+
AC_SEARCH_LIBS([dlopen],
[dl],
[AS_IF([test "$ac_cv_search_dlopen" != "none required"], [
AC_CONFIG_FILES([
libcupsfilters.pc
libppd.pc
+ libppdc.pc
libfontembed.pc
Makefile
utils/cups-browsed
driverless: ${enable_driverless}
apple-raster: ${APPLE_RASTER_FILTER}
pclm: ${enable_pclm}
+ libppdc: ${enable_libppdc}
+ ppdc: ${enable_ppdc}
local queue naming for remote CUPS queues: ${REMOTE_CUPS_LOCAL_QUEUE_NAMING}
keep generated queues during shutdown: ${SAVING_CREATED_QUEUES}
all ipp printer auto-setup: ${enable_auto_setup_all}
#endif /* !HAVE_STRLCPY */
/*
- * 'str_formatd()' - Format a floating-point number.
+ * 'cfStrFormatd()' - Format a floating-point number.
*/
char * /* O - Pointer to end of string */
-str_formatd(char *buf, /* I - String */
- char *bufend, /* I - End of string buffer */
- double number, /* I - Number to format */
- struct lconv *loc) /* I - Locale data */
+cfStrFormatd(char *buf, /* I - String */
+ char *bufend, /* I - End of string buffer */
+ double number, /* I - Number to format */
+ struct lconv *loc) /* I - Locale data */
{
char *bufptr, /* Pointer into buffer */
temp[1024], /* Temporary string */
"*DefaultPageSize: %s\n", "Media Size", ppdname);
for (size = (cups_size_t *)cupsArrayFirst(sizes); size;
size = (cups_size_t *)cupsArrayNext(sizes)) {
- str_formatd(twidth, twidth + sizeof(twidth),
+ cfStrFormatd(twidth, twidth + sizeof(twidth),
size->width * 72.0 / 2540.0, loc);
- str_formatd(tlength, tlength + sizeof(tlength),
+ cfStrFormatd(tlength, tlength + sizeof(tlength),
size->length * 72.0 / 2540.0, loc);
strlcpy(ppdsizename, size->media, sizeof(ppdsizename));
if ((ippsizename = strchr(ppdsizename, ' ')) != NULL) {
"*DefaultPageRegion: %s\n", "Media Size", ppdname);
for (size = (cups_size_t *)cupsArrayFirst(sizes); size;
size = (cups_size_t *)cupsArrayNext(sizes)) {
- str_formatd(twidth, twidth + sizeof(twidth),
+ cfStrFormatd(twidth, twidth + sizeof(twidth),
size->width * 72.0 / 2540.0, loc);
- str_formatd(tlength, tlength + sizeof(tlength),
+ cfStrFormatd(tlength, tlength + sizeof(tlength),
size->length * 72.0 / 2540.0, loc);
strlcpy(ppdsizename, size->media, sizeof(ppdsizename));
if ((ippsizename = strchr(ppdsizename, ' ')) != NULL) {
for (size = (cups_size_t *)cupsArrayFirst(sizes); size;
size = (cups_size_t *)cupsArrayNext(sizes)) {
- str_formatd(tleft, tleft + sizeof(tleft),
+ cfStrFormatd(tleft, tleft + sizeof(tleft),
size->left * 72.0 / 2540.0, loc);
- str_formatd(tbottom, tbottom + sizeof(tbottom),
+ cfStrFormatd(tbottom, tbottom + sizeof(tbottom),
size->bottom * 72.0 / 2540.0, loc);
- str_formatd(tright, tright + sizeof(tright),
+ cfStrFormatd(tright, tright + sizeof(tright),
(size->width - size->right) * 72.0 / 2540.0, loc);
- str_formatd(ttop, ttop + sizeof(ttop),
+ cfStrFormatd(ttop, ttop + sizeof(ttop),
(size->length - size->top) * 72.0 / 2540.0, loc);
- str_formatd(twidth, twidth + sizeof(twidth),
+ cfStrFormatd(twidth, twidth + sizeof(twidth),
size->width * 72.0 / 2540.0, loc);
- str_formatd(tlength, tlength + sizeof(tlength),
+ cfStrFormatd(tlength, tlength + sizeof(tlength),
size->length * 72.0 / 2540.0, loc);
strlcpy(ppdsizename, size->media, sizeof(ppdsizename));
if ((ippsizename = strchr(ppdsizename, ' ')) != NULL)
min_length < INT_MAX) {
char tmax[256], tmin[256]; /* Min/max values */
- str_formatd(tleft, tleft + sizeof(tleft), left * 72.0 / 2540.0, loc);
- str_formatd(tbottom, tbottom + sizeof(tbottom),
+ cfStrFormatd(tleft, tleft + sizeof(tleft), left * 72.0 / 2540.0, loc);
+ cfStrFormatd(tbottom, tbottom + sizeof(tbottom),
bottom * 72.0 / 2540.0, loc);
- str_formatd(tright, tright + sizeof(tright), right * 72.0 / 2540.0,
+ cfStrFormatd(tright, tright + sizeof(tright), right * 72.0 / 2540.0,
loc);
- str_formatd(ttop, ttop + sizeof(ttop), top * 72.0 / 2540.0, loc);
+ cfStrFormatd(ttop, ttop + sizeof(ttop), top * 72.0 / 2540.0, loc);
cupsFilePrintf(fp, "*HWMargins: \"%s %s %s %s\"\n", tleft, tbottom,
tright, ttop);
- str_formatd(tmax, tmax + sizeof(tmax), max_width * 72.0 / 2540.0,
+ cfStrFormatd(tmax, tmax + sizeof(tmax), max_width * 72.0 / 2540.0,
loc);
- str_formatd(tmin, tmin + sizeof(tmin), min_width * 72.0 / 2540.0,
+ cfStrFormatd(tmin, tmin + sizeof(tmin), min_width * 72.0 / 2540.0,
loc);
cupsFilePrintf(fp, "*ParamCustomPageSize Width: 1 points %s %s\n", tmin,
tmax);
- str_formatd(tmax, tmax + sizeof(tmax), max_length * 72.0 / 2540.0,
+ cfStrFormatd(tmax, tmax + sizeof(tmax), max_length * 72.0 / 2540.0,
loc);
- str_formatd(tmin, tmin + sizeof(tmin), min_length * 72.0 / 2540.0,
+ cfStrFormatd(tmin, tmin + sizeof(tmin), min_length * 72.0 / 2540.0,
loc);
cupsFilePrintf(fp, "*ParamCustomPageSize Height: 2 points %s %s\n", tmin,
tmax);
cups_array_t *sizes,char* default_pagesize,
const char *default_cluster_color,
char *status_msg, size_t status_msg_size);
+char *cfStrFormatd(char *buf, char *bufend, double number,
+ struct lconv *loc);
int cfCompareResolutions(void *resolution_a, void *resolution_b,
void *user_data);
void *cfCopyResolution(void *resolution, void *user_data);
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libppdc
+Description: Library for generating PPD files from *.drv files
+Version: @VERSION@
+
+Libs: -L${libdir} -lppdc
+Libs.private: @CUPS_LIBS@ -lcupsfilters -lppd
+Cflags: -I${includedir}/ppdc
--- /dev/null
+//
+// PPD file compiler main entry for the CUPS PPD Compiler.
+//
+// Copyright 2007-2014 by Apple Inc.
+// Copyright 2002-2007 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+#include <cups/array.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+
+//
+// Local globals...
+//
+
+const char *progname;
+
+
+//
+// Local functions...
+//
+
+static void usage(void);
+
+
+//
+// 'main()' - Main entry for the PPD compiler.
+//
+
+int // O - Exit status
+main(int argc, // I - Number of command-line arguments
+ char *argv[]) // I - Command-line arguments
+{
+ int i, j; // Looping vars
+ ppdcCatalog *catalog; // Message catalog
+ const char *outdir; // Output directory
+ ppdcSource *src; // PPD source file data
+ ppdcDriver *d; // Current driver
+ cups_file_t *fp; // PPD file
+ char *opt, // Current option
+ *value, // Value in option
+ *outname, // Output filename
+ make_model[1024],
+ // Make and model
+ pcfilename[1024],
+ // Lowercase pcfilename
+ filename[2048]; // PPD filename
+ int comp, // Compress
+ do_test, // Test PPD files
+ single_language,// Generate single-language files
+ use_model_name, // Use ModelName for filename
+ verbose; // Verbosity
+ ppdcLineEnding le; // Line ending to use
+ ppdcArray *locales; // List of locales
+ cups_array_t *filenames; // List of generated filenames
+
+
+ // Scan the command-line...
+ catalog = NULL;
+ comp = 0;
+ do_test = 0;
+ le = PPDC_LFONLY;
+ locales = NULL;
+ outdir = "ppd";
+ single_language = 0;
+ src = new ppdcSource();
+ use_model_name = 0;
+ verbose = 0;
+ filenames = cupsArrayNew((cups_array_func_t)strcasecmp, NULL);
+
+ progname = strrchr(argv[0], '/');
+ if (progname)
+ progname ++;
+ else
+ progname = argv[0];
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ {
+ for (opt = argv[i] + 1; *opt; opt ++)
+ switch (*opt)
+ {
+ case 'D' : // Define variable
+ i ++;
+ if (i >= argc)
+ usage();
+
+ if ((value = strchr(argv[i], '=')) != NULL)
+ {
+ *value++ = '\0';
+
+ src->set_variable(argv[i], value);
+ }
+ else
+ src->set_variable(argv[i], "1");
+ break;
+
+ case 'I' : // Include directory...
+ i ++;
+ if (i >= argc)
+ usage();
+
+ if (verbose > 1)
+ fprintf(stdout,
+ _("%s: Adding include directory \"%s\".\n"),
+ progname, argv[i]);
+
+ ppdcSource::add_include(argv[i]);
+ break;
+
+ case 'c' : // Message catalog...
+ i ++;
+ if (i >= argc)
+ usage();
+
+ if (verbose > 1)
+ fprintf(stdout,
+ _("%s: Loading messages from \"%s\".\n"),
+ progname, argv[i]);
+
+ if (!catalog)
+ catalog = new ppdcCatalog("en");
+
+ if (catalog->load_messages(argv[i]))
+ {
+ fprintf(stderr,
+ _("%s: Unable to load localization file "
+ "\"%s\" - %s\n"), progname, argv[i], strerror(errno));
+ return (1);
+ }
+ break;
+
+ case 'd' : // Output directory...
+ i ++;
+ if (i >= argc)
+ usage();
+
+ if (verbose > 1)
+ fprintf(stdout,
+ _("%s: Writing PPD files to directory "
+ "\"%s\".\n"), progname, argv[i]);
+
+ outdir = argv[i];
+ break;
+
+ case 'l' : // Language(s)...
+ i ++;
+ if (i >= argc)
+ usage();
+
+ if (strchr(argv[i], ','))
+ {
+ // Comma-delimited list of languages...
+ char temp[1024], // Copy of language list
+ *start, // Start of current locale name
+ *end; // End of current locale name
+
+
+ locales = new ppdcArray();
+
+ strncpy(temp, argv[i], sizeof(temp) - 1);
+ for (start = temp; *start; start = end)
+ {
+ if ((end = strchr(start, ',')) != NULL)
+ *end++ = '\0';
+ else
+ end = start + strlen(start);
+
+ if (end > start)
+ locales->add(new ppdcString(start));
+ }
+ }
+ else
+ {
+ single_language = 1;
+
+ if (verbose > 1)
+ fprintf(stdout,
+ _("%s: Loading messages for locale "
+ "\"%s\".\n"), progname, argv[i]);
+
+ if (catalog)
+ catalog->release();
+
+ catalog = new ppdcCatalog(argv[i]);
+
+ if (catalog->messages->count == 0 && strcmp(argv[i], "en"))
+ {
+ fprintf(stderr,
+ _("%s: Unable to find localization for "
+ "\"%s\" - %s\n"), progname, argv[i],
+ strerror(errno));
+ return (1);
+ }
+ }
+ break;
+
+ case 'm' : // Use ModelName for filename
+ use_model_name = 1;
+ break;
+
+ case 't' : // Test PPDs instead of generating them
+ do_test = 1;
+ break;
+
+ case 'v' : // Be verbose...
+ verbose ++;
+ break;
+
+ case 'z' : // Compress files...
+ comp = 1;
+ break;
+
+ case '-' : // --option
+ if (!strcmp(opt, "-lf"))
+ {
+ le = PPDC_LFONLY;
+ opt += strlen(opt) - 1;
+ break;
+ }
+ else if (!strcmp(opt, "-cr"))
+ {
+ le = PPDC_CRONLY;
+ opt += strlen(opt) - 1;
+ break;
+ }
+ else if (!strcmp(opt, "-crlf"))
+ {
+ le = PPDC_CRLF;
+ opt += strlen(opt) - 1;
+ break;
+ }
+
+ default : // Unknown
+ usage();
+ }
+ }
+ else
+ {
+ // Open and load the driver info file...
+ if (verbose > 1)
+ fprintf(stdout,
+ _("%s: Loading driver information file \"%s\".\n"),
+ progname, argv[i]);
+
+ src->read_file(argv[i]);
+ }
+
+
+ if (src->drivers->count > 0)
+ {
+ // Create the output directory...
+ if (mkdir(outdir, 0777))
+ {
+ if (errno != EEXIST)
+ {
+ fprintf(stderr,
+ _("%s: Unable to create output directory %s: %s\n"),
+ progname, outdir, strerror(errno));
+ return (1);
+ }
+ }
+
+ // Write PPD files...
+ for (d = (ppdcDriver *)src->drivers->first();
+ d;
+ d = (ppdcDriver *)src->drivers->next())
+ {
+ if (do_test)
+ {
+ // Test the PPD file for this driver...
+ int pid, // Process ID
+ fds[2]; // Pipe file descriptors
+
+
+ if (pipe(fds))
+ {
+ fprintf(stderr,
+ _("%s: Unable to create output pipes: %s\n"),
+ progname, strerror(errno));
+ return (1);
+ }
+
+ if ((pid = fork()) == 0)
+ {
+ // Child process comes here...
+ dup2(fds[0], 0);
+
+ close(fds[0]);
+ close(fds[1]);
+
+ execlp("cupstestppd", "cupstestppd", "-", (char *)0);
+
+ fprintf(stderr,
+ _("%s: Unable to execute cupstestppd: %s\n"),
+ progname, strerror(errno));
+ return (errno);
+ }
+ else if (pid < 0)
+ {
+ fprintf(stderr, _("%s: Unable to execute cupstestppd: %s\n"),
+ progname, strerror(errno));
+ return (errno);
+ }
+
+ close(fds[0]);
+ fp = cupsFileOpenFd(fds[1], "w");
+ }
+ else
+ {
+ // Write the PPD file for this driver...
+ if (use_model_name)
+ {
+ if (!strncasecmp(d->model_name->value, d->manufacturer->value,
+ strlen(d->manufacturer->value)))
+ {
+ // Model name already starts with the manufacturer...
+ outname = d->model_name->value;
+ }
+ else
+ {
+ // Add manufacturer to the front of the model name...
+ snprintf(make_model, sizeof(make_model), "%s %s",
+ d->manufacturer->value, d->model_name->value);
+ outname = make_model;
+ }
+ }
+ else if (d->file_name)
+ outname = d->file_name->value;
+ else
+ outname = d->pc_file_name->value;
+
+ if (strstr(outname, ".PPD"))
+ {
+ // Convert PCFileName to lowercase...
+ for (j = 0;
+ outname[j] && j < (int)(sizeof(pcfilename) - 1);
+ j ++)
+ pcfilename[j] = (char)tolower(outname[j] & 255);
+
+ pcfilename[j] = '\0';
+ }
+ else
+ {
+ // Leave PCFileName as-is...
+ strncpy(pcfilename, outname, sizeof(pcfilename));
+ }
+
+ // Open the PPD file for writing...
+ if (comp)
+ snprintf(filename, sizeof(filename), "%s/%s.gz", outdir, pcfilename);
+ else
+ snprintf(filename, sizeof(filename), "%s/%s", outdir, pcfilename);
+
+ if (cupsArrayFind(filenames, filename))
+ fprintf(stderr,
+ _("%s: Warning - overlapping filename \"%s\".\n"),
+ progname, filename);
+ else
+ cupsArrayAdd(filenames, strdup(filename));
+
+ fp = cupsFileOpen(filename, comp ? "w9" : "w");
+ if (!fp)
+ {
+ fprintf(stderr,
+ _("%s: Unable to create PPD file \"%s\" - %s.\n"),
+ progname, filename, strerror(errno));
+ return (1);
+ }
+
+ if (verbose)
+ fprintf(stdout, _("%s: Writing %s.\n"), progname, filename);
+ }
+
+ /*
+ * Write the PPD file...
+ */
+
+ ppdcArray *templocales = locales;
+
+ if (!templocales && !single_language)
+ {
+ templocales = new ppdcArray();
+ for (ppdcCatalog *tempcatalog = (ppdcCatalog *)src->po_files->first();
+ tempcatalog;
+ tempcatalog = (ppdcCatalog *)src->po_files->next())
+ {
+ tempcatalog->locale->retain();
+ templocales->add(tempcatalog->locale);
+ }
+ }
+
+ if (d->write_ppd_file(fp, catalog, templocales, src, le))
+ {
+ cupsFileClose(fp);
+ return (1);
+ }
+
+ if (templocales && templocales != locales)
+ templocales->release();
+
+ cupsFileClose(fp);
+ }
+ }
+ else
+ usage();
+
+ // Delete the printer driver information...
+ src->release();
+
+ // Message catalog...
+ if (catalog)
+ catalog->release();
+
+ // Return with no errors.
+ return (0);
+}
+
+
+//
+// 'usage()' - Show usage and exit.
+//
+
+static void
+usage(void)
+{
+ fprintf(stdout, _("Usage: %s [options] filename.drv [ ... "
+ "filenameN.drv ]\n"), progname);
+ fprintf(stdout, _("Options:\n"));
+ fprintf(stdout, _(" -D name=value Set named variable to "
+ "value.\n"));
+ fprintf(stdout, _(" -I include-dir Add include directory to "
+ "search path.\n"));
+ fprintf(stdout, _(" -c catalog.po Load the specified "
+ "message catalog.\n"));
+ fprintf(stdout, _(" -d output-dir Specify the output "
+ "directory.\n"));
+ fprintf(stdout, _(" -l lang[,lang,...] Specify the output "
+ "language(s) (locale).\n"));
+ fprintf(stdout, _(" -m Use the ModelName value "
+ "as the filename.\n"));
+ fprintf(stdout, _(" -t Test PPDs instead of "
+ "generating them.\n"));
+ fprintf(stdout, _(" -v Be verbose.\n"));
+ fprintf(stdout, _(" -z Compress PPD files using "
+ "GNU zip.\n"));
+ fprintf(stdout, _(" --cr End lines with CR (Mac "
+ "OS 9).\n"));
+ fprintf(stdout, _(" --crlf End lines with CR + LF "
+ "(Windows).\n"));
+ fprintf(stdout, _(" --lf End lines with LF "
+ "(UNIX/Linux/macOS).\n"));
+
+ exit(1);
+}
--- /dev/null
+/*
+ * This file contains model number definitions for the CUPS sample
+ * ESC/P driver.
+ *
+ * Copyright 2007 by Apple Inc.
+ * Copyright 1997-2005 by Easy Software Products.
+ *
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+ */
+
+#define EPSON_9PIN 0 /* 9-pin dot matrix */
+#define EPSON_24PIN 1 /* 24-pin dot matrix */
+#define EPSON_COLOR 2 /* Epson Stylus Color with ESC . */
+#define EPSON_PHOTO 3 /* Epson Stylus Photo with ESC . */
+#define EPSON_ICOLOR 4 /* Epson Stylus Color with ESC i */
+#define EPSON_IPHOTO 5 /* Epson Stylus Photo with ESC i */
--- /dev/null
+/*
+ * Standard font definitions for the CUPS PPD file compiler.
+ *
+ * Copyright © 2007 by Apple Inc.
+ * Copyright © 1997-2005 by Easy Software Products.
+ *
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
+ */
+
+#font AvantGarde-Book Standard "(1.05)" Standard ROM
+#font AvantGarde-BookOblique Standard "(1.05)" Standard ROM
+#font AvantGarde-Demi Standard "(1.05)" Standard ROM
+#font AvantGarde-DemiOblique Standard "(1.05)" Standard ROM
+#font Bookman-Demi Standard "(1.05)" Standard ROM
+#font Bookman-DemiItalic Standard "(1.05)" Standard ROM
+#font Bookman-Light Standard "(1.05)" Standard ROM
+#font Bookman-LightItalic Standard "(1.05)" Standard ROM
+#font Courier Standard "(1.05)" Standard ROM
+#font Courier-Bold Standard "(1.05)" Standard ROM
+#font Courier-BoldOblique Standard "(1.05)" Standard ROM
+#font Courier-Oblique Standard "(1.05)" Standard ROM
+#font Helvetica Standard "(1.05)" Standard ROM
+#font Helvetica-Bold Standard "(1.05)" Standard ROM
+#font Helvetica-BoldOblique Standard "(1.05)" Standard ROM
+#font Helvetica-Narrow Standard "(1.05)" Standard ROM
+#font Helvetica-Narrow-Bold Standard "(1.05)" Standard ROM
+#font Helvetica-Narrow-BoldOblique Standard "(1.05)" Standard ROM
+#font Helvetica-Narrow-Oblique Standard "(1.05)" Standard ROM
+#font Helvetica-Oblique Standard "(1.05)" Standard ROM
+#font NewCenturySchlbk-Bold Standard "(1.05)" Standard ROM
+#font NewCenturySchlbk-BoldItalic Standard "(1.05)" Standard ROM
+#font NewCenturySchlbk-Italic Standard "(1.05)" Standard ROM
+#font NewCenturySchlbk-Roman Standard "(1.05)" Standard ROM
+#font Palatino-Bold Standard "(1.05)" Standard ROM
+#font Palatino-BoldItalic Standard "(1.05)" Standard ROM
+#font Palatino-Italic Standard "(1.05)" Standard ROM
+#font Palatino-Roman Standard "(1.05)" Standard ROM
+#font Symbol Special "(001.005)" Special ROM
+#font Times-Bold Standard "(1.05)" Standard ROM
+#font Times-BoldItalic Standard "(1.05)" Standard ROM
+#font Times-Italic Standard "(1.05)" Standard ROM
+#font Times-Roman Standard "(1.05)" Standard ROM
+#font ZapfChancery-MediumItalic Standard "(1.05)" Standard ROM
+#font ZapfDingbats Special "(001.005)" Special ROM
--- /dev/null
+/*
+ * This file contains model number definitions for the CUPS sample
+ * HP driver.
+ *
+ * Copyright 2007 by Apple Inc.
+ * Copyright 1997-2005 by Easy Software Products.
+ *
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+ */
+
+#define HP_LASERJET 0 /* HP LaserJet */
+#define HP_DESKJET 1 /* HP DeskJet with simple color */
+#define HP_DESKJET2 2 /* HP DeskJet with CRet color */
--- /dev/null
+/*
+ * This file contains model number definitions for the CUPS sample
+ * label printer driver.
+ *
+ * Copyright 2007 by Apple Inc.
+ * Copyright 1997-2005 by Easy Software Products.
+ *
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+ */
+
+#define DYMO_3x0 0 /* Dymo Labelwriter 300/330/330 Turbo */
+
+#define ZEBRA_EPL_LINE 0x10 /* Zebra EPL line mode printers */
+#define ZEBRA_EPL_PAGE 0x11 /* Zebra EPL page mode printers */
+#define ZEBRA_ZPL 0x12 /* Zebra ZPL-based printers */
+#define ZEBRA_CPCL 0x13 /* Zebra CPCL-based printers */
+
+#define INTELLITECH_PCL 0x20 /* Intellitech PCL-based printers */
--- /dev/null
+/*
+ * Adobe standard media size definitions for the CUPS PPD file compiler.
+ *
+ * Copyright © 2007-2016 by Apple Inc.
+ * Copyright © 1997-2005 by Easy Software Products.
+ *
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
+ */
+
+#media "3x5/3 x 5" 216 360
+#media "3.5x5/3.5 x 5" 252 360
+#media "5x7/5 x 7" 360 504
+#media "10x11/10 x 11" 720 792
+#media "10x13/10 x 13" 720 936
+#media "10x14/10 x 14" 720 1008
+#media "12x11/12 x 11" 864 792
+#media "15x11/15 x 11" 1080 792
+#media "7x9/7 x 9" 504 648
+#media "8x10/8 x 10" 576 720
+#media "9x11/9 x 11" 648 792
+#media "9x12/9 x 12" 648 864
+#media "A0/A0" 2384 3370
+#media "A0.Transverse/A0 Long Edge" 3370 2384
+#media "A1/A1" 1684 2384
+#media "A1.Transverse/A1 Long Edge" 2384 1684
+#media "A2/A2" 1191 1684
+#media "A2.Transverse/A2 Long Edge" 1684 1191
+#media "A3/A3" 842 1191
+#media "A3.Transverse/A3 Long Edge" 1191 842
+#media "A3Extra/A3 Oversize" 913 1262
+#media "A3Extra.Transverse/A3 Oversize Long Edge" 913 1262
+#media "A3Rotated/A3 Long Edge" 1191 842
+#media "A4/A4" 595 842
+#media "A4Extra/A4 Oversize" 667 914
+#media "A4Plus/A4 Oversize" 595 936
+#media "A4Rotated/A4 Long Edge" 842 595
+#media "A4Small/A4 Small" 595 842
+#media "A4.Transverse/A4 Long Edge" 842 595
+#media "A5/A5" 420 595
+#media "A5Extra/A5 Oversize" 492 668
+#media "A5Rotated/A5 Long Edge" 595 420
+#media "A5.Transverse/A5 Long Edge" 595 420
+#media "A6/A6" 297 420
+#media "A6Rotated/A6 Long Edge" 420 297
+#media "A7/A7" 210 297
+#media "A8/A8" 148 210
+#media "A9/A9" 105 148
+#media "A10/A10" 73 105
+#media "AnsiA/ANSI A" 612 792
+#media "AnsiB/ANSI B" 792 1224
+#media "AnsiC/ANSI C" 1224 1584
+#media "AnsiD/ANSI D" 1584 2448
+#media "AnsiE/ANSI E" 2448 3168
+#media "ARCHA/Letter Oversize" 648 864
+#media "ARCHA.Transverse/Letter Oversize Long Edge" 864 648
+#media "ARCHB/Tabloid Oversize" 864 1296
+#media "ARCHB.Transverse/Tabloid Oversize Long Edge" 1296 864
+#media "ARCHC/ARCH C" 1296 1728
+#media "ARCHC.Transverse/ARCH C Long Edge" 1728 1296
+#media "ARCHD/ARCH D" 1728 2592
+#media "ARCHD.Transverse/ARCH D Long Edge" 2592 1728
+#media "ARCHE/ARCH E" 2592 3456
+#media "ARCHE.Transverse/ARCH E Long Edge" 3456 2592
+#media "B0/JIS B0" 2920 4127
+#media "B10/JIS B10" 91 127
+#media "B1/JIS B1" 2064 2918
+#media "B1/JIS B1" 2064 2920
+#media "B2/JIS B2" 1460 2064
+#media "B3/JIS B3" 1032 1460
+#media "B4/JIS B4" 729 1032
+#media "B4Rotated/JIS B4 Long Edge" 1032 729
+#media "B5/JIS B5" 516 729
+#media "B5Rotated/JIS B5 Long Edge" 729 516
+#media "B5.Transverse/JIS B5 Long Edge" 516 729
+#media "B6/JIS B6" 363 516
+#media "B6Rotated/JIS B6 Long Edge" 516 363
+#media "B7/JIS B7" 258 363
+#media "B8/JIS B8" 181 258
+#media "B9/JIS B9" 127 181
+#media "C4/Envelope C4" 649 918
+#media "C5/Envelope C5" 459 649
+#media "C6/Envelope C6" 323 459
+#media "DL/Envelope DL" 312 624
+#media "DoublePostcard/Postcard Double" 567 420
+#media "DoublePostcardRotated/Postcard Double Long Edge" 420 567
+#media "Env10/Envelope #10" 297 684
+#media "Env11/Envelope #11" 324 747
+#media "Env12/Envelope #12" 342 792
+#media "Env14/Envelope #14" 360 828
+#media "Env9/Envelope #9" 279 639
+#media "EnvC0/Envelope C0" 2599 3676
+#media "EnvC1/Envelope C1" 1837 2599
+#media "EnvC2/Envelope C2" 1298 1837
+#media "EnvC3/Envelope C3" 918 1296
+#media "EnvC4/Envelope C4" 649 918
+#media "EnvC5/Envelope C5" 459 649
+#media "EnvC65/Envelope C65" 324 648
+#media "EnvC6/Envelope C6" 323 459
+#media "EnvC7/Envelope C7" 230 323
+#media "EnvChou3/Envelope Choukei 3" 340 666
+#media "EnvChou3Rotated/Envelope Choukei 3 Long Edge" 666 340
+#media "EnvChou4/Envelope Choukei 4" 255 581
+#media "EnvChou4Rotated/Envelope Choukei 4 Long Edge" 581 255
+#media "EnvDL/Envelope DL" 312 624
+#media "EnvInvite/Envelope Invite" 624 624
+#media "EnvISOB4/Envelope B4" 708 1001
+#media "EnvISOB5/Envelope B5" 499 709
+#media "EnvISOB6/Envelope B6" 499 354
+#media "EnvItalian/Envelope Italian" 312 652
+#media "EnvKaku2/Envelope Kaku2" 680 941
+#media "EnvKaku2Rotated/Envelope Kaku2 Long Edge" 941 680
+#media "EnvKaku3/Envelope Kaku3" 612 785
+#media "EnvKaku3Rotated/Envelope Kaku3 Long Edge" 785 612
+#media "EnvMonarch/Envelope Monarch" 279 540
+#media "EnvPersonal/Envelope Personal" 261 468
+#media "EnvPRC1/Envelope PRC1" 289 468
+#media "EnvPRC1Rotated/Envelope PRC1 Long Edge" 468 289
+#media "EnvPRC2/Envelope PRC2" 289 499
+#media "EnvPRC2Rotated/Envelope PRC2 Long Edge" 499 289
+#media "EnvPRC3/Envelope PRC3" 354 499
+#media "EnvPRC3Rotated/Envelope PRC3 Long Edge" 499 354
+#media "EnvPRC4/Envelope PRC4" 312 590
+#media "EnvPRC4Rotated/Envelope PRC4 Long Edge" 590 312
+#media "EnvPRC5/Envelope PRC5PRC5" 312 624
+#media "EnvPRC5Rotated/Envelope PRC5 Long Edge" 624 312
+#media "EnvPRC6/Envelope PRC6" 340 652
+#media "EnvPRC6Rotated/Envelope PRC6 Long Edge" 652 340
+#media "EnvPRC7/Envelope PRC7" 454 652
+#media "EnvPRC7Rotated/Envelope PRC7 Long Edge" 652 454
+#media "EnvPRC8/Envelope PRC8" 340 876
+#media "EnvPRC8Rotated/Envelope PRC8 Long Edge" 876 340
+#media "EnvPRC9/Envelope PRC9" 649 918
+#media "EnvPRC9Rotated/Envelope PRC9 Long Edge" 918 649
+#media "EnvPRC10/Envelope PRC10" 918 1298
+#media "EnvPRC10Rotated/Envelope PRC10 Long Edge" 1298 918
+#media "EnvYou4/Envelope You4" 298 666
+#media "EnvYou4Rotated/Envelope You4 Long Edge" 666 298
+#media "Executive/Executive" 522 756
+#media "FanFoldGerman/European Fanfold" 612 864
+#media "FanFoldGermanLegal/European Fanfold Legal" 612 936
+#media "FanFoldUS/US Fanfold" 1071 792
+#media "Folio/Folio" 595 935
+#media "ISOB0/B0" 2835 4008
+#media "ISOB1/B1" 2004 2835
+#media "ISOB2/B2" 1417 2004
+#media "ISOB3/B3" 1001 1417
+#media "ISOB4/B4" 709 1001
+#media "ISOB5/B5" 499 709
+#media "ISOB5Extra/B5 Oversize" 570 782
+#media "ISOB6/B6" 354 499
+#media "ISOB7/B7" 249 354
+#media "ISOB8/B8" 176 249
+#media "ISOB9/B9" 125 176
+#media "ISOB10/B10" 88 125
+#media "Ledger/US Ledger" 1224 792
+#media "Legal/US Legal" 612 1008
+#media "LegalExtra/US Legal Oversize" 684 1080
+#media "Letter/US Letter" 612 792
+#media "Letter.Transverse/US Letter Long Edge" 792 612
+#media "LetterExtra/US Letter Oversize" 684 864
+#media "LetterExtra.Transverse/US Letter Oversize Long Edge" 864 684
+#media "LetterPlus/US Letter Oversize" 612 914
+#media "LetterRotated/US Letter Long Edge" 792 612
+#media "LetterSmall/US Letter Small" 612 792
+#media "Monarch/Envelope Monarch" 279 540
+#media "Note/Note" 612 792
+#media "Postcard/Postcard" 284 419
+#media "PostcardRotated/Postcard Long Edge" 419 284
+#media "PRC16K/PRC16K" 414 610
+#media "PRC16KRotated/PRC16K Long Edge" 610 414
+#media "PRC32K/PRC32K" 275 428
+#media "PRC32KBig/PRC32K Oversize" 275 428
+#media "PRC32KBigRotated/PRC32K Oversize Long Edge" 428 275
+#media "PRC32KRotated/PRC32K Long Edge" 428 275
+#media "Quarto/Quarto" 610 780
+#media "Statement/Statement" 396 612
+#media "SuperA/Super A" 643 1009
+#media "SuperB/Super B" 864 1380
+#media "Tabloid/Tabloid" 792 1224
+#media "TabloidExtra/Tabloid Oversize" 864 1296
+
+/*
+ * Non-standard sizes...
+ */
+
+#media "Photo4x6/Photo" 288 432
+#media "PhotoLabel/Photo Labels" 288 468
+#media "w936h1368/Super B/A3" 936 1368
+#media "w81h252/Address" 81 252
+#media "w101h252/Large Address" 101 252
+#media "w54h144/Return Address" 54 144
+#media "w167h288/Shipping Address" 167 288
+#media "w162h540/Internet Postage 2-Part" 162 540
+#media "w162h504/Internet Postage 3-Part" 162 504
+#media "w41h248/File Folder" 41 248
+#media "w41h144/Hanging Folder" 41 144
+#media "w153h198/3.5\" Disk" 153 198
--- /dev/null
+//
+// Array class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2019 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcArray::ppdcArray()' - Create a new array.
+//
+
+ppdcArray::ppdcArray(ppdcArray *a)
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ if (a)
+ {
+ count = a->count;
+ alloc = count;
+
+ if (count)
+ {
+ // Make a copy of the array...
+ data = new ppdcShared *[count];
+
+ memcpy(data, a->data, (size_t)count * sizeof(ppdcShared *));
+
+ for (size_t i = 0; i < count; i ++)
+ data[i]->retain();
+ }
+ else
+ data = 0;
+ }
+ else
+ {
+ count = 0;
+ alloc = 0;
+ data = 0;
+ }
+
+ current = 0;
+}
+
+
+//
+// 'ppdcArray::~ppdcArray()' - Destroy an array.
+//
+
+ppdcArray::~ppdcArray()
+{
+ PPDC_DELETE;
+
+ for (size_t i = 0; i < count; i ++)
+ data[i]->release();
+
+ if (alloc)
+ delete[] data;
+}
+
+
+//
+// 'ppdcArray::add()' - Add an element to an array.
+//
+
+void
+ppdcArray::add(ppdcShared *d)
+{
+ ppdcShared **temp;
+
+
+ if (count >= alloc)
+ {
+ alloc += 10;
+ temp = new ppdcShared *[alloc];
+
+ memcpy(temp, data, (size_t)count * sizeof(ppdcShared *));
+
+ delete[] data;
+ data = temp;
+ }
+
+ data[count++] = d;
+}
+
+
+//
+// 'ppdcArray::first()' - Return the first element in the array.
+//
+
+ppdcShared *
+ppdcArray::first()
+{
+ current = 0;
+
+ if (current >= count)
+ return (0);
+ else
+ return (data[current ++]);
+}
+
+
+//
+// 'ppdcArray::next()' - Return the next element in the array.
+//
+
+ppdcShared *
+ppdcArray::next()
+{
+ if (current >= count)
+ return (0);
+ else
+ return (data[current ++]);
+}
+
+
+//
+// 'ppdcArray::remove()' - Remove an element from the array.
+//
+
+void
+ppdcArray::remove(ppdcShared *d) // I - Data element
+{
+ size_t i; // Looping var
+
+
+ for (i = 0; i < count; i ++)
+ if (d == data[i])
+ break;
+
+ if (i >= count)
+ return;
+
+ count --;
+ d->release();
+
+ if (i < count)
+ memmove(data + i, data + i + 1, (size_t)(count - i) * sizeof(ppdcShared *));
+}
--- /dev/null
+//
+// Attribute class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcAttr::ppdcAttr()' - Create an attribute.
+//
+
+ppdcAttr::ppdcAttr(const char *n, // I - Name
+ const char *s, // I - Spec string
+ const char *t, // I - Human-readable text
+ const char *v, // I - Value
+ bool loc) // I - Localize this attribute?
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ name = new ppdcString(n);
+ selector = new ppdcString(s);
+ text = new ppdcString(t);
+ value = new ppdcString(v);
+ localizable = loc;
+}
+
+
+//
+// 'ppdcAttr::~ppdcAttr()' - Destroy an attribute.
+//
+
+ppdcAttr::~ppdcAttr()
+{
+ PPDC_DELETE;
+
+ name->release();
+ selector->release();
+ text->release();
+ value->release();
+}
--- /dev/null
+//
+// Shared message catalog class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2017 by Apple Inc.
+// Copyright 2002-2006 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// Character encodings...
+//
+
+typedef enum
+{
+ PPDC_CS_AUTO,
+ PPDC_CS_UTF8,
+ PPDC_CS_UTF16BE,
+ PPDC_CS_UTF16LE
+} ppdc_cs_t;
+
+
+//
+// Local functions...
+//
+
+static int get_utf8(char *&ptr);
+static int get_utf16(cups_file_t *fp, ppdc_cs_t &cs);
+static int put_utf8(int ch, char *&ptr, char *end);
+static int put_utf16(cups_file_t *fp, int ch);
+
+
+//
+// 'ppdcCatalog::ppdcCatalog()' - Create a shared message catalog.
+//
+
+ppdcCatalog::ppdcCatalog(const char *l, // I - Locale
+ const char *f) // I - Message catalog file
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ locale = new ppdcString(l);
+ filename = new ppdcString(f);
+ messages = new ppdcArray();
+
+ if (l && strcmp(l, "en"))
+ {
+ // Try loading the base messages for this locale...
+ char pofile[1024]; // Message catalog file
+ const char *c;
+
+ /* Determine CUPS datadir (usually /usr/share/cups) */
+ if ((c = getenv("CUPS_DATADIR")) == NULL)
+ c = CUPS_DATADIR;
+
+ snprintf(pofile, sizeof(pofile), "%s/locale/%s/cups_%s.po", c, l, l);
+
+ if (load_messages(pofile) && strchr(l, '_'))
+ {
+ // Try the base locale...
+ char baseloc[3]; // Base locale...
+
+ strncpy(baseloc, l, sizeof(baseloc) - 1);
+ snprintf(pofile, sizeof(pofile), "%s/locale/%s/cups_%s.po", c,
+ baseloc, baseloc);
+
+ load_messages(pofile);
+ }
+ }
+
+ if (f && *f)
+ load_messages(f);
+}
+
+
+//
+// 'ppdcCatalog::~ppdcCatalog()' - Destroy a shared message catalog.
+//
+
+ppdcCatalog::~ppdcCatalog()
+{
+ PPDC_DELETE;
+
+ locale->release();
+ filename->release();
+ messages->release();
+}
+
+
+//
+// 'ppdcCatalog::add_message()' - Add a new message.
+//
+
+void
+ppdcCatalog::add_message(
+ const char *id, // I - Message ID to add
+ const char *string) // I - Translation string
+{
+ ppdcMessage *m; // Current message
+ char text[1024]; // Text to translate
+
+
+ // Range check input...
+ if (!id)
+ return;
+
+ // Verify that we don't already have the message ID...
+ for (m = (ppdcMessage *)messages->first();
+ m;
+ m = (ppdcMessage *)messages->next())
+ if (!strcmp(m->id->value, id))
+ {
+ if (string)
+ {
+ m->string->release();
+ m->string = new ppdcString(string);
+ }
+ return;
+ }
+
+ // Add the message...
+ if (!string)
+ {
+ snprintf(text, sizeof(text), "TRANSLATE %s", id);
+ string = text;
+ }
+
+ messages->add(new ppdcMessage(id, string));
+}
+
+
+//
+// 'ppdcCatalog::find_message()' - Find a message in a catalog...
+//
+
+const char * // O - Message text
+ppdcCatalog::find_message(
+ const char *id) // I - Message ID
+{
+ ppdcMessage *m; // Current message
+
+
+ if (!*id)
+ return (id);
+
+ for (m = (ppdcMessage *)messages->first();
+ m;
+ m = (ppdcMessage *)messages->next())
+ if (!strcmp(m->id->value, id))
+ return (m->string->value);
+
+ return (id);
+}
+
+
+//
+// 'ppdcCatalog::load_messages()' - Load messages from a .po file.
+//
+
+int // O - 0 on success, -1 on failure
+ppdcCatalog::load_messages(
+ const char *f) // I - Message catalog file
+{
+ cups_file_t *fp; // Message file
+ char line[4096], // Line buffer
+ *ptr, // Pointer into buffer
+ id[4096], // Translation ID
+ str[4096]; // Translation string
+ int linenum; // Line number
+
+
+ // Open the message catalog file...
+ if ((fp = cupsFileOpen(f, "r")) == NULL)
+ return (-1);
+
+ if ((ptr = (char *)strrchr(f, '.')) == NULL)
+ goto unknown_load_format;
+ else if (!strcmp(ptr, ".strings"))
+ {
+ /*
+ * Read messages in macOS ".strings" format, which are either UTF-8/UTF-16
+ * text files of the format:
+ *
+ * "id" = "str";
+ *
+ * Strings files can also contain C-style comments.
+ */
+
+ ppdc_cs_t cs = PPDC_CS_AUTO; // Character set for file
+ int ch; // Current character from file
+ char *end; // End of buffer
+
+
+ id[0] = '\0';
+ str[0] = '\0';
+ ptr = NULL;
+ end = NULL;
+
+ while ((ch = get_utf16(fp, cs)) != 0)
+ {
+ if (ptr)
+ {
+ if (ch == '\\')
+ {
+ if ((ch = get_utf16(fp, cs)) == 0)
+ break;
+
+ if (ch == 'n')
+ ch = '\n';
+ else if (ch == 't')
+ ch = '\t';
+ }
+ else if (ch == '\"')
+ {
+ *ptr = '\0';
+ ptr = NULL;
+ }
+
+ if (ptr)
+ put_utf8(ch, ptr, end);
+ }
+ else if (ch == '/')
+ {
+ // Start of a comment?
+ if ((ch = get_utf16(fp, cs)) == 0)
+ break;
+
+ if (ch == '*')
+ {
+ // Skip C comment...
+ int lastch = 0;
+
+ while ((ch = get_utf16(fp, cs)) != 0)
+ {
+ if (ch == '/' && lastch == '*')
+ break;
+
+ lastch = ch;
+ }
+ }
+ else if (ch == '/')
+ {
+ // Skip C++ comment...
+ while ((ch = get_utf16(fp, cs)) != 0)
+ if (ch == '\n')
+ break;
+ }
+ }
+ else if (ch == '\"')
+ {
+ // Start quoted string...
+ if (id[0])
+ {
+ ptr = str;
+ end = str + sizeof(str) - 1;
+ }
+ else
+ {
+ ptr = id;
+ end = id + sizeof(id) - 1;
+ }
+ }
+ else if (ch == ';')
+ {
+ // Add string...
+ add_message(id, str);
+ id[0] = '\0';
+ }
+ }
+ }
+ else if (!strcmp(ptr, ".po") || !strcmp(ptr, ".gz"))
+ {
+ /*
+ * Read messages from the catalog file until EOF...
+ *
+ * The format is the GNU gettext .po format, which is fairly simple:
+ *
+ * msgid "some text"
+ * msgstr "localized text"
+ *
+ * The ID and localized text can span multiple lines using the form:
+ *
+ * msgid ""
+ * "some long text"
+ * msgstr ""
+ * "localized text spanning "
+ * "multiple lines"
+ */
+
+ int which, // In msgid?
+ haveid, // Did we get a msgid string?
+ havestr; // Did we get a msgstr string?
+
+ linenum = 0;
+ id[0] = '\0';
+ str[0] = '\0';
+ haveid = 0;
+ havestr = 0;
+ which = 0;
+
+ while (cupsFileGets(fp, line, sizeof(line)))
+ {
+ linenum ++;
+
+ // Skip blank and comment lines...
+ if (line[0] == '#' || !line[0])
+ continue;
+
+ // Strip the trailing quote...
+ if ((ptr = (char *)strrchr(line, '\"')) == NULL)
+ {
+ fprintf(stderr,
+ _("ppdc: Expected quoted string on line %d of %s.\n"),
+ linenum, f);
+ cupsFileClose(fp);
+ return (-1);
+ }
+
+ *ptr = '\0';
+
+ // Find start of value...
+ if ((ptr = strchr(line, '\"')) == NULL)
+ {
+ fprintf(stderr,
+ _("ppdc: Expected quoted string on line %d of %s.\n"),
+ linenum, f);
+ cupsFileClose(fp);
+ return (-1);
+ }
+
+ ptr ++;
+
+ // Unquote the text...
+ char *sptr, *dptr; // Source/destination pointers
+
+ for (sptr = ptr, dptr = ptr; *sptr;)
+ {
+ if (*sptr == '\\')
+ {
+ sptr ++;
+ if (isdigit(*sptr))
+ {
+ *dptr = 0;
+
+ while (isdigit(*sptr))
+ {
+ *dptr = *dptr * 8 + *sptr - '0';
+ sptr ++;
+ }
+
+ dptr ++;
+ }
+ else
+ {
+ if (*sptr == 'n')
+ *dptr++ = '\n';
+ else if (*sptr == 'r')
+ *dptr++ = '\r';
+ else if (*sptr == 't')
+ *dptr++ = '\t';
+ else
+ *dptr++ = *sptr;
+
+ sptr ++;
+ }
+ }
+ else
+ *dptr++ = *sptr++;
+ }
+
+ *dptr = '\0';
+
+ // Create or add to a message...
+ if (!strncmp(line, "msgid", 5))
+ {
+ if (haveid && havestr)
+ add_message(id, str);
+
+ strncpy(id, ptr, sizeof(id) - 1);
+ str[0] = '\0';
+ haveid = 1;
+ havestr = 0;
+ which = 1;
+ }
+ else if (!strncmp(line, "msgstr", 6))
+ {
+ if (!haveid)
+ {
+ fprintf(stderr,
+ _("ppdc: Need a msgid line before any "
+ "translation strings on line %d of %s.\n"),
+ linenum, f);
+ cupsFileClose(fp);
+ return (-1);
+ }
+
+ strncpy(str, ptr, sizeof(str) - 1);
+ havestr = 1;
+ which = 2;
+ }
+ else if (line[0] == '\"' && which == 2)
+ strncat(str, ptr, sizeof(str) - 1);
+ else if (line[0] == '\"' && which == 1)
+ strncat(id, ptr, sizeof(id) - 1);
+ else
+ {
+ fprintf(stderr, _("ppdc: Unexpected text on line %d of %s.\n"),
+ linenum, f);
+ cupsFileClose(fp);
+ return (-1);
+ }
+ }
+
+ if (haveid && havestr)
+ add_message(id, str);
+ }
+ else
+ goto unknown_load_format;
+
+ /*
+ * Close the file and return...
+ */
+
+ cupsFileClose(fp);
+
+ return (0);
+
+ /*
+ * Unknown format error...
+ */
+
+ unknown_load_format:
+
+ fprintf(stderr,
+ _("ppdc: Unknown message catalog format for \"%s\".\n"), f);
+ cupsFileClose(fp);
+ return (-1);
+}
+
+
+//
+// 'ppdcCatalog::save_messages()' - Save the messages to a .po file.
+//
+
+int // O - 0 on success, -1 on error
+ppdcCatalog::save_messages(
+ const char *f) // I - File to save to
+{
+ cups_file_t *fp; // Message file
+ ppdcMessage *m; // Current message
+ char *ptr; // Pointer into string
+ int utf16; // Output UTF-16 .strings file?
+ int ch; // Current character
+
+
+ // Open the file...
+ if ((ptr = (char *)strrchr(f, '.')) == NULL)
+ return (-1);
+
+ if (!strcmp(ptr, ".gz"))
+ fp = cupsFileOpen(f, "w9");
+ else
+ fp = cupsFileOpen(f, "w");
+
+ if (!fp)
+ return (-1);
+
+ // For .strings files, write a BOM for big-endian output...
+ utf16 = !strcmp(ptr, ".strings");
+
+ if (utf16)
+ put_utf16(fp, 0xfeff);
+
+ // Loop through all of the messages...
+ for (m = (ppdcMessage *)messages->first();
+ m;
+ m = (ppdcMessage *)messages->next())
+ {
+ if (utf16)
+ {
+ put_utf16(fp, '\"');
+
+ ptr = m->id->value;
+ while ((ch = get_utf8(ptr)) != 0)
+ switch (ch)
+ {
+ case '\n' :
+ put_utf16(fp, '\\');
+ put_utf16(fp, 'n');
+ break;
+ case '\\' :
+ put_utf16(fp, '\\');
+ put_utf16(fp, '\\');
+ break;
+ case '\"' :
+ put_utf16(fp, '\\');
+ put_utf16(fp, '\"');
+ break;
+ default :
+ put_utf16(fp, ch);
+ break;
+ }
+
+ put_utf16(fp, '\"');
+ put_utf16(fp, ' ');
+ put_utf16(fp, '=');
+ put_utf16(fp, ' ');
+ put_utf16(fp, '\"');
+
+ ptr = m->string->value;
+ while ((ch = get_utf8(ptr)) != 0)
+ switch (ch)
+ {
+ case '\n' :
+ put_utf16(fp, '\\');
+ put_utf16(fp, 'n');
+ break;
+ case '\\' :
+ put_utf16(fp, '\\');
+ put_utf16(fp, '\\');
+ break;
+ case '\"' :
+ put_utf16(fp, '\\');
+ put_utf16(fp, '\"');
+ break;
+ default :
+ put_utf16(fp, ch);
+ break;
+ }
+
+ put_utf16(fp, '\"');
+ put_utf16(fp, ';');
+ put_utf16(fp, '\n');
+ }
+ else
+ {
+ cupsFilePuts(fp, "msgid \"");
+ for (ptr = m->id->value; *ptr; ptr ++)
+ switch (*ptr)
+ {
+ case '\n' :
+ cupsFilePuts(fp, "\\n");
+ break;
+ case '\\' :
+ cupsFilePuts(fp, "\\\\");
+ break;
+ case '\"' :
+ cupsFilePuts(fp, "\\\"");
+ break;
+ default :
+ cupsFilePutChar(fp, *ptr);
+ break;
+ }
+ cupsFilePuts(fp, "\"\n");
+
+ cupsFilePuts(fp, "msgstr \"");
+ for (ptr = m->string->value; *ptr; ptr ++)
+ switch (*ptr)
+ {
+ case '\n' :
+ cupsFilePuts(fp, "\\n");
+ break;
+ case '\\' :
+ cupsFilePuts(fp, "\\\\");
+ break;
+ case '\"' :
+ cupsFilePuts(fp, "\\\"");
+ break;
+ default :
+ cupsFilePutChar(fp, *ptr);
+ break;
+ }
+ cupsFilePuts(fp, "\"\n");
+
+ cupsFilePutChar(fp, '\n');
+ }
+ }
+
+ cupsFileClose(fp);
+
+ return (0);
+}
+
+
+//
+// 'get_utf8()' - Get a UTF-8 character.
+//
+
+static int // O - Unicode character or 0 on EOF
+get_utf8(char *&ptr) // IO - Pointer to character
+{
+ int ch; // Current character
+
+
+ if ((ch = *ptr++ & 255) < 0xc0)
+ return (ch);
+
+ if ((ch & 0xe0) == 0xc0)
+ {
+ // Two-byte UTF-8...
+ if ((*ptr & 0xc0) != 0x80)
+ return (0);
+
+ ch = ((ch & 0x1f) << 6) | (*ptr++ & 0x3f);
+ }
+ else if ((ch & 0xf0) == 0xe0)
+ {
+ // Three-byte UTF-8...
+ if ((*ptr & 0xc0) != 0x80)
+ return (0);
+
+ ch = ((ch & 0x0f) << 6) | (*ptr++ & 0x3f);
+
+ if ((*ptr & 0xc0) != 0x80)
+ return (0);
+
+ ch = (ch << 6) | (*ptr++ & 0x3f);
+ }
+ else if ((ch & 0xf8) == 0xf0)
+ {
+ // Four-byte UTF-8...
+ if ((*ptr & 0xc0) != 0x80)
+ return (0);
+
+ ch = ((ch & 0x07) << 6) | (*ptr++ & 0x3f);
+
+ if ((*ptr & 0xc0) != 0x80)
+ return (0);
+
+ ch = (ch << 6) | (*ptr++ & 0x3f);
+
+ if ((*ptr & 0xc0) != 0x80)
+ return (0);
+
+ ch = (ch << 6) | (*ptr++ & 0x3f);
+ }
+
+ return (ch);
+}
+
+
+//
+// 'get_utf16()' - Get a UTF-16 character...
+//
+
+static int // O - Unicode character or 0 on EOF
+get_utf16(cups_file_t *fp, // I - File to read from
+ ppdc_cs_t &cs) // IO - Character set of file
+{
+ int ch; // Current character
+ unsigned char buffer[3]; // Bytes
+
+
+ if (cs == PPDC_CS_AUTO)
+ {
+ // Get byte-order-mark, if present...
+ if (cupsFileRead(fp, (char *)buffer, 2) != 2)
+ return (0);
+
+ if (buffer[0] == 0xfe && buffer[1] == 0xff)
+ {
+ // Big-endian UTF-16...
+ cs = PPDC_CS_UTF16BE;
+
+ if (cupsFileRead(fp, (char *)buffer, 2) != 2)
+ return (0);
+ }
+ else if (buffer[0] == 0xff && buffer[1] == 0xfe)
+ {
+ // Little-endian UTF-16...
+ cs = PPDC_CS_UTF16LE;
+
+ if (cupsFileRead(fp, (char *)buffer, 2) != 2)
+ return (0);
+ }
+ else if (buffer[0] == 0x00 && buffer[1] != 0x00)
+ {
+ // No BOM, assume big-endian UTF-16...
+ cs = PPDC_CS_UTF16BE;
+ }
+ else if (buffer[0] != 0x00 && buffer[1] == 0x00)
+ {
+ // No BOM, assume little-endian UTF-16...
+ cs = PPDC_CS_UTF16LE;
+ }
+ else
+ {
+ // No BOM, assume UTF-8...
+ cs = PPDC_CS_UTF8;
+
+ cupsFileRewind(fp);
+ }
+ }
+ else if (cs != PPDC_CS_UTF8)
+ {
+ if (cupsFileRead(fp, (char *)buffer, 2) != 2)
+ return (0);
+ }
+
+ if (cs == PPDC_CS_UTF8)
+ {
+ // UTF-8 character...
+ if ((ch = cupsFileGetChar(fp)) < 0)
+ return (0);
+
+ if ((ch & 0xe0) == 0xc0)
+ {
+ // Two-byte UTF-8...
+ if (cupsFileRead(fp, (char *)buffer, 1) != 1)
+ return (0);
+
+ if ((buffer[0] & 0xc0) != 0x80)
+ return (0);
+
+ ch = ((ch & 0x1f) << 6) | (buffer[0] & 0x3f);
+ }
+ else if ((ch & 0xf0) == 0xe0)
+ {
+ // Three-byte UTF-8...
+ if (cupsFileRead(fp, (char *)buffer, 2) != 2)
+ return (0);
+
+ if ((buffer[0] & 0xc0) != 0x80 ||
+ (buffer[1] & 0xc0) != 0x80)
+ return (0);
+
+ ch = ((((ch & 0x0f) << 6) | (buffer[0] & 0x3f)) << 6) |
+ (buffer[1] & 0x3f);
+ }
+ else if ((ch & 0xf8) == 0xf0)
+ {
+ // Four-byte UTF-8...
+ if (cupsFileRead(fp, (char *)buffer, 3) != 3)
+ return (0);
+
+ if ((buffer[0] & 0xc0) != 0x80 ||
+ (buffer[1] & 0xc0) != 0x80 ||
+ (buffer[2] & 0xc0) != 0x80)
+ return (0);
+
+ ch = ((((((ch & 0x07) << 6) | (buffer[0] & 0x3f)) << 6) |
+ (buffer[1] & 0x3f)) << 6) | (buffer[2] & 0x3f);
+ }
+ }
+ else
+ {
+ // UTF-16 character...
+ if (cs == PPDC_CS_UTF16BE)
+ ch = (buffer[0] << 8) | buffer[1];
+ else
+ ch = (buffer[1] << 8) | buffer[0];
+
+ if (ch >= 0xd800 && ch <= 0xdbff)
+ {
+ // Handle multi-word encoding...
+ int lch;
+
+ if (cupsFileRead(fp, (char *)buffer, 2) != 2)
+ return (0);
+
+ if (cs == PPDC_CS_UTF16BE)
+ lch = (buffer[0] << 8) | buffer[1];
+ else
+ lch = (buffer[1] << 8) | buffer[0];
+
+ if (lch < 0xdc00 || lch >= 0xdfff)
+ return (0);
+
+ ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
+ }
+ }
+
+ return (ch);
+}
+
+
+//
+// 'put_utf8()' - Add a UTF-8 character to a string.
+//
+
+static int // O - 0 on success, -1 on failure
+put_utf8(int ch, // I - Unicode character
+ char *&ptr, // IO - String pointer
+ char *end) // I - End of buffer
+{
+ if (ch < 0x80)
+ {
+ // One-byte ASCII...
+ if (ptr >= end)
+ return (-1);
+
+ *ptr++ = (char)ch;
+ }
+ else if (ch < 0x800)
+ {
+ // Two-byte UTF-8...
+ if ((ptr + 1) >= end)
+ return (-1);
+
+ *ptr++ = (char)(0xc0 | (ch >> 6));
+ *ptr++ = (char)(0x80 | (ch & 0x3f));
+ }
+ else if (ch < 0x10000)
+ {
+ // Three-byte UTF-8...
+ if ((ptr + 2) >= end)
+ return (-1);
+
+ *ptr++ = (char)(0xe0 | (ch >> 12));
+ *ptr++ = (char)(0x80 | ((ch >> 6) & 0x3f));
+ *ptr++ = (char)(0x80 | (ch & 0x3f));
+ }
+ else
+ {
+ // Four-byte UTF-8...
+ if ((ptr + 3) >= end)
+ return (-1);
+
+ *ptr++ = (char)(0xf0 | (ch >> 18));
+ *ptr++ = (char)(0x80 | ((ch >> 12) & 0x3f));
+ *ptr++ = (char)(0x80 | ((ch >> 6) & 0x3f));
+ *ptr++ = (char)(0x80 | (ch & 0x3f));
+ }
+
+ return (0);
+}
+
+
+//
+// 'put_utf16()' - Write a UTF-16 character to a file.
+//
+
+static int // O - 0 on success, -1 on failure
+put_utf16(cups_file_t *fp, // I - File to write to
+ int ch) // I - Unicode character
+{
+ unsigned char buffer[4]; // Output buffer
+
+
+ if (ch < 0x10000)
+ {
+ // One-word UTF-16 big-endian...
+ buffer[0] = (unsigned char)(ch >> 8);
+ buffer[1] = (unsigned char)ch;
+
+ if (cupsFileWrite(fp, (char *)buffer, 2) == 2)
+ return (0);
+ }
+ else
+ {
+ // Two-word UTF-16 big-endian...
+ ch -= 0x10000;
+
+ buffer[0] = (unsigned char)(0xd8 | (ch >> 18));
+ buffer[1] = (unsigned char)(ch >> 10);
+ buffer[2] = (unsigned char)(0xdc | ((ch >> 8) & 0x03));
+ buffer[3] = (unsigned char)ch;
+
+ if (cupsFileWrite(fp, (char *)buffer, 4) == 4)
+ return (0);
+ }
+
+ return (-1);
+}
--- /dev/null
+//
+// Option choice class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcChoice::ppdcChoice()' - Create a new option choice.
+//
+
+ppdcChoice::ppdcChoice(const char *n, // I - Name of choice
+ const char *t, // I - Text of choice
+ const char *c) // I - Code of choice
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ name = new ppdcString(n);
+ text = new ppdcString(t);
+ code = new ppdcString(c);
+}
+
+
+//
+// 'ppdcChoice::~ppdcChoice()' - Destroy an option choice.
+//
+
+ppdcChoice::~ppdcChoice()
+{
+ PPDC_DELETE;
+
+ name->release();
+ text->release();
+ code->release();
+}
--- /dev/null
+//
+// Contraint class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcConstraint::ppdcConstraint()' - Create a constraint.
+//
+
+ppdcConstraint::ppdcConstraint(const char *o1, // I - First option
+ const char *c1, // I - First choice
+ const char *o2, // I - Second option
+ const char *c2) // I - Second choice
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ option1 = new ppdcString(o1);
+ choice1 = new ppdcString(c1);
+ option2 = new ppdcString(o2);
+ choice2 = new ppdcString(c2);
+}
+
+
+//
+// 'ppdcConstraint::~ppdcConstraint()' - Destroy a constraint.
+//
+
+ppdcConstraint::~ppdcConstraint()
+{
+ PPDC_DELETE;
+
+ option1->release();
+ choice1->release();
+ option2->release();
+ choice2->release();
+}
--- /dev/null
+//
+// PPD file compiler definitions for the CUPS PPD Compiler.
+//
+// Copyright © 2007-2019 by Apple Inc.
+// Copyright © 2002-2006 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more
+// information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+#include <cupsfilters/ppdgenerator.h>
+
+
+//
+// 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
+//
+
+ppdcDriver::ppdcDriver(ppdcDriver *d) // I - Printer driver template
+ : ppdcShared()
+{
+ ppdcGroup *g; // Current group
+
+
+ PPDC_NEW;
+
+ if (d)
+ {
+ // Bump the use count of any strings we inherit...
+ if (d->manufacturer)
+ d->manufacturer->retain();
+ if (d->version)
+ d->version->retain();
+ if (d->default_font)
+ d->default_font->retain();
+ if (d->default_size)
+ d->default_size->retain();
+ if (d->custom_size_code)
+ d->custom_size_code->retain();
+
+ // Copy all of the data from the driver template...
+ copyright = new ppdcArray(d->copyright);
+ manufacturer = d->manufacturer;
+ model_name = 0;
+ file_name = 0;
+ pc_file_name = 0;
+ type = d->type;
+ version = d->version;
+ model_number = d->model_number;
+ manual_copies = d->manual_copies;
+ color_device = d->color_device;
+ throughput = d->throughput;
+ attrs = new ppdcArray(d->attrs);
+ constraints = new ppdcArray(d->constraints);
+ filters = new ppdcArray(d->filters);
+ fonts = new ppdcArray(d->fonts);
+ profiles = new ppdcArray(d->profiles);
+ sizes = new ppdcArray(d->sizes);
+ default_font = d->default_font;
+ default_size = d->default_size;
+ variable_paper_size = d->variable_paper_size;
+ custom_size_code = d->custom_size_code;
+ left_margin = d->left_margin;
+ bottom_margin = d->bottom_margin;
+ right_margin = d->right_margin;
+ top_margin = d->top_margin;
+ max_width = d->max_width;
+ max_length = d->max_length;
+ min_width = d->min_width;
+ min_length = d->min_length;
+
+ // Then copy the groups manually, since we want separate copies
+ // of the groups and options...
+ groups = new ppdcArray();
+
+ for (g = (ppdcGroup *)d->groups->first(); g; g = (ppdcGroup *)d->groups->next())
+ groups->add(new ppdcGroup(g));
+ }
+ else
+ {
+ // Zero all of the data in the driver...
+ copyright = new ppdcArray();
+ manufacturer = 0;
+ model_name = 0;
+ file_name = 0;
+ pc_file_name = 0;
+ version = 0;
+ type = PPDC_DRIVER_CUSTOM;
+ model_number = 0;
+ manual_copies = 0;
+ color_device = 0;
+ throughput = 1;
+ attrs = new ppdcArray();
+ constraints = new ppdcArray();
+ fonts = new ppdcArray();
+ filters = new ppdcArray();
+ groups = new ppdcArray();
+ profiles = new ppdcArray();
+ sizes = new ppdcArray();
+ default_font = 0;
+ default_size = 0;
+ variable_paper_size = 0;
+ custom_size_code = 0;
+ left_margin = 0;
+ bottom_margin = 0;
+ right_margin = 0;
+ top_margin = 0;
+ max_width = 0;
+ max_length = 0;
+ min_width = 0;
+ min_length = 0;
+ }
+}
+
+
+//
+// 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
+//
+
+ppdcDriver::~ppdcDriver()
+{
+ PPDC_DELETE;
+
+ copyright->release();
+
+ if (manufacturer)
+ manufacturer->release();
+ if (model_name)
+ model_name->release();
+ if (file_name)
+ file_name->release();
+ if (pc_file_name)
+ pc_file_name->release();
+ if (version)
+ version->release();
+ if (default_font)
+ default_font->release();
+ if (default_size)
+ default_size->release();
+ if (custom_size_code)
+ custom_size_code->release();
+
+ attrs->release();
+ constraints->release();
+ filters->release();
+ fonts->release();
+ groups->release();
+ profiles->release();
+ sizes->release();
+}
+
+
+//
+// 'ppdcDriver::find_attr()' - Find an attribute.
+//
+
+ppdcAttr * // O - Attribute or NULL
+ppdcDriver::find_attr(const char *k, // I - Keyword string
+ const char *s) // I - Spec string
+{
+ ppdcAttr *a; // Current attribute
+
+
+ for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
+ if (!strcmp(a->name->value, k) &&
+ ((!s && (!a->selector->value || !a->selector->value[0])) ||
+ (s && a->selector->value && !strcmp(a->selector->value, s))))
+ return (a);
+
+ return (NULL);
+}
+
+
+//
+// 'ppdcDriver::find_group()' - Find a group.
+//
+
+ppdcGroup * // O - Matching group or NULL
+ppdcDriver::find_group(const char *n) // I - Group name
+{
+ ppdcGroup *g; // Current group
+
+
+ for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
+ if (!strcasecmp(n, g->name->value))
+ return (g);
+
+ return (0);
+}
+
+
+//
+// 'ppdcDriver::find_option()' - Find an option.
+//
+
+ppdcOption * // O - Matching option or NULL
+ppdcDriver::find_option(const char *n) // I - Option name
+{
+ return (find_option_group(n, (ppdcGroup **)0));
+}
+
+
+//
+// 'ppdcDriver::find_option_group()' - Find an option and its group.
+//
+
+ppdcOption * // O - Matching option or NULL
+ppdcDriver::find_option_group(
+ const char *n, // I - Option name
+ ppdcGroup **mg) // O - Matching group or NULL
+{
+ ppdcGroup *g; // Current group
+ ppdcOption *o; // Current option
+
+
+ for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
+ for (o = (ppdcOption *)g->options->first(); o; o = (ppdcOption *)g->options->next())
+ if (!strcasecmp(n, o->name->value))
+ {
+ if (mg)
+ *mg = g;
+
+ return (o);
+ }
+
+ if (mg)
+ *mg = (ppdcGroup *)0;
+
+ return (0);
+}
+
+
+//
+// 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
+//
+
+void
+ppdcDriver::set_custom_size_code(
+ const char *c) // I - CustomPageSize code
+{
+ if (custom_size_code)
+ custom_size_code->release();
+
+ custom_size_code = new ppdcString(c);
+}
+
+
+//
+// 'ppdcDriver::set_default_font()' - Set the default font name.
+//
+
+void
+ppdcDriver::set_default_font(
+ ppdcFont *f) // I - Font
+{
+ if (default_font)
+ default_font->release();
+
+ if (f)
+ {
+ f->name->retain();
+ default_font = f->name;
+ }
+ else
+ default_font = 0;
+}
+
+
+//
+// 'ppdcDriver::set_default_size()' - Set the default size name.
+//
+
+void
+ppdcDriver::set_default_size(
+ ppdcMediaSize *m) // I - Media size
+{
+ if (default_size)
+ default_size->release();
+
+ if (m)
+ {
+ m->name->retain();
+ default_size = m->name;
+ }
+ else
+ default_size = 0;
+}
+
+
+//
+// 'ppdcDriver::set_file_name()' - Set the full filename.
+//
+
+void
+ppdcDriver::set_file_name(const char *f)// I - Filename
+{
+ if (file_name)
+ file_name->release();
+
+ file_name = new ppdcString(f);
+}
+
+
+//
+// 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
+//
+
+void
+ppdcDriver::set_manufacturer(
+ const char *m) // I - Model name
+{
+ if (manufacturer)
+ manufacturer->release();
+
+ manufacturer = new ppdcString(m);
+}
+
+
+//
+// 'ppdcDriver::set_model_name()' - Set the model name.
+//
+
+void
+ppdcDriver::set_model_name(
+ const char *m) // I - Model name
+{
+ if (model_name)
+ model_name->release();
+
+ model_name = new ppdcString(m);
+}
+
+
+//
+// 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
+//
+
+void
+ppdcDriver::set_pc_file_name(
+ const char *f) // I - Filename
+{
+ if (pc_file_name)
+ pc_file_name->release();
+
+ pc_file_name = new ppdcString(f);
+}
+
+
+//
+// 'ppdcDriver::set_version()' - Set the version string.
+//
+
+void
+ppdcDriver::set_version(const char *v) // I - Version
+{
+ if (version)
+ version->release();
+
+ version = new ppdcString(v);
+}
+
+
+//
+// 'ppdcDriver::write_ppd_file()' - Write a PPD file...
+//
+
+int // O - 0 on success, -1 on failure
+ppdcDriver::write_ppd_file(
+ cups_file_t *fp, // I - PPD file
+ ppdcCatalog *catalog, // I - Message catalog
+ ppdcArray *locales, // I - Additional languages to add
+ ppdcSource *src, // I - Driver source
+ ppdcLineEnding le) // I - Line endings to use
+{
+ bool delete_cat; // Delete the catalog when we are done?
+ char query[42], // Query attribute
+ custom[42]; // Custom attribute
+ ppdcString *s; // Copyright string
+ ppdcGroup *g; // Current group
+ ppdcOption *o; // Current option
+ ppdcChoice *c; // Current choice
+ ppdcMediaSize *m; // Current media size
+ ppdcProfile *p; // Current color profile
+ ppdcFilter *f; // Current filter
+ ppdcFont *fn, // Current font
+ *bfn; // Current base font
+ ppdcConstraint *cn; // Current constraint
+ ppdcAttr *a; // Current attribute
+ const char *lf; // Linefeed character to use
+
+
+ // If we don't have a message catalog, use an empty (English) one...
+ if (!catalog)
+ {
+ catalog = new ppdcCatalog(NULL);
+ delete_cat = true;
+ }
+ else
+ delete_cat = false;
+
+ // Figure out the end-of-line string...
+ if (le == PPDC_LFONLY)
+ lf = "\n";
+ else if (le == PPDC_CRONLY)
+ lf = "\r";
+ else
+ lf = "\r\n";
+
+ // Write the standard header stuff...
+ cupsFilePrintf(fp, "*PPD-Adobe: \"4.3\"%s", lf);
+ cupsFilePrintf(fp, "*%%%%%%%% PPD file for %s with CUPS.%s",
+ model_name->value, lf);
+ cupsFilePrintf(fp,
+ "*%%%%%%%% Created by the PPD Compiler of cups-filters "
+ PACKAGE_VERSION ".%s", lf);
+ for (s = (ppdcString *)copyright->first();
+ s;
+ s = (ppdcString *)copyright->next())
+ cupsFilePrintf(fp, "*%% %s%s", catalog->find_message(s->value), lf);
+ cupsFilePrintf(fp, "*FormatVersion: \"4.3\"%s", lf);
+ cupsFilePrintf(fp, "*FileVersion: \"%s\"%s", version->value, lf);
+
+ a = find_attr("LanguageVersion", NULL);
+ cupsFilePrintf(fp, "*LanguageVersion: %s%s",
+ catalog->find_message(a ? a->value->value : "English"), lf);
+
+ a = find_attr("LanguageEncoding", NULL);
+ cupsFilePrintf(fp, "*LanguageEncoding: %s%s",
+ catalog->find_message(a ? a->value->value : "ISOLatin1"), lf);
+
+ cupsFilePrintf(fp, "*PCFileName: \"%s\"%s", pc_file_name->value, lf);
+
+ for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
+ if (!strcmp(a->name->value, "Product"))
+ break;
+
+ if (a)
+ {
+ for (; a; a = (ppdcAttr *)attrs->next())
+ if (!strcmp(a->name->value, "Product"))
+ cupsFilePrintf(fp, "*Product: \"%s\"%s", a->value->value, lf);
+ }
+ else
+ cupsFilePrintf(fp, "*Product: \"(%s)\"%s", model_name->value, lf);
+
+ cupsFilePrintf(fp, "*Manufacturer: \"%s\"%s",
+ catalog->find_message(manufacturer->value), lf);
+
+ if ((a = find_attr("ModelName", NULL)) != NULL)
+ cupsFilePrintf(fp, "*ModelName: \"%s\"%s",
+ catalog->find_message(a->value->value), lf);
+ else if (strncasecmp(model_name->value, manufacturer->value,
+ strlen(manufacturer->value)))
+ cupsFilePrintf(fp, "*ModelName: \"%s %s\"%s",
+ catalog->find_message(manufacturer->value),
+ catalog->find_message(model_name->value), lf);
+ else
+ cupsFilePrintf(fp, "*ModelName: \"%s\"%s",
+ catalog->find_message(model_name->value), lf);
+
+ if ((a = find_attr("ShortNickName", NULL)) != NULL)
+ cupsFilePrintf(fp, "*ShortNickName: \"%s\"%s",
+ catalog->find_message(a->value->value), lf);
+ else if (strncasecmp(model_name->value, manufacturer->value,
+ strlen(manufacturer->value)))
+ cupsFilePrintf(fp, "*ShortNickName: \"%s %s\"%s",
+ catalog->find_message(manufacturer->value),
+ catalog->find_message(model_name->value), lf);
+ else
+ cupsFilePrintf(fp, "*ShortNickName: \"%s\"%s",
+ catalog->find_message(model_name->value), lf);
+
+ if ((a = find_attr("NickName", NULL)) != NULL)
+ cupsFilePrintf(fp, "*NickName: \"%s\"%s",
+ catalog->find_message(a->value->value), lf);
+ else if (strncasecmp(model_name->value, manufacturer->value,
+ strlen(manufacturer->value)))
+ cupsFilePrintf(fp, "*NickName: \"%s %s, %s\"%s",
+ catalog->find_message(manufacturer->value),
+ catalog->find_message(model_name->value), version->value,
+ lf);
+ else
+ cupsFilePrintf(fp, "*NickName: \"%s, %s\"%s",
+ catalog->find_message(model_name->value), version->value,
+ lf);
+
+ for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
+ if (!strcmp(a->name->value, "PSVersion"))
+ break;
+
+ if (a)
+ {
+ for (; a; a = (ppdcAttr *)attrs->next())
+ if (!strcmp(a->name->value, "PSVersion"))
+ cupsFilePrintf(fp, "*PSVersion: \"%s\"%s", a->value->value, lf);
+ }
+ else
+ cupsFilePrintf(fp, "*PSVersion: \"(3010.000) 0\"%s", lf);
+
+ if ((a = find_attr("LanguageLevel", NULL)) != NULL)
+ cupsFilePrintf(fp, "*LanguageLevel: \"%s\"%s", a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*LanguageLevel: \"3\"%s", lf);
+
+ cupsFilePrintf(fp, "*ColorDevice: %s%s", color_device ? "True" : "False", lf);
+
+ if ((a = find_attr("DefaultColorSpace", NULL)) != NULL)
+ cupsFilePrintf(fp, "*DefaultColorSpace: %s%s", a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*DefaultColorSpace: %s%s",
+ color_device ? "RGB" : "Gray", lf);
+
+ if ((a = find_attr("FileSystem", NULL)) != NULL)
+ cupsFilePrintf(fp, "*FileSystem: %s%s", a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*FileSystem: False%s", lf);
+
+ cupsFilePrintf(fp, "*Throughput: \"%d\"%s", throughput, lf);
+
+ if ((a = find_attr("LandscapeOrientation", NULL)) != NULL)
+ cupsFilePrintf(fp, "*LandscapeOrientation: %s%s", a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*LandscapeOrientation: Plus90%s", lf);
+
+ if ((a = find_attr("TTRasterizer", NULL)) != NULL)
+ cupsFilePrintf(fp, "*TTRasterizer: %s%s", a->value->value, lf);
+ else if (type != PPDC_DRIVER_PS)
+ cupsFilePrintf(fp, "*TTRasterizer: Type42%s", lf);
+
+ struct lconv *loc = localeconv();
+
+ if (attrs->count)
+ {
+ // Write driver-defined attributes...
+ cupsFilePrintf(fp, "*%% Driver-defined attributes...%s", lf);
+ for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
+ {
+ if (!strcmp(a->name->value, "Product") ||
+ !strcmp(a->name->value, "PSVersion") ||
+ !strcmp(a->name->value, "LanguageLevel") ||
+ !strcmp(a->name->value, "DefaultColorSpace") ||
+ !strcmp(a->name->value, "FileSystem") ||
+ !strcmp(a->name->value, "LandscapeOrientation") ||
+ !strcmp(a->name->value, "TTRasterizer") ||
+ !strcmp(a->name->value, "LanguageVersion") ||
+ !strcmp(a->name->value, "LanguageEncoding") ||
+ !strcmp(a->name->value, "ModelName") ||
+ !strcmp(a->name->value, "NickName") ||
+ !strcmp(a->name->value, "ShortNickName") ||
+ !strcmp(a->name->value, "cupsVersion"))
+ continue;
+
+ if (a->name->value[0] == '?' &&
+ (find_option(a->name->value + 1) ||
+ !strcmp(a->name->value, "?ImageableArea") ||
+ !strcmp(a->name->value, "?PageRegion") ||
+ !strcmp(a->name->value, "?PageSize") ||
+ !strcmp(a->name->value, "?PaperDimension")))
+ continue;
+
+ if (!strncmp(a->name->value, "Custom", 6) &&
+ find_option(a->name->value + 6))
+ continue;
+
+ if (!strncmp(a->name->value, "ParamCustom", 11) &&
+ find_option(a->name->value + 11))
+ continue;
+
+ if (!a->selector->value || !a->selector->value[0])
+ cupsFilePrintf(fp, "*%s", a->name->value);
+ else if (!a->text->value || !a->text->value[0])
+ cupsFilePrintf(fp, "*%s %s", a->name->value, a->selector->value);
+ else
+ cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
+ a->text->value);
+
+ if (strcmp(a->value->value, "False") &&
+ strcmp(a->value->value, "True") &&
+ strcmp(a->name->value, "1284Modes") &&
+ strcmp(a->name->value, "InkName") &&
+ strcmp(a->name->value, "PageStackOrder") &&
+ strncmp(a->name->value, "ParamCustom", 11) &&
+ strcmp(a->name->value, "Protocols") &&
+ strcmp(a->name->value, "ReferencePunch") &&
+ strncmp(a->name->value, "Default", 7))
+ {
+ cupsFilePrintf(fp, ": \"%s\"%s", a->value->value, lf);
+
+ if (strchr(a->value->value, '\n') || strchr(a->value->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+ else
+ cupsFilePrintf(fp, ": %s%s", a->value->value, lf);
+ }
+ }
+
+ if (type != PPDC_DRIVER_PS || filters->count)
+ {
+ if ((a = find_attr("cupsVersion", NULL)) != NULL)
+ cupsFilePrintf(fp, "*cupsVersion: %s%s", a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR,
+ CUPS_VERSION_MINOR, lf);
+ cupsFilePrintf(fp, "*cupsModelNumber: %d%s", model_number, lf);
+ cupsFilePrintf(fp, "*cupsManualCopies: %s%s",
+ manual_copies ? "True" : "False", lf);
+
+ if (filters->count)
+ {
+ for (f = (ppdcFilter *)filters->first();
+ f;
+ f = (ppdcFilter *)filters->next())
+ cupsFilePrintf(fp, "*cupsFilter: \"%s %d %s\"%s", f->mime_type->value,
+ f->cost, f->program->value, lf);
+ }
+ else
+ {
+ switch (type)
+ {
+ case PPDC_DRIVER_LABEL :
+ cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
+ "rastertolabel\"%s", lf);
+ break;
+
+ case PPDC_DRIVER_EPSON :
+ cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
+ "rastertoepson\"%s", lf);
+ break;
+
+ case PPDC_DRIVER_ESCP :
+ cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-command 50 "
+ "commandtoescpx\"%s", lf);
+ cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
+ "rastertoescpx\"%s", lf);
+ break;
+
+ case PPDC_DRIVER_HP :
+ cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
+ "rastertohp\"%s", lf);
+ break;
+
+ case PPDC_DRIVER_PCL :
+ cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-command 50 "
+ "commandtopclx\"%s", lf);
+ cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
+ "rastertopclx\"%s", lf);
+ break;
+
+ default :
+ break;
+ }
+ }
+
+ for (p = (ppdcProfile *)profiles->first();
+ p;
+ p = (ppdcProfile *)profiles->next())
+ {
+ char density[255], gamma[255], profile[9][255];
+
+ cfStrFormatd(density, density + sizeof(density), p->density, loc);
+ cfStrFormatd(gamma, gamma + sizeof(gamma), p->gamma, loc);
+
+ for (int i = 0; i < 9; i ++)
+ cfStrFormatd(profile[i], profile[i] + sizeof(profile[0]),
+ p->profile[i], loc);
+
+ cupsFilePrintf(fp,
+ "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
+ "%s\"%s", p->resolution->value, p->media_type->value,
+ density, gamma, profile[0], profile[1], profile[2],
+ profile[3], profile[4], profile[5], profile[6], profile[7],
+ profile[8], lf);
+ }
+ }
+
+ if (locales)
+ {
+ // Add localizations for additional languages...
+ ppdcString *locale; // Locale name
+ ppdcCatalog *locatalog; // Message catalog for locale
+
+
+ // Write the list of languages...
+ cupsFilePrintf(fp, "*cupsLanguages: \"en");
+
+ for (locale = (ppdcString *)locales->first();
+ locale;
+ locale = (ppdcString *)locales->next())
+ {
+ // Skip (US) English...
+ if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
+ continue;
+
+ // See if we have a po file for this language...
+ if (!src->find_po(locale->value))
+ {
+ // No, see if we can use the base file?
+ locatalog = new ppdcCatalog(locale->value);
+
+ if (locatalog->messages->count == 0)
+ {
+ // No, skip this one...
+ fprintf(stderr,
+ _("ppdc: No message catalog provided for locale "
+ "%s.\n"), locale->value);
+ delete locatalog;
+ continue;
+ }
+
+ // Add the base file to the list...
+ src->po_files->add(locatalog);
+ }
+
+ cupsFilePrintf(fp, " %s", locale->value);
+ }
+
+ cupsFilePrintf(fp, "\"%s", lf);
+ }
+
+ for (cn = (ppdcConstraint *)constraints->first();
+ cn;
+ cn = (ppdcConstraint *)constraints->next())
+ {
+ // First constrain 1 against 2...
+ if (!strncmp(cn->option1->value, "*Custom", 7) ||
+ !strncmp(cn->option2->value, "*Custom", 7))
+ cupsFilePuts(fp, "*NonUIConstraints: ");
+ else
+ cupsFilePuts(fp, "*UIConstraints: ");
+
+ if (cn->option1->value[0] != '*')
+ cupsFilePutChar(fp, '*');
+
+ cupsFilePuts(fp, cn->option1->value);
+
+ if (cn->choice1->value)
+ cupsFilePrintf(fp, " %s", cn->choice1->value);
+
+ cupsFilePutChar(fp, ' ');
+
+ if (cn->option2->value[0] != '*')
+ cupsFilePutChar(fp, '*');
+
+ cupsFilePuts(fp, cn->option2->value);
+
+ if (cn->choice2->value)
+ cupsFilePrintf(fp, " %s", cn->choice2->value);
+
+ cupsFilePuts(fp, lf);
+
+ // Then constrain 2 against 1...
+ if (!strncmp(cn->option1->value, "*Custom", 7) ||
+ !strncmp(cn->option2->value, "*Custom", 7))
+ cupsFilePuts(fp, "*NonUIConstraints: ");
+ else
+ cupsFilePuts(fp, "*UIConstraints: ");
+
+ if (cn->option2->value[0] != '*')
+ cupsFilePutChar(fp, '*');
+
+ cupsFilePuts(fp, cn->option2->value);
+
+ if (cn->choice2->value)
+ cupsFilePrintf(fp, " %s", cn->choice2->value);
+
+ cupsFilePutChar(fp, ' ');
+
+ if (cn->option1->value[0] != '*')
+ cupsFilePutChar(fp, '*');
+
+ cupsFilePuts(fp, cn->option1->value);
+
+ if (cn->choice1->value)
+ cupsFilePrintf(fp, " %s", cn->choice1->value);
+
+ cupsFilePuts(fp, lf);
+ }
+
+ // PageSize option...
+ cupsFilePrintf(fp, "*OpenUI *PageSize/Media Size: PickOne%s", lf);
+ cupsFilePrintf(fp, "*OrderDependency: 10 AnySetup *PageSize%s", lf);
+ cupsFilePrintf(fp, "*DefaultPageSize: %s%s",
+ default_size ? default_size->value : "Letter", lf);
+
+ for (m = (ppdcMediaSize *)sizes->first();
+ m;
+ m = (ppdcMediaSize *)sizes->next())
+ if (m->size_code->value)
+ {
+ cupsFilePrintf(fp, "*PageSize %s/%s: \"%s\"%s",
+ m->name->value, catalog->find_message(m->text->value),
+ m->size_code->value, lf);
+
+ if (strchr(m->size_code->value, '\n') ||
+ strchr(m->size_code->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+ else
+ cupsFilePrintf(fp,
+ "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
+ "/ImagingBBox null>>setpagedevice\"%s",
+ m->name->value, catalog->find_message(m->text->value),
+ m->width, m->length, lf);
+
+ if ((a = find_attr("?PageSize", NULL)) != NULL)
+ {
+ cupsFilePrintf(fp, "*?PageSize: \"%s\"%s", a->value->value, lf);
+
+ if (strchr(a->value->value, '\n') ||
+ strchr(a->value->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+
+ cupsFilePrintf(fp, "*CloseUI: *PageSize%s", lf);
+
+ // PageRegion option...
+ cupsFilePrintf(fp, "*OpenUI *PageRegion/Media Size: PickOne%s", lf);
+ cupsFilePrintf(fp, "*OrderDependency: 10 AnySetup *PageRegion%s", lf);
+ cupsFilePrintf(fp, "*DefaultPageRegion: %s%s",
+ default_size ? default_size->value : "Letter", lf);
+
+ for (m = (ppdcMediaSize *)sizes->first();
+ m;
+ m = (ppdcMediaSize *)sizes->next())
+ if (m->region_code->value)
+ {
+ cupsFilePrintf(fp, "*PageRegion %s/%s: \"%s\"%s",
+ m->name->value, catalog->find_message(m->text->value),
+ m->region_code->value, lf);
+
+ if (strchr(m->region_code->value, '\n') ||
+ strchr(m->region_code->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+ else
+ cupsFilePrintf(fp,
+ "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
+ "/ImagingBBox null>>setpagedevice\"%s",
+ m->name->value, catalog->find_message(m->text->value),
+ m->width, m->length, lf);
+
+ if ((a = find_attr("?PageRegion", NULL)) != NULL)
+ {
+ cupsFilePrintf(fp, "*?PageRegion: \"%s\"%s", a->value->value, lf);
+
+ if (strchr(a->value->value, '\n') ||
+ strchr(a->value->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+
+ cupsFilePrintf(fp, "*CloseUI: *PageRegion%s", lf);
+
+ // ImageableArea info...
+ cupsFilePrintf(fp, "*DefaultImageableArea: %s%s",
+ default_size ? default_size->value : "Letter", lf);
+
+ char left[255], right[255], bottom[255], top[255];
+
+ for (m = (ppdcMediaSize *)sizes->first();
+ m;
+ m = (ppdcMediaSize *)sizes->next())
+ {
+ cfStrFormatd(left, left + sizeof(left), m->left, loc);
+ cfStrFormatd(bottom, bottom + sizeof(bottom), m->bottom, loc);
+ cfStrFormatd(right, right + sizeof(right), m->width - m->right, loc);
+ cfStrFormatd(top, top + sizeof(top), m->length - m->top, loc);
+
+ cupsFilePrintf(fp, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
+ m->name->value, catalog->find_message(m->text->value),
+ left, bottom, right, top, lf);
+ }
+
+ if ((a = find_attr("?ImageableArea", NULL)) != NULL)
+ {
+ cupsFilePrintf(fp, "*?ImageableArea: \"%s\"%s", a->value->value, lf);
+
+ if (strchr(a->value->value, '\n') ||
+ strchr(a->value->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+
+ // PaperDimension info...
+ cupsFilePrintf(fp, "*DefaultPaperDimension: %s%s",
+ default_size ? default_size->value : "Letter", lf);
+
+ char width[255], length[255];
+
+ for (m = (ppdcMediaSize *)sizes->first();
+ m;
+ m = (ppdcMediaSize *)sizes->next())
+ {
+ cfStrFormatd(width, width + sizeof(width), m->width, loc);
+ cfStrFormatd(length, length + sizeof(length), m->length, loc);
+
+ cupsFilePrintf(fp, "*PaperDimension %s/%s: \"%s %s\"%s",
+ m->name->value, catalog->find_message(m->text->value),
+ width, length, lf);
+ }
+
+ if ((a = find_attr("?PaperDimension", NULL)) != NULL)
+ {
+ cupsFilePrintf(fp, "*?PaperDimension: \"%s\"%s", a->value->value, lf);
+
+ if (strchr(a->value->value, '\n') ||
+ strchr(a->value->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+
+ // Custom size support...
+ if (variable_paper_size)
+ {
+ cfStrFormatd(width, width + sizeof(width), max_width, loc);
+ cfStrFormatd(length, length + sizeof(length), max_length, loc);
+
+ cfStrFormatd(left, left + sizeof(left), left_margin, loc);
+ cfStrFormatd(bottom, bottom + sizeof(bottom), bottom_margin, loc);
+ cfStrFormatd(right, right + sizeof(right), right_margin, loc);
+ cfStrFormatd(top, top + sizeof(top), top_margin, loc);
+
+ cupsFilePrintf(fp, "*MaxMediaWidth: \"%s\"%s", width, lf);
+ cupsFilePrintf(fp, "*MaxMediaHeight: \"%s\"%s", length, lf);
+ cupsFilePrintf(fp, "*HWMargins: %s %s %s %s%s", left, bottom, right, top,
+ lf);
+
+ if (custom_size_code && custom_size_code->value)
+ {
+ cupsFilePrintf(fp, "*CustomPageSize True: \"%s\"%s",
+ custom_size_code->value, lf);
+
+ if (strchr(custom_size_code->value, '\n') ||
+ strchr(custom_size_code->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+ else
+ cupsFilePrintf(fp,
+ "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
+ "/ImagingBBox null>>setpagedevice\"%s", lf);
+
+ if ((a = find_attr("ParamCustomPageSize", "Width")) != NULL)
+ cupsFilePrintf(fp, "*ParamCustomPageSize Width: %s%s", a->value->value,
+ lf);
+ else
+ {
+ char width0[255];
+
+ cfStrFormatd(width0, width0 + sizeof(width0), min_width, loc);
+ cfStrFormatd(width, width + sizeof(width), max_width, loc);
+
+ cupsFilePrintf(fp, "*ParamCustomPageSize Width: 1 points %s %s%s",
+ width0, width, lf);
+ }
+
+ if ((a = find_attr("ParamCustomPageSize", "Height")) != NULL)
+ cupsFilePrintf(fp, "*ParamCustomPageSize Height: %s%s", a->value->value,
+ lf);
+ else
+ {
+ char length0[255];
+
+ cfStrFormatd(length0, length0 + sizeof(length0), min_length, loc);
+ cfStrFormatd(length, length + sizeof(length), max_length, loc);
+
+ cupsFilePrintf(fp, "*ParamCustomPageSize Height: 2 points %s %s%s",
+ length0, length, lf);
+ }
+
+ if ((a = find_attr("ParamCustomPageSize", "WidthOffset")) != NULL)
+ cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: %s%s",
+ a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf);
+
+ if ((a = find_attr("ParamCustomPageSize", "HeightOffset")) != NULL)
+ cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: %s%s",
+ a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf);
+
+ if ((a = find_attr("ParamCustomPageSize", "Orientation")) != NULL)
+ cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: %s%s",
+ a->value->value, lf);
+ else
+ cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf);
+ }
+
+ // All other options...
+ for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
+ {
+ if (!g->options->count)
+ continue;
+
+ if (strcasecmp(g->name->value, "General"))
+ cupsFilePrintf(fp, "*OpenGroup: %s/%s%s", g->name->value,
+ catalog->find_message(g->text->value), lf);
+
+ for (o = (ppdcOption *)g->options->first();
+ o;
+ o = (ppdcOption *)g->options->next())
+ {
+ if (!o->choices->count)
+ continue;
+
+ if (o->section == PPDC_SECTION_JCL)
+ {
+ if (!o->text->value)
+ cupsFilePrintf(fp, "*JCLOpenUI *%s/%s: ", o->name->value,
+ catalog->find_message(o->name->value));
+ else
+ cupsFilePrintf(fp, "*JCLOpenUI *%s/%s: ", o->name->value,
+ catalog->find_message(o->text->value));
+ }
+ else if (!o->text->value)
+ cupsFilePrintf(fp, "*OpenUI *%s/%s: ", o->name->value,
+ catalog->find_message(o->name->value));
+ else
+ cupsFilePrintf(fp, "*OpenUI *%s/%s: ", o->name->value,
+ catalog->find_message(o->text->value));
+
+ switch (o->type)
+ {
+ case PPDC_BOOLEAN :
+ cupsFilePrintf(fp, "Boolean%s", lf);
+ break;
+ default :
+ cupsFilePrintf(fp, "PickOne%s", lf);
+ break;
+ case PPDC_PICKMANY :
+ cupsFilePrintf(fp, "PickMany%s", lf);
+ break;
+ }
+
+ char order[255];
+ cfStrFormatd(order, order + sizeof(order), o->order, loc);
+
+ cupsFilePrintf(fp, "*OrderDependency: %s ", order);
+ switch (o->section)
+ {
+ default :
+ cupsFilePrintf(fp, "AnySetup");
+ break;
+ case PPDC_SECTION_DOCUMENT :
+ cupsFilePrintf(fp, "DocumentSetup");
+ break;
+ case PPDC_SECTION_EXIT :
+ cupsFilePrintf(fp, "ExitServer");
+ break;
+ case PPDC_SECTION_JCL :
+ cupsFilePrintf(fp, "JCLSetup");
+ break;
+ case PPDC_SECTION_PAGE :
+ cupsFilePrintf(fp, "PageSetup");
+ break;
+ case PPDC_SECTION_PROLOG :
+ cupsFilePrintf(fp, "Prolog");
+ break;
+ }
+
+ cupsFilePrintf(fp, " *%s%s", o->name->value, lf);
+
+ if (o->defchoice)
+ {
+ // Use the programmer-supplied default...
+ cupsFilePrintf(fp, "*Default%s: %s%s", o->name->value,
+ o->defchoice->value, lf);
+ }
+ else
+ {
+ // Make the first choice the default...
+ c = (ppdcChoice *)o->choices->first();
+ cupsFilePrintf(fp, "*Default%s: %s%s", o->name->value, c->name->value,
+ lf);
+ }
+
+ for (c = (ppdcChoice *)o->choices->first();
+ c;
+ c = (ppdcChoice *)o->choices->next())
+ {
+ // Write this choice...
+ if (!c->text->value)
+ cupsFilePrintf(fp, "*%s %s/%s: \"%s\"%s", o->name->value,
+ c->name->value, catalog->find_message(c->name->value),
+ c->code->value, lf);
+ else
+ cupsFilePrintf(fp, "*%s %s/%s: \"%s\"%s", o->name->value,
+ c->name->value, catalog->find_message(c->text->value),
+ c->code->value, lf);
+
+ // Multi-line commands need a *End line to terminate them.
+ if (strchr(c->code->value, '\n') ||
+ strchr(c->code->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+
+ snprintf(query, sizeof(query), "?%s", o->name->value);
+
+ if ((a = find_attr(query, NULL)) != NULL)
+ {
+ cupsFilePrintf(fp, "*%s: \"%s\"%s", query, a->value->value, lf);
+
+ if (strchr(a->value->value, '\n') ||
+ strchr(a->value->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+ }
+
+ if (o->section == PPDC_SECTION_JCL)
+ cupsFilePrintf(fp, "*JCLCloseUI: *%s%s", o->name->value, lf);
+ else
+ cupsFilePrintf(fp, "*CloseUI: *%s%s", o->name->value, lf);
+
+ snprintf(custom, sizeof(custom), "Custom%s", o->name->value);
+ if ((a = find_attr(custom, "True")) != NULL)
+ {
+ // Output custom option information...
+ cupsFilePrintf(fp, "*%s True: \"%s\"%s", custom, a->value->value, lf);
+ if (strchr(a->value->value, '\n') || strchr(a->value->value, '\r'))
+ cupsFilePrintf(fp, "*End%s", lf);
+
+ snprintf(custom, sizeof(custom), "ParamCustom%s", o->name->value);
+ for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
+ {
+ if (strcmp(a->name->value, custom))
+ continue;
+
+ if (!a->selector->value || !a->selector->value[0])
+ cupsFilePrintf(fp, "*%s", a->name->value);
+ else if (!a->text->value || !a->text->value[0])
+ cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
+ catalog->find_message(a->selector->value));
+ else
+ cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
+ catalog->find_message(a->text->value));
+
+ cupsFilePrintf(fp, ": %s%s", a->value->value, lf);
+ }
+ }
+ }
+
+ if (strcasecmp(g->name->value, "General"))
+ cupsFilePrintf(fp, "*CloseGroup: %s%s", g->name->value, lf);
+ }
+
+ if (locales)
+ {
+ // Add localizations for additional languages...
+ ppdcString *locale; // Locale name
+ ppdcCatalog *locatalog; // Message catalog for locale
+
+
+ // Write the translation strings for each language...
+ for (locale = (ppdcString *)locales->first();
+ locale;
+ locale = (ppdcString *)locales->next())
+ {
+ // Skip (US) English...
+ if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
+ continue;
+
+ // Skip missing languages...
+ if ((locatalog = src->find_po(locale->value)) == NULL)
+ continue;
+
+ // Do the core stuff first...
+ cupsFilePrintf(fp, "*%s.Translation Manufacturer/%s: \"\"%s",
+ locale->value,
+ locatalog->find_message(manufacturer->value), lf);
+
+ if ((a = find_attr("ModelName", NULL)) != NULL)
+ cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
+ locale->value,
+ locatalog->find_message(a->value->value), lf);
+ else if (strncasecmp(model_name->value, manufacturer->value,
+ strlen(manufacturer->value)))
+ cupsFilePrintf(fp, "*%s.Translation ModelName/%s %s: \"\"%s",
+ locale->value,
+ locatalog->find_message(manufacturer->value),
+ locatalog->find_message(model_name->value), lf);
+ else
+ cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
+ locale->value,
+ locatalog->find_message(model_name->value), lf);
+
+ if ((a = find_attr("ShortNickName", NULL)) != NULL)
+ cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
+ locale->value,
+ locatalog->find_message(a->value->value), lf);
+ else if (strncasecmp(model_name->value, manufacturer->value,
+ strlen(manufacturer->value)))
+ cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s %s: \"\"%s",
+ locale->value,
+ locatalog->find_message(manufacturer->value),
+ locatalog->find_message(model_name->value), lf);
+ else
+ cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
+ locale->value,
+ locatalog->find_message(model_name->value), lf);
+
+ if ((a = find_attr("NickName", NULL)) != NULL)
+ cupsFilePrintf(fp, "*%s.Translation NickName/%s: \"\"%s",
+ locale->value,
+ locatalog->find_message(a->value->value), lf);
+ else if (strncasecmp(model_name->value, manufacturer->value,
+ strlen(manufacturer->value)))
+ cupsFilePrintf(fp, "*%s.Translation NickName/%s %s, %s: \"\"%s",
+ locale->value,
+ locatalog->find_message(manufacturer->value),
+ locatalog->find_message(model_name->value),
+ version->value, lf);
+ else
+ cupsFilePrintf(fp, "*%s.Translation NickName/%s, %s: \"\"%s",
+ locale->value,
+ locatalog->find_message(model_name->value),
+ version->value, lf);
+
+ // Then the page sizes...
+ cupsFilePrintf(fp, "*%s.Translation PageSize/%s: \"\"%s", locale->value,
+ locatalog->find_message("Media Size"), lf);
+
+ for (m = (ppdcMediaSize *)sizes->first();
+ m;
+ m = (ppdcMediaSize *)sizes->next())
+ {
+ cupsFilePrintf(fp, "*%s.PageSize %s/%s: \"\"%s", locale->value,
+ m->name->value, locatalog->find_message(m->text->value),
+ lf);
+ }
+
+ // Next the groups and options...
+ for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
+ {
+ if (!g->options->count)
+ continue;
+
+ if (strcasecmp(g->name->value, "General"))
+ cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
+ g->name->value,
+ locatalog->find_message(g->text->value), lf);
+
+ for (o = (ppdcOption *)g->options->first();
+ o;
+ o = (ppdcOption *)g->options->next())
+ {
+ if (!o->choices->count)
+ continue;
+
+ cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
+ o->name->value,
+ locatalog->find_message(o->text->value ?
+ o->text->value :
+ o->name->value), lf);
+
+ for (c = (ppdcChoice *)o->choices->first();
+ c;
+ c = (ppdcChoice *)o->choices->next())
+ {
+ // Write this choice...
+ cupsFilePrintf(fp, "*%s.%s %s/%s: \"\"%s", locale->value,
+ o->name->value, c->name->value,
+ locatalog->find_message(c->text->value ?
+ c->text->value :
+ c->name->value), lf);
+ }
+ }
+ }
+
+ // Finally the localizable attributes...
+ for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
+ {
+ if (!a->localizable &&
+ (!a->text || !a->text->value || !a->text->value[0]) &&
+ strcmp(a->name->value, "APCustomColorMatchingName") &&
+ strcmp(a->name->value, "APPrinterPreset") &&
+ strcmp(a->name->value, "cupsICCProfile") &&
+ strcmp(a->name->value, "cupsIPPReason") &&
+ strcmp(a->name->value, "cupsMarkerName") &&
+ strncmp(a->name->value, "Custom", 6) &&
+ strncmp(a->name->value, "ParamCustom", 11))
+ continue;
+
+ cupsFilePrintf(fp, "*%s.%s %s/%s: \"%s\"%s", locale->value,
+ a->name->value, a->selector->value,
+ locatalog->find_message(a->text && a->text->value ?
+ a->text->value : a->name->value),
+ ((a->localizable && a->value->value[0]) ||
+ !strcmp(a->name->value, "cupsIPPReason")) ?
+ locatalog->find_message(a->value->value) : "",
+ lf);
+ }
+ }
+ }
+
+ if (default_font && default_font->value)
+ cupsFilePrintf(fp, "*DefaultFont: %s%s", default_font->value, lf);
+ else
+ cupsFilePrintf(fp, "*DefaultFont: Courier%s", lf);
+
+ for (fn = (ppdcFont *)fonts->first(); fn; fn = (ppdcFont *)fonts->next())
+ if (!strcmp(fn->name->value, "*"))
+ {
+ for (bfn = (ppdcFont *)src->base_fonts->first();
+ bfn;
+ bfn = (ppdcFont *)src->base_fonts->next())
+ cupsFilePrintf(fp, "*Font %s: %s \"%s\" %s %s%s",
+ bfn->name->value, bfn->encoding->value,
+ bfn->version->value, bfn->charset->value,
+ bfn->status == PPDC_FONT_ROM ? "ROM" : "Disk", lf);
+ }
+ else
+ cupsFilePrintf(fp, "*Font %s: %s \"%s\" %s %s%s",
+ fn->name->value, fn->encoding->value, fn->version->value,
+ fn->charset->value,
+ fn->status == PPDC_FONT_ROM ? "ROM" : "Disk", lf);
+
+ cupsFilePrintf(fp, "*%% End of %s, %05d bytes.%s", pc_file_name->value,
+ (int)((size_t)cupsFileTell(fp) + 25 + strlen(pc_file_name->value)),
+ lf);
+
+ if (delete_cat)
+ catalog->release();
+
+ return (0);
+}
--- /dev/null
+//
+// File class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2010 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcFile::ppdcFile()' - Create (open) a file.
+//
+
+ppdcFile::ppdcFile(const char *f, // I - File to open
+ cups_file_t *ffp) // I - File pointer to use
+{
+ if (ffp)
+ {
+ fp = ffp;
+ cupsFileRewind(fp);
+ }
+ else
+ fp = cupsFileOpen(f, "r");
+
+ close_on_delete = !ffp;
+ filename = f;
+ line = 1;
+
+ if (!fp)
+ fprintf(stderr, _("ppdc: Unable to open %s: %s\n"), f,
+ strerror(errno));
+}
+
+
+//
+// 'ppdcFile::~ppdcFile()' - Delete (close) a file.
+//
+
+ppdcFile::~ppdcFile()
+{
+ if (close_on_delete && fp)
+ cupsFileClose(fp);
+}
+
+
+//
+// 'ppdcFile::get()' - Get a character from a file.
+//
+
+int
+ppdcFile::get()
+{
+ int ch; // Character from file
+
+
+ // Return EOF if there is no open file...
+ if (!fp)
+ return (EOF);
+
+ // Get the character...
+ ch = cupsFileGetChar(fp);
+
+ // Update the line number as needed...
+ if (ch == '\n')
+ line ++;
+
+ // Return the character...
+ return (ch);
+}
+
+
+//
+// 'ppdcFile::peek()' - Look at the next character from a file.
+//
+
+int // O - Next character in file
+ppdcFile::peek()
+{
+ // Return immediaely if there is no open file...
+ if (!fp)
+ return (EOF);
+
+ // Otherwise return the next character without advancing...
+ return (cupsFilePeekChar(fp));
+}
--- /dev/null
+//
+// Filter class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcFilter::ppdcFilter()' - Create a filter.
+//
+
+ppdcFilter::ppdcFilter(const char *t, // I - MIME type
+ const char *p, // I - Filter program
+ int c) // I - Relative cost
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ mime_type = new ppdcString(t);
+ program = new ppdcString(p);
+ cost = c;
+}
+
+
+//
+// 'ppdcFilter::~ppdcFilter()' - Destroy a filter.
+//
+
+ppdcFilter::~ppdcFilter()
+{
+ PPDC_DELETE;
+
+ mime_type->release();
+ program->release();
+}
--- /dev/null
+//
+// Shared font class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcFont::ppdcFont()' - Create a shared font.
+//
+
+ppdcFont::ppdcFont(const char *n, // I - Name of font
+ const char *e, // I - Font encoding
+ const char *v, // I - Font version
+ const char *c, // I - Font charset
+ ppdcFontStatus s) // I - Font status
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ name = new ppdcString(n);
+ encoding = new ppdcString(e);
+ version = new ppdcString(v);
+ charset = new ppdcString(c);
+ status = s;
+}
+
+
+//
+// 'ppdcFont::~ppdcFont()' - Destroy a shared font.
+//
+
+ppdcFont::~ppdcFont()
+{
+ PPDC_DELETE;
+
+ name->release();
+ encoding->release();
+ version->release();
+ charset->release();
+}
--- /dev/null
+//
+// Group class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2011 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcGroup::ppdcGroup()' - Create a new group.
+//
+
+ppdcGroup::ppdcGroup(const char *n, // I - Name of group
+ const char *t) // I - Text of group
+{
+ PPDC_NEWVAL(n);
+
+ name = new ppdcString(n);
+ text = new ppdcString(t);
+ options = new ppdcArray();
+}
+
+
+//
+// 'ppdcGroup::ppdcGroup()' - Copy a new group.
+//
+
+ppdcGroup::ppdcGroup(ppdcGroup *g) // I - Group template
+{
+ PPDC_NEWVAL(g->name->value);
+
+ g->name->retain();
+ g->text->retain();
+
+ name = g->name;
+ text = g->text;
+
+ options = new ppdcArray();
+ for (ppdcOption *o = (ppdcOption *)g->options->first();
+ o;
+ o = (ppdcOption *)g->options->next())
+ options->add(new ppdcOption(o));
+}
+
+
+//
+// 'ppdcGroup::~ppdcGroup()' - Destroy a group.
+//
+
+ppdcGroup::~ppdcGroup()
+{
+ PPDC_DELETEVAL(name ? name->value : NULL);
+
+ name->release();
+ text->release();
+ options->release();
+
+ name = text = 0;
+ options = 0;
+}
+
+
+//
+// 'ppdcGroup::find_option()' - Find an option in a group.
+//
+
+ppdcOption *
+ppdcGroup::find_option(const char *n) // I - Name of option
+{
+ ppdcOption *o; // Current option
+
+
+ for (o = (ppdcOption *)options->first(); o; o = (ppdcOption *)options->next())
+ if (!strcasecmp(n, o->name->value))
+ return (o);
+
+ return (0);
+}
--- /dev/null
+//
+// PPD file import methods for the CUPS PPD Compiler.
+//
+// Copyright 2007-2011 by Apple Inc.
+// Copyright 2002-2006 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+#include <ppd/ppd.h>
+
+
+//
+// 'ppdcSource::import_ppd()' - Import a PPD file.
+//
+
+int // O - 1 on success, 0 on failure
+ppdcSource::import_ppd(const char *f) // I - Filename
+{
+ int i, j, k; // Looping vars
+ cups_file_t *fp; // File
+ char line[256], // Comment line
+ *ptr; // Pointer into line
+ int cost; // Cost for filter
+ ppd_file_t *ppd; // PPD file data
+ ppd_group_t *group; // PPD group
+ ppd_option_t *option; // PPD option
+ ppd_choice_t *choice; // PPD choice
+ ppd_attr_t *attr; // PPD attribute
+ ppd_const_t *constraint; // PPD UI constraint
+ ppd_const_t *constraint2; // Temp PPD UI constraint
+ ppd_size_t *size; // PPD page size
+ ppdcDriver *driver; // Driver
+ ppdcFilter *filter; // Current filter
+ ppdcFont *font; // Font
+ ppdcGroup *cgroup; // UI group
+ ppdcOption *coption; // UI option
+ ppdcChoice *cchoice; // UI choice
+ ppdcConstraint *cconstraint; // UI constraint
+ ppdcMediaSize *csize; // Media size
+
+
+ // Try opening the PPD file...
+ if ((ppd = ppdOpenFile(f)) == NULL)
+ return (0);
+
+ // All PPD files need a PCFileName attribute...
+ if (!ppd->pcfilename)
+ {
+ ppdClose(ppd);
+ return (0);
+ }
+
+ // See if the driver has already been imported...
+ if (find_driver(ppd->pcfilename))
+ {
+ ppdClose(ppd);
+ return (1);
+ }
+
+ // Create a new PPD file...
+ if ((fp = cupsFileOpen(f, "r")) == NULL)
+ {
+ ppdClose(ppd);
+ return (0);
+ }
+
+ driver = new ppdcDriver();
+ driver->type = PPDC_DRIVER_PS;
+
+ drivers->add(driver);
+
+ // Read the initial comments from the PPD file and use them as the
+ // copyright/license text...
+ cupsFileGets(fp, line, sizeof(line));
+ // Skip *PPD-Adobe-M.m
+
+ while (cupsFileGets(fp, line, sizeof(line)))
+ if (strncmp(line, "*%", 2))
+ break;
+ else if (strncmp(line, "*%%%% ", 6))
+ {
+ for (ptr = line + 2; isspace(*ptr); ptr ++);
+
+ driver->add_copyright(ptr);
+ }
+
+ cupsFileClose(fp);
+
+ // Then add the stuff from the PPD file...
+ if (ppd->modelname && ppd->manufacturer &&
+ !strncasecmp(ppd->modelname, ppd->manufacturer,
+ strlen(ppd->manufacturer)))
+ {
+ ptr = ppd->modelname + strlen(ppd->manufacturer);
+
+ while (isspace(*ptr))
+ ptr ++;
+ }
+ else
+ ptr = ppd->modelname;
+
+ if (ppd->nickname)
+ driver->add_attr(new ppdcAttr("NickName", NULL, NULL, ppd->nickname));
+
+ if (ppd->shortnickname)
+ driver->add_attr(new ppdcAttr("ShortNickName", NULL, NULL,
+ ppd->shortnickname));
+
+ driver->manufacturer = new ppdcString(ppd->manufacturer);
+ driver->model_name = new ppdcString(ptr);
+ driver->pc_file_name = new ppdcString(ppd->pcfilename);
+ attr = ppdFindAttr(ppd, "FileVersion", NULL);
+ driver->version = new ppdcString(attr ? attr->value : NULL);
+ driver->model_number = ppd->model_number;
+ driver->manual_copies = ppd->manual_copies;
+ driver->color_device = ppd->color_device;
+ driver->throughput = ppd->throughput;
+ driver->variable_paper_size = ppd->variable_sizes;
+ driver->max_width = ppd->custom_max[0];
+ driver->max_length = ppd->custom_max[1];
+ driver->min_width = ppd->custom_min[0];
+ driver->min_length = ppd->custom_min[1];
+ driver->left_margin = ppd->custom_margins[0];
+ driver->bottom_margin = ppd->custom_margins[1];
+ driver->right_margin = ppd->custom_margins[2];
+ driver->top_margin = ppd->custom_margins[3];
+
+ for (i = 0; i < ppd->num_filters; i ++)
+ {
+ strncpy(line, ppd->filters[i], sizeof(line) - 1);
+
+ for (ptr = line; *ptr; ptr ++)
+ if (isspace(*ptr & 255))
+ break;
+ *ptr++ = '\0';
+
+ cost = strtol(ptr, &ptr, 10);
+
+ while (isspace(*ptr & 255))
+ ptr ++;
+
+ filter = new ppdcFilter(line, ptr, cost);
+ driver->add_filter(filter);
+ }
+
+ attr = ppdFindAttr(ppd, "DefaultFont", NULL);
+ driver->default_font = new ppdcString(attr ? attr->value : NULL);
+
+ // Collect media sizes...
+ ppd_option_t *region_option, // PageRegion option
+ *size_option; // PageSize option
+ ppd_choice_t *region_choice, // PageRegion choice
+ *size_choice; // PageSize choice
+
+ region_option = ppdFindOption(ppd, "PageRegion");
+ size_option = ppdFindOption(ppd, "PageSize");
+
+ for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
+ {
+ // Don't do custom size here...
+ if (!strcasecmp(size->name, "Custom"))
+ continue;
+
+ // Get the code for the PageSize and PageRegion options...
+ region_choice = ppdFindChoice(region_option, size->name);
+ size_choice = ppdFindChoice(size_option, size->name);
+
+ // Create a new media size record and add it to the driver...
+ csize = new ppdcMediaSize(size->name, size_choice->text, size->width,
+ size->length, size->left, size->bottom,
+ size->width - size->right,
+ size->length - size->top,
+ size_choice->code, region_choice->code);
+
+ driver->add_size(csize);
+
+ if (!strcasecmp(size_option->defchoice, size->name))
+ driver->set_default_size(csize);
+ }
+
+ // Now all of the options...
+ for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
+ {
+ cgroup = new ppdcGroup(group->name, group->text);
+ driver->add_group(cgroup);
+
+ for (j = group->num_options, option = group->options; j > 0; j --, option ++)
+ {
+ if (!strcmp(option->keyword, "PageSize") || !strcmp(option->keyword, "PageRegion"))
+ continue;
+
+ coption = new ppdcOption((ppdcOptType)option->ui, option->keyword,
+ option->text, (ppdcOptSection)option->section,
+ option->order);
+ cgroup->add_option(coption);
+
+ for (k = option->num_choices, choice = option->choices; k > 0; k --, choice ++)
+ {
+ if (!strcmp(choice->choice, "Custom"))
+ continue;
+
+ cchoice = new ppdcChoice(choice->choice, choice->text, choice->code);
+ coption->add_choice(cchoice);
+
+ if (!strcasecmp(option->defchoice, choice->choice))
+ coption->set_defchoice(cchoice);
+ }
+ }
+ }
+
+ // Now the constraints...
+ for (i = ppd->num_consts, constraint = ppd->consts;
+ i > 0;
+ i --, constraint ++)
+ {
+ // Look for mirrored constraints...
+ for (j = i - 1, constraint2 = constraint + 1;
+ j > 0;
+ j --, constraint2 ++)
+ if (!strcmp(constraint->option1, constraint2->option2) &&
+ !strcmp(constraint->choice1, constraint2->choice2) &&
+ !strcmp(constraint->option2, constraint2->option1) &&
+ !strcmp(constraint->choice2, constraint2->choice1))
+ break;
+
+ if (j)
+ continue;
+
+ cconstraint = new ppdcConstraint(constraint->option2, constraint->choice2,
+ constraint->option1, constraint->choice1);
+ driver->add_constraint(cconstraint);
+ }
+
+ for (i = 0; i < ppd->num_attrs; i ++)
+ {
+ attr = ppd->attrs[i];
+
+ if (!strcmp(attr->name, "Font"))
+ {
+ // Font...
+ char encoding[256], // Encoding string
+ version[256], // Version string
+ charset[256], // Charset string
+ status[256]; // Status string
+ ppdcFontStatus fstatus; // Status enumeration
+
+
+ if (sscanf(attr->value, "%s%*[^\"]\"%[^\"]\"%s%s", encoding, version,
+ charset, status) != 4)
+ {
+ fprintf(stderr, _("ppdc: Bad font attribute: %s\n"),
+ attr->value);
+ continue;
+ }
+
+ if (!strcmp(status, "ROM"))
+ fstatus = PPDC_FONT_ROM;
+ else
+ fstatus = PPDC_FONT_DISK;
+
+ font = new ppdcFont(attr->spec, encoding, version, charset, fstatus);
+
+ driver->add_font(font);
+ }
+ else if (!strcmp(attr->name, "CustomPageSize"))
+ {
+ driver->set_custom_size_code(attr->value);
+ }
+ else if ((strncmp(attr->name, "Default", 7) ||
+ !strcmp(attr->name, "DefaultColorSpace")) &&
+ strcmp(attr->name, "ColorDevice") &&
+ strcmp(attr->name, "Manufacturer") &&
+ strcmp(attr->name, "ModelName") &&
+ strcmp(attr->name, "MaxMediaHeight") &&
+ strcmp(attr->name, "MaxMediaWidth") &&
+ strcmp(attr->name, "NickName") &&
+ strcmp(attr->name, "ParamCustomPageSize") &&
+ strcmp(attr->name, "ShortNickName") &&
+ strcmp(attr->name, "Throughput") &&
+ strcmp(attr->name, "PCFileName") &&
+ strcmp(attr->name, "FileVersion") &&
+ strcmp(attr->name, "FormatVersion") &&
+ strcmp(attr->name, "HWMargins") &&
+ strcmp(attr->name, "VariablePaperSize") &&
+ strcmp(attr->name, "LanguageEncoding") &&
+ strcmp(attr->name, "LanguageVersion") &&
+ strcmp(attr->name, "cupsFilter") &&
+ strcmp(attr->name, "cupsFlipDuplex") &&
+ strcmp(attr->name, "cupsLanguages") &&
+ strcmp(attr->name, "cupsManualCopies") &&
+ strcmp(attr->name, "cupsModelNumber") &&
+ strcmp(attr->name, "cupsVersion"))
+ {
+ if ((ptr = strchr(attr->name, '.')) != NULL &&
+ ((ptr - attr->name) == 2 || (ptr - attr->name) == 5))
+ {
+ // Might be a localization attribute; test further...
+ if (isalpha(attr->name[0] & 255) &&
+ isalpha(attr->name[1] & 255) &&
+ (attr->name[2] == '.' ||
+ (attr->name[2] == '_' && isalpha(attr->name[3] & 255) &&
+ isalpha(attr->name[4] & 255))))
+ continue;
+ }
+
+ // Attribute...
+ driver->add_attr(new ppdcAttr(attr->name, attr->spec, attr->text,
+ attr->value));
+ }
+ else if (!strncmp(attr->name, "Default", 7) &&
+ !ppdFindOption(ppd, attr->name + 7) &&
+ strcmp(attr->name, "DefaultFont") &&
+ strcmp(attr->name, "DefaultImageableArea") &&
+ strcmp(attr->name, "DefaultPaperDimension") &&
+ strcmp(attr->name, "DefaultFont"))
+ {
+ // Default attribute...
+ driver->add_attr(new ppdcAttr(attr->name, attr->spec, attr->text,
+ attr->value));
+ }
+ }
+
+ ppdClose(ppd);
+
+ return (1);
+}
--- /dev/null
+//
+// Shared media size class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcMediaSize::ppdcMediaSize()' - Create a new media size.
+//
+
+ppdcMediaSize::ppdcMediaSize(const char *n, // I - Name of media size
+ const char *t, // I - Text of media size
+ float w, // I - Width in points
+ float l, // I - Length in points
+ float lm, // I - Left margin in points
+ float bm, // I - Bottom margin in points
+ float rm, // I - Right margin in points
+ float tm, // I - Top margin in points
+ const char *sc, // I - PageSize code, if any
+ const char *rc) // I - PageRegion code, if any
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ name = new ppdcString(n);
+ text = new ppdcString(t);
+ width = w;
+ length = l;
+ left = lm;
+ bottom = bm;
+ right = rm;
+ top = tm;
+ size_code = new ppdcString(sc);
+ region_code = new ppdcString(rc);
+
+ if (left < 0.0f)
+ left = 0.0f;
+ if (bottom < 0.0f)
+ bottom = 0.0f;
+ if (right < 0.0f)
+ right = 0.0f;
+ if (top < 0.0f)
+ top = 0.0f;
+}
+
+
+//
+// 'ppdcMediaSize::~ppdcMediaSize()' - Destroy a media size.
+//
+
+ppdcMediaSize::~ppdcMediaSize()
+{
+ PPDC_DELETE;
+
+ name->release();
+ text->release();
+ size_code->release();
+ region_code->release();
+}
--- /dev/null
+//
+// Shared message class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcMessage::ppdcMessage()' - Create a shared message.
+//
+
+ppdcMessage::ppdcMessage(const char *i, // I - ID
+ const char *s) // I - Text
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ id = new ppdcString(i);
+ string = new ppdcString(s);
+}
+
+
+//
+// 'ppdcMessage::~ppdcMessage()' - Destroy a shared message.
+//
+
+ppdcMessage::~ppdcMessage()
+{
+ PPDC_DELETE;
+
+ id->release();
+ string->release();
+}
--- /dev/null
+//
+// Option class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2011 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcOption::ppdcOption()' - Create a new option.
+//
+
+ppdcOption::ppdcOption(ppdcOptType ot, // I - Option type
+ const char *n, // I - Option name
+ const char *t, // I - Option text
+ ppdcOptSection s, // I - Section
+ float o) // I - Ordering number
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ type = ot;
+ name = new ppdcString(n);
+ text = new ppdcString(t);
+ section = s;
+ order = o;
+ choices = new ppdcArray();
+ defchoice = 0;
+}
+
+
+//
+// 'ppdcOption::ppdcOption()' - Copy a new option.
+//
+
+ppdcOption::ppdcOption(ppdcOption *o) // I - Template option
+{
+ PPDC_NEW;
+
+ o->name->retain();
+ o->text->retain();
+ if (o->defchoice)
+ o->defchoice->retain();
+
+ type = o->type;
+ name = o->name;
+ text = o->text;
+ section = o->section;
+ order = o->order;
+ choices = new ppdcArray(o->choices);
+ defchoice = o->defchoice;
+}
+
+
+//
+// 'ppdcOption::~ppdcOption()' - Destroy an option.
+//
+
+ppdcOption::~ppdcOption()
+{
+ PPDC_DELETE;
+
+ name->release();
+ text->release();
+ if (defchoice)
+ defchoice->release();
+ choices->release();
+}
+
+
+//
+// 'ppdcOption::find_choice()' - Find an option choice.
+//
+
+ppdcChoice * // O - Choice or NULL
+ppdcOption::find_choice(const char *n) // I - Name of choice
+{
+ ppdcChoice *c; // Current choice
+
+
+ for (c = (ppdcChoice *)choices->first(); c; c = (ppdcChoice *)choices->next())
+ if (!strcasecmp(n, c->name->value))
+ return (c);
+
+ return (0);
+}
+
+
+//
+// 'ppdcOption::set_defchoice()' - Set the default choice.
+//
+
+void
+ppdcOption::set_defchoice(ppdcChoice *c) // I - Choice
+{
+ if (defchoice)
+ defchoice->release();
+
+ if (c->name)
+ c->name->retain();
+
+ defchoice = c->name;
+}
--- /dev/null
+//
+// Private definitions for the CUPS PPD Compiler.
+//
+// Copyright 2009-2010 by Apple Inc.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+#ifndef _PPDC_PRIVATE_H_
+# define _PPDC_PRIVATE_H_
+
+//
+// Include necessary headers...
+//
+
+# include "ppdc.h"
+# include <string.h>
+# include <ctype.h>
+# include <stdio.h>
+# include <errno.h>
+# include <config.h>
+
+//
+// Macros...
+//
+
+# ifdef PPDC_DEBUG
+# define PPDC_NEW DEBUG_printf(("%s: %p new", class_name(), this))
+# define PPDC_NEWVAL(s) DEBUG_printf(("%s(\"%s\"): %p new", class_name(), s, this))
+# define PPDC_DELETE DEBUG_printf(("%s: %p delete", class_name(), this))
+# define PPDC_DELETEVAL(s) DEBUG_printf(("%s(\"%s\"): %p delete", class_name(), s, this))
+# else
+# define PPDC_NEW
+# define PPDC_NEWVAL(s)
+# define PPDC_DELETE
+# define PPDC_DELETEVAL(s)
+# endif /* PPDC_DEBUG */
+
+/*
+ * Macro for localized text...
+ */
+
+# define _(x) x
+
+#endif // !_PPDC_PRIVATE_H_
--- /dev/null
+//
+// Color profile class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcProfile::ppdcProfile()' - Create a color profile.
+//
+
+ppdcProfile::ppdcProfile(const char *r, // I - Resolution name
+ const char *m, // I - Media type name
+ float d, // I - Density
+ float g, // I - Gamma
+ const float *p) // I - 3x3 transform matrix
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ resolution = new ppdcString(r);
+ media_type = new ppdcString(m);
+ density = d;
+ gamma = g;
+
+ memcpy(profile, p, sizeof(profile));
+}
+
+
+//
+// 'ppdcProfile::~ppdcProfile()' - Destroy a color profile.
+//
+
+ppdcProfile::~ppdcProfile()
+{
+ PPDC_DELETE;
+
+ resolution->release();
+ media_type->release();
+}
--- /dev/null
+//
+// Shared data class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcShared::ppdcShared()' - Create shared data.
+//
+
+ppdcShared::ppdcShared()
+{
+ use = 1;
+}
+
+
+//
+// 'ppdcShared::~ppdcShared()' - Destroy shared data.
+//
+
+ppdcShared::~ppdcShared()
+{
+}
+
+
+//
+// 'ppdcShared::release()' - Decrement the use count and delete as needed.
+//
+
+void
+ppdcShared::release(void)
+{
+ use --;
+
+#ifdef DEBUG
+ if (use < 0)
+ {
+ fprintf(stderr, "ERROR: Over-release of %s: %p\n", class_name(), this);
+ abort();
+ }
+#endif /* DEBUG */
+
+ if (use == 0)
+ delete this;
+}
+
+
+//
+// 'ppdcShared::retain()' - Increment the use count for this data.
+//
+
+void
+ppdcShared::retain()
+{
+ use ++;
+}
--- /dev/null
+//
+// Source class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2018 by Apple Inc.
+// Copyright 2002-2007 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more
+// information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+#include <limits.h>
+#include <math.h>
+#include <unistd.h>
+#include <cups/raster.h>
+#include "epson.h"
+#include "hp.h"
+#include "label.h"
+#ifndef _WIN32
+# include <sys/utsname.h>
+#endif // !_WIN32
+
+
+//
+// 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
+ cups_file_t *ffp)// I - File pointer to use
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ filename = new ppdcString(f);
+ base_fonts = new ppdcArray();
+ drivers = new ppdcArray();
+ po_files = new ppdcArray();
+ sizes = new ppdcArray();
+ vars = new ppdcArray();
+ cond_state = PPDC_COND_NORMAL;
+ cond_current = cond_stack;
+ cond_stack[0] = PPDC_COND_NORMAL;
+
+ // Add standard #define variables...
+#define MAKE_STRING(x) #x
+
+ vars->add(new ppdcVariable("CUPS_VERSION", MAKE_STRING(CUPS_VERSION)));
+ vars->add(new ppdcVariable("CUPS_VERSION_MAJOR", MAKE_STRING(CUPS_VERSION_MAJOR)));
+ vars->add(new ppdcVariable("CUPS_VERSION_MINOR", MAKE_STRING(CUPS_VERSION_MINOR)));
+ vars->add(new ppdcVariable("CUPS_VERSION_PATCH", MAKE_STRING(CUPS_VERSION_PATCH)));
+
+#ifdef _WIN32
+ vars->add(new ppdcVariable("PLATFORM_NAME", "Windows"));
+ vars->add(new ppdcVariable("PLATFORM_ARCH", "X86"));
+
+#else
+ struct utsname name; // uname information
+
+ if (!uname(&name))
+ {
+ vars->add(new ppdcVariable("PLATFORM_NAME", name.sysname));
+ vars->add(new ppdcVariable("PLATFORM_ARCH", name.machine));
+ }
+ else
+ {
+ vars->add(new ppdcVariable("PLATFORM_NAME", "unknown"));
+ vars->add(new ppdcVariable("PLATFORM_ARCH", "unknown"));
+ }
+#endif // _WIN32
+
+ if (f)
+ read_file(f, ffp);
+}
+
+
+//
+// 'ppdcSource::~ppdcSource()' - Free a driver source file.
+//
+
+ppdcSource::~ppdcSource()
+{
+ PPDC_DELETE;
+
+ filename->release();
+ base_fonts->release();
+ drivers->release();
+ po_files->release();
+ sizes->release();
+ vars->release();
+}
+
+
+//
+// '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
+ const char *c;
+
+
+ // 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...
+ strncpy(temp, f + 1, sizeof(temp) - 1);
+ 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, (size_t)nlen, "%s/%s", base, f);
+ else
+ strncpy(n, f, (size_t)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, (size_t)nlen, "%s/%s", dir->value, f);
+ if (!access(n, 0))
+ return (n);
+ }
+ }
+
+ // Search our own include directory (Usually /usr/share/ppdc)
+ if ((c = getenv("PPDC_DATADIR")) == NULL)
+ c = PPDC_DATADIR;
+
+ snprintf(n, (size_t)nlen, "%s/%s", c, f);
+ if (!access(n, 0))
+ return (n);
+
+ snprintf(n, (size_t)nlen, "%s/po/%s", c, f);
+ if (!access(n, 0))
+ return (n);
+
+ // Search the CUPS include directories...
+ if ((c = getenv("CUPS_DATADIR")) == NULL)
+ c = CUPS_DATADIR;
+
+ snprintf(n, (size_t)nlen, "%s/ppdc/%s", c, f);
+ if (!access(n, 0))
+ return (n);
+
+ snprintf(n, (size_t)nlen, "%s/po/%s", c, f);
+ if (!access(n, 0))
+ return (n);
+
+ 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
+ bool loc) // I - Localize this attribute?
+{
+ 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 %s on line %d of %s.\n"),
+ loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
+ return (0);
+ }
+
+ if (!get_token(fp, selector, sizeof(selector)))
+ {
+ fprintf(stderr,
+ _("ppdc: Expected selector after %s on line %d of %s.\n"),
+ loc ? "LocAttribute" : "Attribute", 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 %s on line %d of %s.\n"),
+ loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
+ return (0);
+ }
+
+ return (new ppdcAttr(name, selector, text, value, loc));
+}
+
+
+//
+// '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, d, g, 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 (cond_state)
+ 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") || !strcasecmp(temp, "rotated") ||
+ !strcasecmp(temp, "manualtumble"))
+ {
+ 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"));
+
+ for (attr = (ppdcAttr *)d->attrs->first();
+ attr;
+ attr = (ppdcAttr *)d->attrs->next())
+ if (!strcmp(attr->name->value, "cupsBackSide"))
+ {
+ d->attrs->remove(attr);
+ break;
+ }
+
+ if (!strcasecmp(temp, "flip"))
+ d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Flipped"));
+ else if (!strcasecmp(temp, "rotated"))
+ d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Rotated"));
+ else if (!strcasecmp(temp, "manualtumble"))
+ d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "ManualTumble"));
+ else
+ d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Normal"));
+ }
+ 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 ++;
+
+ strncpy(program, ptr, sizeof(program) - 1);
+ }
+ 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[2048]; // 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);
+ }
+
+ 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.
+//
+
+#define PPDC_XX -1 // Bad
+#define PPDC_EQ 0 // ==
+#define PPDC_NE 1 // !=
+#define PPDC_LT 2 // <
+#define PPDC_LE 3 // <=
+#define PPDC_GT 4 // >
+#define PPDC_GE 5 // >=
+
+int // O - Integer value
+ppdcSource::get_integer(const char *v) // I - Value string
+{
+ long val; // Value
+ long temp, // Temporary value
+ temp2; // Second temporary value
+ char *newv, // New value string pointer
+ ch; // Temporary character
+ ppdcVariable *var; // #define variable
+ int compop; // Comparison operator
+
+
+ // Parse the value string...
+ if (!v)
+ return (-1);
+
+ if (isdigit(*v & 255) || *v == '-' || *v == '+')
+ {
+ // Return a simple integer value
+ val = strtol(v, (char **)&v, 0);
+ if (*v || val == LONG_MIN)
+ return (-1);
+ else
+ return ((int)val);
+ }
+ else if (*v == '(')
+ {
+ // Evaluate and expression in any of the following formats:
+ //
+ // (number number ... number) Bitwise OR of all numbers
+ // (NAME == value) 1 if equal, 0 otherwise
+ // (NAME != value) 1 if not equal, 0 otherwise
+ // (NAME < value) 1 if less than, 0 otherwise
+ // (NAME <= value) 1 if less than or equal, 0 otherwise
+ // (NAME > value) 1 if greater than, 0 otherwise
+ // (NAME >= value) 1 if greater than or equal, 0 otherwise
+
+ v ++;
+ val = 0;
+
+ while (*v && *v != ')')
+ {
+ // Skip leading whitespace...
+ while (*v && isspace(*v & 255))
+ v ++;
+
+ if (!*v || *v == ')')
+ break;
+
+ if (isdigit(*v & 255) || *v == '-' || *v == '+')
+ {
+ // Bitwise OR a number...
+ temp = strtol(v, &newv, 0);
+
+ if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
+ temp == LONG_MIN)
+ return (-1);
+ }
+ else
+ {
+ // NAME logicop value
+ for (newv = (char *)v + 1;
+ *newv && (isalnum(*newv & 255) || *newv == '_');
+ newv ++)
+ /* do nothing */;
+
+ ch = *newv;
+ *newv = '\0';
+
+ if ((var = find_variable(v)) != NULL)
+ {
+ if (!var->value || !var->value->value || !var->value->value[0])
+ temp = 0;
+ else if (isdigit(var->value->value[0] & 255) ||
+ var->value->value[0] == '-' ||
+ var->value->value[0] == '+')
+ temp = strtol(var->value->value, NULL, 0);
+ else
+ temp = 1;
+ }
+ else
+ temp = 0;
+
+ *newv = ch;
+ while (isspace(*newv & 255))
+ newv ++;
+
+ if (!strncmp(newv, "==", 2))
+ {
+ compop = PPDC_EQ;
+ newv += 2;
+ }
+ else if (!strncmp(newv, "!=", 2))
+ {
+ compop = PPDC_NE;
+ newv += 2;
+ }
+ else if (!strncmp(newv, "<=", 2))
+ {
+ compop = PPDC_LE;
+ newv += 2;
+ }
+ else if (*newv == '<')
+ {
+ compop = PPDC_LT;
+ newv ++;
+ }
+ else if (!strncmp(newv, ">=", 2))
+ {
+ compop = PPDC_GE;
+ newv += 2;
+ }
+ else if (*newv == '>')
+ {
+ compop = PPDC_GT;
+ newv ++;
+ }
+ else
+ compop = PPDC_XX;
+
+ if (compop != PPDC_XX)
+ {
+ while (isspace(*newv & 255))
+ newv ++;
+
+ if (*newv == ')' || !*newv)
+ return (-1);
+
+ if (isdigit(*newv & 255) || *newv == '-' || *newv == '+')
+ {
+ // Get the second number...
+ temp2 = strtol(newv, &newv, 0);
+ if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
+ temp == LONG_MIN)
+ return (-1);
+ }
+ else
+ {
+ // Lookup the second name...
+ for (v = newv, newv ++;
+ *newv && (isalnum(*newv & 255) || *newv == '_');
+ newv ++);
+
+ ch = *newv;
+ *newv = '\0';
+
+ if ((var = find_variable(v)) != NULL)
+ {
+ if (!var->value || !var->value->value || !var->value->value[0])
+ temp2 = 0;
+ else if (isdigit(var->value->value[0] & 255) ||
+ var->value->value[0] == '-' ||
+ var->value->value[0] == '+')
+ temp2 = strtol(var->value->value, NULL, 0);
+ else
+ temp2 = 1;
+ }
+ else
+ temp2 = 0;
+
+ *newv = ch;
+ }
+
+ // Do the comparison...
+ switch (compop)
+ {
+ case PPDC_EQ :
+ temp = temp == temp2;
+ break;
+ case PPDC_NE :
+ temp = temp != temp2;
+ break;
+ case PPDC_LT :
+ temp = temp < temp2;
+ break;
+ case PPDC_LE :
+ temp = temp <= temp2;
+ break;
+ case PPDC_GT :
+ temp = temp > temp2;
+ break;
+ case PPDC_GE :
+ temp = temp >= temp2;
+ break;
+ }
+ }
+ }
+
+ val |= temp;
+ v = newv;
+ }
+
+ if (*v == ')' && !v[1])
+ return ((int)val);
+ else
+ return (-1);
+ }
+ else if ((var = find_variable(v)) != NULL)
+ {
+ // NAME by itself returns 1 if the #define variable is not blank and
+ // not "0"...
+ return (var->value->value && var->value->value[0] &&
+ strcmp(var->value->value, "0"));
+ }
+ else
+ {
+ // Anything else is an error...
+ 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
+ ppdcGroup *mg; // Matching group, if any
+
+
+ // 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_group(name, &mg)) == NULL)
+ {
+ // Nope, add a new one...
+ o = new ppdcOption(ot, name, text, section, order);
+ }
+ else if (o->type != ot)
+ {
+ fprintf(stderr,
+ _("ppdc: Option %s redefined with a different type on line "
+ "%d of %s.\n"), name, fp->line, fp->filename);
+ return (NULL);
+ }
+ else if (g != mg)
+ {
+ fprintf(stderr,
+ _("ppdc: Option %s defined in two different groups on line "
+ "%d of %s.\n"), name, 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...
+ strncpy(basedir, fp->filename, sizeof(basedir) - 1);
+
+ if ((baseptr = strrchr(basedir, '/')) != NULL)
+ *baseptr = '\0';
+ else
+ strncpy(basedir, ".", sizeof(basedir));
+
+ // Find the po file...
+ pofilename[0] = '\0';
+
+ if (!poname[0] ||
+ 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...
+ cat->filename->release();
+ 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 1 :
+ ydpi = xdpi;
+ break;
+ case 2 :
+ break;
+ default :
+ fprintf(stderr,
+ _("ppdc: Bad resolution name \"%s\" on line %d of "
+ "%s.\n"), name, fp->line, fp->filename);
+ 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) - (size_t)(commptr - command),
+ "/cupsColorOrder %d", color_order);
+ commptr += strlen(commptr);
+ }
+
+ if (color_space >= 0)
+ {
+ snprintf(commptr, sizeof(command) - (size_t)(commptr - command),
+ "/cupsColorSpace %d", color_space);
+ commptr += strlen(commptr);
+ }
+
+ if (compression >= 0)
+ {
+ snprintf(commptr, sizeof(command) - (size_t)(commptr - command),
+ "/cupsCompression %d", compression);
+ commptr += strlen(commptr);
+ }
+
+ snprintf(commptr, sizeof(command) - (size_t)(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, kd, g, 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++ = (char)fp->get();
+ }
+
+ if (nameptr == name)
+ {
+ // Just substitute this character...
+ if (ch == '$')
+ {
+ // $$ = $
+ if (bufptr < bufend)
+ *bufptr++ = (char)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, (size_t)(bufend - bufptr + 1));
+ bufptr += strlen(bufptr);
+ }
+ else
+ {
+ if (!(cond_state & PPDC_COND_SKIP))
+ fprintf(stderr,
+ _("ppdc: Undefined variable (%s) on line %d of "
+ "%s.\n"), name, fp->line, fp->filename);
+
+ snprintf(bufptr, (size_t)(bufend - bufptr + 1), "$%s", name);
+ bufptr += strlen(bufptr);
+ }
+ }
+ }
+ 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++ = (char)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++ = (char)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++ = (char)ch;
+ }
+ else if ((ch == ')' && quote == '(') || (ch == '>' && quote == '<'))
+ {
+ quote = 0;
+
+ if (bufptr < bufend)
+ *bufptr++ = (char)ch;
+ }
+ else if (ch == '\\')
+ {
+ empty = 0;
+
+ if ((ch = fp->get()) == EOF)
+ break;
+
+ if (bufptr < bufend)
+ *bufptr++ = (char)ch;
+ }
+ else if (bufptr < bufend)
+ {
+ empty = 0;
+
+ *bufptr++ = (char)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';
+ 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++;
+ else
+ size = '\0';
+
+ 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;
+
+ memcpy(tformat, bufformat, (size_t)(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;
+
+ memcpy(tformat, bufformat, (size_t)(format - bufformat));
+ tformat[format - bufformat] = '\0';
+
+# ifdef HAVE_LONG_LONG
+ if (size == 'L')
+ bytes += cupsFilePrintf(fp, tformat, va_arg(ap, long long));
+ else
+# endif /* HAVE_LONG_LONG */
+ if (size == 'l')
+ bytes += cupsFilePrintf(fp, tformat, va_arg(ap, long));
+ else
+ bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
+ break;
+
+ case 'p' : // Pointer value
+ if ((format - bufformat + 1) > (int)sizeof(tformat))
+ break;
+
+ memcpy(tformat, bufformat, (size_t)(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 *), (size_t)width);
+ bytes += width;
+ }
+ break;
+
+ case 's' : // String
+ if ((s = va_arg(ap, char *)) == NULL)
+ s = (char *)"(nil)";
+
+ slen = (int)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
+ cups_file_t *ffp) // I - File pointer to use
+{
+ ppdcFile *fp = new ppdcFile(f, ffp);
+ scan_file(fp);
+ delete fp;
+
+ if (cond_current != cond_stack)
+ fprintf(stderr, _("ppdc: Missing #endif at end of \"%s\".\n"), f);
+}
+
+
+//
+// '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
+ *mg, // Matching 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;
+ d->retain();
+ }
+ 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, "#if"))
+ {
+ if ((cond_current - cond_stack) >= 100)
+ {
+ fprintf(stderr,
+ _("ppdc: Too many nested #if's on line %d of %s.\n"),
+ fp->line, fp->filename);
+ break;
+ }
+
+ cond_current ++;
+ if (get_integer(fp) > 0)
+ *cond_current = PPDC_COND_SATISFIED;
+ else
+ {
+ *cond_current = PPDC_COND_SKIP;
+ cond_state |= PPDC_COND_SKIP;
+ }
+ }
+ else if (!strcasecmp(temp, "#elif"))
+ {
+ if (cond_current == cond_stack)
+ {
+ fprintf(stderr, _("ppdc: Missing #if on line %d of %s.\n"),
+ fp->line, fp->filename);
+ break;
+ }
+
+ if (*cond_current & PPDC_COND_SATISFIED)
+ {
+ get_integer(fp);
+ *cond_current |= PPDC_COND_SKIP;
+ }
+ else if (get_integer(fp) > 0)
+ {
+ *cond_current |= PPDC_COND_SATISFIED;
+ *cond_current &= ~PPDC_COND_SKIP;
+ }
+ else
+ *cond_current |= PPDC_COND_SKIP;
+
+ // Update the current state
+ int *cond_temp = cond_current; // Temporary stack pointer
+
+ cond_state = PPDC_COND_NORMAL;
+ while (cond_temp > cond_stack)
+ if (*cond_temp & PPDC_COND_SKIP)
+ {
+ cond_state = PPDC_COND_SKIP;
+ break;
+ }
+ else
+ cond_temp --;
+ }
+ else if (!strcasecmp(temp, "#else"))
+ {
+ if (cond_current == cond_stack)
+ {
+ fprintf(stderr, _("ppdc: Missing #if on line %d of %s.\n"),
+ fp->line, fp->filename);
+ break;
+ }
+
+ if (*cond_current & PPDC_COND_SATISFIED)
+ *cond_current |= PPDC_COND_SKIP;
+ else
+ {
+ *cond_current |= PPDC_COND_SATISFIED;
+ *cond_current &= ~PPDC_COND_SKIP;
+ }
+
+ // Update the current state
+ int *cond_temp = cond_current; // Temporary stack pointer
+
+ cond_state = PPDC_COND_NORMAL;
+ while (cond_temp > cond_stack)
+ if (*cond_temp & PPDC_COND_SKIP)
+ {
+ cond_state = PPDC_COND_SKIP;
+ break;
+ }
+ else
+ cond_temp --;
+ }
+ else if (!strcasecmp(temp, "#endif"))
+ {
+ if (cond_current == cond_stack)
+ {
+ fprintf(stderr, _("ppdc: Missing #if on line %d of %s.\n"),
+ fp->line, fp->filename);
+ break;
+ }
+
+ cond_current --;
+
+ // Update the current state
+ int *cond_temp = cond_current; // Temporary stack pointer
+
+ cond_state = PPDC_COND_NORMAL;
+ while (cond_temp > cond_stack)
+ if (*cond_temp & PPDC_COND_SKIP)
+ {
+ cond_state = PPDC_COND_SKIP;
+ break;
+ }
+ else
+ cond_temp --;
+ }
+ 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
+ int *old_current = cond_current;
+ // Previous current stack
+
+
+ // 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;
+ }
+
+ if (cond_state)
+ continue;
+
+ // Figure out the current directory...
+ strncpy(basedir, fp->filename, sizeof(basedir) - 1);
+
+ if ((baseptr = strrchr(basedir, '/')) != NULL)
+ *baseptr = '\0';
+ else
+ strncpy(basedir, ".", sizeof(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;
+
+ if (cond_current != old_current)
+ fprintf(stderr, _("ppdc: Missing #endif at end of \"%s\".\n"),
+ incname);
+ }
+ 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)
+ {
+ if (cond_state)
+ m->release();
+ else
+ sizes->add(m);
+ }
+ }
+ else if (!strcasecmp(temp, "#po"))
+ {
+ ppdcCatalog *cat; // Message catalog
+
+
+ // Get a message catalog...
+ cat = get_po(fp);
+ if (cat)
+ {
+ if (cond_state)
+ cat->release();
+ else
+ po_files->add(cat);
+ }
+ }
+ else if (!strcasecmp(temp, "Attribute") ||
+ !strcasecmp(temp, "LocAttribute"))
+ {
+ ppdcAttr *a; // Attribute
+
+
+ // Get an attribute...
+ a = get_attr(fp, !strcasecmp(temp, "LocAttribute"));
+ if (a)
+ {
+ if (cond_state)
+ a->release();
+ else
+ d->add_attr(a);
+ }
+ }
+ else if (!strcasecmp(temp, "Choice"))
+ {
+ // Get a choice...
+ c = get_choice(fp);
+ if (!c)
+ break;
+
+ if (cond_state)
+ {
+ c->release();
+ continue;
+ }
+
+ // Add it to the current option...
+ if (!o)
+ {
+ c->release();
+ fprintf(stderr,
+ _("ppdc: Choice found on line %d of %s with no "
+ "Option.\n"), fp->line, fp->filename);
+ break;
+ }
+
+ o->add_choice(c);
+
+ if (isdefault)
+ o->set_defchoice(c);
+ }
+ else if (!strcasecmp(temp, "ColorDevice"))
+ {
+ // ColorDevice boolean
+ if (cond_state)
+ get_boolean(fp);
+ else
+ d->color_device = get_boolean(fp);
+ }
+ else if (!strcasecmp(temp, "ColorModel"))
+ {
+ // Get the color model
+ c = get_color_model(fp);
+ if (!c)
+ continue;
+
+ if (cond_state)
+ {
+ c->release();
+ 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)
+ {
+ if (cond_state)
+ p->release();
+ else
+ 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;
+ }
+
+ if (cond_state)
+ continue;
+
+ // 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 (cond_state)
+ {
+ m->release();
+ continue;
+ }
+
+ 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 || cond_state)
+ continue;
+
+ if (!d->find_option("CutMedia"))
+ {
+ 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;
+
+ if (cond_state)
+ {
+ c->release();
+ continue;
+ }
+
+ // Add the choice to the cupsDarkness option...
+ if ((o = d->find_option_group("cupsDarkness", &mg)) == NULL)
+ {
+ // Create the cupsDarkness option...
+ o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
+ g = general;
+ g->add_option(o);
+ }
+ else if (mg != general)
+ {
+ fprintf(stderr,
+ _("ppdc: Option %s defined in two different groups on "
+ "line %d of %s.\n"), "cupsDarkness", fp->line,
+ fp->filename);
+ c->release();
+ continue;
+ }
+
+ 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;
+ }
+
+ if (cond_state)
+ 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)
+ {
+ if (cond_state)
+ f->release();
+ else
+ d->filters->add(f);
+ }
+ }
+ else if (!strcasecmp(temp, "Finishing"))
+ {
+ // Get the finishing choice...
+ c = get_generic(fp, "Finishing", "OutputType", NULL);
+ if (!c)
+ continue;
+
+ if (cond_state)
+ {
+ c->release();
+ continue;
+ }
+
+ // Add the choice to the cupsFinishing option...
+ if ((o = d->find_option_group("cupsFinishing", &mg)) == NULL)
+ {
+ // Create the cupsFinishing option...
+ o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
+ g = general;
+ g->add_option(o);
+ }
+ else if (mg != general)
+ {
+ fprintf(stderr,
+ _("ppdc: Option %s defined in two different groups on "
+ "line %d of %s.\n"), "cupsFinishing", fp->line,
+ fp->filename);
+ c->release();
+ continue;
+ }
+
+ 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 (cond_state)
+ f->release();
+ else
+ {
+ 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...
+ ppdcGroup *tempg = get_group(fp, d);
+
+ if (!tempg)
+ break;
+
+ if (cond_state)
+ {
+ if (!d->find_group(tempg->name->value))
+ tempg->release();
+ }
+ else
+ {
+ if (!d->find_group(tempg->name->value))
+ d->add_group(tempg);
+
+ g = tempg;
+ }
+ }
+ 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;
+
+ if (cond_state)
+ {
+ c->release();
+ continue;
+ }
+
+ // Add the choice to the InputSlot option...
+
+ if ((o = d->find_option_group("InputSlot", &mg)) == NULL)
+ {
+ // Create the InputSlot option...
+ o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
+ PPDC_SECTION_ANY, 10.0f);
+ g = general;
+ g->add_option(o);
+ }
+ else if (mg != general)
+ {
+ fprintf(stderr,
+ _("ppdc: Option %s defined in two different groups on "
+ "line %d of %s.\n"), "InputSlot", fp->line,
+ fp->filename);
+ c->release();
+ continue;
+ }
+
+ 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)
+ {
+ if (cond_state)
+ o->release();
+ else
+ install->add_option(o);
+
+ o = NULL;
+ }
+ }
+ else if (!strcasecmp(temp, "ManualCopies"))
+ {
+ // ManualCopies boolean
+ if (cond_state)
+ get_boolean(fp);
+ else
+ 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;
+ }
+
+ if (!cond_state)
+ d->set_manufacturer(name);
+ }
+ else if (!strcasecmp(temp, "MaxSize"))
+ {
+ // MaxSize width length
+ if (cond_state)
+ {
+ get_measurement(fp);
+ get_measurement(fp);
+ }
+ else
+ {
+ 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;
+ }
+
+ if (cond_state)
+ continue;
+
+ 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;
+
+ if (cond_state)
+ {
+ c->release();
+ continue;
+ }
+
+ // Add the choice to the MediaType option...
+ if ((o = d->find_option_group("MediaType", &mg)) == NULL)
+ {
+ // Create the MediaType option...
+ o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
+ PPDC_SECTION_ANY, 10.0f);
+ g = general;
+ g->add_option(o);
+ }
+ else if (mg != general)
+ {
+ fprintf(stderr,
+ _("ppdc: Option %s defined in two different groups on "
+ "line %d of %s.\n"), "MediaType", fp->line,
+ fp->filename);
+ c->release();
+ continue;
+ }
+
+ o->add_choice(c);
+
+ if (isdefault)
+ o->set_defchoice(c);
+
+ o = NULL;
+ }
+ else if (!strcasecmp(temp, "MinSize"))
+ {
+ // MinSize width length
+ if (cond_state)
+ {
+ get_measurement(fp);
+ get_measurement(fp);
+ }
+ else
+ {
+ 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;
+ }
+
+ if (!cond_state)
+ d->set_model_name(name);
+ }
+ else if (!strcasecmp(temp, "ModelNumber"))
+ {
+ // ModelNumber number
+ if (cond_state)
+ get_integer(fp);
+ else
+ d->model_number = get_integer(fp);
+ }
+ else if (!strcasecmp(temp, "Option"))
+ {
+ // Get an option...
+ ppdcOption *tempo = get_option(fp, d, g);
+
+ if (!tempo)
+ break;
+
+ if (cond_state)
+ {
+ if (!g->find_option(tempo->name->value))
+ tempo->release();
+ }
+ else
+ {
+ if (!g->find_option(tempo->name->value))
+ g->add_option(tempo);
+
+ o = tempo;
+ }
+ }
+ else if (!strcasecmp(temp, "FileName"))
+ {
+ // FileName name
+ char name[256]; // Filename string
+
+
+ if (!get_token(fp, name, sizeof(name)))
+ {
+ fprintf(stderr,
+ _("ppdc: Expected name after FileName on line %d of "
+ "%s.\n"), fp->line, fp->filename);
+ break;
+ }
+
+ if (!cond_state)
+ d->set_file_name(name);
+ }
+ else if (!strcasecmp(temp, "PCFileName"))
+ {
+ // PCFileName name
+ char name[256]; // PC filename 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;
+ }
+
+ if (!cond_state)
+ d->set_pc_file_name(name);
+ }
+ else if (!strcasecmp(temp, "Resolution"))
+ {
+ // Get the resolution choice...
+ c = get_resolution(fp);
+ if (!c)
+ continue;
+
+ if (cond_state)
+ {
+ c->release();
+ continue;
+ }
+
+ // Add the choice to the Resolution option...
+ if ((o = d->find_option_group("Resolution", &mg)) == NULL)
+ {
+ // Create the Resolution option...
+ o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
+ 10.0f);
+ g = general;
+ g->add_option(o);
+ }
+ else if (mg != general)
+ {
+ fprintf(stderr,
+ _("ppdc: Option %s defined in two different groups on "
+ "line %d of %s.\n"), "Resolution", fp->line,
+ fp->filename);
+ c->release();
+ continue;
+ }
+
+ 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)
+ {
+ if (cond_state)
+ p->release();
+ else
+ d->profiles->add(p);
+ }
+ }
+ else if (!strcasecmp(temp, "Throughput"))
+ {
+ // Throughput number
+ if (cond_state)
+ get_integer(fp);
+ else
+ d->throughput = get_integer(fp);
+ }
+ else if (!strcasecmp(temp, "UIConstraints"))
+ {
+ ppdcConstraint *con; // Constraint
+
+
+ con = get_constraint(fp);
+
+ if (con)
+ {
+ if (cond_state)
+ con->release();
+ else
+ d->constraints->add(con);
+ }
+ }
+ else if (!strcasecmp(temp, "VariablePaperSize"))
+ {
+ // VariablePaperSize boolean
+ if (cond_state)
+ get_boolean(fp);
+ else
+ 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;
+ }
+
+ if (!cond_state)
+ 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);
+ }
+ }
+ else if (inc && td)
+ td->release();
+}
+
+
+//
+// '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, "// PPD Compiler of cups-filters " PACKAGE_VERSION "\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 && 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->file_name && d->file_name->value)
+ quotef(fp, " FileName \"%s\"\n", d->file_name->value);
+ if (d->pc_file_name && d->pc_file_name->value)
+ quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value);
+ if (d->version && 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_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);
+}
--- /dev/null
+//
+// Shared string class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2012 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcString::ppdcString()' - Create a shared string.
+//
+
+ppdcString::ppdcString(const char *v) // I - String
+ : ppdcShared()
+{
+ PPDC_NEWVAL(v);
+
+ if (v)
+ {
+ size_t vlen = strlen(v);
+
+ value = new char[vlen + 1];
+ memcpy(value, v, vlen + 1);
+ }
+ else
+ value = 0;
+}
+
+
+//
+// 'ppdcString::~ppdcString()' - Destroy a shared string.
+//
+
+ppdcString::~ppdcString()
+{
+ PPDC_DELETEVAL(value);
+
+ if (value)
+ delete[] value;
+}
--- /dev/null
+//
+// Variable class for the CUPS PPD Compiler.
+//
+// Copyright 2007-2009 by Apple Inc.
+// Copyright 2002-2005 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+//
+// Include necessary headers...
+//
+
+#include "ppdc-private.h"
+
+
+//
+// 'ppdcVariable::ppdcVariable()' - Create a variable.
+//
+
+ppdcVariable::ppdcVariable(const char *n, // I - Name of variable
+ const char *v) // I - Value of variable
+ : ppdcShared()
+{
+ PPDC_NEW;
+
+ name = new ppdcString(n);
+ value = new ppdcString(v);
+}
+
+
+//
+// 'ppdcVariable::~ppdcVariable()' - Destroy a variable.
+//
+
+ppdcVariable::~ppdcVariable()
+{
+ PPDC_DELETE;
+
+ name->release();
+ value->release();
+}
+
+
+//
+// 'ppdcVariable::set_value()' - Set the value of a variable.
+//
+
+void
+ppdcVariable::set_value(const char *v)
+{
+ value->release();
+ value = new ppdcString(v);
+}
--- /dev/null
+//
+// Definitions for the CUPS PPD Compiler.
+//
+// Copyright 2007-2019 by Apple Inc.
+// Copyright 2002-2007 by Easy Software Products.
+//
+// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+//
+
+#ifndef _PPDC_H_
+# define _PPDC_H_
+
+//
+// Include necessary headers...
+//
+
+# include <cups/file.h>
+# include <stdlib.h>
+
+
+//
+// Macros...
+//
+
+# define PPDC_NAME(s) const char *class_name() { return (s); }
+
+
+//
+// Enumerations...
+//
+
+enum ppdcDrvType //// Driver type
+{
+ PPDC_DRIVER_CUSTOM, // Custom driver
+ PPDC_DRIVER_PS, // PostScript driver
+ PPDC_DRIVER_ESCP, // rastertoescpx driver
+ PPDC_DRIVER_PCL, // rastertopclx driver
+ PPDC_DRIVER_LABEL, // rastertolabel/rastertodymo driver
+ PPDC_DRIVER_EPSON, // rastertoepson driver
+ PPDC_DRIVER_HP, // rastertohp driver
+ PPDC_DRIVER_MAX // Number of driver types defined
+};
+
+enum ppdcFontStatus //// Load status of font
+{
+ PPDC_FONT_ROM, // Font is in ROM
+ PPDC_FONT_DISK // Font is on disk
+};
+
+enum ppdcOptSection //// Option section
+{
+ PPDC_SECTION_ANY, // AnySetup
+ PPDC_SECTION_DOCUMENT, // DocumentSetup
+ PPDC_SECTION_EXIT, // ExitServer
+ PPDC_SECTION_JCL, // JCLSetup
+ PPDC_SECTION_PAGE, // PageSetup
+ PPDC_SECTION_PROLOG // Prolog
+};
+
+enum ppdcOptType //// Option type
+{
+ PPDC_BOOLEAN, // True/false option
+ PPDC_PICKONE, // Single choice from list
+ PPDC_PICKMANY // Multiple choices from list
+};
+
+enum ppdcLineEnding //// Line endings
+{
+ PPDC_LFONLY, // LF only
+ PPDC_CRONLY, // CR only
+ PPDC_CRLF // CR + LF
+};
+
+enum ppdcCondFlags //// Condition flags
+{
+ PPDC_COND_NORMAL = 0, // Normal state
+ PPDC_COND_SKIP = 1, // Skip state
+ PPDC_COND_SATISFIED = 2 // At least one condition satisfied
+};
+
+
+//
+// Printer description data...
+//
+
+class ppdcShared //// Shared Data Value
+{
+ private:
+
+ int use; // Use count (delete when 0)
+
+ public:
+
+ ppdcShared();
+ virtual ~ppdcShared();
+
+ virtual const char *class_name() = 0;
+
+ void retain();
+ void release();
+};
+
+class ppdcArray //// Shared Array
+ : public ppdcShared
+{
+ public:
+
+ size_t count, // Number of elements
+ alloc, // Allocated elements
+ current; // Current element
+ ppdcShared **data; // Elements
+
+ ppdcArray(ppdcArray *a = 0);
+ ~ppdcArray();
+
+ PPDC_NAME("ppdcArray")
+
+ void add(ppdcShared *d);
+ ppdcShared *first();
+ ppdcShared *next();
+ void remove(ppdcShared *d);
+};
+
+class ppdcString //// Shared String
+ : public ppdcShared
+{
+ public:
+
+ char *value; // String value
+
+ ppdcString(const char *v);
+ ~ppdcString();
+
+ PPDC_NAME("ppdcString")
+};
+
+class ppdcInteger //// Shared integer
+ : public ppdcShared
+{
+ public:
+
+ int *value; // Integer value
+
+ ppdcInteger(int *v) { value = v; }
+
+ PPDC_NAME("ppdcInteger")
+};
+
+class ppdcMessage //// Translation message
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *id, // Translation ID
+ *string; // Translation string
+
+ ppdcMessage(const char *i, const char *s);
+ ~ppdcMessage();
+
+ PPDC_NAME("ppdcMessage")
+};
+
+class ppdcCatalog //// Translation catalog
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *locale; // Name of locale
+ ppdcString *filename; // Name of translation file
+ ppdcArray *messages; // Array of translation messages
+
+ ppdcCatalog(const char *l, const char *f = 0);
+ ~ppdcCatalog();
+
+ PPDC_NAME("ppdcCatalog")
+
+ void add_message(const char *id, const char *string = NULL);
+ const char *find_message(const char *id);
+ int load_messages(const char *f);
+ int save_messages(const char *f);
+};
+
+class ppdcAttr //// Attribute
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *name, // Name of attribute
+ *selector, // Selector string
+ *text, // Text string
+ *value; // Value string
+ bool localizable; // Should this attribute be localized?
+
+ ppdcAttr(const char *n, const char *s, const char *t, const char *v,
+ bool loc = false);
+ ~ppdcAttr();
+
+ PPDC_NAME("ppdcAttr")
+};
+
+class ppdcFont //// Shared Font
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *name, // Font name
+ *encoding, // Font base encoding
+ *version, // Font version
+ *charset; // Font charset
+ ppdcFontStatus status; // Font status (ROM or Disk)
+
+ ppdcFont(const char *n, const char *e, const char *v, const char *c,
+ ppdcFontStatus s);
+ ~ppdcFont();
+
+ PPDC_NAME("ppdcFont")
+};
+
+class ppdcChoice //// Option Choice
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *name, // Name of choice
+ *text, // Human-readable text of choice
+ *code; // PS code of choice
+
+ ppdcChoice(const char *n, const char *t, const char *c);
+ ~ppdcChoice();
+
+ PPDC_NAME("ppdcChoice")
+};
+
+class ppdcOption //// Option
+ : public ppdcShared
+{
+ public:
+
+ ppdcOptType type; // Type of option
+ ppdcString *name, // Name of option
+ *text; // Human-readable text of option
+ ppdcOptSection section; // Section for option code
+ float order; // Order number
+ ppdcArray *choices; // Choices
+ ppdcString *defchoice; // Default choice
+
+ ppdcOption(ppdcOptType ot, const char *n, const char *t, ppdcOptSection s,
+ float o);
+ ppdcOption(ppdcOption *o);
+ ~ppdcOption();
+
+ PPDC_NAME("ppdcOption")
+
+ void add_choice(ppdcChoice *c) { choices->add(c); }
+ ppdcChoice *find_choice(const char *n);
+ void set_defchoice(ppdcChoice *c);
+};
+
+class ppdcGroup //// Group of Options
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *name, // Name of option
+ *text; // Human-readable text of option
+ ppdcArray *options; // Options
+
+ ppdcGroup(const char *n, const char *t);
+ ppdcGroup(ppdcGroup *g);
+ ~ppdcGroup();
+
+ PPDC_NAME("ppdcGroup")
+
+ void add_option(ppdcOption *o) { options->add(o); }
+ ppdcOption *find_option(const char *n);
+};
+
+class ppdcConstraint //// Constraint
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *option1, // First option
+ *choice1, // First choice
+ *option2, // Second option
+ *choice2; // Second choice
+
+ ppdcConstraint(const char *o1, const char *c1, const char *o2,
+ const char *c2);
+ ~ppdcConstraint();
+
+ PPDC_NAME("ppdcConstraint")
+};
+
+class ppdcFilter //// Filter Program
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *mime_type, // MIME type
+ *program; // Filter program
+ int cost; // Relative cost of filter
+
+ ppdcFilter(const char *t, const char *p, int c);
+ ~ppdcFilter();
+
+ PPDC_NAME("ppdcFilter")
+};
+
+class ppdcMediaSize //// Media Size
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *name, // Name of size
+ *text; // Human-readable text
+ float width, // Width in points
+ length, // Length in points
+ left, // Left limit in points
+ bottom, // Bottom limit in points
+ right, // Right limit in points
+ top; // Top limit in points
+ ppdcString *size_code, // PageSize code, if any
+ *region_code; // PageRegion code, if any
+
+ ppdcMediaSize(const char *n, const char *t, float w, float l,
+ float lm, float bm, float rm, float tm,
+ const char *sc = 0, const char *rc = 0);
+ ~ppdcMediaSize();
+
+ PPDC_NAME("ppdcMediaSize")
+};
+
+class ppdcProfile //// Color Profile
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *resolution, // Resolution name
+ *media_type; // Media type name
+ float density, // Color profile density
+ gamma, // Color profile gamma
+ profile[9]; // Color profile matrix
+
+ ppdcProfile(const char *r, const char *m, float d, float g, const float *p);
+ ~ppdcProfile();
+
+ PPDC_NAME("ppdcProfile")
+};
+
+class ppdcSource;
+
+class ppdcDriver //// Printer Driver Data
+ : public ppdcShared
+{
+ public:
+
+ ppdcDrvType type; // Driver type
+ ppdcArray *copyright; // Copyright strings
+ ppdcString *manufacturer, // Manufacturer
+ *model_name, // Name of printer model
+ *file_name, // Output filename for PPD
+ *pc_file_name, // 8 character PC filename for PPD
+ *version; // Version number
+ int model_number, // Model number for driver
+ manual_copies, // Do manual copies?
+ color_device, // Support color?
+ throughput; // Throughput in pages per minute
+ ppdcArray *attrs, // Attributes
+ *constraints, // Constraints
+ *filters, // Filters
+ *fonts, // Fonts
+ *groups, // Option groups
+ *profiles, // Color profiles
+ *sizes; // Fixed sizes
+ ppdcString *default_font, // Default font
+ *default_size; // Default size option
+ int variable_paper_size; // Support variable sizes?
+ ppdcString *custom_size_code; // Custom page size code, if any
+ float left_margin, // Margins for device in points
+ bottom_margin,
+ right_margin,
+ top_margin,
+ max_width, // Maximum width (points)
+ max_length, // Maximum length (points)
+ min_width, // Minimum width (points)
+ min_length; // Minimum length (points)
+
+ ppdcDriver(ppdcDriver *d = 0);
+ ~ppdcDriver();
+
+ PPDC_NAME("ppdcDriver")
+
+ void add_attr(ppdcAttr *a) { attrs->add(a); }
+ void add_constraint(ppdcConstraint *c) { constraints->add(c); }
+ void add_copyright(const char *c) {
+ copyright->add(new ppdcString(c));
+ }
+ void add_filter(ppdcFilter *f) { filters->add(f); }
+ void add_font(ppdcFont *f) { fonts->add(f); }
+ void add_group(ppdcGroup *g) { groups->add(g); }
+ void add_profile(ppdcProfile *p) { profiles->add(p); }
+ void add_size(ppdcMediaSize *m) { sizes->add(m); }
+
+ ppdcAttr *find_attr(const char *k, const char *s);
+ ppdcGroup *find_group(const char *n);
+ ppdcOption *find_option(const char *n);
+ ppdcOption *find_option_group(const char *n, ppdcGroup **mg);
+
+ void set_custom_size_code(const char *c);
+ void set_default_font(ppdcFont *f);
+ void set_default_size(ppdcMediaSize *m);
+ void set_file_name(const char *f);
+ void set_manufacturer(const char *m);
+ void set_model_name(const char *m);
+ void set_pc_file_name(const char *f);
+ void set_version(const char *v);
+
+ int write_ppd_file(cups_file_t *fp, ppdcCatalog *catalog,
+ ppdcArray *locales, ppdcSource *src,
+ ppdcLineEnding le);
+};
+
+class ppdcVariable //// Variable Definition
+ : public ppdcShared
+{
+ public:
+
+ ppdcString *name, // Name of variable
+ *value; // Value of variable
+
+ ppdcVariable(const char *n, const char *v);
+ ~ppdcVariable();
+
+ PPDC_NAME("ppdcVariable")
+
+ void set_value(const char *v);
+};
+
+class ppdcFile //// File
+{
+ public:
+
+ bool close_on_delete; // Close file on delete?
+ cups_file_t *fp; // File pointer
+ const char *filename; // Filename
+ int line; // Line in file
+
+ ppdcFile(const char *f, cups_file_t *ffp = (cups_file_t *)0);
+ ~ppdcFile();
+
+ int get();
+ int peek();
+};
+
+class ppdcSource //// Source File
+ : public ppdcShared
+{
+ public:
+
+ static ppdcArray *includes; // Include directories
+ static const char *driver_types[]; // Driver types
+
+ ppdcString *filename; // Filename
+ ppdcArray *base_fonts, // Base fonts
+ *drivers, // Printer drivers
+ *po_files, // Message catalogs
+ *sizes, // Predefined media sizes
+ *vars; // Defined variables
+ int cond_state, // Cummulative conditional state
+ *cond_current, // Current #if state
+ cond_stack[101]; // #if state stack
+
+
+ ppdcSource(const char *f = 0, cups_file_t *ffp = (cups_file_t *)0);
+ ~ppdcSource();
+
+ PPDC_NAME("ppdcSource")
+
+ static void add_include(const char *d);
+ ppdcDriver *find_driver(const char *f);
+ static char *find_include(const char *f, const char *base, char *n,
+ int nlen);
+ ppdcCatalog *find_po(const char *l);
+ ppdcMediaSize *find_size(const char *s);
+ ppdcVariable *find_variable(const char *n);
+ ppdcAttr *get_attr(ppdcFile *fp, bool loc = false);
+ int get_boolean(ppdcFile *fp);
+ ppdcChoice *get_choice(ppdcFile *fp);
+ ppdcChoice *get_color_model(ppdcFile *fp);
+ int get_color_order(const char *co);
+ ppdcProfile *get_color_profile(ppdcFile *fp);
+ int get_color_space(const char *cs);
+ ppdcConstraint *get_constraint(ppdcFile *fp);
+ ppdcMediaSize *get_custom_size(ppdcFile *fp);
+ void get_duplex(ppdcFile *fp, ppdcDriver *d);
+ ppdcFilter *get_filter(ppdcFile *fp);
+ float get_float(ppdcFile *fp);
+ ppdcFont *get_font(ppdcFile *fp);
+ ppdcChoice *get_generic(ppdcFile *fp, const char *keyword,
+ const char *tattr, const char *nattr);
+ ppdcGroup *get_group(ppdcFile *fp, ppdcDriver *d);
+ ppdcOption *get_installable(ppdcFile *fp);
+ int get_integer(const char *v);
+ int get_integer(ppdcFile *fp);
+ float get_measurement(ppdcFile *fp);
+ ppdcOption *get_option(ppdcFile *fp, ppdcDriver *d, ppdcGroup *g);
+ ppdcCatalog *get_po(ppdcFile *fp);
+ ppdcChoice *get_resolution(ppdcFile *fp);
+ ppdcProfile *get_simple_profile(ppdcFile *fp);
+ ppdcMediaSize *get_size(ppdcFile *fp);
+ char *get_token(ppdcFile *fp, char *buffer, int buflen);
+ ppdcVariable *get_variable(ppdcFile *fp);
+ int import_ppd(const char *f);
+ int quotef(cups_file_t *fp, const char *format, ...);
+ void read_file(const char *f, cups_file_t *ffp = (cups_file_t *)0);
+ void scan_file(ppdcFile *fp, ppdcDriver *td = 0, bool inc = false);
+ ppdcVariable *set_variable(const char *name, const char *value);
+ int write_file(const char *f);
+};
+
+
+#endif // !_PPDC_H_
--- /dev/null
+/*
+ * This file contains the standard definitions for enumerated attributes
+ * in the CUPS raster page device dictionary.
+ *
+ * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 1997-2005 by Easy Software Products.
+ *
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
+ */
+
+/* Jog values */
+#define CUPS_JOG_NONE 0 /* Never move pages */
+#define CUPS_JOG_FILE 1 /* Move pages after this file */
+#define CUPS_JOG_JOB 2 /* Move pages after this job */
+#define CUPS_JOG_SET 3 /* Move pages after this set */
+
+/* Orientation values */
+#define CUPS_ORIENT_0 0 /* Don't rotate the page */
+#define CUPS_ORIENT_90 1 /* Rotate the page counter-clockwise */
+#define CUPS_ORIENT_180 2 /* Turn the page upside down */
+#define CUPS_ORIENT_270 3 /* Rotate the page clockwise */
+
+/* CutMedia values */
+#define CUPS_CUT_NONE 0 /* Never cut the roll */
+#define CUPS_CUT_FILE 1 /* Cut the roll after this file */
+#define CUPS_CUT_JOB 2 /* Cut the roll after this job */
+#define CUPS_CUT_SET 3 /* Cut the roll after this set */
+#define CUPS_CUT_PAGE 4 /* Cut the roll after this page */
+
+/* AdvanceMedia values */
+#define CUPS_ADVANCE_NONE 0 /* Never advance the roll */
+#define CUPS_ADVANCE_FILE 1 /* Advance the roll after this file */
+#define CUPS_ADVANCE_JOB 2 /* Advance the roll after this job */
+#define CUPS_ADVANCE_SET 3 /* Advance the roll after this set */
+#define CUPS_ADVANCE_PAGE 4 /* Advance the roll after this page */
+
+/* LeadingEdge values */
+#define CUPS_EDGE_TOP 0 /* Leading edge is the top of the page */
+#define CUPS_EDGE_RIGHT 1 /* Leading edge is the right of the page */
+#define CUPS_EDGE_BOTTOM 2 /* Leading edge is the bottom of the page */
+#define CUPS_EDGE_LEFT 3 /* Leading edge is the left of the page */
+
+/* cupsColorOrder values */
+#define CUPS_ORDER_CHUNKED 0 /* CMYK CMYK CMYK ... */
+#define CUPS_ORDER_BANDED 1 /* CCC MMM YYY KKK ... */
+#define CUPS_ORDER_PLANAR 2 /* CCC ... MMM ... YYY ... KKK ... */
+
+/* cupsColorSpace values */
+#define CUPS_CSPACE_W 0 /* Luminance */
+#define CUPS_CSPACE_RGB 1 /* Red, green, blue */
+#define CUPS_CSPACE_RGBA 2 /* Red, green, blue, alpha */
+#define CUPS_CSPACE_K 3 /* Black */
+#define CUPS_CSPACE_CMY 4 /* Cyan, magenta, yellow */
+#define CUPS_CSPACE_YMC 5 /* Yellow, magenta, cyan */
+#define CUPS_CSPACE_CMYK 6 /* Cyan, magenta, yellow, black */
+#define CUPS_CSPACE_YMCK 7 /* Yellow, magenta, cyan, black */
+#define CUPS_CSPACE_KCMY 8 /* Black, cyan, magenta, yellow */
+#define CUPS_CSPACE_KCMYcm 9 /* Black, cyan, magenta, yellow, *
+ * light-cyan, light-magenta */
+#define CUPS_CSPACE_GMCK 10 /* Gold, magenta, yellow, black */
+#define CUPS_CSPACE_GMCS 11 /* Gold, magenta, yellow, silver */
+#define CUPS_CSPACE_WHITE 12 /* White ink (as black) */
+#define CUPS_CSPACE_GOLD 13 /* Gold foil */
+#define CUPS_CSPACE_SILVER 14 /* Silver foil */
+
+#define CUPS_CSPACE_CIEXYZ 15 /* CIE XYZ */
+#define CUPS_CSPACE_CIELab 16 /* CIE Lab */
+
+#define CUPS_CSPACE_ICC1 32 /* ICC-based, 1 color */
+#define CUPS_CSPACE_ICC2 33 /* ICC-based, 2 colors */
+#define CUPS_CSPACE_ICC3 34 /* ICC-based, 3 colors */
+#define CUPS_CSPACE_ICC4 35 /* ICC-based, 4 colors */
+#define CUPS_CSPACE_ICC5 36 /* ICC-based, 5 colors */
+#define CUPS_CSPACE_ICC6 37 /* ICC-based, 6 colors */
+#define CUPS_CSPACE_ICC7 38 /* ICC-based, 7 colors */
+#define CUPS_CSPACE_ICC8 39 /* ICC-based, 8 colors */
+#define CUPS_CSPACE_ICC9 40 /* ICC-based, 9 colors */
+#define CUPS_CSPACE_ICCA 41 /* ICC-based, 10 colors */
+#define CUPS_CSPACE_ICCB 42 /* ICC-based, 11 colors */
+#define CUPS_CSPACE_ICCC 43 /* ICC-based, 12 colors */
+#define CUPS_CSPACE_ICCD 44 /* ICC-based, 13 colors */
+#define CUPS_CSPACE_ICCE 45 /* ICC-based, 14 colors */
+#define CUPS_CSPACE_ICCF 46 /* ICC-based, 15 colors */