xref: /aosp_15_r20/external/libcups/cups/ppd-mark.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Option marking routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  *
10*5e7646d2SAndroid Build Coastguard Worker  * PostScript is a trademark of Adobe Systems, Inc.
11*5e7646d2SAndroid Build Coastguard Worker  */
12*5e7646d2SAndroid Build Coastguard Worker 
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
15*5e7646d2SAndroid Build Coastguard Worker  */
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
18*5e7646d2SAndroid Build Coastguard Worker #include "ppd-private.h"
19*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker /*
23*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
24*5e7646d2SAndroid Build Coastguard Worker  */
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
27*5e7646d2SAndroid Build Coastguard Worker static void	ppd_debug_marked(ppd_file_t *ppd, const char *title);
28*5e7646d2SAndroid Build Coastguard Worker #else
29*5e7646d2SAndroid Build Coastguard Worker #  define	ppd_debug_marked(ppd,title)
30*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
31*5e7646d2SAndroid Build Coastguard Worker static void	ppd_defaults(ppd_file_t *ppd, ppd_group_t *g);
32*5e7646d2SAndroid Build Coastguard Worker static void	ppd_mark_choices(ppd_file_t *ppd, const char *s);
33*5e7646d2SAndroid Build Coastguard Worker static void	ppd_mark_option(ppd_file_t *ppd, const char *option,
34*5e7646d2SAndroid Build Coastguard Worker 		                const char *choice);
35*5e7646d2SAndroid Build Coastguard Worker 
36*5e7646d2SAndroid Build Coastguard Worker 
37*5e7646d2SAndroid Build Coastguard Worker /*
38*5e7646d2SAndroid Build Coastguard Worker  * 'cupsMarkOptions()' - Mark command-line options in a PPD file.
39*5e7646d2SAndroid Build Coastguard Worker  *
40*5e7646d2SAndroid Build Coastguard Worker  * This function maps the IPP "finishings", "media", "mirror",
41*5e7646d2SAndroid Build Coastguard Worker  * "multiple-document-handling", "output-bin", "print-color-mode",
42*5e7646d2SAndroid Build Coastguard Worker  * "print-quality", "printer-resolution", and "sides" attributes to their
43*5e7646d2SAndroid Build Coastguard Worker  * corresponding PPD options and choices.
44*5e7646d2SAndroid Build Coastguard Worker  */
45*5e7646d2SAndroid Build Coastguard Worker 
46*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 if conflicts exist, 0 otherwise */
cupsMarkOptions(ppd_file_t * ppd,int num_options,cups_option_t * options)47*5e7646d2SAndroid Build Coastguard Worker cupsMarkOptions(
48*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t    *ppd,			/* I - PPD file */
49*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of options */
50*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options)		/* I - Options */
51*5e7646d2SAndroid Build Coastguard Worker {
52*5e7646d2SAndroid Build Coastguard Worker   int		i, j;			/* Looping vars */
53*5e7646d2SAndroid Build Coastguard Worker   char		*ptr,			/* Pointer into string */
54*5e7646d2SAndroid Build Coastguard Worker 		s[255];			/* Temporary string */
55*5e7646d2SAndroid Build Coastguard Worker   const char	*val,			/* Pointer into value */
56*5e7646d2SAndroid Build Coastguard Worker 		*media,			/* media option */
57*5e7646d2SAndroid Build Coastguard Worker 		*output_bin,		/* output-bin option */
58*5e7646d2SAndroid Build Coastguard Worker 		*page_size,		/* PageSize option */
59*5e7646d2SAndroid Build Coastguard Worker 		*ppd_keyword,		/* PPD keyword */
60*5e7646d2SAndroid Build Coastguard Worker 		*print_color_mode,	/* print-color-mode option */
61*5e7646d2SAndroid Build Coastguard Worker 		*print_quality,		/* print-quality option */
62*5e7646d2SAndroid Build Coastguard Worker 		*sides;			/* sides option */
63*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*optptr;		/* Current option */
64*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t	*attr;			/* PPD attribute */
65*5e7646d2SAndroid Build Coastguard Worker   _ppd_cache_t	*cache;			/* PPD cache and mapping data */
66*5e7646d2SAndroid Build Coastguard Worker 
67*5e7646d2SAndroid Build Coastguard Worker 
68*5e7646d2SAndroid Build Coastguard Worker  /*
69*5e7646d2SAndroid Build Coastguard Worker   * Check arguments...
70*5e7646d2SAndroid Build Coastguard Worker   */
71*5e7646d2SAndroid Build Coastguard Worker 
72*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || num_options <= 0 || !options)
73*5e7646d2SAndroid Build Coastguard Worker     return (0);
74*5e7646d2SAndroid Build Coastguard Worker 
75*5e7646d2SAndroid Build Coastguard Worker   ppd_debug_marked(ppd, "Before...");
76*5e7646d2SAndroid Build Coastguard Worker 
77*5e7646d2SAndroid Build Coastguard Worker  /*
78*5e7646d2SAndroid Build Coastguard Worker   * Do special handling for finishings, media, output-bin, output-mode,
79*5e7646d2SAndroid Build Coastguard Worker   * print-color-mode, print-quality, and PageSize...
80*5e7646d2SAndroid Build Coastguard Worker   */
81*5e7646d2SAndroid Build Coastguard Worker 
82*5e7646d2SAndroid Build Coastguard Worker   media         = cupsGetOption("media", num_options, options);
83*5e7646d2SAndroid Build Coastguard Worker   output_bin    = cupsGetOption("output-bin", num_options, options);
84*5e7646d2SAndroid Build Coastguard Worker   page_size     = cupsGetOption("PageSize", num_options, options);
85*5e7646d2SAndroid Build Coastguard Worker   print_quality = cupsGetOption("print-quality", num_options, options);
86*5e7646d2SAndroid Build Coastguard Worker   sides         = cupsGetOption("sides", num_options, options);
87*5e7646d2SAndroid Build Coastguard Worker 
88*5e7646d2SAndroid Build Coastguard Worker   if ((print_color_mode = cupsGetOption("print-color-mode", num_options,
89*5e7646d2SAndroid Build Coastguard Worker                                         options)) == NULL)
90*5e7646d2SAndroid Build Coastguard Worker     print_color_mode = cupsGetOption("output-mode", num_options, options);
91*5e7646d2SAndroid Build Coastguard Worker 
92*5e7646d2SAndroid Build Coastguard Worker   if ((media || output_bin || print_color_mode || print_quality || sides) &&
93*5e7646d2SAndroid Build Coastguard Worker       !ppd->cache)
94*5e7646d2SAndroid Build Coastguard Worker   {
95*5e7646d2SAndroid Build Coastguard Worker    /*
96*5e7646d2SAndroid Build Coastguard Worker     * Load PPD cache and mapping data as needed...
97*5e7646d2SAndroid Build Coastguard Worker     */
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker     ppd->cache = _ppdCacheCreateWithPPD(ppd);
100*5e7646d2SAndroid Build Coastguard Worker   }
101*5e7646d2SAndroid Build Coastguard Worker 
102*5e7646d2SAndroid Build Coastguard Worker   cache = ppd->cache;
103*5e7646d2SAndroid Build Coastguard Worker 
104*5e7646d2SAndroid Build Coastguard Worker   if (media)
105*5e7646d2SAndroid Build Coastguard Worker   {
106*5e7646d2SAndroid Build Coastguard Worker    /*
107*5e7646d2SAndroid Build Coastguard Worker     * Loop through the option string, separating it at commas and marking each
108*5e7646d2SAndroid Build Coastguard Worker     * individual option as long as the corresponding PPD option (PageSize,
109*5e7646d2SAndroid Build Coastguard Worker     * InputSlot, etc.) is not also set.
110*5e7646d2SAndroid Build Coastguard Worker     *
111*5e7646d2SAndroid Build Coastguard Worker     * For PageSize, we also check for an empty option value since some versions
112*5e7646d2SAndroid Build Coastguard Worker     * of macOS use it to specify auto-selection of the media based solely on
113*5e7646d2SAndroid Build Coastguard Worker     * the size.
114*5e7646d2SAndroid Build Coastguard Worker     */
115*5e7646d2SAndroid Build Coastguard Worker 
116*5e7646d2SAndroid Build Coastguard Worker     for (val = media; *val;)
117*5e7646d2SAndroid Build Coastguard Worker     {
118*5e7646d2SAndroid Build Coastguard Worker      /*
119*5e7646d2SAndroid Build Coastguard Worker       * Extract the sub-option from the string...
120*5e7646d2SAndroid Build Coastguard Worker       */
121*5e7646d2SAndroid Build Coastguard Worker 
122*5e7646d2SAndroid Build Coastguard Worker       for (ptr = s; *val && *val != ',' && (size_t)(ptr - s) < (sizeof(s) - 1);)
123*5e7646d2SAndroid Build Coastguard Worker 	*ptr++ = *val++;
124*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = '\0';
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker       if (*val == ',')
127*5e7646d2SAndroid Build Coastguard Worker 	val ++;
128*5e7646d2SAndroid Build Coastguard Worker 
129*5e7646d2SAndroid Build Coastguard Worker      /*
130*5e7646d2SAndroid Build Coastguard Worker       * Mark it...
131*5e7646d2SAndroid Build Coastguard Worker       */
132*5e7646d2SAndroid Build Coastguard Worker 
133*5e7646d2SAndroid Build Coastguard Worker       if (!page_size || !page_size[0])
134*5e7646d2SAndroid Build Coastguard Worker       {
135*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strncasecmp(s, "Custom.", 7) || ppdPageSize(ppd, s))
136*5e7646d2SAndroid Build Coastguard Worker           ppd_mark_option(ppd, "PageSize", s);
137*5e7646d2SAndroid Build Coastguard Worker         else if ((ppd_keyword = _ppdCacheGetPageSize(cache, NULL, s, NULL)) != NULL)
138*5e7646d2SAndroid Build Coastguard Worker 	  ppd_mark_option(ppd, "PageSize", ppd_keyword);
139*5e7646d2SAndroid Build Coastguard Worker       }
140*5e7646d2SAndroid Build Coastguard Worker 
141*5e7646d2SAndroid Build Coastguard Worker       if (cache && cache->source_option &&
142*5e7646d2SAndroid Build Coastguard Worker           !cupsGetOption(cache->source_option, num_options, options) &&
143*5e7646d2SAndroid Build Coastguard Worker 	  (ppd_keyword = _ppdCacheGetInputSlot(cache, NULL, s)) != NULL)
144*5e7646d2SAndroid Build Coastguard Worker 	ppd_mark_option(ppd, cache->source_option, ppd_keyword);
145*5e7646d2SAndroid Build Coastguard Worker 
146*5e7646d2SAndroid Build Coastguard Worker       if (!cupsGetOption("MediaType", num_options, options) &&
147*5e7646d2SAndroid Build Coastguard Worker 	  (ppd_keyword = _ppdCacheGetMediaType(cache, NULL, s)) != NULL)
148*5e7646d2SAndroid Build Coastguard Worker 	ppd_mark_option(ppd, "MediaType", ppd_keyword);
149*5e7646d2SAndroid Build Coastguard Worker     }
150*5e7646d2SAndroid Build Coastguard Worker   }
151*5e7646d2SAndroid Build Coastguard Worker 
152*5e7646d2SAndroid Build Coastguard Worker   if (cache)
153*5e7646d2SAndroid Build Coastguard Worker   {
154*5e7646d2SAndroid Build Coastguard Worker     if (!cupsGetOption("com.apple.print.DocumentTicket.PMSpoolFormat",
155*5e7646d2SAndroid Build Coastguard Worker                        num_options, options) &&
156*5e7646d2SAndroid Build Coastguard Worker         !cupsGetOption("APPrinterPreset", num_options, options) &&
157*5e7646d2SAndroid Build Coastguard Worker         (print_color_mode || print_quality))
158*5e7646d2SAndroid Build Coastguard Worker     {
159*5e7646d2SAndroid Build Coastguard Worker      /*
160*5e7646d2SAndroid Build Coastguard Worker       * Map output-mode and print-quality to a preset...
161*5e7646d2SAndroid Build Coastguard Worker       */
162*5e7646d2SAndroid Build Coastguard Worker 
163*5e7646d2SAndroid Build Coastguard Worker       _pwg_print_color_mode_t	pwg_pcm;/* print-color-mode index */
164*5e7646d2SAndroid Build Coastguard Worker       _pwg_print_quality_t	pwg_pq;	/* print-quality index */
165*5e7646d2SAndroid Build Coastguard Worker       cups_option_t		*preset;/* Current preset option */
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker       if (print_color_mode && !strcmp(print_color_mode, "monochrome"))
168*5e7646d2SAndroid Build Coastguard Worker 	pwg_pcm = _PWG_PRINT_COLOR_MODE_MONOCHROME;
169*5e7646d2SAndroid Build Coastguard Worker       else
170*5e7646d2SAndroid Build Coastguard Worker 	pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
171*5e7646d2SAndroid Build Coastguard Worker 
172*5e7646d2SAndroid Build Coastguard Worker       if (print_quality)
173*5e7646d2SAndroid Build Coastguard Worker       {
174*5e7646d2SAndroid Build Coastguard Worker 	pwg_pq = (_pwg_print_quality_t)(atoi(print_quality) - IPP_QUALITY_DRAFT);
175*5e7646d2SAndroid Build Coastguard Worker 	if (pwg_pq < _PWG_PRINT_QUALITY_DRAFT)
176*5e7646d2SAndroid Build Coastguard Worker 	  pwg_pq = _PWG_PRINT_QUALITY_DRAFT;
177*5e7646d2SAndroid Build Coastguard Worker 	else if (pwg_pq > _PWG_PRINT_QUALITY_HIGH)
178*5e7646d2SAndroid Build Coastguard Worker 	  pwg_pq = _PWG_PRINT_QUALITY_HIGH;
179*5e7646d2SAndroid Build Coastguard Worker       }
180*5e7646d2SAndroid Build Coastguard Worker       else
181*5e7646d2SAndroid Build Coastguard Worker 	pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker       if (cache->num_presets[pwg_pcm][pwg_pq] == 0)
184*5e7646d2SAndroid Build Coastguard Worker       {
185*5e7646d2SAndroid Build Coastguard Worker        /*
186*5e7646d2SAndroid Build Coastguard Worker 	* Try to find a preset that works so that we maximize the chances of us
187*5e7646d2SAndroid Build Coastguard Worker 	* getting a good print using IPP attributes.
188*5e7646d2SAndroid Build Coastguard Worker 	*/
189*5e7646d2SAndroid Build Coastguard Worker 
190*5e7646d2SAndroid Build Coastguard Worker 	if (cache->num_presets[pwg_pcm][_PWG_PRINT_QUALITY_NORMAL] > 0)
191*5e7646d2SAndroid Build Coastguard Worker 	  pwg_pq = _PWG_PRINT_QUALITY_NORMAL;
192*5e7646d2SAndroid Build Coastguard Worker 	else if (cache->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_pq] > 0)
193*5e7646d2SAndroid Build Coastguard Worker 	  pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
194*5e7646d2SAndroid Build Coastguard Worker 	else
195*5e7646d2SAndroid Build Coastguard Worker 	{
196*5e7646d2SAndroid Build Coastguard Worker 	  pwg_pq  = _PWG_PRINT_QUALITY_NORMAL;
197*5e7646d2SAndroid Build Coastguard Worker 	  pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR;
198*5e7646d2SAndroid Build Coastguard Worker 	}
199*5e7646d2SAndroid Build Coastguard Worker       }
200*5e7646d2SAndroid Build Coastguard Worker 
201*5e7646d2SAndroid Build Coastguard Worker       if (cache->num_presets[pwg_pcm][pwg_pq] > 0)
202*5e7646d2SAndroid Build Coastguard Worker       {
203*5e7646d2SAndroid Build Coastguard Worker        /*
204*5e7646d2SAndroid Build Coastguard Worker 	* Copy the preset options as long as the corresponding names are not
205*5e7646d2SAndroid Build Coastguard Worker 	* already defined in the IPP request...
206*5e7646d2SAndroid Build Coastguard Worker 	*/
207*5e7646d2SAndroid Build Coastguard Worker 
208*5e7646d2SAndroid Build Coastguard Worker 	for (i = cache->num_presets[pwg_pcm][pwg_pq],
209*5e7646d2SAndroid Build Coastguard Worker 		 preset = cache->presets[pwg_pcm][pwg_pq];
210*5e7646d2SAndroid Build Coastguard Worker 	     i > 0;
211*5e7646d2SAndroid Build Coastguard Worker 	     i --, preset ++)
212*5e7646d2SAndroid Build Coastguard Worker 	{
213*5e7646d2SAndroid Build Coastguard Worker 	  if (!cupsGetOption(preset->name, num_options, options))
214*5e7646d2SAndroid Build Coastguard Worker 	    ppd_mark_option(ppd, preset->name, preset->value);
215*5e7646d2SAndroid Build Coastguard Worker 	}
216*5e7646d2SAndroid Build Coastguard Worker       }
217*5e7646d2SAndroid Build Coastguard Worker     }
218*5e7646d2SAndroid Build Coastguard Worker 
219*5e7646d2SAndroid Build Coastguard Worker     if (output_bin && !cupsGetOption("OutputBin", num_options, options) &&
220*5e7646d2SAndroid Build Coastguard Worker 	(ppd_keyword = _ppdCacheGetOutputBin(cache, output_bin)) != NULL)
221*5e7646d2SAndroid Build Coastguard Worker     {
222*5e7646d2SAndroid Build Coastguard Worker      /*
223*5e7646d2SAndroid Build Coastguard Worker       * Map output-bin to OutputBin...
224*5e7646d2SAndroid Build Coastguard Worker       */
225*5e7646d2SAndroid Build Coastguard Worker 
226*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "OutputBin", ppd_keyword);
227*5e7646d2SAndroid Build Coastguard Worker     }
228*5e7646d2SAndroid Build Coastguard Worker 
229*5e7646d2SAndroid Build Coastguard Worker     if (sides && cache->sides_option &&
230*5e7646d2SAndroid Build Coastguard Worker         !cupsGetOption(cache->sides_option, num_options, options))
231*5e7646d2SAndroid Build Coastguard Worker     {
232*5e7646d2SAndroid Build Coastguard Worker      /*
233*5e7646d2SAndroid Build Coastguard Worker       * Map sides to duplex option...
234*5e7646d2SAndroid Build Coastguard Worker       */
235*5e7646d2SAndroid Build Coastguard Worker 
236*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(sides, "one-sided") && cache->sides_1sided)
237*5e7646d2SAndroid Build Coastguard Worker         ppd_mark_option(ppd, cache->sides_option, cache->sides_1sided);
238*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(sides, "two-sided-long-edge") &&
239*5e7646d2SAndroid Build Coastguard Worker                cache->sides_2sided_long)
240*5e7646d2SAndroid Build Coastguard Worker         ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_long);
241*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(sides, "two-sided-short-edge") &&
242*5e7646d2SAndroid Build Coastguard Worker                cache->sides_2sided_short)
243*5e7646d2SAndroid Build Coastguard Worker         ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_short);
244*5e7646d2SAndroid Build Coastguard Worker     }
245*5e7646d2SAndroid Build Coastguard Worker   }
246*5e7646d2SAndroid Build Coastguard Worker 
247*5e7646d2SAndroid Build Coastguard Worker  /*
248*5e7646d2SAndroid Build Coastguard Worker   * Mark other options...
249*5e7646d2SAndroid Build Coastguard Worker   */
250*5e7646d2SAndroid Build Coastguard Worker 
251*5e7646d2SAndroid Build Coastguard Worker   for (i = num_options, optptr = options; i > 0; i --, optptr ++)
252*5e7646d2SAndroid Build Coastguard Worker   {
253*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(optptr->name, "media") ||
254*5e7646d2SAndroid Build Coastguard Worker         !_cups_strcasecmp(optptr->name, "output-bin") ||
255*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(optptr->name, "output-mode") ||
256*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(optptr->name, "print-quality") ||
257*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(optptr->name, "sides"))
258*5e7646d2SAndroid Build Coastguard Worker       continue;
259*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(optptr->name, "resolution") ||
260*5e7646d2SAndroid Build Coastguard Worker              !_cups_strcasecmp(optptr->name, "printer-resolution"))
261*5e7646d2SAndroid Build Coastguard Worker     {
262*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "Resolution", optptr->value);
263*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "SetResolution", optptr->value);
264*5e7646d2SAndroid Build Coastguard Worker       	/* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
265*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "JCLResolution", optptr->value);
266*5e7646d2SAndroid Build Coastguard Worker       	/* HP */
267*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "CNRes_PGP", optptr->value);
268*5e7646d2SAndroid Build Coastguard Worker       	/* Canon */
269*5e7646d2SAndroid Build Coastguard Worker     }
270*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(optptr->name, "multiple-document-handling"))
271*5e7646d2SAndroid Build Coastguard Worker     {
272*5e7646d2SAndroid Build Coastguard Worker       if (!cupsGetOption("Collate", num_options, options) &&
273*5e7646d2SAndroid Build Coastguard Worker           ppdFindOption(ppd, "Collate"))
274*5e7646d2SAndroid Build Coastguard Worker       {
275*5e7646d2SAndroid Build Coastguard Worker         if (_cups_strcasecmp(optptr->value, "separate-documents-uncollated-copies"))
276*5e7646d2SAndroid Build Coastguard Worker 	  ppd_mark_option(ppd, "Collate", "True");
277*5e7646d2SAndroid Build Coastguard Worker 	else
278*5e7646d2SAndroid Build Coastguard Worker 	  ppd_mark_option(ppd, "Collate", "False");
279*5e7646d2SAndroid Build Coastguard Worker       }
280*5e7646d2SAndroid Build Coastguard Worker     }
281*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(optptr->name, "finishings"))
282*5e7646d2SAndroid Build Coastguard Worker     {
283*5e7646d2SAndroid Build Coastguard Worker      /*
284*5e7646d2SAndroid Build Coastguard Worker       * Lookup cupsIPPFinishings attributes for each value...
285*5e7646d2SAndroid Build Coastguard Worker       */
286*5e7646d2SAndroid Build Coastguard Worker 
287*5e7646d2SAndroid Build Coastguard Worker       for (ptr = optptr->value; *ptr;)
288*5e7646d2SAndroid Build Coastguard Worker       {
289*5e7646d2SAndroid Build Coastguard Worker        /*
290*5e7646d2SAndroid Build Coastguard Worker         * Get the next finishings number...
291*5e7646d2SAndroid Build Coastguard Worker 	*/
292*5e7646d2SAndroid Build Coastguard Worker 
293*5e7646d2SAndroid Build Coastguard Worker         if (!isdigit(*ptr & 255))
294*5e7646d2SAndroid Build Coastguard Worker 	  break;
295*5e7646d2SAndroid Build Coastguard Worker 
296*5e7646d2SAndroid Build Coastguard Worker         if ((j = (int)strtol(ptr, &ptr, 10)) < 3)
297*5e7646d2SAndroid Build Coastguard Worker 	  break;
298*5e7646d2SAndroid Build Coastguard Worker 
299*5e7646d2SAndroid Build Coastguard Worker        /*
300*5e7646d2SAndroid Build Coastguard Worker         * Skip separator as needed...
301*5e7646d2SAndroid Build Coastguard Worker 	*/
302*5e7646d2SAndroid Build Coastguard Worker 
303*5e7646d2SAndroid Build Coastguard Worker         if (*ptr == ',')
304*5e7646d2SAndroid Build Coastguard Worker 	  ptr ++;
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker        /*
307*5e7646d2SAndroid Build Coastguard Worker         * Look it up in the PPD file...
308*5e7646d2SAndroid Build Coastguard Worker 	*/
309*5e7646d2SAndroid Build Coastguard Worker 
310*5e7646d2SAndroid Build Coastguard Worker 	snprintf(s, sizeof(s), "%d", j);
311*5e7646d2SAndroid Build Coastguard Worker 
312*5e7646d2SAndroid Build Coastguard Worker         if ((attr = ppdFindAttr(ppd, "cupsIPPFinishings", s)) == NULL)
313*5e7646d2SAndroid Build Coastguard Worker 	  continue;
314*5e7646d2SAndroid Build Coastguard Worker 
315*5e7646d2SAndroid Build Coastguard Worker        /*
316*5e7646d2SAndroid Build Coastguard Worker         * Apply "*Option Choice" settings from the attribute value...
317*5e7646d2SAndroid Build Coastguard Worker 	*/
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker         ppd_mark_choices(ppd, attr->value);
320*5e7646d2SAndroid Build Coastguard Worker       }
321*5e7646d2SAndroid Build Coastguard Worker     }
322*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(optptr->name, "APPrinterPreset"))
323*5e7646d2SAndroid Build Coastguard Worker     {
324*5e7646d2SAndroid Build Coastguard Worker      /*
325*5e7646d2SAndroid Build Coastguard Worker       * Lookup APPrinterPreset value...
326*5e7646d2SAndroid Build Coastguard Worker       */
327*5e7646d2SAndroid Build Coastguard Worker 
328*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ppdFindAttr(ppd, "APPrinterPreset", optptr->value)) != NULL)
329*5e7646d2SAndroid Build Coastguard Worker       {
330*5e7646d2SAndroid Build Coastguard Worker        /*
331*5e7646d2SAndroid Build Coastguard Worker         * Apply "*Option Choice" settings from the attribute value...
332*5e7646d2SAndroid Build Coastguard Worker 	*/
333*5e7646d2SAndroid Build Coastguard Worker 
334*5e7646d2SAndroid Build Coastguard Worker         ppd_mark_choices(ppd, attr->value);
335*5e7646d2SAndroid Build Coastguard Worker       }
336*5e7646d2SAndroid Build Coastguard Worker     }
337*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(optptr->name, "mirror"))
338*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "MirrorPrint", optptr->value);
339*5e7646d2SAndroid Build Coastguard Worker     else
340*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, optptr->name, optptr->value);
341*5e7646d2SAndroid Build Coastguard Worker   }
342*5e7646d2SAndroid Build Coastguard Worker 
343*5e7646d2SAndroid Build Coastguard Worker   if (print_quality)
344*5e7646d2SAndroid Build Coastguard Worker   {
345*5e7646d2SAndroid Build Coastguard Worker     int pq = atoi(print_quality);       /* print-quaity value */
346*5e7646d2SAndroid Build Coastguard Worker 
347*5e7646d2SAndroid Build Coastguard Worker     if (pq == IPP_QUALITY_DRAFT)
348*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "cupsPrintQuality", "Draft");
349*5e7646d2SAndroid Build Coastguard Worker     else if (pq == IPP_QUALITY_HIGH)
350*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "cupsPrintQuality", "High");
351*5e7646d2SAndroid Build Coastguard Worker     else
352*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, "cupsPrintQuality", "Normal");
353*5e7646d2SAndroid Build Coastguard Worker   }
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker   ppd_debug_marked(ppd, "After...");
356*5e7646d2SAndroid Build Coastguard Worker 
357*5e7646d2SAndroid Build Coastguard Worker   return (ppdConflicts(ppd) > 0);
358*5e7646d2SAndroid Build Coastguard Worker }
359*5e7646d2SAndroid Build Coastguard Worker 
360*5e7646d2SAndroid Build Coastguard Worker 
361*5e7646d2SAndroid Build Coastguard Worker /*
362*5e7646d2SAndroid Build Coastguard Worker  * 'ppdFindChoice()' - Return a pointer to an option choice.
363*5e7646d2SAndroid Build Coastguard Worker  */
364*5e7646d2SAndroid Build Coastguard Worker 
365*5e7646d2SAndroid Build Coastguard Worker ppd_choice_t *				/* O - Choice pointer or @code NULL@ */
ppdFindChoice(ppd_option_t * o,const char * choice)366*5e7646d2SAndroid Build Coastguard Worker ppdFindChoice(ppd_option_t *o,		/* I - Pointer to option */
367*5e7646d2SAndroid Build Coastguard Worker               const char   *choice)	/* I - Name of choice */
368*5e7646d2SAndroid Build Coastguard Worker {
369*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
370*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*c;			/* Current choice */
371*5e7646d2SAndroid Build Coastguard Worker 
372*5e7646d2SAndroid Build Coastguard Worker 
373*5e7646d2SAndroid Build Coastguard Worker   if (!o || !choice)
374*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
375*5e7646d2SAndroid Build Coastguard Worker 
376*5e7646d2SAndroid Build Coastguard Worker   if (choice[0] == '{' || !_cups_strncasecmp(choice, "Custom.", 7))
377*5e7646d2SAndroid Build Coastguard Worker     choice = "Custom";
378*5e7646d2SAndroid Build Coastguard Worker 
379*5e7646d2SAndroid Build Coastguard Worker   for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
380*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(c->choice, choice))
381*5e7646d2SAndroid Build Coastguard Worker       return (c);
382*5e7646d2SAndroid Build Coastguard Worker 
383*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
384*5e7646d2SAndroid Build Coastguard Worker }
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker 
387*5e7646d2SAndroid Build Coastguard Worker /*
388*5e7646d2SAndroid Build Coastguard Worker  * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
389*5e7646d2SAndroid Build Coastguard Worker  */
390*5e7646d2SAndroid Build Coastguard Worker 
391*5e7646d2SAndroid Build Coastguard Worker ppd_choice_t *				/* O - Pointer to choice or @code NULL@ */
ppdFindMarkedChoice(ppd_file_t * ppd,const char * option)392*5e7646d2SAndroid Build Coastguard Worker ppdFindMarkedChoice(ppd_file_t *ppd,	/* I - PPD file */
393*5e7646d2SAndroid Build Coastguard Worker                     const char *option)	/* I - Keyword/option name */
394*5e7646d2SAndroid Build Coastguard Worker {
395*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	key,			/* Search key for choice */
396*5e7646d2SAndroid Build Coastguard Worker 		*marked;		/* Marked choice */
397*5e7646d2SAndroid Build Coastguard Worker 
398*5e7646d2SAndroid Build Coastguard Worker 
399*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ppdFindMarkedChoice(ppd=%p, option=\"%s\")", ppd, option));
400*5e7646d2SAndroid Build Coastguard Worker 
401*5e7646d2SAndroid Build Coastguard Worker   if ((key.option = ppdFindOption(ppd, option)) == NULL)
402*5e7646d2SAndroid Build Coastguard Worker   {
403*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("3ppdFindMarkedChoice: Option not found, returning NULL");
404*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
405*5e7646d2SAndroid Build Coastguard Worker   }
406*5e7646d2SAndroid Build Coastguard Worker 
407*5e7646d2SAndroid Build Coastguard Worker   marked = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key);
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3ppdFindMarkedChoice: Returning %p(%s)...", marked,
410*5e7646d2SAndroid Build Coastguard Worker                 marked ? marked->choice : "NULL"));
411*5e7646d2SAndroid Build Coastguard Worker 
412*5e7646d2SAndroid Build Coastguard Worker   return (marked);
413*5e7646d2SAndroid Build Coastguard Worker }
414*5e7646d2SAndroid Build Coastguard Worker 
415*5e7646d2SAndroid Build Coastguard Worker 
416*5e7646d2SAndroid Build Coastguard Worker /*
417*5e7646d2SAndroid Build Coastguard Worker  * 'ppdFindOption()' - Return a pointer to the specified option.
418*5e7646d2SAndroid Build Coastguard Worker  */
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *				/* O - Pointer to option or @code NULL@ */
ppdFindOption(ppd_file_t * ppd,const char * option)421*5e7646d2SAndroid Build Coastguard Worker ppdFindOption(ppd_file_t *ppd,		/* I - PPD file data */
422*5e7646d2SAndroid Build Coastguard Worker               const char *option)	/* I - Option/Keyword name */
423*5e7646d2SAndroid Build Coastguard Worker {
424*5e7646d2SAndroid Build Coastguard Worker  /*
425*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
426*5e7646d2SAndroid Build Coastguard Worker   */
427*5e7646d2SAndroid Build Coastguard Worker 
428*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !option)
429*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
430*5e7646d2SAndroid Build Coastguard Worker 
431*5e7646d2SAndroid Build Coastguard Worker   if (ppd->options)
432*5e7646d2SAndroid Build Coastguard Worker   {
433*5e7646d2SAndroid Build Coastguard Worker    /*
434*5e7646d2SAndroid Build Coastguard Worker     * Search in the array...
435*5e7646d2SAndroid Build Coastguard Worker     */
436*5e7646d2SAndroid Build Coastguard Worker 
437*5e7646d2SAndroid Build Coastguard Worker     ppd_option_t	key;		/* Option search key */
438*5e7646d2SAndroid Build Coastguard Worker 
439*5e7646d2SAndroid Build Coastguard Worker 
440*5e7646d2SAndroid Build Coastguard Worker     strlcpy(key.keyword, option, sizeof(key.keyword));
441*5e7646d2SAndroid Build Coastguard Worker 
442*5e7646d2SAndroid Build Coastguard Worker     return ((ppd_option_t *)cupsArrayFind(ppd->options, &key));
443*5e7646d2SAndroid Build Coastguard Worker   }
444*5e7646d2SAndroid Build Coastguard Worker   else
445*5e7646d2SAndroid Build Coastguard Worker   {
446*5e7646d2SAndroid Build Coastguard Worker    /*
447*5e7646d2SAndroid Build Coastguard Worker     * Search in each group...
448*5e7646d2SAndroid Build Coastguard Worker     */
449*5e7646d2SAndroid Build Coastguard Worker 
450*5e7646d2SAndroid Build Coastguard Worker     int			i, j;		/* Looping vars */
451*5e7646d2SAndroid Build Coastguard Worker     ppd_group_t		*group;		/* Current group */
452*5e7646d2SAndroid Build Coastguard Worker     ppd_option_t	*optptr;	/* Current option */
453*5e7646d2SAndroid Build Coastguard Worker 
454*5e7646d2SAndroid Build Coastguard Worker 
455*5e7646d2SAndroid Build Coastguard Worker     for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
456*5e7646d2SAndroid Build Coastguard Worker       for (j = group->num_options, optptr = group->options;
457*5e7646d2SAndroid Build Coastguard Worker            j > 0;
458*5e7646d2SAndroid Build Coastguard Worker 	   j --, optptr ++)
459*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strcasecmp(optptr->keyword, option))
460*5e7646d2SAndroid Build Coastguard Worker 	  return (optptr);
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
463*5e7646d2SAndroid Build Coastguard Worker   }
464*5e7646d2SAndroid Build Coastguard Worker }
465*5e7646d2SAndroid Build Coastguard Worker 
466*5e7646d2SAndroid Build Coastguard Worker 
467*5e7646d2SAndroid Build Coastguard Worker /*
468*5e7646d2SAndroid Build Coastguard Worker  * 'ppdIsMarked()' - Check to see if an option is marked.
469*5e7646d2SAndroid Build Coastguard Worker  */
470*5e7646d2SAndroid Build Coastguard Worker 
471*5e7646d2SAndroid Build Coastguard Worker int					/* O - Non-zero if option is marked */
ppdIsMarked(ppd_file_t * ppd,const char * option,const char * choice)472*5e7646d2SAndroid Build Coastguard Worker ppdIsMarked(ppd_file_t *ppd,		/* I - PPD file data */
473*5e7646d2SAndroid Build Coastguard Worker             const char *option,		/* I - Option/Keyword name */
474*5e7646d2SAndroid Build Coastguard Worker             const char *choice)		/* I - Choice name */
475*5e7646d2SAndroid Build Coastguard Worker {
476*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	key,			/* Search key */
477*5e7646d2SAndroid Build Coastguard Worker 		*c;			/* Choice pointer */
478*5e7646d2SAndroid Build Coastguard Worker 
479*5e7646d2SAndroid Build Coastguard Worker 
480*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
481*5e7646d2SAndroid Build Coastguard Worker     return (0);
482*5e7646d2SAndroid Build Coastguard Worker 
483*5e7646d2SAndroid Build Coastguard Worker   if ((key.option = ppdFindOption(ppd, option)) == NULL)
484*5e7646d2SAndroid Build Coastguard Worker     return (0);
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker   if ((c = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) == NULL)
487*5e7646d2SAndroid Build Coastguard Worker     return (0);
488*5e7646d2SAndroid Build Coastguard Worker 
489*5e7646d2SAndroid Build Coastguard Worker   return (!strcmp(c->choice, choice));
490*5e7646d2SAndroid Build Coastguard Worker }
491*5e7646d2SAndroid Build Coastguard Worker 
492*5e7646d2SAndroid Build Coastguard Worker 
493*5e7646d2SAndroid Build Coastguard Worker /*
494*5e7646d2SAndroid Build Coastguard Worker  * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
495*5e7646d2SAndroid Build Coastguard Worker  */
496*5e7646d2SAndroid Build Coastguard Worker 
497*5e7646d2SAndroid Build Coastguard Worker void
ppdMarkDefaults(ppd_file_t * ppd)498*5e7646d2SAndroid Build Coastguard Worker ppdMarkDefaults(ppd_file_t *ppd)	/* I - PPD file record */
499*5e7646d2SAndroid Build Coastguard Worker {
500*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping variables */
501*5e7646d2SAndroid Build Coastguard Worker   ppd_group_t	*g;			/* Current group */
502*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*c;			/* Current choice */
503*5e7646d2SAndroid Build Coastguard Worker 
504*5e7646d2SAndroid Build Coastguard Worker 
505*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
506*5e7646d2SAndroid Build Coastguard Worker     return;
507*5e7646d2SAndroid Build Coastguard Worker 
508*5e7646d2SAndroid Build Coastguard Worker  /*
509*5e7646d2SAndroid Build Coastguard Worker   * Clean out the marked array...
510*5e7646d2SAndroid Build Coastguard Worker   */
511*5e7646d2SAndroid Build Coastguard Worker 
512*5e7646d2SAndroid Build Coastguard Worker   for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked);
513*5e7646d2SAndroid Build Coastguard Worker        c;
514*5e7646d2SAndroid Build Coastguard Worker        c = (ppd_choice_t *)cupsArrayNext(ppd->marked))
515*5e7646d2SAndroid Build Coastguard Worker   {
516*5e7646d2SAndroid Build Coastguard Worker     cupsArrayRemove(ppd->marked, c);
517*5e7646d2SAndroid Build Coastguard Worker     c->marked = 0;
518*5e7646d2SAndroid Build Coastguard Worker   }
519*5e7646d2SAndroid Build Coastguard Worker 
520*5e7646d2SAndroid Build Coastguard Worker  /*
521*5e7646d2SAndroid Build Coastguard Worker   * Then repopulate it with the defaults...
522*5e7646d2SAndroid Build Coastguard Worker   */
523*5e7646d2SAndroid Build Coastguard Worker 
524*5e7646d2SAndroid Build Coastguard Worker   for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
525*5e7646d2SAndroid Build Coastguard Worker     ppd_defaults(ppd, g);
526*5e7646d2SAndroid Build Coastguard Worker 
527*5e7646d2SAndroid Build Coastguard Worker  /*
528*5e7646d2SAndroid Build Coastguard Worker   * Finally, tag any conflicts (API compatibility) once at the end.
529*5e7646d2SAndroid Build Coastguard Worker   */
530*5e7646d2SAndroid Build Coastguard Worker 
531*5e7646d2SAndroid Build Coastguard Worker   ppdConflicts(ppd);
532*5e7646d2SAndroid Build Coastguard Worker }
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker 
535*5e7646d2SAndroid Build Coastguard Worker /*
536*5e7646d2SAndroid Build Coastguard Worker  * 'ppdMarkOption()' - Mark an option in a PPD file and return the number of
537*5e7646d2SAndroid Build Coastguard Worker  *                     conflicts.
538*5e7646d2SAndroid Build Coastguard Worker  */
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of conflicts */
ppdMarkOption(ppd_file_t * ppd,const char * option,const char * choice)541*5e7646d2SAndroid Build Coastguard Worker ppdMarkOption(ppd_file_t *ppd,		/* I - PPD file record */
542*5e7646d2SAndroid Build Coastguard Worker               const char *option,	/* I - Keyword */
543*5e7646d2SAndroid Build Coastguard Worker               const char *choice)	/* I - Option name */
544*5e7646d2SAndroid Build Coastguard Worker {
545*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")",
546*5e7646d2SAndroid Build Coastguard Worker         	ppd, option, choice));
547*5e7646d2SAndroid Build Coastguard Worker 
548*5e7646d2SAndroid Build Coastguard Worker  /*
549*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
550*5e7646d2SAndroid Build Coastguard Worker   */
551*5e7646d2SAndroid Build Coastguard Worker 
552*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !option || !choice)
553*5e7646d2SAndroid Build Coastguard Worker     return (0);
554*5e7646d2SAndroid Build Coastguard Worker 
555*5e7646d2SAndroid Build Coastguard Worker  /*
556*5e7646d2SAndroid Build Coastguard Worker   * Mark the option...
557*5e7646d2SAndroid Build Coastguard Worker   */
558*5e7646d2SAndroid Build Coastguard Worker 
559*5e7646d2SAndroid Build Coastguard Worker   ppd_mark_option(ppd, option, choice);
560*5e7646d2SAndroid Build Coastguard Worker 
561*5e7646d2SAndroid Build Coastguard Worker  /*
562*5e7646d2SAndroid Build Coastguard Worker   * Return the number of conflicts...
563*5e7646d2SAndroid Build Coastguard Worker   */
564*5e7646d2SAndroid Build Coastguard Worker 
565*5e7646d2SAndroid Build Coastguard Worker   return (ppdConflicts(ppd));
566*5e7646d2SAndroid Build Coastguard Worker }
567*5e7646d2SAndroid Build Coastguard Worker 
568*5e7646d2SAndroid Build Coastguard Worker 
569*5e7646d2SAndroid Build Coastguard Worker /*
570*5e7646d2SAndroid Build Coastguard Worker  * 'ppdFirstOption()' - Return the first option in the PPD file.
571*5e7646d2SAndroid Build Coastguard Worker  *
572*5e7646d2SAndroid Build Coastguard Worker  * Options are returned from all groups in ascending alphanumeric order.
573*5e7646d2SAndroid Build Coastguard Worker  *
574*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
575*5e7646d2SAndroid Build Coastguard Worker  */
576*5e7646d2SAndroid Build Coastguard Worker 
577*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *				/* O - First option or @code NULL@ */
ppdFirstOption(ppd_file_t * ppd)578*5e7646d2SAndroid Build Coastguard Worker ppdFirstOption(ppd_file_t *ppd)		/* I - PPD file */
579*5e7646d2SAndroid Build Coastguard Worker {
580*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
581*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
582*5e7646d2SAndroid Build Coastguard Worker   else
583*5e7646d2SAndroid Build Coastguard Worker     return ((ppd_option_t *)cupsArrayFirst(ppd->options));
584*5e7646d2SAndroid Build Coastguard Worker }
585*5e7646d2SAndroid Build Coastguard Worker 
586*5e7646d2SAndroid Build Coastguard Worker 
587*5e7646d2SAndroid Build Coastguard Worker /*
588*5e7646d2SAndroid Build Coastguard Worker  * 'ppdNextOption()' - Return the next option in the PPD file.
589*5e7646d2SAndroid Build Coastguard Worker  *
590*5e7646d2SAndroid Build Coastguard Worker  * Options are returned from all groups in ascending alphanumeric order.
591*5e7646d2SAndroid Build Coastguard Worker  *
592*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
593*5e7646d2SAndroid Build Coastguard Worker  */
594*5e7646d2SAndroid Build Coastguard Worker 
595*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *				/* O - Next option or @code NULL@ */
ppdNextOption(ppd_file_t * ppd)596*5e7646d2SAndroid Build Coastguard Worker ppdNextOption(ppd_file_t *ppd)		/* I - PPD file */
597*5e7646d2SAndroid Build Coastguard Worker {
598*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
599*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
600*5e7646d2SAndroid Build Coastguard Worker   else
601*5e7646d2SAndroid Build Coastguard Worker     return ((ppd_option_t *)cupsArrayNext(ppd->options));
602*5e7646d2SAndroid Build Coastguard Worker }
603*5e7646d2SAndroid Build Coastguard Worker 
604*5e7646d2SAndroid Build Coastguard Worker 
605*5e7646d2SAndroid Build Coastguard Worker /*
606*5e7646d2SAndroid Build Coastguard Worker  * '_ppdParseOptions()' - Parse options from a PPD file.
607*5e7646d2SAndroid Build Coastguard Worker  *
608*5e7646d2SAndroid Build Coastguard Worker  * This function looks for strings of the form:
609*5e7646d2SAndroid Build Coastguard Worker  *
610*5e7646d2SAndroid Build Coastguard Worker  *     *option choice ... *optionN choiceN
611*5e7646d2SAndroid Build Coastguard Worker  *     property value ... propertyN valueN
612*5e7646d2SAndroid Build Coastguard Worker  *
613*5e7646d2SAndroid Build Coastguard Worker  * It stops when it finds a string that doesn't match this format.
614*5e7646d2SAndroid Build Coastguard Worker  */
615*5e7646d2SAndroid Build Coastguard Worker 
616*5e7646d2SAndroid Build Coastguard Worker int					/* O  - Number of options */
_ppdParseOptions(const char * s,int num_options,cups_option_t ** options,_ppd_parse_t which)617*5e7646d2SAndroid Build Coastguard Worker _ppdParseOptions(
618*5e7646d2SAndroid Build Coastguard Worker     const char    *s,			/* I  - String to parse */
619*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I  - Number of options */
620*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **options,		/* IO - Options */
621*5e7646d2SAndroid Build Coastguard Worker     _ppd_parse_t  which)		/* I  - What to parse */
622*5e7646d2SAndroid Build Coastguard Worker {
623*5e7646d2SAndroid Build Coastguard Worker   char	option[PPD_MAX_NAME * 2 + 1],	/* Current option/property */
624*5e7646d2SAndroid Build Coastguard Worker 	choice[PPD_MAX_NAME],		/* Current choice/value */
625*5e7646d2SAndroid Build Coastguard Worker 	*ptr;				/* Pointer into option or choice */
626*5e7646d2SAndroid Build Coastguard Worker 
627*5e7646d2SAndroid Build Coastguard Worker 
628*5e7646d2SAndroid Build Coastguard Worker   if (!s)
629*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
630*5e7646d2SAndroid Build Coastguard Worker 
631*5e7646d2SAndroid Build Coastguard Worker  /*
632*5e7646d2SAndroid Build Coastguard Worker   * Read all of the "*Option Choice" and "property value" pairs from the
633*5e7646d2SAndroid Build Coastguard Worker   * string, add them to an options array as we go...
634*5e7646d2SAndroid Build Coastguard Worker   */
635*5e7646d2SAndroid Build Coastguard Worker 
636*5e7646d2SAndroid Build Coastguard Worker   while (*s)
637*5e7646d2SAndroid Build Coastguard Worker   {
638*5e7646d2SAndroid Build Coastguard Worker    /*
639*5e7646d2SAndroid Build Coastguard Worker     * Skip leading whitespace...
640*5e7646d2SAndroid Build Coastguard Worker     */
641*5e7646d2SAndroid Build Coastguard Worker 
642*5e7646d2SAndroid Build Coastguard Worker     while (_cups_isspace(*s))
643*5e7646d2SAndroid Build Coastguard Worker       s ++;
644*5e7646d2SAndroid Build Coastguard Worker 
645*5e7646d2SAndroid Build Coastguard Worker    /*
646*5e7646d2SAndroid Build Coastguard Worker     * Get the option/property name...
647*5e7646d2SAndroid Build Coastguard Worker     */
648*5e7646d2SAndroid Build Coastguard Worker 
649*5e7646d2SAndroid Build Coastguard Worker     ptr = option;
650*5e7646d2SAndroid Build Coastguard Worker     while (*s && !_cups_isspace(*s) && ptr < (option + sizeof(option) - 1))
651*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = *s++;
652*5e7646d2SAndroid Build Coastguard Worker 
653*5e7646d2SAndroid Build Coastguard Worker     if (ptr == s || !_cups_isspace(*s))
654*5e7646d2SAndroid Build Coastguard Worker       break;
655*5e7646d2SAndroid Build Coastguard Worker 
656*5e7646d2SAndroid Build Coastguard Worker     *ptr = '\0';
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker    /*
659*5e7646d2SAndroid Build Coastguard Worker     * Get the choice...
660*5e7646d2SAndroid Build Coastguard Worker     */
661*5e7646d2SAndroid Build Coastguard Worker 
662*5e7646d2SAndroid Build Coastguard Worker     while (_cups_isspace(*s))
663*5e7646d2SAndroid Build Coastguard Worker       s ++;
664*5e7646d2SAndroid Build Coastguard Worker 
665*5e7646d2SAndroid Build Coastguard Worker     if (!*s)
666*5e7646d2SAndroid Build Coastguard Worker       break;
667*5e7646d2SAndroid Build Coastguard Worker 
668*5e7646d2SAndroid Build Coastguard Worker     ptr = choice;
669*5e7646d2SAndroid Build Coastguard Worker     while (*s && !_cups_isspace(*s) && ptr < (choice + sizeof(choice) - 1))
670*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = *s++;
671*5e7646d2SAndroid Build Coastguard Worker 
672*5e7646d2SAndroid Build Coastguard Worker     if (*s && !_cups_isspace(*s))
673*5e7646d2SAndroid Build Coastguard Worker       break;
674*5e7646d2SAndroid Build Coastguard Worker 
675*5e7646d2SAndroid Build Coastguard Worker     *ptr = '\0';
676*5e7646d2SAndroid Build Coastguard Worker 
677*5e7646d2SAndroid Build Coastguard Worker    /*
678*5e7646d2SAndroid Build Coastguard Worker     * Add it to the options array...
679*5e7646d2SAndroid Build Coastguard Worker     */
680*5e7646d2SAndroid Build Coastguard Worker 
681*5e7646d2SAndroid Build Coastguard Worker     if (option[0] == '*' && which != _PPD_PARSE_PROPERTIES)
682*5e7646d2SAndroid Build Coastguard Worker       num_options = cupsAddOption(option + 1, choice, num_options, options);
683*5e7646d2SAndroid Build Coastguard Worker     else if (option[0] != '*' && which != _PPD_PARSE_OPTIONS)
684*5e7646d2SAndroid Build Coastguard Worker       num_options = cupsAddOption(option, choice, num_options, options);
685*5e7646d2SAndroid Build Coastguard Worker   }
686*5e7646d2SAndroid Build Coastguard Worker 
687*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
688*5e7646d2SAndroid Build Coastguard Worker }
689*5e7646d2SAndroid Build Coastguard Worker 
690*5e7646d2SAndroid Build Coastguard Worker 
691*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
692*5e7646d2SAndroid Build Coastguard Worker /*
693*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_debug_marked()' - Output the marked array to stdout...
694*5e7646d2SAndroid Build Coastguard Worker  */
695*5e7646d2SAndroid Build Coastguard Worker 
696*5e7646d2SAndroid Build Coastguard Worker static void
ppd_debug_marked(ppd_file_t * ppd,const char * title)697*5e7646d2SAndroid Build Coastguard Worker ppd_debug_marked(ppd_file_t *ppd,		/* I - PPD file data */
698*5e7646d2SAndroid Build Coastguard Worker              const char *title)		/* I - Title for list */
699*5e7646d2SAndroid Build Coastguard Worker {
700*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*c;			/* Current choice */
701*5e7646d2SAndroid Build Coastguard Worker 
702*5e7646d2SAndroid Build Coastguard Worker 
703*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2cupsMarkOptions: %s", title));
704*5e7646d2SAndroid Build Coastguard Worker 
705*5e7646d2SAndroid Build Coastguard Worker   for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked);
706*5e7646d2SAndroid Build Coastguard Worker        c;
707*5e7646d2SAndroid Build Coastguard Worker        c = (ppd_choice_t *)cupsArrayNext(ppd->marked))
708*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("2cupsMarkOptions: %s=%s", c->option->keyword, c->choice));
709*5e7646d2SAndroid Build Coastguard Worker }
710*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
711*5e7646d2SAndroid Build Coastguard Worker 
712*5e7646d2SAndroid Build Coastguard Worker 
713*5e7646d2SAndroid Build Coastguard Worker /*
714*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
715*5e7646d2SAndroid Build Coastguard Worker  */
716*5e7646d2SAndroid Build Coastguard Worker 
717*5e7646d2SAndroid Build Coastguard Worker static void
ppd_defaults(ppd_file_t * ppd,ppd_group_t * g)718*5e7646d2SAndroid Build Coastguard Worker ppd_defaults(ppd_file_t  *ppd,		/* I - PPD file */
719*5e7646d2SAndroid Build Coastguard Worker              ppd_group_t *g)		/* I - Group to default */
720*5e7646d2SAndroid Build Coastguard Worker {
721*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
722*5e7646d2SAndroid Build Coastguard Worker   ppd_option_t	*o;			/* Current option */
723*5e7646d2SAndroid Build Coastguard Worker   ppd_group_t	*sg;			/* Current sub-group */
724*5e7646d2SAndroid Build Coastguard Worker 
725*5e7646d2SAndroid Build Coastguard Worker 
726*5e7646d2SAndroid Build Coastguard Worker   for (i = g->num_options, o = g->options; i > 0; i --, o ++)
727*5e7646d2SAndroid Build Coastguard Worker     if (_cups_strcasecmp(o->keyword, "PageRegion") != 0)
728*5e7646d2SAndroid Build Coastguard Worker       ppd_mark_option(ppd, o->keyword, o->defchoice);
729*5e7646d2SAndroid Build Coastguard Worker 
730*5e7646d2SAndroid Build Coastguard Worker   for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++)
731*5e7646d2SAndroid Build Coastguard Worker     ppd_defaults(ppd, sg);
732*5e7646d2SAndroid Build Coastguard Worker }
733*5e7646d2SAndroid Build Coastguard Worker 
734*5e7646d2SAndroid Build Coastguard Worker 
735*5e7646d2SAndroid Build Coastguard Worker /*
736*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_mark_choices()' - Mark one or more option choices from a string.
737*5e7646d2SAndroid Build Coastguard Worker  */
738*5e7646d2SAndroid Build Coastguard Worker 
739*5e7646d2SAndroid Build Coastguard Worker static void
ppd_mark_choices(ppd_file_t * ppd,const char * s)740*5e7646d2SAndroid Build Coastguard Worker ppd_mark_choices(ppd_file_t *ppd,	/* I - PPD file */
741*5e7646d2SAndroid Build Coastguard Worker                  const char *s)		/* I - "*Option Choice ..." string */
742*5e7646d2SAndroid Build Coastguard Worker {
743*5e7646d2SAndroid Build Coastguard Worker   int		i,			/* Looping var */
744*5e7646d2SAndroid Build Coastguard Worker 		num_options;		/* Number of options */
745*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*options,		/* Options */
746*5e7646d2SAndroid Build Coastguard Worker 		*option;		/* Current option */
747*5e7646d2SAndroid Build Coastguard Worker 
748*5e7646d2SAndroid Build Coastguard Worker 
749*5e7646d2SAndroid Build Coastguard Worker   if (!s)
750*5e7646d2SAndroid Build Coastguard Worker     return;
751*5e7646d2SAndroid Build Coastguard Worker 
752*5e7646d2SAndroid Build Coastguard Worker   options     = NULL;
753*5e7646d2SAndroid Build Coastguard Worker   num_options = _ppdParseOptions(s, 0, &options, 0);
754*5e7646d2SAndroid Build Coastguard Worker 
755*5e7646d2SAndroid Build Coastguard Worker   for (i = num_options, option = options; i > 0; i --, option ++)
756*5e7646d2SAndroid Build Coastguard Worker     ppd_mark_option(ppd, option->name, option->value);
757*5e7646d2SAndroid Build Coastguard Worker 
758*5e7646d2SAndroid Build Coastguard Worker   cupsFreeOptions(num_options, options);
759*5e7646d2SAndroid Build Coastguard Worker }
760*5e7646d2SAndroid Build Coastguard Worker 
761*5e7646d2SAndroid Build Coastguard Worker 
762*5e7646d2SAndroid Build Coastguard Worker /*
763*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_mark_option()' - Quick mark an option without checking for conflicts.
764*5e7646d2SAndroid Build Coastguard Worker  */
765*5e7646d2SAndroid Build Coastguard Worker 
766*5e7646d2SAndroid Build Coastguard Worker static void
ppd_mark_option(ppd_file_t * ppd,const char * option,const char * choice)767*5e7646d2SAndroid Build Coastguard Worker ppd_mark_option(ppd_file_t *ppd,	/* I - PPD file */
768*5e7646d2SAndroid Build Coastguard Worker                 const char *option,	/* I - Option name */
769*5e7646d2SAndroid Build Coastguard Worker                 const char *choice)	/* I - Choice name */
770*5e7646d2SAndroid Build Coastguard Worker {
771*5e7646d2SAndroid Build Coastguard Worker   int		i, j;			/* Looping vars */
772*5e7646d2SAndroid Build Coastguard Worker   ppd_option_t	*o;			/* Option pointer */
773*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*c,			/* Choice pointer */
774*5e7646d2SAndroid Build Coastguard Worker 		*oldc,			/* Old choice pointer */
775*5e7646d2SAndroid Build Coastguard Worker 		key;			/* Search key for choice */
776*5e7646d2SAndroid Build Coastguard Worker   struct lconv	*loc;			/* Locale data */
777*5e7646d2SAndroid Build Coastguard Worker 
778*5e7646d2SAndroid Build Coastguard Worker 
779*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("7ppd_mark_option(ppd=%p, option=\"%s\", choice=\"%s\")",
780*5e7646d2SAndroid Build Coastguard Worker         	ppd, option, choice));
781*5e7646d2SAndroid Build Coastguard Worker 
782*5e7646d2SAndroid Build Coastguard Worker  /*
783*5e7646d2SAndroid Build Coastguard Worker   * AP_D_InputSlot is the "default input slot" on macOS, and setting
784*5e7646d2SAndroid Build Coastguard Worker   * it clears the regular InputSlot choices...
785*5e7646d2SAndroid Build Coastguard Worker   */
786*5e7646d2SAndroid Build Coastguard Worker 
787*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(option, "AP_D_InputSlot"))
788*5e7646d2SAndroid Build Coastguard Worker   {
789*5e7646d2SAndroid Build Coastguard Worker     cupsArraySave(ppd->options);
790*5e7646d2SAndroid Build Coastguard Worker 
791*5e7646d2SAndroid Build Coastguard Worker     if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
792*5e7646d2SAndroid Build Coastguard Worker     {
793*5e7646d2SAndroid Build Coastguard Worker       key.option = o;
794*5e7646d2SAndroid Build Coastguard Worker       if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
795*5e7646d2SAndroid Build Coastguard Worker       {
796*5e7646d2SAndroid Build Coastguard Worker         oldc->marked = 0;
797*5e7646d2SAndroid Build Coastguard Worker         cupsArrayRemove(ppd->marked, oldc);
798*5e7646d2SAndroid Build Coastguard Worker       }
799*5e7646d2SAndroid Build Coastguard Worker     }
800*5e7646d2SAndroid Build Coastguard Worker 
801*5e7646d2SAndroid Build Coastguard Worker     cupsArrayRestore(ppd->options);
802*5e7646d2SAndroid Build Coastguard Worker   }
803*5e7646d2SAndroid Build Coastguard Worker 
804*5e7646d2SAndroid Build Coastguard Worker  /*
805*5e7646d2SAndroid Build Coastguard Worker   * Check for custom options...
806*5e7646d2SAndroid Build Coastguard Worker   */
807*5e7646d2SAndroid Build Coastguard Worker 
808*5e7646d2SAndroid Build Coastguard Worker   cupsArraySave(ppd->options);
809*5e7646d2SAndroid Build Coastguard Worker 
810*5e7646d2SAndroid Build Coastguard Worker   o = ppdFindOption(ppd, option);
811*5e7646d2SAndroid Build Coastguard Worker 
812*5e7646d2SAndroid Build Coastguard Worker   cupsArrayRestore(ppd->options);
813*5e7646d2SAndroid Build Coastguard Worker 
814*5e7646d2SAndroid Build Coastguard Worker   if (!o)
815*5e7646d2SAndroid Build Coastguard Worker     return;
816*5e7646d2SAndroid Build Coastguard Worker 
817*5e7646d2SAndroid Build Coastguard Worker   loc = localeconv();
818*5e7646d2SAndroid Build Coastguard Worker 
819*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strncasecmp(choice, "Custom.", 7))
820*5e7646d2SAndroid Build Coastguard Worker   {
821*5e7646d2SAndroid Build Coastguard Worker    /*
822*5e7646d2SAndroid Build Coastguard Worker     * Handle a custom option...
823*5e7646d2SAndroid Build Coastguard Worker     */
824*5e7646d2SAndroid Build Coastguard Worker 
825*5e7646d2SAndroid Build Coastguard Worker     if ((c = ppdFindChoice(o, "Custom")) == NULL)
826*5e7646d2SAndroid Build Coastguard Worker       return;
827*5e7646d2SAndroid Build Coastguard Worker 
828*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(option, "PageSize"))
829*5e7646d2SAndroid Build Coastguard Worker     {
830*5e7646d2SAndroid Build Coastguard Worker      /*
831*5e7646d2SAndroid Build Coastguard Worker       * Handle custom page sizes...
832*5e7646d2SAndroid Build Coastguard Worker       */
833*5e7646d2SAndroid Build Coastguard Worker 
834*5e7646d2SAndroid Build Coastguard Worker       ppdPageSize(ppd, choice);
835*5e7646d2SAndroid Build Coastguard Worker     }
836*5e7646d2SAndroid Build Coastguard Worker     else
837*5e7646d2SAndroid Build Coastguard Worker     {
838*5e7646d2SAndroid Build Coastguard Worker      /*
839*5e7646d2SAndroid Build Coastguard Worker       * Handle other custom options...
840*5e7646d2SAndroid Build Coastguard Worker       */
841*5e7646d2SAndroid Build Coastguard Worker 
842*5e7646d2SAndroid Build Coastguard Worker       ppd_coption_t	*coption;	/* Custom option */
843*5e7646d2SAndroid Build Coastguard Worker       ppd_cparam_t	*cparam;	/* Custom parameter */
844*5e7646d2SAndroid Build Coastguard Worker       char		*units;		/* Custom points units */
845*5e7646d2SAndroid Build Coastguard Worker 
846*5e7646d2SAndroid Build Coastguard Worker 
847*5e7646d2SAndroid Build Coastguard Worker       if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
848*5e7646d2SAndroid Build Coastguard Worker       {
849*5e7646d2SAndroid Build Coastguard Worker         if ((cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) == NULL)
850*5e7646d2SAndroid Build Coastguard Worker 	  return;
851*5e7646d2SAndroid Build Coastguard Worker 
852*5e7646d2SAndroid Build Coastguard Worker         switch (cparam->type)
853*5e7646d2SAndroid Build Coastguard Worker 	{
854*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_UNKNOWN :
855*5e7646d2SAndroid Build Coastguard Worker 	      break;
856*5e7646d2SAndroid Build Coastguard Worker 
857*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_CURVE :
858*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_INVCURVE :
859*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_REAL :
860*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_real = (float)_cupsStrScand(choice + 7,
861*5e7646d2SAndroid Build Coastguard Worker 	                                                         NULL, loc);
862*5e7646d2SAndroid Build Coastguard Worker 	      break;
863*5e7646d2SAndroid Build Coastguard Worker 
864*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_POINTS :
865*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_points = (float)_cupsStrScand(choice + 7,
866*5e7646d2SAndroid Build Coastguard Worker 	                                                           &units,
867*5e7646d2SAndroid Build Coastguard Worker 	                                                           loc);
868*5e7646d2SAndroid Build Coastguard Worker 
869*5e7646d2SAndroid Build Coastguard Worker               if (units)
870*5e7646d2SAndroid Build Coastguard Worker 	      {
871*5e7646d2SAndroid Build Coastguard Worker         	if (!_cups_strcasecmp(units, "cm"))
872*5e7646d2SAndroid Build Coastguard Worker 	          cparam->current.custom_points *= 72.0f / 2.54f;
873*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "mm"))
874*5e7646d2SAndroid Build Coastguard Worker 	          cparam->current.custom_points *= 72.0f / 25.4f;
875*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "m"))
876*5e7646d2SAndroid Build Coastguard Worker 	          cparam->current.custom_points *= 72.0f / 0.0254f;
877*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "in"))
878*5e7646d2SAndroid Build Coastguard Worker 	          cparam->current.custom_points *= 72.0f;
879*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "ft"))
880*5e7646d2SAndroid Build Coastguard Worker 	          cparam->current.custom_points *= 12.0f * 72.0f;
881*5e7646d2SAndroid Build Coastguard Worker               }
882*5e7646d2SAndroid Build Coastguard Worker 	      break;
883*5e7646d2SAndroid Build Coastguard Worker 
884*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_INT :
885*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_int = atoi(choice + 7);
886*5e7646d2SAndroid Build Coastguard Worker 	      break;
887*5e7646d2SAndroid Build Coastguard Worker 
888*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_PASSCODE :
889*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_PASSWORD :
890*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_STRING :
891*5e7646d2SAndroid Build Coastguard Worker 	      if (cparam->current.custom_string)
892*5e7646d2SAndroid Build Coastguard Worker 	        free(cparam->current.custom_string);
893*5e7646d2SAndroid Build Coastguard Worker 
894*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_string = strdup(choice + 7);
895*5e7646d2SAndroid Build Coastguard Worker 	      break;
896*5e7646d2SAndroid Build Coastguard Worker 	}
897*5e7646d2SAndroid Build Coastguard Worker       }
898*5e7646d2SAndroid Build Coastguard Worker     }
899*5e7646d2SAndroid Build Coastguard Worker 
900*5e7646d2SAndroid Build Coastguard Worker    /*
901*5e7646d2SAndroid Build Coastguard Worker     * Make sure that we keep the option marked below...
902*5e7646d2SAndroid Build Coastguard Worker     */
903*5e7646d2SAndroid Build Coastguard Worker 
904*5e7646d2SAndroid Build Coastguard Worker     choice = "Custom";
905*5e7646d2SAndroid Build Coastguard Worker   }
906*5e7646d2SAndroid Build Coastguard Worker   else if (choice[0] == '{')
907*5e7646d2SAndroid Build Coastguard Worker   {
908*5e7646d2SAndroid Build Coastguard Worker    /*
909*5e7646d2SAndroid Build Coastguard Worker     * Handle multi-value custom options...
910*5e7646d2SAndroid Build Coastguard Worker     */
911*5e7646d2SAndroid Build Coastguard Worker 
912*5e7646d2SAndroid Build Coastguard Worker     ppd_coption_t	*coption;	/* Custom option */
913*5e7646d2SAndroid Build Coastguard Worker     ppd_cparam_t	*cparam;	/* Custom parameter */
914*5e7646d2SAndroid Build Coastguard Worker     char		*units;		/* Custom points units */
915*5e7646d2SAndroid Build Coastguard Worker     int			num_vals;	/* Number of values */
916*5e7646d2SAndroid Build Coastguard Worker     cups_option_t	*vals,		/* Values */
917*5e7646d2SAndroid Build Coastguard Worker 			*val;		/* Value */
918*5e7646d2SAndroid Build Coastguard Worker 
919*5e7646d2SAndroid Build Coastguard Worker 
920*5e7646d2SAndroid Build Coastguard Worker     if ((c = ppdFindChoice(o, "Custom")) == NULL)
921*5e7646d2SAndroid Build Coastguard Worker       return;
922*5e7646d2SAndroid Build Coastguard Worker 
923*5e7646d2SAndroid Build Coastguard Worker     if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
924*5e7646d2SAndroid Build Coastguard Worker     {
925*5e7646d2SAndroid Build Coastguard Worker       num_vals = cupsParseOptions(choice, 0, &vals);
926*5e7646d2SAndroid Build Coastguard Worker 
927*5e7646d2SAndroid Build Coastguard Worker       for (i = 0, val = vals; i < num_vals; i ++, val ++)
928*5e7646d2SAndroid Build Coastguard Worker       {
929*5e7646d2SAndroid Build Coastguard Worker         if ((cparam = ppdFindCustomParam(coption, val->name)) == NULL)
930*5e7646d2SAndroid Build Coastguard Worker 	  continue;
931*5e7646d2SAndroid Build Coastguard Worker 
932*5e7646d2SAndroid Build Coastguard Worker 	switch (cparam->type)
933*5e7646d2SAndroid Build Coastguard Worker 	{
934*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_UNKNOWN :
935*5e7646d2SAndroid Build Coastguard Worker 	      break;
936*5e7646d2SAndroid Build Coastguard Worker 
937*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_CURVE :
938*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_INVCURVE :
939*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_REAL :
940*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_real = (float)_cupsStrScand(val->value,
941*5e7646d2SAndroid Build Coastguard Worker 	                                                         NULL, loc);
942*5e7646d2SAndroid Build Coastguard Worker 	      break;
943*5e7646d2SAndroid Build Coastguard Worker 
944*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_POINTS :
945*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_points = (float)_cupsStrScand(val->value,
946*5e7646d2SAndroid Build Coastguard Worker 	                                                           &units,
947*5e7646d2SAndroid Build Coastguard Worker 	                                                           loc);
948*5e7646d2SAndroid Build Coastguard Worker 
949*5e7646d2SAndroid Build Coastguard Worker 	      if (units)
950*5e7646d2SAndroid Build Coastguard Worker 	      {
951*5e7646d2SAndroid Build Coastguard Worker         	if (!_cups_strcasecmp(units, "cm"))
952*5e7646d2SAndroid Build Coastguard Worker 		  cparam->current.custom_points *= 72.0f / 2.54f;
953*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "mm"))
954*5e7646d2SAndroid Build Coastguard Worker 		  cparam->current.custom_points *= 72.0f / 25.4f;
955*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "m"))
956*5e7646d2SAndroid Build Coastguard Worker 		  cparam->current.custom_points *= 72.0f / 0.0254f;
957*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "in"))
958*5e7646d2SAndroid Build Coastguard Worker 		  cparam->current.custom_points *= 72.0f;
959*5e7646d2SAndroid Build Coastguard Worker         	else if (!_cups_strcasecmp(units, "ft"))
960*5e7646d2SAndroid Build Coastguard Worker 		  cparam->current.custom_points *= 12.0f * 72.0f;
961*5e7646d2SAndroid Build Coastguard Worker 	      }
962*5e7646d2SAndroid Build Coastguard Worker 	      break;
963*5e7646d2SAndroid Build Coastguard Worker 
964*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_INT :
965*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_int = atoi(val->value);
966*5e7646d2SAndroid Build Coastguard Worker 	      break;
967*5e7646d2SAndroid Build Coastguard Worker 
968*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_PASSCODE :
969*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_PASSWORD :
970*5e7646d2SAndroid Build Coastguard Worker 	  case PPD_CUSTOM_STRING :
971*5e7646d2SAndroid Build Coastguard Worker 	      if (cparam->current.custom_string)
972*5e7646d2SAndroid Build Coastguard Worker 		free(cparam->current.custom_string);
973*5e7646d2SAndroid Build Coastguard Worker 
974*5e7646d2SAndroid Build Coastguard Worker 	      cparam->current.custom_string = strdup(val->value);
975*5e7646d2SAndroid Build Coastguard Worker 	      break;
976*5e7646d2SAndroid Build Coastguard Worker 	}
977*5e7646d2SAndroid Build Coastguard Worker       }
978*5e7646d2SAndroid Build Coastguard Worker 
979*5e7646d2SAndroid Build Coastguard Worker       cupsFreeOptions(num_vals, vals);
980*5e7646d2SAndroid Build Coastguard Worker     }
981*5e7646d2SAndroid Build Coastguard Worker   }
982*5e7646d2SAndroid Build Coastguard Worker   else
983*5e7646d2SAndroid Build Coastguard Worker   {
984*5e7646d2SAndroid Build Coastguard Worker     for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
985*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(c->choice, choice))
986*5e7646d2SAndroid Build Coastguard Worker         break;
987*5e7646d2SAndroid Build Coastguard Worker 
988*5e7646d2SAndroid Build Coastguard Worker     if (!i)
989*5e7646d2SAndroid Build Coastguard Worker       return;
990*5e7646d2SAndroid Build Coastguard Worker   }
991*5e7646d2SAndroid Build Coastguard Worker 
992*5e7646d2SAndroid Build Coastguard Worker  /*
993*5e7646d2SAndroid Build Coastguard Worker   * Option found; mark it and then handle unmarking any other options.
994*5e7646d2SAndroid Build Coastguard Worker   */
995*5e7646d2SAndroid Build Coastguard Worker 
996*5e7646d2SAndroid Build Coastguard Worker   if (o->ui != PPD_UI_PICKMANY)
997*5e7646d2SAndroid Build Coastguard Worker   {
998*5e7646d2SAndroid Build Coastguard Worker    /*
999*5e7646d2SAndroid Build Coastguard Worker     * Unmark all other choices...
1000*5e7646d2SAndroid Build Coastguard Worker     */
1001*5e7646d2SAndroid Build Coastguard Worker 
1002*5e7646d2SAndroid Build Coastguard Worker     if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, c)) != NULL)
1003*5e7646d2SAndroid Build Coastguard Worker     {
1004*5e7646d2SAndroid Build Coastguard Worker       oldc->marked = 0;
1005*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRemove(ppd->marked, oldc);
1006*5e7646d2SAndroid Build Coastguard Worker     }
1007*5e7646d2SAndroid Build Coastguard Worker 
1008*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(option, "PageSize") || !_cups_strcasecmp(option, "PageRegion"))
1009*5e7646d2SAndroid Build Coastguard Worker     {
1010*5e7646d2SAndroid Build Coastguard Worker      /*
1011*5e7646d2SAndroid Build Coastguard Worker       * Mark current page size...
1012*5e7646d2SAndroid Build Coastguard Worker       */
1013*5e7646d2SAndroid Build Coastguard Worker 
1014*5e7646d2SAndroid Build Coastguard Worker       for (j = 0; j < ppd->num_sizes; j ++)
1015*5e7646d2SAndroid Build Coastguard Worker 	ppd->sizes[j].marked = !_cups_strcasecmp(ppd->sizes[j].name,
1016*5e7646d2SAndroid Build Coastguard Worker 		                           choice);
1017*5e7646d2SAndroid Build Coastguard Worker 
1018*5e7646d2SAndroid Build Coastguard Worker      /*
1019*5e7646d2SAndroid Build Coastguard Worker       * Unmark the current PageSize or PageRegion setting, as
1020*5e7646d2SAndroid Build Coastguard Worker       * appropriate...
1021*5e7646d2SAndroid Build Coastguard Worker       */
1022*5e7646d2SAndroid Build Coastguard Worker 
1023*5e7646d2SAndroid Build Coastguard Worker       cupsArraySave(ppd->options);
1024*5e7646d2SAndroid Build Coastguard Worker 
1025*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(option, "PageSize"))
1026*5e7646d2SAndroid Build Coastguard Worker       {
1027*5e7646d2SAndroid Build Coastguard Worker 	if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
1028*5e7646d2SAndroid Build Coastguard Worker         {
1029*5e7646d2SAndroid Build Coastguard Worker           key.option = o;
1030*5e7646d2SAndroid Build Coastguard Worker           if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
1031*5e7646d2SAndroid Build Coastguard Worker           {
1032*5e7646d2SAndroid Build Coastguard Worker             oldc->marked = 0;
1033*5e7646d2SAndroid Build Coastguard Worker             cupsArrayRemove(ppd->marked, oldc);
1034*5e7646d2SAndroid Build Coastguard Worker           }
1035*5e7646d2SAndroid Build Coastguard Worker         }
1036*5e7646d2SAndroid Build Coastguard Worker       }
1037*5e7646d2SAndroid Build Coastguard Worker       else
1038*5e7646d2SAndroid Build Coastguard Worker       {
1039*5e7646d2SAndroid Build Coastguard Worker 	if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
1040*5e7646d2SAndroid Build Coastguard Worker         {
1041*5e7646d2SAndroid Build Coastguard Worker           key.option = o;
1042*5e7646d2SAndroid Build Coastguard Worker           if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
1043*5e7646d2SAndroid Build Coastguard Worker           {
1044*5e7646d2SAndroid Build Coastguard Worker             oldc->marked = 0;
1045*5e7646d2SAndroid Build Coastguard Worker             cupsArrayRemove(ppd->marked, oldc);
1046*5e7646d2SAndroid Build Coastguard Worker           }
1047*5e7646d2SAndroid Build Coastguard Worker         }
1048*5e7646d2SAndroid Build Coastguard Worker       }
1049*5e7646d2SAndroid Build Coastguard Worker 
1050*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRestore(ppd->options);
1051*5e7646d2SAndroid Build Coastguard Worker     }
1052*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(option, "InputSlot"))
1053*5e7646d2SAndroid Build Coastguard Worker     {
1054*5e7646d2SAndroid Build Coastguard Worker      /*
1055*5e7646d2SAndroid Build Coastguard Worker       * Unmark ManualFeed option...
1056*5e7646d2SAndroid Build Coastguard Worker       */
1057*5e7646d2SAndroid Build Coastguard Worker 
1058*5e7646d2SAndroid Build Coastguard Worker       cupsArraySave(ppd->options);
1059*5e7646d2SAndroid Build Coastguard Worker 
1060*5e7646d2SAndroid Build Coastguard Worker       if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
1061*5e7646d2SAndroid Build Coastguard Worker       {
1062*5e7646d2SAndroid Build Coastguard Worker         key.option = o;
1063*5e7646d2SAndroid Build Coastguard Worker         if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
1064*5e7646d2SAndroid Build Coastguard Worker         {
1065*5e7646d2SAndroid Build Coastguard Worker           oldc->marked = 0;
1066*5e7646d2SAndroid Build Coastguard Worker           cupsArrayRemove(ppd->marked, oldc);
1067*5e7646d2SAndroid Build Coastguard Worker         }
1068*5e7646d2SAndroid Build Coastguard Worker       }
1069*5e7646d2SAndroid Build Coastguard Worker 
1070*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRestore(ppd->options);
1071*5e7646d2SAndroid Build Coastguard Worker     }
1072*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(option, "ManualFeed") &&
1073*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(choice, "True"))
1074*5e7646d2SAndroid Build Coastguard Worker     {
1075*5e7646d2SAndroid Build Coastguard Worker      /*
1076*5e7646d2SAndroid Build Coastguard Worker       * Unmark InputSlot option...
1077*5e7646d2SAndroid Build Coastguard Worker       */
1078*5e7646d2SAndroid Build Coastguard Worker 
1079*5e7646d2SAndroid Build Coastguard Worker       cupsArraySave(ppd->options);
1080*5e7646d2SAndroid Build Coastguard Worker 
1081*5e7646d2SAndroid Build Coastguard Worker       if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
1082*5e7646d2SAndroid Build Coastguard Worker       {
1083*5e7646d2SAndroid Build Coastguard Worker         key.option = o;
1084*5e7646d2SAndroid Build Coastguard Worker         if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
1085*5e7646d2SAndroid Build Coastguard Worker         {
1086*5e7646d2SAndroid Build Coastguard Worker           oldc->marked = 0;
1087*5e7646d2SAndroid Build Coastguard Worker           cupsArrayRemove(ppd->marked, oldc);
1088*5e7646d2SAndroid Build Coastguard Worker         }
1089*5e7646d2SAndroid Build Coastguard Worker       }
1090*5e7646d2SAndroid Build Coastguard Worker 
1091*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRestore(ppd->options);
1092*5e7646d2SAndroid Build Coastguard Worker     }
1093*5e7646d2SAndroid Build Coastguard Worker   }
1094*5e7646d2SAndroid Build Coastguard Worker 
1095*5e7646d2SAndroid Build Coastguard Worker   c->marked = 1;
1096*5e7646d2SAndroid Build Coastguard Worker 
1097*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(ppd->marked, c);
1098*5e7646d2SAndroid Build Coastguard Worker }
1099