4 * PPD cache implementation for CUPS.
6 * Copyright 2010-2011 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * _ppdCacheCreateWithFile() - Create PPD cache and mapping data from a
20 * _ppdCacheCreateWithPPD() - Create PWG mapping data from a PPD file.
21 * _ppdCacheDestroy() - Free all memory used for PWG mapping data.
22 * _ppdCacheGetBin() - Get the PWG output-bin keyword associated with
24 * _ppdCacheGetInputSlot() - Get the PPD InputSlot associated with the job
25 * attributes or a keyword string.
26 * _ppdCacheGetMediaType() - Get the PPD MediaType associated with the job
27 * attributes or a keyword string.
28 * _ppdCacheGetOutputBin() - Get the PPD OutputBin associated with the
30 * _ppdCacheGetPageSize() - Get the PPD PageSize associated with the job
31 * attributes or a keyword string.
32 * _ppdCacheGetSize() - Get the PWG size associated with a PPD
34 * _ppdCacheGetSource() - Get the PWG media-source associated with a PPD
36 * _ppdCacheGetType() - Get the PWG media-type associated with a PPD
38 * _ppdCacheWriteFile() - Write PWG mapping data to a file.
39 * _pwgInputSlotForSource() - Get the InputSlot name for the given PWG
41 * _pwgMediaTypeForType() - Get the MediaType name for the given PWG
43 * _pwgPageSizeForMedia() - Get the PageSize name for the given media.
44 * pwg_ppdize_name() - Convert an IPP keyword to a PPD keyword.
45 * pwg_unppdize_name() - Convert a PPD keyword to a lowercase IPP
50 * Include necessary headers...
53 #include "cups-private.h"
58 * Macro to test for two almost-equal PWG measurements.
61 #define _PWG_EQUIVALENT(x, y) (abs((x)-(y)) < 2)
68 static void pwg_ppdize_name(const char *ipp
, char *name
, size_t namesize
);
69 static void pwg_unppdize_name(const char *ppd
, char *name
, size_t namesize
);
73 * '_ppdCacheCreateWithFile()' - Create PPD cache and mapping data from a
76 * Use the @link _ppdCacheWriteFile@ function to write PWG mapping data to a
80 _ppd_cache_t
* /* O - PPD cache and mapping data */
81 _ppdCacheCreateWithFile(
82 const char *filename
, /* I - File to read */
83 ipp_t
**attrs
) /* IO - IPP attributes, if any */
85 cups_file_t
*fp
; /* File */
86 _ppd_cache_t
*pc
; /* PWG mapping data */
87 _pwg_size_t
*size
; /* Current size */
88 _pwg_map_t
*map
; /* Current map */
89 int linenum
, /* Current line number */
90 num_bins
, /* Number of bins in file */
91 num_sizes
, /* Number of sizes in file */
92 num_sources
, /* Number of sources in file */
93 num_types
; /* Number of types in file */
94 char line
[2048], /* Current line */
95 *value
, /* Pointer to value in line */
96 *valueptr
, /* Pointer into value */
97 pwg_keyword
[128], /* PWG keyword */
98 ppd_keyword
[PPD_MAX_NAME
];
100 _pwg_print_color_mode_t print_color_mode
;
101 /* Print color mode for preset */
102 _pwg_print_quality_t print_quality
; /* Print quality for preset */
105 DEBUG_printf(("_ppdCacheCreateWithFile(filename=\"%s\")", filename
));
108 * Range check input...
116 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(EINVAL
), 0);
124 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
126 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
131 * Read the first line and make sure it has "#CUPS-PPD-CACHE-version" in it...
134 if (!cupsFileGets(fp
, line
, sizeof(line
)))
136 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
137 DEBUG_puts("_ppdCacheCreateWithFile: Unable to read first line.");
142 if (strncmp(line
, "#CUPS-PPD-CACHE-", 16))
144 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
145 DEBUG_printf(("_ppdCacheCreateWithFile: Wrong first line \"%s\".", line
));
150 if (atoi(line
+ 16) != _PPD_CACHE_VERSION
)
152 _cupsSetError(IPP_INTERNAL_ERROR
, _("Out of date PPD cache file."), 1);
153 DEBUG_printf(("_ppdCacheCreateWithFile: Cache file has version %s, "
154 "expected %d.", line
+ 16, _PPD_CACHE_VERSION
));
160 * Allocate the mapping data structure...
163 if ((pc
= calloc(1, sizeof(_ppd_cache_t
))) == NULL
)
165 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
166 DEBUG_puts("_ppdCacheCreateWithFile: Unable to allocate _ppd_cache_t.");
180 while (cupsFileGetConf(fp
, line
, sizeof(line
), &value
, &linenum
))
182 DEBUG_printf(("_ppdCacheCreateWithFile: line=\"%s\", value=\"%s\", "
183 "linenum=%d", line
, value
, linenum
));
187 DEBUG_printf(("_ppdCacheCreateWithFile: Missing value on line %d.",
189 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
192 else if (!_cups_strcasecmp(line
, "Filter"))
195 pc
->filters
= cupsArrayNew3(NULL
, NULL
, NULL
, 0,
196 (cups_acopy_func_t
)_cupsStrAlloc
,
197 (cups_afree_func_t
)_cupsStrFree
);
199 cupsArrayAdd(pc
->filters
, value
);
201 else if (!_cups_strcasecmp(line
, "PreFilter"))
204 pc
->prefilters
= cupsArrayNew3(NULL
, NULL
, NULL
, 0,
205 (cups_acopy_func_t
)_cupsStrAlloc
,
206 (cups_afree_func_t
)_cupsStrFree
);
208 cupsArrayAdd(pc
->prefilters
, value
);
210 else if (!_cups_strcasecmp(line
, "Product"))
212 pc
->product
= _cupsStrAlloc(value
);
214 else if (!_cups_strcasecmp(line
, "SingleFile"))
216 pc
->single_file
= !_cups_strcasecmp(value
, "true");
218 else if (!_cups_strcasecmp(line
, "IPP"))
220 off_t pos
= cupsFileTell(fp
), /* Position in file */
221 length
= strtol(value
, NULL
, 10);
222 /* Length of IPP attributes */
226 DEBUG_puts("_ppdCacheCreateWithFile: IPP listed multiple times.");
227 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
230 else if (length
<= 0)
232 DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP length.");
233 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
240 * Read IPP attributes into the provided variable...
245 if (ippReadIO(fp
, (ipp_iocb_t
)cupsFileRead
, 1, NULL
,
248 DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data.");
249 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
256 * Skip the IPP data entirely...
259 cupsFileSeek(fp
, pos
+ length
);
262 if (cupsFileTell(fp
) != (pos
+ length
))
264 DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data.");
265 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
269 else if (!_cups_strcasecmp(line
, "NumBins"))
273 DEBUG_puts("_ppdCacheCreateWithFile: NumBins listed multiple times.");
274 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
278 if ((num_bins
= atoi(value
)) <= 0 || num_bins
> 65536)
280 DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumBins value %d on line "
281 "%d.", num_sizes
, linenum
));
282 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
286 if ((pc
->bins
= calloc(num_bins
, sizeof(_pwg_map_t
))) == NULL
)
288 DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d bins.",
290 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
294 else if (!_cups_strcasecmp(line
, "Bin"))
296 if (sscanf(value
, "%127s%40s", pwg_keyword
, ppd_keyword
) != 2)
298 DEBUG_printf(("_ppdCacheCreateWithFile: Bad Bin on line %d.", linenum
));
299 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
303 if (pc
->num_bins
>= num_bins
)
305 DEBUG_printf(("_ppdCacheCreateWithFile: Too many Bin's on line %d.",
307 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
311 map
= pc
->bins
+ pc
->num_bins
;
312 map
->pwg
= _cupsStrAlloc(pwg_keyword
);
313 map
->ppd
= _cupsStrAlloc(ppd_keyword
);
317 else if (!_cups_strcasecmp(line
, "NumSizes"))
321 DEBUG_puts("_ppdCacheCreateWithFile: NumSizes listed multiple times.");
322 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
326 if ((num_sizes
= atoi(value
)) <= 0 || num_sizes
> 65536)
328 DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSizes value %d on line "
329 "%d.", num_sizes
, linenum
));
330 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
334 if ((pc
->sizes
= calloc(num_sizes
, sizeof(_pwg_size_t
))) == NULL
)
336 DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sizes.",
338 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
342 else if (!_cups_strcasecmp(line
, "Size"))
344 if (pc
->num_sizes
>= num_sizes
)
346 DEBUG_printf(("_ppdCacheCreateWithFile: Too many Size's on line %d.",
348 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
352 size
= pc
->sizes
+ pc
->num_sizes
;
354 if (sscanf(value
, "%127s%40s%d%d%d%d%d%d", pwg_keyword
, ppd_keyword
,
355 &(size
->width
), &(size
->length
), &(size
->left
),
356 &(size
->bottom
), &(size
->right
), &(size
->top
)) != 8)
358 DEBUG_printf(("_ppdCacheCreateWithFile: Bad Size on line %d.",
360 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
364 size
->map
.pwg
= _cupsStrAlloc(pwg_keyword
);
365 size
->map
.ppd
= _cupsStrAlloc(ppd_keyword
);
369 else if (!_cups_strcasecmp(line
, "CustomSize"))
371 if (pc
->custom_max_width
> 0)
373 DEBUG_printf(("_ppdCacheCreateWithFile: Too many CustomSize's on line "
375 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
379 if (sscanf(value
, "%d%d%d%d%d%d%d%d", &(pc
->custom_max_width
),
380 &(pc
->custom_max_length
), &(pc
->custom_min_width
),
381 &(pc
->custom_min_length
), &(pc
->custom_size
.left
),
382 &(pc
->custom_size
.bottom
), &(pc
->custom_size
.right
),
383 &(pc
->custom_size
.top
)) != 8)
385 DEBUG_printf(("_ppdCacheCreateWithFile: Bad CustomSize on line %d.",
387 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
391 _pwgGenerateSize(pwg_keyword
, sizeof(pwg_keyword
), "custom", "max",
392 pc
->custom_max_width
, pc
->custom_max_length
);
393 pc
->custom_max_keyword
= _cupsStrAlloc(pwg_keyword
);
395 _pwgGenerateSize(pwg_keyword
, sizeof(pwg_keyword
), "custom", "min",
396 pc
->custom_min_width
, pc
->custom_min_length
);
397 pc
->custom_min_keyword
= _cupsStrAlloc(pwg_keyword
);
399 else if (!_cups_strcasecmp(line
, "SourceOption"))
401 pc
->source_option
= _cupsStrAlloc(value
);
403 else if (!_cups_strcasecmp(line
, "NumSources"))
407 DEBUG_puts("_ppdCacheCreateWithFile: NumSources listed multiple "
409 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
413 if ((num_sources
= atoi(value
)) <= 0 || num_sources
> 65536)
415 DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSources value %d on "
416 "line %d.", num_sources
, linenum
));
417 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
421 if ((pc
->sources
= calloc(num_sources
, sizeof(_pwg_map_t
))) == NULL
)
423 DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sources.",
425 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
429 else if (!_cups_strcasecmp(line
, "Source"))
431 if (sscanf(value
, "%127s%40s", pwg_keyword
, ppd_keyword
) != 2)
433 DEBUG_printf(("_ppdCacheCreateWithFile: Bad Source on line %d.",
435 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
439 if (pc
->num_sources
>= num_sources
)
441 DEBUG_printf(("_ppdCacheCreateWithFile: Too many Source's on line %d.",
443 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
447 map
= pc
->sources
+ pc
->num_sources
;
448 map
->pwg
= _cupsStrAlloc(pwg_keyword
);
449 map
->ppd
= _cupsStrAlloc(ppd_keyword
);
453 else if (!_cups_strcasecmp(line
, "NumTypes"))
457 DEBUG_puts("_ppdCacheCreateWithFile: NumTypes listed multiple times.");
458 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
462 if ((num_types
= atoi(value
)) <= 0 || num_types
> 65536)
464 DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumTypes value %d on "
465 "line %d.", num_types
, linenum
));
466 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
470 if ((pc
->types
= calloc(num_types
, sizeof(_pwg_map_t
))) == NULL
)
472 DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d types.",
474 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
478 else if (!_cups_strcasecmp(line
, "Type"))
480 if (sscanf(value
, "%127s%40s", pwg_keyword
, ppd_keyword
) != 2)
482 DEBUG_printf(("_ppdCacheCreateWithFile: Bad Type on line %d.",
484 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
488 if (pc
->num_types
>= num_types
)
490 DEBUG_printf(("_ppdCacheCreateWithFile: Too many Type's on line %d.",
492 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
496 map
= pc
->types
+ pc
->num_types
;
497 map
->pwg
= _cupsStrAlloc(pwg_keyword
);
498 map
->ppd
= _cupsStrAlloc(ppd_keyword
);
502 else if (!_cups_strcasecmp(line
, "Preset"))
505 * Preset output-mode print-quality name=value ...
508 print_color_mode
= (_pwg_print_color_mode_t
)strtol(value
, &valueptr
, 10);
509 print_quality
= (_pwg_print_quality_t
)strtol(valueptr
, &valueptr
, 10);
511 if (print_color_mode
< _PWG_PRINT_COLOR_MODE_MONOCHROME
||
512 print_color_mode
>= _PWG_PRINT_COLOR_MODE_MAX
||
513 print_quality
< _PWG_PRINT_QUALITY_DRAFT
||
514 print_quality
>= _PWG_PRINT_QUALITY_MAX
||
515 valueptr
== value
|| !*valueptr
)
517 DEBUG_printf(("_ppdCacheCreateWithFile: Bad Preset on line %d.",
519 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
523 pc
->num_presets
[print_color_mode
][print_quality
] =
524 cupsParseOptions(valueptr
, 0,
525 pc
->presets
[print_color_mode
] + print_quality
);
527 else if (!_cups_strcasecmp(line
, "SidesOption"))
528 pc
->sides_option
= _cupsStrAlloc(value
);
529 else if (!_cups_strcasecmp(line
, "Sides1Sided"))
530 pc
->sides_1sided
= _cupsStrAlloc(value
);
531 else if (!_cups_strcasecmp(line
, "Sides2SidedLong"))
532 pc
->sides_2sided_long
= _cupsStrAlloc(value
);
533 else if (!_cups_strcasecmp(line
, "Sides2SidedShort"))
534 pc
->sides_2sided_short
= _cupsStrAlloc(value
);
537 DEBUG_printf(("_ppdCacheCreateWithFile: Unknown %s on line %d.", line
,
542 if (pc
->num_sizes
< num_sizes
)
544 DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sizes (%d < %d).",
545 pc
->num_sizes
, num_sizes
));
546 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
550 if (pc
->num_sources
< num_sources
)
552 DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sources (%d < %d).",
553 pc
->num_sources
, num_sources
));
554 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
558 if (pc
->num_types
< num_types
)
560 DEBUG_printf(("_ppdCacheCreateWithFile: Not enough types (%d < %d).",
561 pc
->num_types
, num_types
));
562 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PPD cache file."), 1);
571 * If we get here the file was bad - free any data and return...
577 _ppdCacheDestroy(pc
);
590 * '_ppdCacheCreateWithPPD()' - Create PWG mapping data from a PPD file.
593 _ppd_cache_t
* /* O - PPD cache and mapping data */
594 _ppdCacheCreateWithPPD(ppd_file_t
*ppd
) /* I - PPD file */
596 int i
, j
, k
; /* Looping vars */
597 _ppd_cache_t
*pc
; /* PWG mapping data */
598 ppd_option_t
*input_slot
, /* InputSlot option */
599 *media_type
, /* MediaType option */
600 *output_bin
, /* OutputBin option */
601 *color_model
, /* ColorModel option */
602 *duplex
; /* Duplex option */
603 ppd_choice_t
*choice
; /* Current InputSlot/MediaType */
604 _pwg_map_t
*map
; /* Current source/type map */
605 ppd_attr_t
*ppd_attr
; /* Current PPD preset attribute */
606 int num_options
; /* Number of preset options and props */
607 cups_option_t
*options
; /* Preset options and properties */
608 ppd_size_t
*ppd_size
; /* Current PPD size */
609 _pwg_size_t
*pwg_size
; /* Current PWG size */
610 char pwg_keyword
[3 + PPD_MAX_NAME
+ 1 + 12 + 1 + 12 + 3],
611 /* PWG keyword string */
612 ppd_name
[PPD_MAX_NAME
];
613 /* Normalized PPD name */
614 const char *pwg_name
; /* Standard PWG media name */
615 _pwg_media_t
*pwg_media
; /* PWG media data */
616 _pwg_print_color_mode_t pwg_print_color_mode
;
617 /* print-color-mode index */
618 _pwg_print_quality_t pwg_print_quality
;
619 /* print-quality index */
620 int similar
; /* Are the old and new size similar? */
621 _pwg_size_t
*old_size
; /* Current old size */
622 int old_imageable
, /* Old imageable length in 2540ths */
623 old_borderless
, /* Old borderless state */
624 old_known_pwg
; /* Old PWG name is well-known */
625 int new_width
, /* New width in 2540ths */
626 new_length
, /* New length in 2540ths */
627 new_left
, /* New left margin in 2540ths */
628 new_bottom
, /* New bottom margin in 2540ths */
629 new_right
, /* New right margin in 2540ths */
630 new_top
, /* New top margin in 2540ths */
631 new_imageable
, /* New imageable length in 2540ths */
632 new_borderless
, /* New borderless state */
633 new_known_pwg
; /* New PWG name is well-known */
634 _pwg_size_t
*new_size
; /* New size to add, if any */
635 const char *filter
; /* Current filter */
638 DEBUG_printf(("_ppdCacheCreateWithPPD(ppd=%p)", ppd
));
641 * Range check input...
651 if ((pc
= calloc(1, sizeof(_ppd_cache_t
))) == NULL
)
653 DEBUG_puts("_ppdCacheCreateWithPPD: Unable to allocate _ppd_cache_t.");
658 * Copy and convert size data...
661 if (ppd
->num_sizes
== 0)
663 DEBUG_puts("_ppdCacheCreateWithPPD: No page sizes in PPD.");
667 if ((pc
->sizes
= calloc(ppd
->num_sizes
, sizeof(_pwg_size_t
))) == NULL
)
669 DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
670 "_pwg_size_t's.", ppd
->num_sizes
));
674 for (i
= ppd
->num_sizes
, pwg_size
= pc
->sizes
, ppd_size
= ppd
->sizes
;
679 * Don't copy over custom size...
682 if (!_cups_strcasecmp(ppd_size
->name
, "Custom"))
686 * Convert the PPD size name to the corresponding PWG keyword name.
689 if ((pwg_media
= _pwgMediaForPPD(ppd_size
->name
)) != NULL
)
692 * Standard name, do we have conflicts?
695 for (j
= 0; j
< pc
->num_sizes
; j
++)
696 if (!strcmp(pc
->sizes
[j
].map
.pwg
, pwg_media
->pwg
))
706 * Standard name and no conflicts, use it!
709 pwg_name
= pwg_media
->pwg
;
715 * Not a standard name; convert it to a PWG vendor name of the form:
717 * pp_lowerppd_WIDTHxHEIGHTuu
720 pwg_name
= pwg_keyword
;
723 pwg_unppdize_name(ppd_size
->name
, ppd_name
, sizeof(ppd_name
));
724 _pwgGenerateSize(pwg_keyword
, sizeof(pwg_keyword
), NULL
, ppd_name
,
725 _PWG_FROMPTS(ppd_size
->width
),
726 _PWG_FROMPTS(ppd_size
->length
));
730 * If we have a similar paper with non-zero margins then we only
731 * want to keep it if it has a larger imageable area length.
734 new_width
= _PWG_FROMPTS(ppd_size
->width
);
735 new_length
= _PWG_FROMPTS(ppd_size
->length
);
736 new_left
= _PWG_FROMPTS(ppd_size
->left
);
737 new_bottom
= _PWG_FROMPTS(ppd_size
->bottom
);
738 new_right
= _PWG_FROMPTS(ppd_size
->width
- ppd_size
->right
);
739 new_top
= _PWG_FROMPTS(ppd_size
->length
- ppd_size
->top
);
740 new_imageable
= new_length
- new_top
- new_bottom
;
741 new_borderless
= new_bottom
== 0 && new_top
== 0 &&
742 new_left
== 0 && new_right
== 0;
744 for (k
= pc
->num_sizes
, similar
= 0, old_size
= pc
->sizes
, new_size
= NULL
;
748 old_imageable
= old_size
->length
- old_size
->top
- old_size
->bottom
;
749 old_borderless
= old_size
->left
== 0 && old_size
->bottom
== 0 &&
750 old_size
->right
== 0 && old_size
->top
== 0;
751 old_known_pwg
= strncmp(old_size
->map
.pwg
, "oe_", 3) &&
752 strncmp(old_size
->map
.pwg
, "om_", 3);
754 similar
= old_borderless
== new_borderless
&&
755 _PWG_EQUIVALENT(old_size
->width
, new_width
) &&
756 _PWG_EQUIVALENT(old_size
->length
, new_length
);
759 (new_known_pwg
|| (!old_known_pwg
&& new_imageable
> old_imageable
)))
762 * The new paper has a larger imageable area so it could replace
763 * the older paper. Regardless of the imageable area, we always
764 * prefer the size with a well-known PWG name.
768 _cupsStrFree(old_size
->map
.ppd
);
769 _cupsStrFree(old_size
->map
.pwg
);
776 * The paper was unique enough to deserve its own entry so add it to the
780 new_size
= pwg_size
++;
790 new_size
->map
.ppd
= _cupsStrAlloc(ppd_size
->name
);
791 new_size
->map
.pwg
= _cupsStrAlloc(pwg_name
);
792 new_size
->width
= new_width
;
793 new_size
->length
= new_length
;
794 new_size
->left
= new_left
;
795 new_size
->bottom
= new_bottom
;
796 new_size
->right
= new_right
;
797 new_size
->top
= new_top
;
801 if (ppd
->variable_sizes
)
804 * Generate custom size data...
807 _pwgGenerateSize(pwg_keyword
, sizeof(pwg_keyword
), "custom", "max",
808 _PWG_FROMPTS(ppd
->custom_max
[0]),
809 _PWG_FROMPTS(ppd
->custom_max
[1]));
810 pc
->custom_max_keyword
= _cupsStrAlloc(pwg_keyword
);
811 pc
->custom_max_width
= _PWG_FROMPTS(ppd
->custom_max
[0]);
812 pc
->custom_max_length
= _PWG_FROMPTS(ppd
->custom_max
[1]);
814 _pwgGenerateSize(pwg_keyword
, sizeof(pwg_keyword
), "custom", "min",
815 _PWG_FROMPTS(ppd
->custom_min
[0]),
816 _PWG_FROMPTS(ppd
->custom_min
[1]));
817 pc
->custom_min_keyword
= _cupsStrAlloc(pwg_keyword
);
818 pc
->custom_min_width
= _PWG_FROMPTS(ppd
->custom_min
[0]);
819 pc
->custom_min_length
= _PWG_FROMPTS(ppd
->custom_min
[1]);
821 pc
->custom_size
.left
= _PWG_FROMPTS(ppd
->custom_margins
[0]);
822 pc
->custom_size
.bottom
= _PWG_FROMPTS(ppd
->custom_margins
[1]);
823 pc
->custom_size
.right
= _PWG_FROMPTS(ppd
->custom_margins
[2]);
824 pc
->custom_size
.top
= _PWG_FROMPTS(ppd
->custom_margins
[3]);
828 * Copy and convert InputSlot data...
831 if ((input_slot
= ppdFindOption(ppd
, "InputSlot")) == NULL
)
832 input_slot
= ppdFindOption(ppd
, "HPPaperSource");
836 pc
->source_option
= _cupsStrAlloc(input_slot
->keyword
);
838 if ((pc
->sources
= calloc(input_slot
->num_choices
,
839 sizeof(_pwg_map_t
))) == NULL
)
841 DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
842 "_pwg_map_t's for InputSlot.", input_slot
->num_choices
));
846 pc
->num_sources
= input_slot
->num_choices
;
848 for (i
= input_slot
->num_choices
, choice
= input_slot
->choices
,
851 i
--, choice
++, map
++)
853 if (!_cups_strncasecmp(choice
->choice
, "Auto", 4) ||
854 !_cups_strcasecmp(choice
->choice
, "Default"))
856 else if (!_cups_strcasecmp(choice
->choice
, "Cassette"))
858 else if (!_cups_strcasecmp(choice
->choice
, "PhotoTray"))
860 else if (!_cups_strcasecmp(choice
->choice
, "CDTray"))
862 else if (!_cups_strncasecmp(choice
->choice
, "Multipurpose", 12) ||
863 !_cups_strcasecmp(choice
->choice
, "MP") ||
864 !_cups_strcasecmp(choice
->choice
, "MPTray"))
865 pwg_name
= "alternate";
866 else if (!_cups_strcasecmp(choice
->choice
, "LargeCapacity"))
867 pwg_name
= "large-capacity";
868 else if (!_cups_strncasecmp(choice
->choice
, "Lower", 5))
870 else if (!_cups_strncasecmp(choice
->choice
, "Middle", 6))
872 else if (!_cups_strncasecmp(choice
->choice
, "Upper", 5))
874 else if (!_cups_strncasecmp(choice
->choice
, "Side", 4))
876 else if (!_cups_strcasecmp(choice
->choice
, "Roll"))
877 pwg_name
= "main-roll";
881 * Convert PPD name to lowercase...
884 pwg_name
= pwg_keyword
;
885 pwg_unppdize_name(choice
->choice
, pwg_keyword
, sizeof(pwg_keyword
));
888 map
->pwg
= _cupsStrAlloc(pwg_name
);
889 map
->ppd
= _cupsStrAlloc(choice
->choice
);
894 * Copy and convert MediaType data...
897 if ((media_type
= ppdFindOption(ppd
, "MediaType")) != NULL
)
899 if ((pc
->types
= calloc(media_type
->num_choices
,
900 sizeof(_pwg_map_t
))) == NULL
)
902 DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
903 "_pwg_map_t's for MediaType.", media_type
->num_choices
));
907 pc
->num_types
= media_type
->num_choices
;
909 for (i
= media_type
->num_choices
, choice
= media_type
->choices
,
912 i
--, choice
++, map
++)
914 if (!_cups_strncasecmp(choice
->choice
, "Auto", 4) ||
915 !_cups_strcasecmp(choice
->choice
, "Any") ||
916 !_cups_strcasecmp(choice
->choice
, "Default"))
918 else if (!_cups_strncasecmp(choice
->choice
, "Card", 4))
919 pwg_name
= "cardstock";
920 else if (!_cups_strncasecmp(choice
->choice
, "Env", 3))
921 pwg_name
= "envelope";
922 else if (!_cups_strncasecmp(choice
->choice
, "Gloss", 5))
923 pwg_name
= "photographic-glossy";
924 else if (!_cups_strcasecmp(choice
->choice
, "HighGloss"))
925 pwg_name
= "photographic-high-gloss";
926 else if (!_cups_strcasecmp(choice
->choice
, "Matte"))
927 pwg_name
= "photographic-matte";
928 else if (!_cups_strncasecmp(choice
->choice
, "Plain", 5))
929 pwg_name
= "stationery";
930 else if (!_cups_strncasecmp(choice
->choice
, "Coated", 6))
931 pwg_name
= "stationery-coated";
932 else if (!_cups_strcasecmp(choice
->choice
, "Inkjet"))
933 pwg_name
= "stationery-inkjet";
934 else if (!_cups_strcasecmp(choice
->choice
, "Letterhead"))
935 pwg_name
= "stationery-letterhead";
936 else if (!_cups_strncasecmp(choice
->choice
, "Preprint", 8))
937 pwg_name
= "stationery-preprinted";
938 else if (!_cups_strcasecmp(choice
->choice
, "Recycled"))
939 pwg_name
= "stationery-recycled";
940 else if (!_cups_strncasecmp(choice
->choice
, "Transparen", 10))
941 pwg_name
= "transparency";
945 * Convert PPD name to lowercase...
948 pwg_name
= pwg_keyword
;
949 pwg_unppdize_name(choice
->choice
, pwg_keyword
, sizeof(pwg_keyword
));
952 map
->pwg
= _cupsStrAlloc(pwg_name
);
953 map
->ppd
= _cupsStrAlloc(choice
->choice
);
958 * Copy and convert OutputBin data...
961 if ((output_bin
= ppdFindOption(ppd
, "OutputBin")) != NULL
)
963 if ((pc
->bins
= calloc(output_bin
->num_choices
,
964 sizeof(_pwg_map_t
))) == NULL
)
966 DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
967 "_pwg_map_t's for OutputBin.", output_bin
->num_choices
));
971 pc
->num_bins
= output_bin
->num_choices
;
973 for (i
= output_bin
->num_choices
, choice
= output_bin
->choices
,
976 i
--, choice
++, map
++)
978 pwg_unppdize_name(choice
->choice
, pwg_keyword
, sizeof(pwg_keyword
));
980 map
->pwg
= _cupsStrAlloc(pwg_keyword
);
981 map
->ppd
= _cupsStrAlloc(choice
->choice
);
985 if ((ppd_attr
= ppdFindAttr(ppd
, "APPrinterPreset", NULL
)) != NULL
)
988 * Copy and convert APPrinterPreset (output-mode + print-quality) data...
991 const char *quality
, /* com.apple.print.preset.quality value */
992 *output_mode
, /* com.apple.print.preset.output-mode value */
993 *color_model_val
, /* ColorModel choice */
994 *graphicsType
, /* com.apple.print.preset.graphicsType value */
995 *media_front_coating
; /* com.apple.print.preset.media-front-coating value */
999 num_options
= _ppdParseOptions(ppd_attr
->value
, 0, &options
,
1002 if ((quality
= cupsGetOption("com.apple.print.preset.quality",
1003 num_options
, options
)) != NULL
)
1006 * Get the print-quality for this preset...
1009 if (!strcmp(quality
, "low"))
1010 pwg_print_quality
= _PWG_PRINT_QUALITY_DRAFT
;
1011 else if (!strcmp(quality
, "high"))
1012 pwg_print_quality
= _PWG_PRINT_QUALITY_HIGH
;
1014 pwg_print_quality
= _PWG_PRINT_QUALITY_NORMAL
;
1017 * Ignore graphicsType "Photo" presets that are not high quality.
1020 graphicsType
= cupsGetOption("com.apple.print.preset.graphicsType",
1021 num_options
, options
);
1023 if (pwg_print_quality
!= _PWG_PRINT_QUALITY_HIGH
&& graphicsType
&&
1024 !strcmp(graphicsType
, "Photo"))
1028 * Ignore presets for normal and draft quality where the coating
1029 * isn't "none" or "autodetect".
1032 media_front_coating
= cupsGetOption(
1033 "com.apple.print.preset.media-front-coating",
1034 num_options
, options
);
1036 if (pwg_print_quality
!= _PWG_PRINT_QUALITY_HIGH
&&
1037 media_front_coating
&&
1038 strcmp(media_front_coating
, "none") &&
1039 strcmp(media_front_coating
, "autodetect"))
1043 * Get the output mode for this preset...
1046 output_mode
= cupsGetOption("com.apple.print.preset.output-mode",
1047 num_options
, options
);
1048 color_model_val
= cupsGetOption("ColorModel", num_options
, options
);
1052 if (!strcmp(output_mode
, "monochrome"))
1053 pwg_print_color_mode
= _PWG_PRINT_COLOR_MODE_MONOCHROME
;
1055 pwg_print_color_mode
= _PWG_PRINT_COLOR_MODE_COLOR
;
1057 else if (color_model_val
)
1059 if (!_cups_strcasecmp(color_model_val
, "Gray"))
1060 pwg_print_color_mode
= _PWG_PRINT_COLOR_MODE_MONOCHROME
;
1062 pwg_print_color_mode
= _PWG_PRINT_COLOR_MODE_COLOR
;
1065 pwg_print_color_mode
= _PWG_PRINT_COLOR_MODE_COLOR
;
1068 * Save the options for this combination as needed...
1071 if (!pc
->num_presets
[pwg_print_color_mode
][pwg_print_quality
])
1072 pc
->num_presets
[pwg_print_color_mode
][pwg_print_quality
] =
1073 _ppdParseOptions(ppd_attr
->value
, 0,
1074 pc
->presets
[pwg_print_color_mode
] +
1075 pwg_print_quality
, _PPD_PARSE_OPTIONS
);
1078 cupsFreeOptions(num_options
, options
);
1080 while ((ppd_attr
= ppdFindNextAttr(ppd
, "APPrinterPreset", NULL
)) != NULL
);
1083 if (!pc
->num_presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
][_PWG_PRINT_QUALITY_DRAFT
] &&
1084 !pc
->num_presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
][_PWG_PRINT_QUALITY_NORMAL
] &&
1085 !pc
->num_presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
][_PWG_PRINT_QUALITY_HIGH
])
1088 * Try adding some common color options to create grayscale presets. These
1089 * are listed in order of popularity...
1092 const char *color_option
= NULL
, /* Color control option */
1093 *gray_choice
= NULL
; /* Choice to select grayscale */
1095 if ((color_model
= ppdFindOption(ppd
, "ColorModel")) != NULL
&&
1096 ppdFindChoice(color_model
, "Gray"))
1098 color_option
= "ColorModel";
1099 gray_choice
= "Gray";
1101 else if ((color_model
= ppdFindOption(ppd
, "HPColorMode")) != NULL
&&
1102 ppdFindChoice(color_model
, "grayscale"))
1104 color_option
= "HPColorMode";
1105 gray_choice
= "grayscale";
1107 else if ((color_model
= ppdFindOption(ppd
, "BRMonoColor")) != NULL
&&
1108 ppdFindChoice(color_model
, "Mono"))
1110 color_option
= "BRMonoColor";
1111 gray_choice
= "Mono";
1113 else if ((color_model
= ppdFindOption(ppd
, "CNIJSGrayScale")) != NULL
&&
1114 ppdFindChoice(color_model
, "1"))
1116 color_option
= "CNIJSGrayScale";
1119 else if ((color_model
= ppdFindOption(ppd
, "HPColorAsGray")) != NULL
&&
1120 ppdFindChoice(color_model
, "True"))
1122 color_option
= "HPColorAsGray";
1123 gray_choice
= "True";
1126 if (color_option
&& gray_choice
)
1129 * Copy and convert ColorModel (output-mode) data...
1132 cups_option_t
*coption
, /* Color option */
1133 *moption
; /* Monochrome option */
1135 for (pwg_print_quality
= _PWG_PRINT_QUALITY_DRAFT
;
1136 pwg_print_quality
< _PWG_PRINT_QUALITY_MAX
;
1137 pwg_print_quality
++)
1139 if (pc
->num_presets
[_PWG_PRINT_COLOR_MODE_COLOR
][pwg_print_quality
])
1142 * Copy the color options...
1145 num_options
= pc
->num_presets
[_PWG_PRINT_COLOR_MODE_COLOR
]
1146 [pwg_print_quality
];
1147 options
= calloc(sizeof(cups_option_t
), num_options
);
1151 for (i
= num_options
, moption
= options
,
1152 coption
= pc
->presets
[_PWG_PRINT_COLOR_MODE_COLOR
]
1153 [pwg_print_quality
];
1155 i
--, moption
++, coption
++)
1157 moption
->name
= _cupsStrRetain(coption
->name
);
1158 moption
->value
= _cupsStrRetain(coption
->value
);
1161 pc
->num_presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
][pwg_print_quality
] =
1163 pc
->presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
][pwg_print_quality
] =
1167 else if (pwg_print_quality
!= _PWG_PRINT_QUALITY_NORMAL
)
1171 * Add the grayscale option to the preset...
1174 pc
->num_presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
][pwg_print_quality
] =
1175 cupsAddOption(color_option
, gray_choice
,
1176 pc
->num_presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
]
1177 [pwg_print_quality
],
1178 pc
->presets
[_PWG_PRINT_COLOR_MODE_MONOCHROME
] +
1185 * Copy and convert Duplex (sides) data...
1188 if ((duplex
= ppdFindOption(ppd
, "Duplex")) == NULL
)
1189 if ((duplex
= ppdFindOption(ppd
, "JCLDuplex")) == NULL
)
1190 if ((duplex
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
1191 if ((duplex
= ppdFindOption(ppd
, "EFDuplexing")) == NULL
)
1192 duplex
= ppdFindOption(ppd
, "KD03Duplex");
1196 pc
->sides_option
= _cupsStrAlloc(duplex
->keyword
);
1198 for (i
= duplex
->num_choices
, choice
= duplex
->choices
;
1202 if ((!_cups_strcasecmp(choice
->choice
, "None") ||
1203 !_cups_strcasecmp(choice
->choice
, "False")) && !pc
->sides_1sided
)
1204 pc
->sides_1sided
= _cupsStrAlloc(choice
->choice
);
1205 else if ((!_cups_strcasecmp(choice
->choice
, "DuplexNoTumble") ||
1206 !_cups_strcasecmp(choice
->choice
, "LongEdge") ||
1207 !_cups_strcasecmp(choice
->choice
, "Top")) && !pc
->sides_2sided_long
)
1208 pc
->sides_2sided_long
= _cupsStrAlloc(choice
->choice
);
1209 else if ((!_cups_strcasecmp(choice
->choice
, "DuplexTumble") ||
1210 !_cups_strcasecmp(choice
->choice
, "ShortEdge") ||
1211 !_cups_strcasecmp(choice
->choice
, "Bottom")) &&
1212 !pc
->sides_2sided_short
)
1213 pc
->sides_2sided_short
= _cupsStrAlloc(choice
->choice
);
1218 * Copy filters and pre-filters...
1221 pc
->filters
= cupsArrayNew3(NULL
, NULL
, NULL
, 0,
1222 (cups_acopy_func_t
)_cupsStrAlloc
,
1223 (cups_afree_func_t
)_cupsStrFree
);
1225 cupsArrayAdd(pc
->filters
,
1226 "application/vnd.cups-raw application/octet-stream 0 -");
1228 if ((ppd_attr
= ppdFindAttr(ppd
, "cupsFilter2", NULL
)) != NULL
)
1232 cupsArrayAdd(pc
->filters
, ppd_attr
->value
);
1234 while ((ppd_attr
= ppdFindNextAttr(ppd
, "cupsFilter2", NULL
)) != NULL
);
1236 else if (ppd
->num_filters
> 0)
1238 for (i
= 0; i
< ppd
->num_filters
; i
++)
1239 cupsArrayAdd(pc
->filters
, ppd
->filters
[i
]);
1242 cupsArrayAdd(pc
->filters
, "application/vnd.cups-postscript 0 -");
1245 * See if we have a command filter...
1248 for (filter
= (const char *)cupsArrayFirst(pc
->filters
);
1250 filter
= (const char *)cupsArrayNext(pc
->filters
))
1251 if (!_cups_strncasecmp(filter
, "application/vnd.cups-command", 28) &&
1252 _cups_isspace(filter
[28]))
1256 ((ppd_attr
= ppdFindAttr(ppd
, "cupsCommands", NULL
)) == NULL
||
1257 _cups_strcasecmp(ppd_attr
->value
, "none")))
1260 * No command filter and no cupsCommands keyword telling us not to use one.
1261 * See if this is a PostScript printer, and if so add a PostScript command
1265 for (filter
= (const char *)cupsArrayFirst(pc
->filters
);
1267 filter
= (const char *)cupsArrayNext(pc
->filters
))
1268 if (!_cups_strncasecmp(filter
, "application/vnd.cups-postscript", 31) &&
1269 _cups_isspace(filter
[31]))
1273 cupsArrayAdd(pc
->filters
,
1274 "application/vnd.cups-command application/postscript 0 -");
1277 if ((ppd_attr
= ppdFindAttr(ppd
, "cupsPreFilter", NULL
)) != NULL
)
1279 pc
->prefilters
= cupsArrayNew3(NULL
, NULL
, NULL
, 0,
1280 (cups_acopy_func_t
)_cupsStrAlloc
,
1281 (cups_afree_func_t
)_cupsStrFree
);
1285 cupsArrayAdd(pc
->prefilters
, ppd_attr
->value
);
1287 while ((ppd_attr
= ppdFindNextAttr(ppd
, "cupsPreFilter", NULL
)) != NULL
);
1290 if ((ppd_attr
= ppdFindAttr(ppd
, "cupsSingleFile", NULL
)) != NULL
)
1291 pc
->single_file
= !_cups_strcasecmp(ppd_attr
->value
, "true");
1294 * Copy the product string, if any...
1298 pc
->product
= _cupsStrAlloc(ppd
->product
);
1301 * Return the cache data...
1307 * If we get here we need to destroy the PWG mapping data and return NULL...
1312 _cupsSetError(IPP_INTERNAL_ERROR
, _("Out of memory."), 1);
1313 _ppdCacheDestroy(pc
);
1320 * '_ppdCacheDestroy()' - Free all memory used for PWG mapping data.
1324 _ppdCacheDestroy(_ppd_cache_t
*pc
) /* I - PPD cache and mapping data */
1326 int i
; /* Looping var */
1327 _pwg_map_t
*map
; /* Current map */
1328 _pwg_size_t
*size
; /* Current size */
1332 * Range check input...
1339 * Free memory as needed...
1344 for (i
= pc
->num_bins
, map
= pc
->bins
; i
> 0; i
--, map
++)
1346 _cupsStrFree(map
->pwg
);
1347 _cupsStrFree(map
->ppd
);
1355 for (i
= pc
->num_sizes
, size
= pc
->sizes
; i
> 0; i
--, size
++)
1357 _cupsStrFree(size
->map
.pwg
);
1358 _cupsStrFree(size
->map
.ppd
);
1364 if (pc
->source_option
)
1365 _cupsStrFree(pc
->source_option
);
1369 for (i
= pc
->num_sources
, map
= pc
->sources
; i
> 0; i
--, map
++)
1371 _cupsStrFree(map
->pwg
);
1372 _cupsStrFree(map
->ppd
);
1380 for (i
= pc
->num_types
, map
= pc
->types
; i
> 0; i
--, map
++)
1382 _cupsStrFree(map
->pwg
);
1383 _cupsStrFree(map
->ppd
);
1389 if (pc
->custom_max_keyword
)
1390 _cupsStrFree(pc
->custom_max_keyword
);
1392 if (pc
->custom_min_keyword
)
1393 _cupsStrFree(pc
->custom_min_keyword
);
1395 _cupsStrFree(pc
->product
);
1396 cupsArrayDelete(pc
->filters
);
1397 cupsArrayDelete(pc
->prefilters
);
1404 * '_ppdCacheGetBin()' - Get the PWG output-bin keyword associated with a PPD
1408 const char * /* O - output-bin or NULL */
1410 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1411 const char *output_bin
) /* I - PPD OutputBin string */
1413 int i
; /* Looping var */
1417 * Range check input...
1420 if (!pc
|| !output_bin
)
1424 * Look up the OutputBin string...
1428 for (i
= 0; i
< pc
->num_bins
; i
++)
1429 if (!_cups_strcasecmp(output_bin
, pc
->bins
[i
].ppd
))
1430 return (pc
->bins
[i
].pwg
);
1437 * '_ppdCacheGetInputSlot()' - Get the PPD InputSlot associated with the job
1438 * attributes or a keyword string.
1441 const char * /* O - PPD InputSlot or NULL */
1442 _ppdCacheGetInputSlot(
1443 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1444 ipp_t
*job
, /* I - Job attributes or NULL */
1445 const char *keyword
) /* I - Keyword string or NULL */
1448 * Range check input...
1451 if (!pc
|| pc
->num_sources
== 0 || (!job
&& !keyword
))
1454 if (job
&& !keyword
)
1457 * Lookup the media-col attribute and any media-source found there...
1460 ipp_attribute_t
*media_col
, /* media-col attribute */
1461 *media_source
; /* media-source attribute */
1462 _pwg_size_t size
; /* Dimensional size */
1463 int margins_set
; /* Were the margins set? */
1465 media_col
= ippFindAttribute(job
, "media-col", IPP_TAG_BEGIN_COLLECTION
);
1467 (media_source
= ippFindAttribute(media_col
->values
[0].collection
,
1469 IPP_TAG_KEYWORD
)) != NULL
)
1472 * Use the media-source value from media-col...
1475 keyword
= media_source
->values
[0].string
.text
;
1477 else if (_pwgInitSize(&size
, job
, &margins_set
))
1480 * For media <= 5x7, look for a photo tray...
1483 if (size
.width
<= (5 * 2540) && size
.length
<= (7 * 2540))
1490 int i
; /* Looping var */
1492 for (i
= 0; i
< pc
->num_sources
; i
++)
1493 if (!_cups_strcasecmp(keyword
, pc
->sources
[i
].pwg
))
1494 return (pc
->sources
[i
].ppd
);
1502 * '_ppdCacheGetMediaType()' - Get the PPD MediaType associated with the job
1503 * attributes or a keyword string.
1506 const char * /* O - PPD MediaType or NULL */
1507 _ppdCacheGetMediaType(
1508 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1509 ipp_t
*job
, /* I - Job attributes or NULL */
1510 const char *keyword
) /* I - Keyword string or NULL */
1513 * Range check input...
1516 if (!pc
|| pc
->num_types
== 0 || (!job
&& !keyword
))
1519 if (job
&& !keyword
)
1522 * Lookup the media-col attribute and any media-source found there...
1525 ipp_attribute_t
*media_col
, /* media-col attribute */
1526 *media_type
; /* media-type attribute */
1528 media_col
= ippFindAttribute(job
, "media-col", IPP_TAG_BEGIN_COLLECTION
);
1531 if ((media_type
= ippFindAttribute(media_col
->values
[0].collection
,
1533 IPP_TAG_KEYWORD
)) == NULL
)
1534 media_type
= ippFindAttribute(media_col
->values
[0].collection
,
1535 "media-type", IPP_TAG_NAME
);
1538 keyword
= media_type
->values
[0].string
.text
;
1544 int i
; /* Looping var */
1546 for (i
= 0; i
< pc
->num_types
; i
++)
1547 if (!_cups_strcasecmp(keyword
, pc
->types
[i
].pwg
))
1548 return (pc
->types
[i
].ppd
);
1556 * '_ppdCacheGetOutputBin()' - Get the PPD OutputBin associated with the keyword
1560 const char * /* O - PPD OutputBin or NULL */
1561 _ppdCacheGetOutputBin(
1562 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1563 const char *output_bin
) /* I - Keyword string */
1565 int i
; /* Looping var */
1569 * Range check input...
1572 if (!pc
|| !output_bin
)
1576 * Look up the OutputBin string...
1580 for (i
= 0; i
< pc
->num_bins
; i
++)
1581 if (!_cups_strcasecmp(output_bin
, pc
->bins
[i
].pwg
))
1582 return (pc
->bins
[i
].ppd
);
1589 * '_ppdCacheGetPageSize()' - Get the PPD PageSize associated with the job
1590 * attributes or a keyword string.
1593 const char * /* O - PPD PageSize or NULL */
1594 _ppdCacheGetPageSize(
1595 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1596 ipp_t
*job
, /* I - Job attributes or NULL */
1597 const char *keyword
, /* I - Keyword string or NULL */
1598 int *exact
) /* O - 1 if exact match, 0 otherwise */
1600 int i
; /* Looping var */
1601 _pwg_size_t
*size
, /* Current size */
1602 *closest
, /* Closest size */
1603 jobsize
; /* Size data from job */
1604 int margins_set
, /* Were the margins set? */
1605 dwidth
, /* Difference in width */
1606 dlength
, /* Difference in length */
1607 dleft
, /* Difference in left margins */
1608 dright
, /* Difference in right margins */
1609 dbottom
, /* Difference in bottom margins */
1610 dtop
, /* Difference in top margins */
1611 dmin
, /* Minimum difference */
1612 dclosest
; /* Closest difference */
1613 const char *ppd_name
; /* PPD media name */
1616 DEBUG_printf(("_ppdCacheGetPageSize(pc=%p, job=%p, keyword=\"%s\", exact=%p)",
1617 pc
, job
, keyword
, exact
));
1620 * Range check input...
1623 if (!pc
|| (!job
&& !keyword
))
1634 * Try getting the PPD media name from the job attributes...
1637 ipp_attribute_t
*attr
; /* Job attribute */
1639 if ((attr
= ippFindAttribute(job
, "PageSize", IPP_TAG_ZERO
)) == NULL
)
1640 if ((attr
= ippFindAttribute(job
, "PageRegion", IPP_TAG_ZERO
)) == NULL
)
1641 attr
= ippFindAttribute(job
, "media", IPP_TAG_ZERO
);
1645 DEBUG_printf(("1_ppdCacheGetPageSize: Found attribute %s (%s)",
1646 attr
->name
, ippTagString(attr
->value_tag
)));
1648 DEBUG_puts("1_ppdCacheGetPageSize: Did not find media attribute.");
1651 if (attr
&& (attr
->value_tag
== IPP_TAG_NAME
||
1652 attr
->value_tag
== IPP_TAG_KEYWORD
))
1653 ppd_name
= attr
->values
[0].string
.text
;
1656 DEBUG_printf(("1_ppdCacheGetPageSize: ppd_name=\"%s\"", ppd_name
));
1661 * Try looking up the named PPD size first...
1664 for (i
= pc
->num_sizes
, size
= pc
->sizes
; i
> 0; i
--, size
++)
1666 DEBUG_printf(("2_ppdCacheGetPageSize: size[%d]=[\"%s\" \"%s\"]",
1667 (int)(size
- pc
->sizes
), size
->map
.pwg
, size
->map
.ppd
));
1669 if (!_cups_strcasecmp(ppd_name
, size
->map
.ppd
) ||
1670 !_cups_strcasecmp(ppd_name
, size
->map
.pwg
))
1675 DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", ppd_name
));
1677 return (size
->map
.ppd
);
1682 if (job
&& !keyword
)
1685 * Get the size using media-col or media, with the preference being
1689 if (!_pwgInitSize(&jobsize
, job
, &margins_set
))
1695 * Get the size using a media keyword...
1698 _pwg_media_t
*media
; /* Media definition */
1701 if ((media
= _pwgMediaForPWG(keyword
)) == NULL
)
1702 if ((media
= _pwgMediaForLegacy(keyword
)) == NULL
)
1703 if ((media
= _pwgMediaForPPD(keyword
)) == NULL
)
1706 jobsize
.width
= media
->width
;
1707 jobsize
.length
= media
->length
;
1712 * Now that we have the dimensions and possibly the margins, look at the
1713 * available sizes and find the match...
1717 dclosest
= 999999999;
1719 if (!ppd_name
|| _cups_strncasecmp(ppd_name
, "Custom.", 7) ||
1720 _cups_strncasecmp(ppd_name
, "custom_", 7))
1722 for (i
= pc
->num_sizes
, size
= pc
->sizes
; i
> 0; i
--, size
++)
1725 * Adobe uses a size matching algorithm with an epsilon of 5 points, which
1726 * is just about 176/2540ths...
1729 dwidth
= size
->width
- jobsize
.width
;
1730 dlength
= size
->length
- jobsize
.length
;
1732 if (dwidth
<= -176 || dwidth
>= 176 || dlength
<= -176 || dlength
>= 176)
1738 * Use a tighter epsilon of 1 point (35/2540ths) for margins...
1741 dleft
= size
->left
- jobsize
.left
;
1742 dright
= size
->right
- jobsize
.right
;
1743 dtop
= size
->top
- jobsize
.top
;
1744 dbottom
= size
->bottom
- jobsize
.bottom
;
1746 if (dleft
<= -35 || dleft
>= 35 || dright
<= -35 || dright
>= 35 ||
1747 dtop
<= -35 || dtop
>= 35 || dbottom
<= -35 || dbottom
>= 35)
1749 dleft
= dleft
< 0 ? -dleft
: dleft
;
1750 dright
= dright
< 0 ? -dright
: dright
;
1751 dbottom
= dbottom
< 0 ? -dbottom
: dbottom
;
1752 dtop
= dtop
< 0 ? -dtop
: dtop
;
1753 dmin
= dleft
+ dright
+ dbottom
+ dtop
;
1755 if (dmin
< dclosest
)
1768 DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", size
->map
.ppd
));
1770 return (size
->map
.ppd
);
1776 DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (closest)",
1779 return (closest
->map
.ppd
);
1783 * If we get here we need to check for custom page size support...
1786 if (jobsize
.width
>= pc
->custom_min_width
&&
1787 jobsize
.width
<= pc
->custom_max_width
&&
1788 jobsize
.length
>= pc
->custom_min_length
&&
1789 jobsize
.length
<= pc
->custom_max_length
)
1792 * In range, format as Custom.WWWWxLLLL (points).
1795 snprintf(pc
->custom_ppd_size
, sizeof(pc
->custom_ppd_size
), "Custom.%dx%d",
1796 (int)_PWG_TOPTS(jobsize
.width
), (int)_PWG_TOPTS(jobsize
.length
));
1798 if (margins_set
&& exact
)
1800 dleft
= pc
->custom_size
.left
- jobsize
.left
;
1801 dright
= pc
->custom_size
.right
- jobsize
.right
;
1802 dtop
= pc
->custom_size
.top
- jobsize
.top
;
1803 dbottom
= pc
->custom_size
.bottom
- jobsize
.bottom
;
1805 if (dleft
> -35 && dleft
< 35 && dright
> -35 && dright
< 35 &&
1806 dtop
> -35 && dtop
< 35 && dbottom
> -35 && dbottom
< 35)
1812 DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (custom)",
1813 pc
->custom_ppd_size
));
1815 return (pc
->custom_ppd_size
);
1819 * No custom page size support or the size is out of range - return NULL.
1822 DEBUG_puts("1_ppdCacheGetPageSize: Returning NULL");
1829 * '_ppdCacheGetSize()' - Get the PWG size associated with a PPD PageSize.
1832 _pwg_size_t
* /* O - PWG size or NULL */
1834 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1835 const char *page_size
) /* I - PPD PageSize */
1838 _pwg_size_t
*size
; /* Current size */
1842 * Range check input...
1845 if (!pc
|| !page_size
)
1848 if (!_cups_strncasecmp(page_size
, "Custom.", 7))
1851 * Custom size; size name can be one of the following:
1853 * Custom.WIDTHxLENGTHin - Size in inches
1854 * Custom.WIDTHxLENGTHft - Size in feet
1855 * Custom.WIDTHxLENGTHcm - Size in centimeters
1856 * Custom.WIDTHxLENGTHmm - Size in millimeters
1857 * Custom.WIDTHxLENGTHm - Size in meters
1858 * Custom.WIDTHxLENGTH[pt] - Size in points
1861 double w
, l
; /* Width and length of page */
1862 char *ptr
; /* Pointer into PageSize */
1863 struct lconv
*loc
; /* Locale data */
1866 w
= (float)_cupsStrScand(page_size
+ 7, &ptr
, loc
);
1867 if (!ptr
|| *ptr
!= 'x')
1870 l
= (float)_cupsStrScand(ptr
+ 1, &ptr
, loc
);
1874 if (!_cups_strcasecmp(ptr
, "in"))
1879 else if (!_cups_strcasecmp(ptr
, "ft"))
1884 else if (!_cups_strcasecmp(ptr
, "mm"))
1889 else if (!_cups_strcasecmp(ptr
, "cm"))
1894 else if (!_cups_strcasecmp(ptr
, "m"))
1905 pc
->custom_size
.width
= (int)w
;
1906 pc
->custom_size
.length
= (int)l
;
1908 return (&(pc
->custom_size
));
1912 * Not a custom size - look it up...
1915 for (i
= pc
->num_sizes
, size
= pc
->sizes
; i
> 0; i
--, size
++)
1916 if (!_cups_strcasecmp(page_size
, size
->map
.ppd
))
1924 * '_ppdCacheGetSource()' - Get the PWG media-source associated with a PPD
1928 const char * /* O - PWG media-source keyword */
1930 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1931 const char *input_slot
) /* I - PPD InputSlot */
1933 int i
; /* Looping var */
1934 _pwg_map_t
*source
; /* Current source */
1938 * Range check input...
1941 if (!pc
|| !input_slot
)
1944 for (i
= pc
->num_sources
, source
= pc
->sources
; i
> 0; i
--, source
++)
1945 if (!_cups_strcasecmp(input_slot
, source
->ppd
))
1946 return (source
->pwg
);
1953 * '_ppdCacheGetType()' - Get the PWG media-type associated with a PPD
1957 const char * /* O - PWG media-type keyword */
1959 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1960 const char *media_type
) /* I - PPD MediaType */
1962 int i
; /* Looping var */
1963 _pwg_map_t
*type
; /* Current type */
1967 * Range check input...
1970 if (!pc
|| !media_type
)
1973 for (i
= pc
->num_types
, type
= pc
->types
; i
> 0; i
--, type
++)
1974 if (!_cups_strcasecmp(media_type
, type
->ppd
))
1982 * '_ppdCacheWriteFile()' - Write PWG mapping data to a file.
1985 int /* O - 1 on success, 0 on failure */
1987 _ppd_cache_t
*pc
, /* I - PPD cache and mapping data */
1988 const char *filename
, /* I - File to write */
1989 ipp_t
*attrs
) /* I - Attributes to write, if any */
1991 int i
, j
, k
; /* Looping vars */
1992 cups_file_t
*fp
; /* Output file */
1993 _pwg_size_t
*size
; /* Current size */
1994 _pwg_map_t
*map
; /* Current map */
1995 cups_option_t
*option
; /* Current option */
1996 const char *value
; /* Filter/pre-filter value */
1997 char newfile
[1024]; /* New filename */
2001 * Range check input...
2004 if (!pc
|| !filename
)
2006 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(EINVAL
), 0);
2011 * Open the file and write with compression...
2014 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
2015 if ((fp
= cupsFileOpen(newfile
, "w9")) == NULL
)
2017 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
2022 * Standard header...
2025 cupsFilePrintf(fp
, "#CUPS-PPD-CACHE-%d\n", _PPD_CACHE_VERSION
);
2031 if (pc
->num_bins
> 0)
2033 cupsFilePrintf(fp
, "NumBins %d\n", pc
->num_bins
);
2034 for (i
= pc
->num_bins
, map
= pc
->bins
; i
> 0; i
--, map
++)
2035 cupsFilePrintf(fp
, "Bin %s %s\n", map
->pwg
, map
->ppd
);
2042 cupsFilePrintf(fp
, "NumSizes %d\n", pc
->num_sizes
);
2043 for (i
= pc
->num_sizes
, size
= pc
->sizes
; i
> 0; i
--, size
++)
2044 cupsFilePrintf(fp
, "Size %s %s %d %d %d %d %d %d\n", size
->map
.pwg
,
2045 size
->map
.ppd
, size
->width
, size
->length
, size
->left
,
2046 size
->bottom
, size
->right
, size
->top
);
2047 if (pc
->custom_max_width
> 0)
2048 cupsFilePrintf(fp
, "CustomSize %d %d %d %d %d %d %d %d\n",
2049 pc
->custom_max_width
, pc
->custom_max_length
,
2050 pc
->custom_min_width
, pc
->custom_min_length
,
2051 pc
->custom_size
.left
, pc
->custom_size
.bottom
,
2052 pc
->custom_size
.right
, pc
->custom_size
.top
);
2058 if (pc
->source_option
)
2059 cupsFilePrintf(fp
, "SourceOption %s\n", pc
->source_option
);
2061 if (pc
->num_sources
> 0)
2063 cupsFilePrintf(fp
, "NumSources %d\n", pc
->num_sources
);
2064 for (i
= pc
->num_sources
, map
= pc
->sources
; i
> 0; i
--, map
++)
2065 cupsFilePrintf(fp
, "Source %s %s\n", map
->pwg
, map
->ppd
);
2072 if (pc
->num_types
> 0)
2074 cupsFilePrintf(fp
, "NumTypes %d\n", pc
->num_types
);
2075 for (i
= pc
->num_types
, map
= pc
->types
; i
> 0; i
--, map
++)
2076 cupsFilePrintf(fp
, "Type %s %s\n", map
->pwg
, map
->ppd
);
2083 for (i
= _PWG_PRINT_COLOR_MODE_MONOCHROME
; i
< _PWG_PRINT_COLOR_MODE_MAX
; i
++)
2084 for (j
= _PWG_PRINT_QUALITY_DRAFT
; j
< _PWG_PRINT_QUALITY_MAX
; j
++)
2085 if (pc
->num_presets
[i
][j
])
2087 cupsFilePrintf(fp
, "Preset %d %d", i
, j
);
2088 for (k
= pc
->num_presets
[i
][j
], option
= pc
->presets
[i
][j
];
2091 cupsFilePrintf(fp
, " %s=%s", option
->name
, option
->value
);
2092 cupsFilePutChar(fp
, '\n');
2099 if (pc
->sides_option
)
2100 cupsFilePrintf(fp
, "SidesOption %s\n", pc
->sides_option
);
2102 if (pc
->sides_1sided
)
2103 cupsFilePrintf(fp
, "Sides1Sided %s\n", pc
->sides_1sided
);
2105 if (pc
->sides_2sided_long
)
2106 cupsFilePrintf(fp
, "Sides2SidedLong %s\n", pc
->sides_2sided_long
);
2108 if (pc
->sides_2sided_short
)
2109 cupsFilePrintf(fp
, "Sides2SidedShort %s\n", pc
->sides_2sided_short
);
2112 * Product, cupsFilter, cupsFilter2, and cupsPreFilter...
2116 cupsFilePutConf(fp
, "Product", pc
->product
);
2118 for (value
= (const char *)cupsArrayFirst(pc
->filters
);
2120 value
= (const char *)cupsArrayNext(pc
->filters
))
2121 cupsFilePutConf(fp
, "Filter", value
);
2123 for (value
= (const char *)cupsArrayFirst(pc
->prefilters
);
2125 value
= (const char *)cupsArrayNext(pc
->prefilters
))
2126 cupsFilePutConf(fp
, "PreFilter", value
);
2128 cupsFilePrintf(fp
, "SingleFile %s\n", pc
->single_file
? "true" : "false");
2131 * IPP attributes, if any...
2136 cupsFilePrintf(fp
, "IPP " CUPS_LLFMT
"\n", CUPS_LLCAST
ippLength(attrs
));
2138 attrs
->state
= IPP_IDLE
;
2139 ippWriteIO(fp
, (ipp_iocb_t
)cupsFileWrite
, 1, NULL
, attrs
);
2143 * Close and return...
2146 if (cupsFileClose(fp
))
2153 return (!rename(newfile
, filename
));
2158 * '_pwgInputSlotForSource()' - Get the InputSlot name for the given PWG
2162 const char * /* O - InputSlot name */
2163 _pwgInputSlotForSource(
2164 const char *media_source
, /* I - PWG media-source */
2165 char *name
, /* I - Name buffer */
2166 size_t namesize
) /* I - Size of name buffer */
2169 * Range check input...
2172 if (!media_source
|| !name
|| namesize
< PPD_MAX_NAME
)
2175 if (_cups_strcasecmp(media_source
, "main"))
2176 strlcpy(name
, "Cassette", namesize
);
2177 else if (_cups_strcasecmp(media_source
, "alternate"))
2178 strlcpy(name
, "Multipurpose", namesize
);
2179 else if (_cups_strcasecmp(media_source
, "large-capacity"))
2180 strlcpy(name
, "LargeCapacity", namesize
);
2181 else if (_cups_strcasecmp(media_source
, "bottom"))
2182 strlcpy(name
, "Lower", namesize
);
2183 else if (_cups_strcasecmp(media_source
, "middle"))
2184 strlcpy(name
, "Middle", namesize
);
2185 else if (_cups_strcasecmp(media_source
, "top"))
2186 strlcpy(name
, "Upper", namesize
);
2187 else if (_cups_strcasecmp(media_source
, "rear"))
2188 strlcpy(name
, "Rear", namesize
);
2189 else if (_cups_strcasecmp(media_source
, "side"))
2190 strlcpy(name
, "Side", namesize
);
2191 else if (_cups_strcasecmp(media_source
, "envelope"))
2192 strlcpy(name
, "Envelope", namesize
);
2193 else if (_cups_strcasecmp(media_source
, "main-roll"))
2194 strlcpy(name
, "Roll", namesize
);
2195 else if (_cups_strcasecmp(media_source
, "alternate-roll"))
2196 strlcpy(name
, "Roll2", namesize
);
2198 pwg_ppdize_name(media_source
, name
, namesize
);
2205 * '_pwgMediaTypeForType()' - Get the MediaType name for the given PWG
2209 const char * /* O - MediaType name */
2210 _pwgMediaTypeForType(
2211 const char *media_type
, /* I - PWG media-type */
2212 char *name
, /* I - Name buffer */
2213 size_t namesize
) /* I - Size of name buffer */
2216 * Range check input...
2219 if (!media_type
|| !name
|| namesize
< PPD_MAX_NAME
)
2222 if (_cups_strcasecmp(media_type
, "auto"))
2223 strlcpy(name
, "Auto", namesize
);
2224 else if (_cups_strcasecmp(media_type
, "cardstock"))
2225 strlcpy(name
, "Cardstock", namesize
);
2226 else if (_cups_strcasecmp(media_type
, "envelope"))
2227 strlcpy(name
, "Envelope", namesize
);
2228 else if (_cups_strcasecmp(media_type
, "photographic-glossy"))
2229 strlcpy(name
, "Glossy", namesize
);
2230 else if (_cups_strcasecmp(media_type
, "photographic-high-gloss"))
2231 strlcpy(name
, "HighGloss", namesize
);
2232 else if (_cups_strcasecmp(media_type
, "photographic-matte"))
2233 strlcpy(name
, "Matte", namesize
);
2234 else if (_cups_strcasecmp(media_type
, "stationery"))
2235 strlcpy(name
, "Plain", namesize
);
2236 else if (_cups_strcasecmp(media_type
, "stationery-coated"))
2237 strlcpy(name
, "Coated", namesize
);
2238 else if (_cups_strcasecmp(media_type
, "stationery-inkjet"))
2239 strlcpy(name
, "Inkjet", namesize
);
2240 else if (_cups_strcasecmp(media_type
, "stationery-letterhead"))
2241 strlcpy(name
, "Letterhead", namesize
);
2242 else if (_cups_strcasecmp(media_type
, "stationery-preprinted"))
2243 strlcpy(name
, "Preprinted", namesize
);
2244 else if (_cups_strcasecmp(media_type
, "transparency"))
2245 strlcpy(name
, "Transparency", namesize
);
2247 pwg_ppdize_name(media_type
, name
, namesize
);
2254 * '_pwgPageSizeForMedia()' - Get the PageSize name for the given media.
2257 const char * /* O - PageSize name */
2258 _pwgPageSizeForMedia(
2259 _pwg_media_t
*media
, /* I - Media */
2260 char *name
, /* I - PageSize name buffer */
2261 size_t namesize
) /* I - Size of name buffer */
2263 const char *sizeptr
, /* Pointer to size in PWG name */
2264 *dimptr
; /* Pointer to dimensions in PWG name */
2268 * Range check input...
2271 if (!media
|| !name
|| namesize
< PPD_MAX_NAME
)
2275 * Copy or generate a PageSize name...
2281 * Use a standard Adobe name...
2284 strlcpy(name
, media
->ppd
, namesize
);
2286 else if (!media
->pwg
|| !strncmp(media
->pwg
, "custom_", 7) ||
2287 (sizeptr
= strchr(media
->pwg
, '_')) == NULL
||
2288 (dimptr
= strchr(sizeptr
+ 1, '_')) == NULL
||
2289 (size_t)(dimptr
- sizeptr
) > namesize
)
2292 * Use a name of the form "wNNNhNNN"...
2295 snprintf(name
, namesize
, "w%dh%d", (int)_PWG_TOPTS(media
->width
),
2296 (int)_PWG_TOPTS(media
->length
));
2301 * Copy the size name from class_sizename_dimensions...
2304 memcpy(name
, sizeptr
+ 1, dimptr
- sizeptr
- 1);
2305 name
[dimptr
- sizeptr
- 1] = '\0';
2313 * 'pwg_ppdize_name()' - Convert an IPP keyword to a PPD keyword.
2317 pwg_ppdize_name(const char *ipp
, /* I - IPP keyword */
2318 char *name
, /* I - Name buffer */
2319 size_t namesize
) /* I - Size of name buffer */
2321 char *ptr
, /* Pointer into name buffer */
2322 *end
; /* End of name buffer */
2325 *name
= toupper(*ipp
++);
2327 for (ptr
= name
+ 1, end
= name
+ namesize
- 1; *ipp
&& ptr
< end
;)
2329 if (*ipp
== '-' && _cups_isalpha(ipp
[1]))
2332 *ptr
++ = toupper(*ipp
++ & 255);
2343 * 'pwg_unppdize_name()' - Convert a PPD keyword to a lowercase IPP keyword.
2347 pwg_unppdize_name(const char *ppd
, /* I - PPD keyword */
2348 char *name
, /* I - Name buffer */
2349 size_t namesize
) /* I - Size of name buffer */
2351 char *ptr
, /* Pointer into name buffer */
2352 *end
; /* End of name buffer */
2355 for (ptr
= name
, end
= name
+ namesize
- 1; *ppd
&& ptr
< end
; ppd
++)
2357 if (_cups_isalnum(*ppd
) || *ppd
== '-')
2358 *ptr
++ = tolower(*ppd
& 255);
2359 else if (*ppd
== '_' || *ppd
== '.')
2362 if (!_cups_isupper(*ppd
) && _cups_isalnum(*ppd
) &&
2363 _cups_isupper(ppd
[1]) && ptr
< end
)