in cups/ppd-mark.c [33:358]
static void ppd_mark_option(ppd_file_t *ppd, const char *option,
const char *choice);
/*
* 'cupsMarkOptions()' - Mark command-line options in a PPD file.
*
* This function maps the IPP "finishings", "media", "mirror",
* "multiple-document-handling", "output-bin", "print-color-mode",
* "print-quality", "printer-resolution", and "sides" attributes to their
* corresponding PPD options and choices.
*/
int /* O - 1 if conflicts exist, 0 otherwise */
cupsMarkOptions(
ppd_file_t *ppd, /* I - PPD file */
int num_options, /* I - Number of options */
cups_option_t *options) /* I - Options */
{
int i, j; /* Looping vars */
char *ptr, /* Pointer into string */
s[255]; /* Temporary string */
const char *val, /* Pointer into value */
*media, /* media option */
*output_bin, /* output-bin option */
*page_size, /* PageSize option */
*ppd_keyword, /* PPD keyword */
*print_color_mode, /* print-color-mode option */
*print_quality, /* print-quality option */
*sides; /* sides option */
cups_option_t *optptr; /* Current option */
ppd_attr_t *attr; /* PPD attribute */
_ppd_cache_t *cache; /* PPD cache and mapping data */
/*
* Check arguments...
*/
if (!ppd || num_options <= 0 || !options)
return (0);
ppd_debug_marked(ppd, "Before...");
/*
* Do special handling for finishings, media, output-bin, output-mode,
* print-color-mode, print-quality, and PageSize...
*/
media = cupsGetOption("media", num_options, options);
output_bin = cupsGetOption("output-bin", num_options, options);
page_size = cupsGetOption("PageSize", num_options, options);
print_quality = cupsGetOption("print-quality", num_options, options);
sides = cupsGetOption("sides", num_options, options);
if ((print_color_mode = cupsGetOption("print-color-mode", num_options,
options)) == NULL)
print_color_mode = cupsGetOption("output-mode", num_options, options);
if ((media || output_bin || print_color_mode || print_quality || sides) &&
!ppd->cache)
{
/*
* Load PPD cache and mapping data as needed...
*/
ppd->cache = _ppdCacheCreateWithPPD(ppd);
}
cache = ppd->cache;
if (media)
{
/*
* Loop through the option string, separating it at commas and marking each
* individual option as long as the corresponding PPD option (PageSize,
* InputSlot, etc.) is not also set.
*
* For PageSize, we also check for an empty option value since some versions
* of macOS use it to specify auto-selection of the media based solely on
* the size.
*/
for (val = media; *val;)
{
/*
* Extract the sub-option from the string...
*/
for (ptr = s; *val && *val != ',' && (size_t)(ptr - s) < (sizeof(s) - 1);)
*ptr++ = *val++;
*ptr++ = '\0';
if (*val == ',')
val ++;
/*
* Mark it...
*/
if (!page_size || !page_size[0])
{
if (!_cups_strncasecmp(s, "Custom.", 7) || ppdPageSize(ppd, s))
ppd_mark_option(ppd, "PageSize", s);
else if ((ppd_keyword = _ppdCacheGetPageSize(cache, NULL, s, NULL)) != NULL)
ppd_mark_option(ppd, "PageSize", ppd_keyword);
}
if (cache && cache->source_option &&
!cupsGetOption(cache->source_option, num_options, options) &&
(ppd_keyword = _ppdCacheGetInputSlot(cache, NULL, s)) != NULL)
ppd_mark_option(ppd, cache->source_option, ppd_keyword);
if (!cupsGetOption("MediaType", num_options, options) &&
(ppd_keyword = _ppdCacheGetMediaType(cache, NULL, s)) != NULL)
ppd_mark_option(ppd, "MediaType", ppd_keyword);
}
}
if (cache)
{
if (!cupsGetOption("com.apple.print.DocumentTicket.PMSpoolFormat",
num_options, options) &&
!cupsGetOption("APPrinterPreset", num_options, options) &&
(print_color_mode || print_quality))
{
/*
* Map output-mode and print-quality to a preset...
*/
_pwg_print_color_mode_t pwg_pcm;/* print-color-mode index */
_pwg_print_quality_t pwg_pq; /* print-quality index */
cups_option_t *preset;/* Current preset option */
if (print_color_mode && !strcmp(print_color_mode, "monochrome"))
pwg_pcm = _PWG_PRINT_COLOR_MODE_MONOCHROME;
else
pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
if (print_quality)
{
pwg_pq = (_pwg_print_quality_t)(atoi(print_quality) - IPP_QUALITY_DRAFT);
if (pwg_pq < _PWG_PRINT_QUALITY_DRAFT)
pwg_pq = _PWG_PRINT_QUALITY_DRAFT;
else if (pwg_pq > _PWG_PRINT_QUALITY_HIGH)
pwg_pq = _PWG_PRINT_QUALITY_HIGH;
}
else
pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
if (cache->num_presets[pwg_pcm][pwg_pq] == 0)
{
/*
* Try to find a preset that works so that we maximize the chances of us
* getting a good print using IPP attributes.
*/
if (cache->num_presets[pwg_pcm][_PWG_PRINT_QUALITY_NORMAL] > 0)
pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
else if (cache->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_pq] > 0)
pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
else
{
pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
}
}
if (cache->num_presets[pwg_pcm][pwg_pq] > 0)
{
/*
* Copy the preset options as long as the corresponding names are not
* already defined in the IPP request...
*/
for (i = cache->num_presets[pwg_pcm][pwg_pq],
preset = cache->presets[pwg_pcm][pwg_pq];
i > 0;
i --, preset ++)
{
if (!cupsGetOption(preset->name, num_options, options))
ppd_mark_option(ppd, preset->name, preset->value);
}
}
}
if (output_bin && !cupsGetOption("OutputBin", num_options, options) &&
(ppd_keyword = _ppdCacheGetOutputBin(cache, output_bin)) != NULL)
{
/*
* Map output-bin to OutputBin...
*/
ppd_mark_option(ppd, "OutputBin", ppd_keyword);
}
if (sides && cache->sides_option &&
!cupsGetOption(cache->sides_option, num_options, options))
{
/*
* Map sides to duplex option...
*/
if (!strcmp(sides, "one-sided") && cache->sides_1sided)
ppd_mark_option(ppd, cache->sides_option, cache->sides_1sided);
else if (!strcmp(sides, "two-sided-long-edge") &&
cache->sides_2sided_long)
ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_long);
else if (!strcmp(sides, "two-sided-short-edge") &&
cache->sides_2sided_short)
ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_short);
}
}
/*
* Mark other options...
*/
for (i = num_options, optptr = options; i > 0; i --, optptr ++)
{
if (!_cups_strcasecmp(optptr->name, "media") ||
!_cups_strcasecmp(optptr->name, "output-bin") ||
!_cups_strcasecmp(optptr->name, "output-mode") ||
!_cups_strcasecmp(optptr->name, "print-quality") ||
!_cups_strcasecmp(optptr->name, "sides"))
continue;
else if (!_cups_strcasecmp(optptr->name, "resolution") ||
!_cups_strcasecmp(optptr->name, "printer-resolution"))
{
ppd_mark_option(ppd, "Resolution", optptr->value);
ppd_mark_option(ppd, "SetResolution", optptr->value);
/* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
ppd_mark_option(ppd, "JCLResolution", optptr->value);
/* HP */
ppd_mark_option(ppd, "CNRes_PGP", optptr->value);
/* Canon */
}
else if (!_cups_strcasecmp(optptr->name, "multiple-document-handling"))
{
if (!cupsGetOption("Collate", num_options, options) &&
ppdFindOption(ppd, "Collate"))
{
if (_cups_strcasecmp(optptr->value, "separate-documents-uncollated-copies"))
ppd_mark_option(ppd, "Collate", "True");
else
ppd_mark_option(ppd, "Collate", "False");
}
}
else if (!_cups_strcasecmp(optptr->name, "finishings"))
{
/*
* Lookup cupsIPPFinishings attributes for each value...
*/
for (ptr = optptr->value; *ptr;)
{
/*
* Get the next finishings number...
*/
if (!isdigit(*ptr & 255))
break;
if ((j = (int)strtol(ptr, &ptr, 10)) < 3)
break;
/*
* Skip separator as needed...
*/
if (*ptr == ',')
ptr ++;
/*
* Look it up in the PPD file...
*/
snprintf(s, sizeof(s), "%d", j);
if ((attr = ppdFindAttr(ppd, "cupsIPPFinishings", s)) == NULL)
continue;
/*
* Apply "*Option Choice" settings from the attribute value...
*/
ppd_mark_choices(ppd, attr->value);
}
}
else if (!_cups_strcasecmp(optptr->name, "APPrinterPreset"))
{
/*
* Lookup APPrinterPreset value...
*/
if ((attr = ppdFindAttr(ppd, "APPrinterPreset", optptr->value)) != NULL)
{
/*
* Apply "*Option Choice" settings from the attribute value...
*/
ppd_mark_choices(ppd, attr->value);
}
}
else if (!_cups_strcasecmp(optptr->name, "mirror"))
ppd_mark_option(ppd, "MirrorPrint", optptr->value);
else
ppd_mark_option(ppd, optptr->name, optptr->value);
}
if (print_quality)
{
int pq = atoi(print_quality); /* print-quaity value */
if (pq == IPP_QUALITY_DRAFT)
ppd_mark_option(ppd, "cupsPrintQuality", "Draft");
else if (pq == IPP_QUALITY_HIGH)
ppd_mark_option(ppd, "cupsPrintQuality", "High");
else
ppd_mark_option(ppd, "cupsPrintQuality", "Normal");
}
ppd_debug_marked(ppd, "After...");
return (ppdConflicts(ppd) > 0);
}