|
|
//
|
|
|
// 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"
|
|
|
|
|
|
|
|
|
//
|
|
|
// '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 (!_cups_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 (!_cups_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 CUPS PPD Compiler " CUPS_SVERSION
|
|
|
".%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 (_cups_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 (_cups_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 (_cups_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];
|
|
|
|
|
|
_cupsStrFormatd(density, density + sizeof(density), p->density, loc);
|
|
|
_cupsStrFormatd(gamma, gamma + sizeof(gamma), p->gamma, loc);
|
|
|
|
|
|
for (int i = 0; i < 9; i ++)
|
|
|
_cupsStrFormatd(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...
|
|
|
_cupsLangPrintf(stderr,
|
|
|
_("ppdc: No message catalog provided for locale "
|
|
|
"%s."), 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())
|
|
|
{
|
|
|
_cupsStrFormatd(left, left + sizeof(left), m->left, loc);
|
|
|
_cupsStrFormatd(bottom, bottom + sizeof(bottom), m->bottom, loc);
|
|
|
_cupsStrFormatd(right, right + sizeof(right), m->width - m->right, loc);
|
|
|
_cupsStrFormatd(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())
|
|
|
{
|
|
|
_cupsStrFormatd(width, width + sizeof(width), m->width, loc);
|
|
|
_cupsStrFormatd(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)
|
|
|
{
|
|
|
_cupsStrFormatd(width, width + sizeof(width), max_width, loc);
|
|
|
_cupsStrFormatd(length, length + sizeof(length), max_length, loc);
|
|
|
|
|
|
_cupsStrFormatd(left, left + sizeof(left), left_margin, loc);
|
|
|
_cupsStrFormatd(bottom, bottom + sizeof(bottom), bottom_margin, loc);
|
|
|
_cupsStrFormatd(right, right + sizeof(right), right_margin, loc);
|
|
|
_cupsStrFormatd(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];
|
|
|
|
|
|
_cupsStrFormatd(width0, width0 + sizeof(width0), min_width, loc);
|
|
|
_cupsStrFormatd(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];
|
|
|
|
|
|
_cupsStrFormatd(length0, length0 + sizeof(length0), min_length, loc);
|
|
|
_cupsStrFormatd(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 (_cups_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];
|
|
|
_cupsStrFormatd(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 (_cups_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 (_cups_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 (_cups_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 (_cups_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 (_cups_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);
|
|
|
}
|