/*
* PPD cache implementation for CUPS.
*
- * Copyright © 2010-2018 by Apple Inc.
+ * Copyright © 2010-2019 by Apple Inc.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
* information.
#include "cups-private.h"
#include "ppd-private.h"
+#include "debug-internal.h"
#include <math.h>
int num_finishings = 0, /* Number of finishing values */
finishings[10]; /* Finishing enum values */
ppd_choice_t *choice; /* Marked choice */
- int finishings_copies = copies;
+ int finishings_copies = copies,
/* Number of copies for finishings */
+ job_pages = 0, /* job-pages value */
+ number_up = 1; /* number-up value */
+ const char *value; /* Option value */
/*
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, keyword);
else if (pc->sides_option && (choice = ppdFindMarkedChoice(ppd, pc->sides_option)) != NULL)
{
- if (!_cups_strcasecmp(choice->choice, pc->sides_1sided))
+ if (pc->sides_1sided && !_cups_strcasecmp(choice->choice, pc->sides_1sided))
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "one-sided");
- else if (!_cups_strcasecmp(choice->choice, pc->sides_2sided_long))
+ else if (pc->sides_2sided_long && !_cups_strcasecmp(choice->choice, pc->sides_2sided_long))
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-long-edge");
- if (!_cups_strcasecmp(choice->choice, pc->sides_2sided_short))
+ else if (pc->sides_2sided_short && !_cups_strcasecmp(choice->choice, pc->sides_2sided_short))
ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-short-edge");
}
* Map finishing options...
*/
+ if (copies != finishings_copies)
+ {
+ // Figure out the proper job-pages-per-set value...
+ if ((value = cupsGetOption("job-pages", num_options, options)) == NULL)
+ value = cupsGetOption("com.apple.print.PrintSettings.PMTotalBeginPages..n.", num_options, options);
+
+ if (value)
+ job_pages = atoi(value);
+
+ // Adjust for number-up
+ if ((value = cupsGetOption("number-up", num_options, options)) != NULL)
+ number_up = atoi(value);
+
+ job_pages = (job_pages + number_up - 1) / number_up;
+
+ // When duplex printing, raster data will include an extra (blank) page to
+ // make the total number of pages even. Make sure this is reflected in the
+ // page count...
+ if ((job_pages & 1) && (keyword = cupsGetOption("sides", num_options, options)) != NULL && strcmp(keyword, "one-sided"))
+ job_pages ++;
+ }
+
if ((finishing_template = cupsGetOption("cupsFinishingTemplate", num_options, options)) == NULL)
finishing_template = cupsGetOption("finishing-template", num_options, options);
- if (finishing_template)
+ if (finishing_template && strcmp(finishing_template, "none"))
{
ipp_t *fin_col = ippNew(); /* finishings-col value */
ippAddCollection(request, IPP_TAG_JOB, "finishings-col", fin_col);
ippDelete(fin_col);
- if (copies != finishings_copies && (keyword = cupsGetOption("job-impressions", num_options, options)) != NULL)
+ if (copies != finishings_copies && job_pages > 0)
{
/*
* Send job-pages-per-set attribute to apply finishings correctly...
*/
- ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", atoi(keyword) / finishings_copies);
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", job_pages);
}
}
else
{
ippAddIntegers(request, IPP_TAG_JOB, IPP_TAG_ENUM, "finishings", num_finishings, finishings);
- if (copies != finishings_copies && (keyword = cupsGetOption("job-impressions", num_options, options)) != NULL)
+ if (copies != finishings_copies && job_pages > 0)
{
/*
* Send job-pages-per-set attribute to apply finishings correctly...
*/
- ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", atoi(keyword) / finishings_copies);
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", job_pages);
}
}
}
else if (!_cups_strcasecmp(line, "Filter"))
{
if (!pc->filters)
- pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0,
- (cups_acopy_func_t)_cupsStrAlloc,
- (cups_afree_func_t)_cupsStrFree);
+ pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
cupsArrayAdd(pc->filters, value);
}
else if (!_cups_strcasecmp(line, "PreFilter"))
{
if (!pc->prefilters)
- pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0,
- (cups_acopy_func_t)_cupsStrAlloc,
- (cups_afree_func_t)_cupsStrFree);
+ pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
cupsArrayAdd(pc->prefilters, value);
}
else if (!_cups_strcasecmp(line, "Product"))
{
- pc->product = _cupsStrAlloc(value);
+ pc->product = strdup(value);
}
else if (!_cups_strcasecmp(line, "SingleFile"))
{
}
map = pc->bins + pc->num_bins;
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(ppd_keyword);
+ map->pwg = strdup(pwg_keyword);
+ map->ppd = strdup(ppd_keyword);
pc->num_bins ++;
}
goto create_error;
}
- size->map.pwg = _cupsStrAlloc(pwg_keyword);
- size->map.ppd = _cupsStrAlloc(ppd_keyword);
+ size->map.pwg = strdup(pwg_keyword);
+ size->map.ppd = strdup(ppd_keyword);
pc->num_sizes ++;
}
pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
pc->custom_max_width, pc->custom_max_length, NULL);
- pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
+ pc->custom_max_keyword = strdup(pwg_keyword);
pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
pc->custom_min_width, pc->custom_min_length, NULL);
- pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
+ pc->custom_min_keyword = strdup(pwg_keyword);
}
else if (!_cups_strcasecmp(line, "SourceOption"))
{
- pc->source_option = _cupsStrAlloc(value);
+ pc->source_option = strdup(value);
}
else if (!_cups_strcasecmp(line, "NumSources"))
{
}
map = pc->sources + pc->num_sources;
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(ppd_keyword);
+ map->pwg = strdup(pwg_keyword);
+ map->ppd = strdup(ppd_keyword);
pc->num_sources ++;
}
}
map = pc->types + pc->num_types;
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(ppd_keyword);
+ map->pwg = strdup(pwg_keyword);
+ map->ppd = strdup(ppd_keyword);
pc->num_types ++;
}
pc->presets[print_color_mode] + print_quality);
}
else if (!_cups_strcasecmp(line, "SidesOption"))
- pc->sides_option = _cupsStrAlloc(value);
+ pc->sides_option = strdup(value);
else if (!_cups_strcasecmp(line, "Sides1Sided"))
- pc->sides_1sided = _cupsStrAlloc(value);
+ pc->sides_1sided = strdup(value);
else if (!_cups_strcasecmp(line, "Sides2SidedLong"))
- pc->sides_2sided_long = _cupsStrAlloc(value);
+ pc->sides_2sided_long = strdup(value);
else if (!_cups_strcasecmp(line, "Sides2SidedShort"))
- pc->sides_2sided_short = _cupsStrAlloc(value);
+ pc->sides_2sided_short = strdup(value);
else if (!_cups_strcasecmp(line, "Finishings"))
{
if (!pc->finishings)
else if (!_cups_strcasecmp(line, "FinishingTemplate"))
{
if (!pc->templates)
- pc->templates = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)_cupsStrAlloc, (cups_afree_func_t)_cupsStrFree);
+ pc->templates = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
cupsArrayAdd(pc->templates, value);
}
else if (!_cups_strcasecmp(line, "MaxCopies"))
pc->max_copies = atoi(value);
else if (!_cups_strcasecmp(line, "ChargeInfoURI"))
- pc->charge_info_uri = _cupsStrAlloc(value);
+ pc->charge_info_uri = strdup(value);
else if (!_cups_strcasecmp(line, "JobAccountId"))
pc->account_id = !_cups_strcasecmp(value, "true");
else if (!_cups_strcasecmp(line, "JobAccountingUserId"))
pc->accounting_user_id = !_cups_strcasecmp(value, "true");
else if (!_cups_strcasecmp(line, "JobPassword"))
- pc->password = _cupsStrAlloc(value);
+ pc->password = strdup(value);
else if (!_cups_strcasecmp(line, "Mandatory"))
{
if (pc->mandatory)
else if (!_cups_strcasecmp(line, "SupportFile"))
{
if (!pc->support_files)
- pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
- (cups_acopy_func_t)_cupsStrAlloc,
- (cups_afree_func_t)_cupsStrFree);
+ pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
cupsArrayAdd(pc->support_files, value);
}
* Convert the PPD size name to the corresponding PWG keyword name.
*/
- if ((pwg_media = pwgMediaForPPD(ppd_size->name)) != NULL)
+ if ((pwg_media = pwgMediaForSize(PWG_FROM_POINTS(ppd_size->width), PWG_FROM_POINTS(ppd_size->length))) != NULL)
{
/*
* Standard name, do we have conflicts?
*/
new_size = old_size;
- _cupsStrFree(old_size->map.ppd);
- _cupsStrFree(old_size->map.pwg);
+ free(old_size->map.ppd);
+ free(old_size->map.pwg);
}
}
* Save this size...
*/
- new_size->map.ppd = _cupsStrAlloc(ppd_size->name);
- new_size->map.pwg = _cupsStrAlloc(pwg_name);
+ new_size->map.ppd = strdup(ppd_size->name);
+ new_size->map.pwg = strdup(pwg_name);
new_size->width = new_width;
new_size->length = new_length;
new_size->left = new_left;
pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
PWG_FROM_POINTS(ppd->custom_max[0]),
PWG_FROM_POINTS(ppd->custom_max[1]), NULL);
- pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
+ pc->custom_max_keyword = strdup(pwg_keyword);
pc->custom_max_width = PWG_FROM_POINTS(ppd->custom_max[0]);
pc->custom_max_length = PWG_FROM_POINTS(ppd->custom_max[1]);
pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
PWG_FROM_POINTS(ppd->custom_min[0]),
PWG_FROM_POINTS(ppd->custom_min[1]), NULL);
- pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
+ pc->custom_min_keyword = strdup(pwg_keyword);
pc->custom_min_width = PWG_FROM_POINTS(ppd->custom_min[0]);
pc->custom_min_length = PWG_FROM_POINTS(ppd->custom_min[1]);
if (input_slot)
{
- pc->source_option = _cupsStrAlloc(input_slot->keyword);
+ pc->source_option = strdup(input_slot->keyword);
if ((pc->sources = calloc((size_t)input_slot->num_choices, sizeof(pwg_map_t))) == NULL)
{
"_");
}
- map->pwg = _cupsStrAlloc(pwg_name);
- map->ppd = _cupsStrAlloc(choice->choice);
+ map->pwg = strdup(pwg_name);
+ map->ppd = strdup(choice->choice);
/*
* Add localized text for PWG keyword to message catalog...
"_");
}
- map->pwg = _cupsStrAlloc(pwg_name);
- map->ppd = _cupsStrAlloc(choice->choice);
+ map->pwg = strdup(pwg_name);
+ map->ppd = strdup(choice->choice);
/*
* Add localized text for PWG keyword to message catalog...
{
pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword), "_");
- map->pwg = _cupsStrAlloc(pwg_keyword);
- map->ppd = _cupsStrAlloc(choice->choice);
+ map->pwg = strdup(pwg_keyword);
+ map->ppd = strdup(choice->choice);
/*
* Add localized text for PWG keyword to message catalog...
*/
- snprintf(msg_id, sizeof(msg_id), "output-bin.%s", pwg_name);
+ snprintf(msg_id, sizeof(msg_id), "output-bin.%s", pwg_keyword);
pwg_add_message(pc->strings, msg_id, choice->text);
}
}
if (duplex)
{
- pc->sides_option = _cupsStrAlloc(duplex->keyword);
+ pc->sides_option = strdup(duplex->keyword);
for (i = duplex->num_choices, choice = duplex->choices;
i > 0;
{
if ((!_cups_strcasecmp(choice->choice, "None") ||
!_cups_strcasecmp(choice->choice, "False")) && !pc->sides_1sided)
- pc->sides_1sided = _cupsStrAlloc(choice->choice);
+ pc->sides_1sided = strdup(choice->choice);
else if ((!_cups_strcasecmp(choice->choice, "DuplexNoTumble") ||
!_cups_strcasecmp(choice->choice, "LongEdge") ||
!_cups_strcasecmp(choice->choice, "Top")) && !pc->sides_2sided_long)
- pc->sides_2sided_long = _cupsStrAlloc(choice->choice);
+ pc->sides_2sided_long = strdup(choice->choice);
else if ((!_cups_strcasecmp(choice->choice, "DuplexTumble") ||
!_cups_strcasecmp(choice->choice, "ShortEdge") ||
!_cups_strcasecmp(choice->choice, "Bottom")) &&
!pc->sides_2sided_short)
- pc->sides_2sided_short = _cupsStrAlloc(choice->choice);
+ pc->sides_2sided_short = strdup(choice->choice);
}
}
* Copy filters and pre-filters...
*/
- pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0,
- (cups_acopy_func_t)_cupsStrAlloc,
- (cups_afree_func_t)_cupsStrFree);
+ pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
cupsArrayAdd(pc->filters,
"application/vnd.cups-raw application/octet-stream 0 -");
if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
{
- pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0,
- (cups_acopy_func_t)_cupsStrAlloc,
- (cups_afree_func_t)_cupsStrFree);
+ pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
do
{
*/
if (ppd->product)
- pc->product = _cupsStrAlloc(ppd->product);
+ pc->product = strdup(ppd->product);
/*
* Copy finishings mapping data...
if ((ppd_option = ppdFindOption(ppd, "cupsFinishingTemplate")) != NULL)
{
- pc->templates = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)_cupsStrAlloc, (cups_afree_func_t)_cupsStrFree);
+ pc->templates = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
for (choice = ppd_option->choices, i = ppd_option->num_choices; i > 0; choice ++, i --)
{
*/
if ((ppd_attr = ppdFindAttr(ppd, "cupsChargeInfoURI", NULL)) != NULL)
- pc->charge_info_uri = _cupsStrAlloc(ppd_attr->value);
+ pc->charge_info_uri = strdup(ppd_attr->value);
if ((ppd_attr = ppdFindAttr(ppd, "cupsJobAccountId", NULL)) != NULL)
pc->account_id = !_cups_strcasecmp(ppd_attr->value, "true");
pc->accounting_user_id = !_cups_strcasecmp(ppd_attr->value, "true");
if ((ppd_attr = ppdFindAttr(ppd, "cupsJobPassword", NULL)) != NULL)
- pc->password = _cupsStrAlloc(ppd_attr->value);
+ pc->password = strdup(ppd_attr->value);
if ((ppd_attr = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
pc->mandatory = _cupsArrayNewStrings(ppd_attr->value, ' ');
* Support files...
*/
- pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
- (cups_acopy_func_t)_cupsStrAlloc,
- (cups_afree_func_t)_cupsStrFree);
+ pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
for (ppd_attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
ppd_attr;
{
for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++)
{
- _cupsStrFree(map->pwg);
- _cupsStrFree(map->ppd);
+ free(map->pwg);
+ free(map->ppd);
}
free(pc->bins);
{
for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
{
- _cupsStrFree(size->map.pwg);
- _cupsStrFree(size->map.ppd);
+ free(size->map.pwg);
+ free(size->map.ppd);
}
free(pc->sizes);
}
- if (pc->source_option)
- _cupsStrFree(pc->source_option);
+ free(pc->source_option);
if (pc->sources)
{
for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++)
{
- _cupsStrFree(map->pwg);
- _cupsStrFree(map->ppd);
+ free(map->pwg);
+ free(map->ppd);
}
free(pc->sources);
{
for (i = pc->num_types, map = pc->types; i > 0; i --, map ++)
{
- _cupsStrFree(map->pwg);
- _cupsStrFree(map->ppd);
+ free(map->pwg);
+ free(map->ppd);
}
free(pc->types);
}
- if (pc->custom_max_keyword)
- _cupsStrFree(pc->custom_max_keyword);
+ free(pc->custom_max_keyword);
+ free(pc->custom_min_keyword);
- if (pc->custom_min_keyword)
- _cupsStrFree(pc->custom_min_keyword);
-
- _cupsStrFree(pc->product);
+ free(pc->product);
cupsArrayDelete(pc->filters);
cupsArrayDelete(pc->prefilters);
cupsArrayDelete(pc->finishings);
- _cupsStrFree(pc->charge_info_uri);
- _cupsStrFree(pc->password);
+ free(pc->charge_info_uri);
+ free(pc->password);
cupsArrayDelete(pc->mandatory);
f;
f = (_pwg_finishings_t *)cupsArrayNext(pc->finishings))
{
- DEBUG_printf(("_ppdCacheGetFinishingValues: Checking %d (%s)", f->value, ippEnumString("finishings", f->value)));
+ DEBUG_printf(("_ppdCacheGetFinishingValues: Checking %d (%s)", (int)f->value, ippEnumString("finishings", (int)f->value)));
for (i = f->num_options, option = f->options; i > 0; i --, option ++)
{
if (i == 0)
{
- DEBUG_printf(("_ppdCacheGetFinishingValues: Adding %d (%s)", f->value, ippEnumString("finishings", f->value)));
+ DEBUG_printf(("_ppdCacheGetFinishingValues: Adding %d (%s)", (int)f->value, ippEnumString("finishings", (int)f->value)));
- values[num_values ++] = f->value;
+ values[num_values ++] = (int)f->value;
if (num_values >= max_values)
break;
if (pc->charge_info_uri)
cupsFilePutConf(fp, "ChargeInfoURI", pc->charge_info_uri);
- cupsFilePrintf(fp, "AccountId %s\n", pc->account_id ? "true" : "false");
- cupsFilePrintf(fp, "AccountingUserId %s\n",
+ cupsFilePrintf(fp, "JobAccountId %s\n", pc->account_id ? "true" : "false");
+ cupsFilePrintf(fp, "JobAccountingUserId %s\n",
pc->accounting_user_id ? "true" : "false");
if (pc->password)
- cupsFilePutConf(fp, "Password", pc->password);
+ cupsFilePutConf(fp, "JobPassword", pc->password);
for (value = (char *)cupsArrayFirst(pc->mandatory);
value;
cupsFilePrintf(fp, "*Manufacturer: \"%s\"\n", make);
cupsFilePrintf(fp, "*ModelName: \"%s\"\n", model);
cupsFilePrintf(fp, "*Product: \"(%s)\"\n", model);
- cupsFilePrintf(fp, "*NickName: \"%s\"\n", model);
- cupsFilePrintf(fp, "*ShortNickName: \"%s\"\n", model);
+ cupsFilePrintf(fp, "*NickName: \"%s - IPP Everywhere\"\n", model);
+ cupsFilePrintf(fp, "*ShortNickName: \"%s - IPP Everywhere\"\n", model);
if ((attr = ippFindAttribute(response, "color-supported", IPP_TAG_BOOLEAN)) != NULL && ippGetBoolean(attr, 0))
cupsFilePuts(fp, "*ColorDevice: True\n");
httpClose(http);
}
+ /*
+ * Accounting...
+ */
+
+ if (ippGetBoolean(ippFindAttribute(response, "job-account-id-supported", IPP_TAG_BOOLEAN), 0))
+ cupsFilePuts(fp, "*cupsJobAccountId: True\n");
+
+ if (ippGetBoolean(ippFindAttribute(response, "job-accounting-user-id-supported", IPP_TAG_BOOLEAN), 0))
+ cupsFilePuts(fp, "*cupsJobAccountingUserId: True\n");
+
/*
* Password/PIN printing...
*/
/* Type of password */
if (maxlen > (int)(sizeof(pattern) - 1))
- maxlen = sizeof(pattern) - 1;
+ maxlen = (int)sizeof(pattern) - 1;
if (!repertoire || !strcmp(repertoire, "iana_us-ascii_digits"))
- memset(pattern, '1', maxlen);
+ memset(pattern, '1', (size_t)maxlen);
else if (!strcmp(repertoire, "iana_us-ascii_letters"))
- memset(pattern, 'A', maxlen);
+ memset(pattern, 'A', (size_t)maxlen);
else if (!strcmp(repertoire, "iana_us-ascii_complex"))
- memset(pattern, 'C', maxlen);
+ memset(pattern, 'C', (size_t)maxlen);
else if (!strcmp(repertoire, "iana_us-ascii_any"))
- memset(pattern, '.', maxlen);
+ memset(pattern, '.', (size_t)maxlen);
else if (!strcmp(repertoire, "iana_utf-8_digits"))
- memset(pattern, 'N', maxlen);
+ memset(pattern, 'N', (size_t)maxlen);
else if (!strcmp(repertoire, "iana_utf-8_letters"))
- memset(pattern, 'U', maxlen);
+ memset(pattern, 'U', (size_t)maxlen);
else
- memset(pattern, '*', maxlen);
+ memset(pattern, '*', (size_t)maxlen);
pattern[maxlen] = '\0';
- cupsFilePrintf(fp, "*cupsPassword: \"%s\"\n", pattern);
+ cupsFilePrintf(fp, "*cupsJobPassword: \"%s\"\n", pattern);
}
/*
if (ippContainsString(attr, "image/png"))
cupsFilePuts(fp, "*cupsFilter2: \"image/png image/png 0 -\"\n");
if (is_pdf)
- cupsFilePuts(fp, "*cupsFilter2: \"application/vnd.cups-pdf application/pdf 10 -\"\n");
+ {
+ /*
+ * Don't locally filter PDF content when printing to a CUPS shared
+ * printer, otherwise the options will be applied twice...
+ */
+
+ if (ippContainsString(attr, "application/vnd.cups-pdf"))
+ cupsFilePuts(fp, "*cupsFilter2: \"application/pdf application/pdf 0 -\"\n");
+ else
+ cupsFilePuts(fp, "*cupsFilter2: \"application/vnd.cups-pdf application/pdf 10 -\"\n");
+ }
+ else
+ cupsFilePuts(fp, "*cupsManualCopies: True\n");
if (is_apple)
cupsFilePuts(fp, "*cupsFilter2: \"image/urf image/urf 100 -\"\n");
if (is_pwg)
if ((attr = ippFindAttribute(ippGetCollection(defattr, 0), "media-source", IPP_TAG_ZERO)) != NULL)
pwg_ppdize_name(ippGetString(attr, 0, NULL), ppdname, sizeof(ppdname));
else
- strlcpy(ppdname, "Unknown", sizeof(ppdname));
+ ppdname[0] = '\0';
if ((attr = ippFindAttribute(response, "media-source-supported", IPP_TAG_ZERO)) != NULL && (count = ippGetCount(attr)) > 1)
{
+ int have_default = ppdname[0] != '\0';
+ /* Do we have a default InputSlot? */
static const char * const sources[] =
{ /* Standard "media-source" strings */
"auto",
"roll-10"
};
- cupsFilePrintf(fp, "*OpenUI *InputSlot: PickOne\n"
- "*OrderDependency: 10 AnySetup *InputSlot\n"
- "*DefaultInputSlot: %s\n", ppdname);
- for (i = 0, count = ippGetCount(attr); i < count; i ++)
+ cupsFilePuts(fp, "*OpenUI *InputSlot: PickOne\n"
+ "*OrderDependency: 10 AnySetup *InputSlot\n");
+ if (have_default)
+ cupsFilePrintf(fp, "*DefaultInputSlot: %s\n", ppdname);
+
+ for (i = 0; i < count; i ++)
{
keyword = ippGetString(attr, i, NULL);
pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
+ if (i == 0 && !have_default)
+ cupsFilePrintf(fp, "*DefaultInputSlot: %s\n", ppdname);
+
for (j = 0; j < (int)(sizeof(sources) / sizeof(sources[0])); j ++)
if (!strcmp(sources[j], keyword))
{
snprintf(msgid, sizeof(msgid), "media-source.%s", keyword);
- cupsFilePrintf(fp, "*InputSlot %s/%s: \"<</MediaPosition %d>>setpagedevice\"\n", ppdname, _cupsLangString(lang, msgid), j);
+
+ if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
+ if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
+ msgstr = keyword;
+
+ cupsFilePrintf(fp, "*InputSlot %s: \"<</MediaPosition %d>>setpagedevice\"\n", ppdname, j);
+ cupsFilePrintf(fp, "*%s.InputSlot %s/%s: \"\"\n", lang->language, ppdname, msgstr);
break;
}
}
if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
msgstr = keyword;
- cupsFilePrintf(fp, "*MediaType %s/%s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, msgstr, ppdname);
+ cupsFilePrintf(fp, "*MediaType %s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, ppdname);
+ cupsFilePrintf(fp, "*%s.MediaType %s/%s: \"\"\n", lang->language, ppdname, msgstr);
}
cupsFilePuts(fp, "*CloseUI: *MediaType\n");
}
int wrote_color = 0;
const char *default_color = NULL; /* Default */
+ cupsFilePrintf(fp, "*%% ColorModel from %s\n", ippGetName(attr));
+
for (i = 0, count = ippGetCount(attr); i < count; i ++)
{
keyword = ippGetString(attr, i, NULL);
-#define PRINTF_COLORMODEL if (!wrote_color) { cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n*OrderDependency: 10 AnySetup *ColorModel\n", _cupsLangString(lang, _("Color Mode"))); wrote_color = 1; }
-#define PRINTF_COLOROPTION(name,text,cspace,bpp) cupsFilePrintf(fp, "*ColorModel %s/%s: \"<</cupsColorSpace %d/cupsBitsPerColor %d/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", name, _cupsLangString(lang, text), cspace, bpp)
+#define PRINTF_COLORMODEL if (!wrote_color) { cupsFilePrintf(fp, "*OpenUI *ColorModel: PickOne\n*OrderDependency: 10 AnySetup *ColorModel\n*%s.Translation ColorModel/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color Mode"))); wrote_color = 1; }
+#define PRINTF_COLOROPTION(name,text,cspace,bpp) { cupsFilePrintf(fp, "*ColorModel %s: \"<</cupsColorSpace %d/cupsBitsPerColor %d/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", name, cspace, bpp); cupsFilePrintf(fp, "*%s.ColorModel %s/%s: \"\"\n", lang->language, name, _cupsLangString(lang, text)); }
if (!strcasecmp(keyword, "black_1") || !strcmp(keyword, "bi-level") || !strcmp(keyword, "process-bi-level"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("FastGray", _("Fast Grayscale"), CUPS_CSPACE_K, 1);
+ PRINTF_COLOROPTION("FastGray", _("Fast Grayscale"), CUPS_CSPACE_K, 1)
- if (!default_color)
+ if (!default_color)
default_color = "FastGray";
}
else if (!strcasecmp(keyword, "sgray_8") || !strcmp(keyword, "W8") || !strcmp(keyword, "monochrome") || !strcmp(keyword, "process-monochrome"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("Gray", _("Grayscale"), CUPS_CSPACE_SW, 8);
+ PRINTF_COLOROPTION("Gray", _("Grayscale"), CUPS_CSPACE_SW, 8)
- if (!default_color || !strcmp(default_color, "FastGray"))
+ if (!default_color || !strcmp(default_color, "FastGray"))
default_color = "Gray";
}
else if (!strcasecmp(keyword, "sgray_16") || !strcmp(keyword, "W8-16"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- if (!strcmp(keyword, "W8-16"))
- {
- PRINTF_COLOROPTION("Gray", _("Grayscale"), CUPS_CSPACE_SW, 8);
+ if (!strcmp(keyword, "W8-16"))
+ {
+ PRINTF_COLOROPTION("Gray", _("Grayscale"), CUPS_CSPACE_SW, 8)
if (!default_color || !strcmp(default_color, "FastGray"))
default_color = "Gray";
- }
+ }
- PRINTF_COLOROPTION("Gray16", _("Deep Gray"), CUPS_CSPACE_SW, 16);
+ PRINTF_COLOROPTION("Gray16", _("Deep Gray"), CUPS_CSPACE_SW, 16)
}
else if (!strcasecmp(keyword, "srgb_8") || !strncmp(keyword, "SRGB24", 7) || !strcmp(keyword, "color"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("RGB", _("Color"), CUPS_CSPACE_SRGB, 8);
+ PRINTF_COLOROPTION("RGB", _("Color"), CUPS_CSPACE_SRGB, 8)
default_color = "RGB";
+
+ // Apparently some printers only advertise color support, so make sure
+ // we also do grayscale for these printers...
+ if (!ippContainsString(attr, "sgray_8") && !ippContainsString(attr, "black_1") && !ippContainsString(attr, "black_8") && !ippContainsString(attr, "W8") && !ippContainsString(attr, "W8-16"))
+ PRINTF_COLOROPTION("Gray", _("GrayScale"), CUPS_CSPACE_SW, 8)
}
else if (!strcasecmp(keyword, "adobe-rgb_16") || !strcmp(keyword, "ADOBERGB48") || !strcmp(keyword, "ADOBERGB24-48"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("AdobeRGB", _("Deep Color"), CUPS_CSPACE_ADOBERGB, 16);
+ PRINTF_COLOROPTION("AdobeRGB", _("Deep Color"), CUPS_CSPACE_ADOBERGB, 16)
- if (!default_color)
+ if (!default_color)
default_color = "AdobeRGB";
}
else if ((!strcasecmp(keyword, "adobe-rgb_8") && !ippContainsString(attr, "adobe-rgb_16")) || !strcmp(keyword, "ADOBERGB24"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("AdobeRGB", _("Deep Color"), CUPS_CSPACE_ADOBERGB, 8);
+ PRINTF_COLOROPTION("AdobeRGB", _("Deep Color"), CUPS_CSPACE_ADOBERGB, 8)
- if (!default_color)
+ if (!default_color)
default_color = "AdobeRGB";
}
else if ((!strcasecmp(keyword, "black_8") && !ippContainsString(attr, "black_16")) || !strcmp(keyword, "DEVW8"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("DeviceGray", _("Device Gray"), CUPS_CSPACE_W, 8);
+ PRINTF_COLOROPTION("DeviceGray", _("Device Gray"), CUPS_CSPACE_W, 8)
}
else if (!strcasecmp(keyword, "black_16") || !strcmp(keyword, "DEVW16") || !strcmp(keyword, "DEVW8-16"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("DeviceGray", _("Device Gray"), CUPS_CSPACE_W, 16);
+ PRINTF_COLOROPTION("DeviceGray", _("Device Gray"), CUPS_CSPACE_W, 16)
}
else if ((!strcasecmp(keyword, "cmyk_8") && !ippContainsString(attr, "cmyk_16")) || !strcmp(keyword, "DEVCMYK32"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("CMYK", _("Device CMYK"), CUPS_CSPACE_CMYK, 8);
+ PRINTF_COLOROPTION("CMYK", _("Device CMYK"), CUPS_CSPACE_CMYK, 8)
}
else if (!strcasecmp(keyword, "cmyk_16") || !strcmp(keyword, "DEVCMYK32-64") || !strcmp(keyword, "DEVCMYK64"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("CMYK", _("Device CMYK"), CUPS_CSPACE_CMYK, 16);
+ PRINTF_COLOROPTION("CMYK", _("Device CMYK"), CUPS_CSPACE_CMYK, 16)
}
else if ((!strcasecmp(keyword, "rgb_8") && ippContainsString(attr, "rgb_16")) || !strcmp(keyword, "DEVRGB24"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("DeviceRGB", _("Device RGB"), CUPS_CSPACE_RGB, 8);
+ PRINTF_COLOROPTION("DeviceRGB", _("Device RGB"), CUPS_CSPACE_RGB, 8)
}
else if (!strcasecmp(keyword, "rgb_16") || !strcmp(keyword, "DEVRGB24-48") || !strcmp(keyword, "DEVRGB48"))
{
- PRINTF_COLORMODEL
+ PRINTF_COLORMODEL
- PRINTF_COLOROPTION("DeviceRGB", _("Device RGB"), CUPS_CSPACE_RGB, 16);
+ PRINTF_COLOROPTION("DeviceRGB", _("Device RGB"), CUPS_CSPACE_RGB, 16)
}
}
if ((attr = ippFindAttribute(response, "sides-supported", IPP_TAG_KEYWORD)) != NULL && ippContainsString(attr, "two-sided-long-edge"))
{
- cupsFilePrintf(fp, "*OpenUI *Duplex/%s: PickOne\n"
+ cupsFilePrintf(fp, "*OpenUI *Duplex: PickOne\n"
"*OrderDependency: 10 AnySetup *Duplex\n"
+ "*%s.Translation Duplex/%s: \"\"\n"
"*DefaultDuplex: None\n"
- "*Duplex None/%s: \"<</Duplex false>>setpagedevice\"\n"
- "*Duplex DuplexNoTumble/%s: \"<</Duplex true/Tumble false>>setpagedevice\"\n"
- "*Duplex DuplexTumble/%s: \"<</Duplex true/Tumble true>>setpagedevice\"\n"
- "*CloseUI: *Duplex\n", _cupsLangString(lang, _("2-Sided Printing")), _cupsLangString(lang, _("Off (1-Sided)")), _cupsLangString(lang, _("Long-Edge (Portrait)")), _cupsLangString(lang, _("Short-Edge (Landscape)")));
+ "*Duplex None: \"<</Duplex false>>setpagedevice\"\n"
+ "*%s.Duplex None/%s: \"\"\n"
+ "*Duplex DuplexNoTumble: \"<</Duplex true/Tumble false>>setpagedevice\"\n"
+ "*%s.Duplex DuplexNoTumble/%s: \"\"\n"
+ "*Duplex DuplexTumble: \"<</Duplex true/Tumble true>>setpagedevice\"\n"
+ "*%s.Duplex DuplexTumble/%s: \"\"\n"
+ "*CloseUI: *Duplex\n", lang->language, _cupsLangString(lang, _("2-Sided Printing")), lang->language, _cupsLangString(lang, _("Off (1-Sided)")), lang->language, _cupsLangString(lang, _("Long-Edge (Portrait)")), lang->language, _cupsLangString(lang, _("Short-Edge (Landscape)")));
if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
{
else
strlcpy(ppdname, "Unknown", sizeof(ppdname));
- if ((attr = ippFindAttribute(response, "output-bin-supported", IPP_TAG_ZERO)) != NULL && (count = ippGetCount(attr)) > 1)
+ if ((attr = ippFindAttribute(response, "output-bin-supported", IPP_TAG_ZERO)) != NULL && (count = ippGetCount(attr)) > 0)
{
+ ipp_attribute_t *trays = ippFindAttribute(response, "printer-output-tray", IPP_TAG_STRING);
+ /* printer-output-tray attribute, if any */
+ const char *tray_ptr; /* printer-output-tray value */
+ int tray_len; /* Len of printer-output-tray value */
+ char tray[IPP_MAX_OCTETSTRING];
+ /* printer-output-tray string value */
+
cupsFilePrintf(fp, "*OpenUI *OutputBin: PickOne\n"
"*OrderDependency: 10 AnySetup *OutputBin\n"
"*DefaultOutputBin: %s\n", ppdname);
+ if (!strcmp(ppdname, "FaceUp"))
+ cupsFilePuts(fp, "*DefaultOutputOrder: Reverse\n");
+ else
+ cupsFilePuts(fp, "*DefaultOutputOrder: Normal\n");
+
for (i = 0; i < count; i ++)
{
keyword = ippGetString(attr, i, NULL);
if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
msgstr = keyword;
- cupsFilePrintf(fp, "*OutputBin %s/%s: \"\"\n", ppdname, msgstr);
+ cupsFilePrintf(fp, "*OutputBin %s: \"\"\n", ppdname);
+ cupsFilePrintf(fp, "*%s.OutputBin %s/%s: \"\"\n", lang->language, ppdname, msgstr);
+
+ if ((tray_ptr = ippGetOctetString(trays, i, &tray_len)) != NULL)
+ {
+ if (tray_len >= (int)sizeof(tray))
+ tray_len = (int)sizeof(tray) - 1;
+
+ memcpy(tray, tray_ptr, (size_t)tray_len);
+ tray[tray_len] = '\0';
+
+ if (strstr(tray, "stackingorder=lastToFirst;"))
+ cupsFilePrintf(fp, "*PageStackOrder %s: Reverse\n", ppdname);
+ else
+ cupsFilePrintf(fp, "*PageStackOrder %s: Normal\n", ppdname);
+ }
+ else if (!strcmp(ppdname, "FaceUp"))
+ cupsFilePrintf(fp, "*PageStackOrder %s: Reverse\n", ppdname);
+ else
+ cupsFilePrintf(fp, "*PageStackOrder %s: Normal\n", ppdname);
}
cupsFilePuts(fp, "*CloseUI: *OutputBin\n");
}
if ((attr = ippFindAttribute(response, "finishings-supported", IPP_TAG_ENUM)) != NULL)
{
int value; /* Enum value */
+ const char *ppd_keyword; /* PPD keyword for enum */
cups_array_t *names; /* Names we've added */
+ static const char * const base_keywords[] =
+ { /* Base STD 92 keywords */
+ NULL, /* none */
+ "SingleAuto", /* staple */
+ "SingleAuto", /* punch */
+ NULL, /* cover */
+ "BindAuto", /* bind */
+ "SaddleStitch", /* saddle-stitch */
+ "EdgeStitchAuto", /* edge-stitch */
+ "Auto", /* fold */
+ NULL, /* trim */
+ NULL, /* bale */
+ NULL, /* booklet-maker */
+ NULL, /* jog-offset */
+ NULL, /* coat */
+ NULL /* laminate */
+ };
count = ippGetCount(attr);
names = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
if (i < count)
{
+ static const char * const staple_keywords[] =
+ { /* StapleLocation keywords */
+ "SinglePortrait",
+ "SingleRevLandscape",
+ "SingleLandscape",
+ "SingleRevPortrait",
+ "EdgeStitchPortrait",
+ "EdgeStitchLandscape",
+ "EdgeStitchRevPortrait",
+ "EdgeStitchRevLandscape",
+ "DualPortrait",
+ "DualLandscape",
+ "DualRevPortrait",
+ "DualRevLandscape",
+ "TriplePortrait",
+ "TripleLandscape",
+ "TripleRevPortrait",
+ "TripleRevLandscape"
+ };
+ static const char * const bind_keywords[] =
+ { /* StapleLocation binding keywords */
+ "BindPortrait",
+ "BindLandscape",
+ "BindRevPortrait",
+ "BindRevLandscape"
+ };
+
cupsArrayAdd(fin_options, "*StapleLocation");
- cupsFilePrintf(fp, "*OpenUI *StapleLocation/%s: PickOne\n", _cupsLangString(lang, _("Staple")));
+ cupsFilePuts(fp, "*OpenUI *StapleLocation: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *StapleLocation\n");
+ cupsFilePrintf(fp, "*%s.Translation StapleLocation/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Staple")));
cupsFilePuts(fp, "*DefaultStapleLocation: None\n");
- cupsFilePrintf(fp, "*StapleLocation None/%s: \"\"\n", _cupsLangString(lang, _("None")));
+ cupsFilePuts(fp, "*StapleLocation None: \"\"\n");
+ cupsFilePrintf(fp, "*%s.StapleLocation None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
for (; i < count; i ++)
{
if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
msgstr = keyword;
- cupsFilePrintf(fp, "*StapleLocation %s/%s: \"\"\n", keyword, msgstr);
- cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*StapleLocation %s\"\n", value, keyword, keyword);
+ if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
+ ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
+ else if (value >= IPP_FINISHINGS_STAPLE_TOP_LEFT && value <= IPP_FINISHINGS_STAPLE_TRIPLE_BOTTOM)
+ ppd_keyword = staple_keywords[value - IPP_FINISHINGS_STAPLE_TOP_LEFT];
+ else if (value >= IPP_FINISHINGS_BIND_LEFT && value <= IPP_FINISHINGS_BIND_BOTTOM)
+ ppd_keyword = bind_keywords[value - IPP_FINISHINGS_BIND_LEFT];
+ else
+ ppd_keyword = NULL;
+
+ if (!ppd_keyword)
+ continue;
+
+ cupsFilePrintf(fp, "*StapleLocation %s: \"\"\n", ppd_keyword);
+ cupsFilePrintf(fp, "*%s.StapleLocation %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*StapleLocation %s\"\n", value, keyword, ppd_keyword);
}
cupsFilePuts(fp, "*CloseUI: *StapleLocation\n");
value = ippGetInteger(attr, i);
keyword = ippEnumString("finishings", value);
- if (!strncmp(keyword, "fold-", 5))
+ if (!strncmp(keyword, "cups-fold-", 10) || !strcmp(keyword, "fold") || !strncmp(keyword, "fold-", 5))
break;
}
if (i < count)
{
+ static const char * const fold_keywords[] =
+ { /* FoldType keywords */
+ "Accordion",
+ "DoubleGate",
+ "Gate",
+ "Half",
+ "HalfZ",
+ "LeftGate",
+ "Letter",
+ "Parallel",
+ "XFold",
+ "RightGate",
+ "ZFold",
+ "EngineeringZ"
+ };
+
cupsArrayAdd(fin_options, "*FoldType");
- cupsFilePrintf(fp, "*OpenUI *FoldType/%s: PickOne\n", _cupsLangString(lang, _("Fold")));
+ cupsFilePuts(fp, "*OpenUI *FoldType: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *FoldType\n");
+ cupsFilePrintf(fp, "*%s.Translation FoldType/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Fold")));
cupsFilePuts(fp, "*DefaultFoldType: None\n");
- cupsFilePrintf(fp, "*FoldType None/%s: \"\"\n", _cupsLangString(lang, _("None")));
+ cupsFilePuts(fp, "*FoldType None: \"\"\n");
+ cupsFilePrintf(fp, "*%s.FoldType None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
for (; i < count; i ++)
{
value = ippGetInteger(attr, i);
keyword = ippEnumString("finishings", value);
- if (strncmp(keyword, "fold-", 5))
+ if (!strncmp(keyword, "cups-fold-", 10))
+ keyword += 5;
+ else if (strcmp(keyword, "fold") && strncmp(keyword, "fold-", 5))
continue;
if (cupsArrayFind(names, (char *)keyword))
if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
msgstr = keyword;
- cupsFilePrintf(fp, "*FoldType %s/%s: \"\"\n", keyword, msgstr);
- cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*FoldType %s\"\n", value, keyword, keyword);
+ if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
+ ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
+ else if (value >= IPP_FINISHINGS_FOLD_ACCORDION && value <= IPP_FINISHINGS_FOLD_ENGINEERING_Z)
+ ppd_keyword = fold_keywords[value - IPP_FINISHINGS_FOLD_ACCORDION];
+ else if (value >= IPP_FINISHINGS_CUPS_FOLD_ACCORDION && value <= IPP_FINISHINGS_CUPS_FOLD_Z)
+ ppd_keyword = fold_keywords[value - IPP_FINISHINGS_CUPS_FOLD_ACCORDION];
+ else
+ ppd_keyword = NULL;
+
+ if (!ppd_keyword)
+ continue;
+
+ cupsFilePrintf(fp, "*FoldType %s: \"\"\n", ppd_keyword);
+ cupsFilePrintf(fp, "*%s.FoldType %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*FoldType %s\"\n", value, keyword, ppd_keyword);
}
cupsFilePuts(fp, "*CloseUI: *FoldType\n");
value = ippGetInteger(attr, i);
keyword = ippEnumString("finishings", value);
- if (!strncmp(keyword, "punch-", 6))
+ if (!strncmp(keyword, "cups-punch-", 11) || !strncmp(keyword, "punch-", 6))
break;
}
if (i < count)
{
+ static const char * const punch_keywords[] =
+ { /* PunchMedia keywords */
+ "SinglePortrait",
+ "SingleRevLandscape",
+ "SingleLandscape",
+ "SingleRevPortrait",
+ "DualPortrait",
+ "DualLandscape",
+ "DualRevPortrait",
+ "DualRevLandscape",
+ "TriplePortrait",
+ "TripleLandscape",
+ "TripleRevPortrait",
+ "TripleRevLandscape",
+ "QuadPortrait",
+ "QuadLandscape",
+ "QuadRevPortrait",
+ "QuadRevLandscape",
+ "MultiplePortrait",
+ "MultipleLandscape",
+ "MultipleRevPortrait",
+ "MultipleRevLandscape"
+ };
+
cupsArrayAdd(fin_options, "*PunchMedia");
- cupsFilePrintf(fp, "*OpenUI *PunchMedia/%s: PickOne\n", _cupsLangString(lang, _("Punch")));
+ cupsFilePuts(fp, "*OpenUI *PunchMedia: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *PunchMedia\n");
+ cupsFilePrintf(fp, "*%s.Translation PunchMedia/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Punch")));
cupsFilePuts(fp, "*DefaultPunchMedia: None\n");
- cupsFilePrintf(fp, "*PunchMedia None/%s: \"\"\n", _cupsLangString(lang, _("None")));
+ cupsFilePuts(fp, "*PunchMedia None: \"\"\n");
+ cupsFilePrintf(fp, "*%s.PunchMedia None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
for (i = 0; i < count; i ++)
{
value = ippGetInteger(attr, i);
keyword = ippEnumString("finishings", value);
- if (strncmp(keyword, "punch-", 6))
+ if (!strncmp(keyword, "cups-punch-", 11))
+ keyword += 5;
+ else if (strncmp(keyword, "punch-", 6))
continue;
if (cupsArrayFind(names, (char *)keyword))
if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
msgstr = keyword;
- cupsFilePrintf(fp, "*PunchMedia %s/%s: \"\"\n", keyword, msgstr);
- cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*PunchMedia %s\"\n", value, keyword, keyword);
+ if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
+ ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
+ else if (value >= IPP_FINISHINGS_PUNCH_TOP_LEFT && value <= IPP_FINISHINGS_PUNCH_MULTIPLE_BOTTOM)
+ ppd_keyword = punch_keywords[value - IPP_FINISHINGS_PUNCH_TOP_LEFT];
+ else if (value >= IPP_FINISHINGS_CUPS_PUNCH_TOP_LEFT && value <= IPP_FINISHINGS_CUPS_PUNCH_QUAD_BOTTOM)
+ ppd_keyword = punch_keywords[value - IPP_FINISHINGS_CUPS_PUNCH_TOP_LEFT];
+ else
+ ppd_keyword = NULL;
+
+ if (!ppd_keyword)
+ continue;
+
+ cupsFilePrintf(fp, "*PunchMedia %s: \"\"\n", ppd_keyword);
+ cupsFilePrintf(fp, "*%s.PunchMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*PunchMedia %s\"\n", value, keyword, ppd_keyword);
}
cupsFilePuts(fp, "*CloseUI: *PunchMedia\n");
{
cupsArrayAdd(fin_options, "*Booklet");
- cupsFilePrintf(fp, "*OpenUI *Booklet/%s: Boolean\n", _cupsLangString(lang, _("Booklet")));
+ cupsFilePuts(fp, "*OpenUI *Booklet: Boolean\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *Booklet\n");
+ cupsFilePrintf(fp, "*%s.Translation Booklet/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Booklet")));
cupsFilePuts(fp, "*DefaultBooklet: False\n");
cupsFilePuts(fp, "*Booklet False: \"\"\n");
cupsFilePuts(fp, "*Booklet True: \"\"\n");
cupsFilePuts(fp, "*CloseUI: *Booklet\n");
}
+ /*
+ * CutMedia
+ */
+
+ for (i = 0; i < count; i ++)
+ {
+ value = ippGetInteger(attr, i);
+ keyword = ippEnumString("finishings", value);
+
+ if (!strcmp(keyword, "trim") || !strncmp(keyword, "trim-", 5))
+ break;
+ }
+
+ if (i < count)
+ {
+ static const char * const trim_keywords[] =
+ { /* CutMedia keywords */
+ "EndOfPage",
+ "EndOfDoc",
+ "EndOfSet",
+ "EndOfJob"
+ };
+
+ cupsArrayAdd(fin_options, "*CutMedia");
+
+ cupsFilePuts(fp, "*OpenUI *CutMedia: PickOne\n");
+ cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *CutMedia\n");
+ cupsFilePrintf(fp, "*%s.Translation CutMedia/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Cut")));
+ cupsFilePuts(fp, "*DefaultCutMedia: None\n");
+ cupsFilePuts(fp, "*CutMedia None: \"\"\n");
+ cupsFilePrintf(fp, "*%s.CutMedia None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
+
+ for (i = 0; i < count; i ++)
+ {
+ value = ippGetInteger(attr, i);
+ keyword = ippEnumString("finishings", value);
+
+ if (strcmp(keyword, "trim") && strncmp(keyword, "trim-", 5))
+ continue;
+
+ if (cupsArrayFind(names, (char *)keyword))
+ continue; /* Already did this finishing template */
+
+ cupsArrayAdd(names, (char *)keyword);
+
+ snprintf(msgid, sizeof(msgid), "finishings.%d", value);
+ if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
+ if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
+ msgstr = keyword;
+
+ if (value == IPP_FINISHINGS_TRIM)
+ ppd_keyword = "Auto";
+ else
+ ppd_keyword = trim_keywords[value - IPP_FINISHINGS_TRIM_AFTER_PAGES];
+
+ cupsFilePrintf(fp, "*CutMedia %s: \"\"\n", ppd_keyword);
+ cupsFilePrintf(fp, "*%s.CutMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*CutMedia %s\"\n", value, keyword, ppd_keyword);
+ }
+
+ cupsFilePuts(fp, "*CloseUI: *CutMedia\n");
+ }
+
cupsArrayDelete(names);
}
ipp_attribute_t *finishing_attr; /* Current finishing member attribute */
cups_array_t *templates; /* Finishing templates */
- cupsFilePrintf(fp, "*OpenUI *cupsFinishingTemplate/%s: PickOne\n", _cupsLangString(lang, _("Finishing Preset")));
+ cupsFilePuts(fp, "*OpenUI *cupsFinishingTemplate: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *cupsFinishingTemplate\n");
+ cupsFilePrintf(fp, "*%s.Translation cupsFinishingTemplate/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Finishing Preset")));
cupsFilePuts(fp, "*DefaultcupsFinishingTemplate: none\n");
- cupsFilePrintf(fp, "*cupsFinishingTemplate none/%s: \"\"\n", _cupsLangString(lang, _("None")));
+ cupsFilePuts(fp, "*cupsFinishingTemplate none: \"\"\n");
+ cupsFilePrintf(fp, "*%s.cupsFinishingTemplate none/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
templates = cupsArrayNew((cups_array_func_t)strcmp, NULL);
count = ippGetCount(attr);
if (!keyword || cupsArrayFind(templates, (void *)keyword))
continue;
- if (strncmp(keyword, "fold-", 5) && (strstr(keyword, "-bottom") || strstr(keyword, "-left") || strstr(keyword, "-right") || strstr(keyword, "-top")))
+ if (!strcmp(keyword, "none"))
continue;
cupsArrayAdd(templates, (void *)keyword);
if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
msgstr = keyword;
- cupsFilePrintf(fp, "*cupsFinishingTemplate %s/%s: \"\n", keyword, msgstr);
+ cupsFilePrintf(fp, "*cupsFinishingTemplate %s: \"\n", keyword);
for (finishing_attr = ippFirstAttribute(finishing_col); finishing_attr; finishing_attr = ippNextAttribute(finishing_col))
{
if (ippGetValueTag(finishing_attr) == IPP_TAG_BEGIN_COLLECTION)
}
}
cupsFilePuts(fp, "\"\n");
+ cupsFilePrintf(fp, "*%s.cupsFinishingTemplate %s/%s: \"\"\n", lang->language, keyword, msgstr);
cupsFilePuts(fp, "*End\n");
}
cupsFilePrintf(fp, "*DefaultResolution: %ddpi\n", lowdpi);
- cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n"
- "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality")));
+ cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
+ "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
+ "*%s.Translation cupsPrintQuality/%s: \"\"\n"
+ "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
if ((lowdpi & 1) == 0)
- cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi / 2);
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi / 2, lang->language, _cupsLangString(lang, _("Draft")));
else if (ippContainsInteger(quality, IPP_QUALITY_DRAFT))
- cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi);
- cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), lowdpi, lowdpi);
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Draft")));
+
+ cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Normal")));
+
if (hidpi > lowdpi || ippContainsInteger(quality, IPP_QUALITY_HIGH))
- cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), hidpi, hidpi);
+ cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", hidpi, hidpi, lang->language, _cupsLangString(lang, _("High")));
cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
}
}
pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, ppdname, sizeof(ppdname));
cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
- cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n"
- "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality")));
+ cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
+ "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
+ "*%s.Translation cupsPrintQuality/%s: \"\"\n"
+ "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
if (count > 2 || ippContainsInteger(quality, IPP_QUALITY_DRAFT))
{
pwg_ppdize_resolution(attr, resolutions[0], &xres, &yres, NULL, 0);
- cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), xres, yres);
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
+ cupsFilePrintf(fp, "*%s.cupsPrintQuality Draft/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Draft")));
}
+
pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, NULL, 0);
- cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), xres, yres);
+ cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
+ cupsFilePrintf(fp, "*%s.cupsPrintQuality Normal/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Normal")));
+
if (count > 1 || ippContainsInteger(quality, IPP_QUALITY_HIGH))
{
pwg_ppdize_resolution(attr, resolutions[count - 1], &xres, &yres, NULL, 0);
- cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), xres, yres);
+ cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
+ cupsFilePrintf(fp, "*%s.cupsPrintQuality High/%s: \"\"\n", lang->language, _cupsLangString(lang, _("High")));
}
cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
- cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n"
+ cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
"*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality")));
+ "*%s.Translation cupsPrintQuality/%s: \"\"\n"
+ "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
if (ippContainsInteger(quality, IPP_QUALITY_DRAFT))
- cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), xres, yres);
- cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), xres, yres);
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Draft")));
+
+ cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Normal")));
+
if (ippContainsInteger(quality, IPP_QUALITY_HIGH))
- cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), xres, yres);
+ cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("High")));
cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
}
if (!preset || !preset_name)
continue;
- if ((localized_name = _cupsMessageLookup(strings, preset_name)) == preset_name)
- cupsFilePrintf(fp, "*APPrinterPreset %s: \"\n", preset_name);
- else
- cupsFilePrintf(fp, "*APPrinterPreset %s/%s: \"\n", preset_name, localized_name);
-
+ cupsFilePrintf(fp, "*APPrinterPreset %s: \"\n", preset_name);
for (member = ippFirstAttribute(preset); member; member = ippNextAttribute(preset))
{
member_name = ippGetName(member);
}
cupsFilePuts(fp, "\"\n*End\n");
+
+ if ((localized_name = _cupsMessageLookup(strings, preset_name)) != preset_name)
+ cupsFilePrintf(fp, "*%s.APPrinterPreset %s/%s: \"\"\n", lang->language, preset_name, localized_name);
}
}
{
char *ptr, /* Pointer into name buffer */
*end; /* End of name buffer */
+ int nodash = 1; /* Next char in IPP name cannot be a
+ dash (first char or after a dash) */
if (_cups_islower(*ppd))
const char *ppdptr; /* Pointer into PPD keyword */
for (ppdptr = ppd + 1; *ppdptr; ppdptr ++)
- if (_cups_isupper(*ppdptr) || strchr(dashchars, *ppdptr))
+ if (_cups_isupper(*ppdptr) || strchr(dashchars, *ppdptr) ||
+ (*ppdptr == '-' && *(ppdptr - 1) == '-') ||
+ (*ppdptr == '-' && *(ppdptr + 1) == '\0'))
break;
if (!*ppdptr)
for (ptr = name, end = name + namesize - 1; *ppd && ptr < end; ppd ++)
{
- if (_cups_isalnum(*ppd) || *ppd == '-')
+ if (_cups_isalnum(*ppd))
+ {
*ptr++ = (char)tolower(*ppd & 255);
- else if (strchr(dashchars, *ppd))
- *ptr++ = '-';
+ nodash = 0;
+ }
+ else if (*ppd == '-' || strchr(dashchars, *ppd))
+ {
+ if (nodash == 0)
+ {
+ *ptr++ = '-';
+ nodash = 1;
+ }
+ }
else
+ {
*ptr++ = *ppd;
+ nodash = 0;
+ }
- if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) &&
- _cups_isupper(ppd[1]) && ptr < end)
- *ptr++ = '-';
- else if (!isdigit(*ppd & 255) && isdigit(ppd[1] & 255))
- *ptr++ = '-';
+ if (nodash == 0)
+ {
+ if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) &&
+ _cups_isupper(ppd[1]) && ptr < end)
+ {
+ *ptr++ = '-';
+ nodash = 1;
+ }
+ else if (!isdigit(*ppd & 255) && isdigit(ppd[1] & 255))
+ {
+ *ptr++ = '-';
+ nodash = 1;
+ }
+ }
}
+ /* Remove trailing dashes */
+ while (ptr > name && *(ptr - 1) == '-')
+ ptr --;
+
*ptr = '\0';
}