xref: /aosp_15_r20/external/libcups/cups/ppd-conflicts.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Option conflict management routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2018 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 constants...
24*5e7646d2SAndroid Build Coastguard Worker  */
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker enum
27*5e7646d2SAndroid Build Coastguard Worker {
28*5e7646d2SAndroid Build Coastguard Worker   _PPD_OPTION_CONSTRAINTS,
29*5e7646d2SAndroid Build Coastguard Worker   _PPD_INSTALLABLE_CONSTRAINTS,
30*5e7646d2SAndroid Build Coastguard Worker   _PPD_ALL_CONSTRAINTS
31*5e7646d2SAndroid Build Coastguard Worker };
32*5e7646d2SAndroid Build Coastguard Worker 
33*5e7646d2SAndroid Build Coastguard Worker 
34*5e7646d2SAndroid Build Coastguard Worker /*
35*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
36*5e7646d2SAndroid Build Coastguard Worker  */
37*5e7646d2SAndroid Build Coastguard Worker 
38*5e7646d2SAndroid Build Coastguard Worker static int		ppd_is_installable(ppd_group_t *installable,
39*5e7646d2SAndroid Build Coastguard Worker 			                   const char *option);
40*5e7646d2SAndroid Build Coastguard Worker static void		ppd_load_constraints(ppd_file_t *ppd);
41*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*ppd_test_constraints(ppd_file_t *ppd,
42*5e7646d2SAndroid Build Coastguard Worker 			                      const char *option,
43*5e7646d2SAndroid Build Coastguard Worker 					      const char *choice,
44*5e7646d2SAndroid Build Coastguard Worker 			                      int num_options,
45*5e7646d2SAndroid Build Coastguard Worker 			                      cups_option_t *options,
46*5e7646d2SAndroid Build Coastguard Worker 					      int which);
47*5e7646d2SAndroid Build Coastguard Worker 
48*5e7646d2SAndroid Build Coastguard Worker 
49*5e7646d2SAndroid Build Coastguard Worker /*
50*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetConflicts()' - Get a list of conflicting options in a marked PPD.
51*5e7646d2SAndroid Build Coastguard Worker  *
52*5e7646d2SAndroid Build Coastguard Worker  * This function gets a list of options that would conflict if "option" and
53*5e7646d2SAndroid Build Coastguard Worker  * "choice" were marked in the PPD.  You would typically call this function
54*5e7646d2SAndroid Build Coastguard Worker  * after marking the currently selected options in the PPD in order to
55*5e7646d2SAndroid Build Coastguard Worker  * determine whether a new option selection would cause a conflict.
56*5e7646d2SAndroid Build Coastguard Worker  *
57*5e7646d2SAndroid Build Coastguard Worker  * The number of conflicting options are returned with "options" pointing to
58*5e7646d2SAndroid Build Coastguard Worker  * the conflicting options.  The returned option array must be freed using
59*5e7646d2SAndroid Build Coastguard Worker  * @link cupsFreeOptions@.
60*5e7646d2SAndroid Build Coastguard Worker  *
61*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.4/macOS 10.6@
62*5e7646d2SAndroid Build Coastguard Worker  */
63*5e7646d2SAndroid Build Coastguard Worker 
64*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of conflicting options */
cupsGetConflicts(ppd_file_t * ppd,const char * option,const char * choice,cups_option_t ** options)65*5e7646d2SAndroid Build Coastguard Worker cupsGetConflicts(
66*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t    *ppd,			/* I - PPD file */
67*5e7646d2SAndroid Build Coastguard Worker     const char    *option,		/* I - Option to test */
68*5e7646d2SAndroid Build Coastguard Worker     const char    *choice,		/* I - Choice to test */
69*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **options)		/* O - Conflicting options */
70*5e7646d2SAndroid Build Coastguard Worker {
71*5e7646d2SAndroid Build Coastguard Worker   int			i,		/* Looping var */
72*5e7646d2SAndroid Build Coastguard Worker 			num_options;	/* Number of conflicting options */
73*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*active;	/* Active conflicts */
74*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconsts_t	*c;		/* Current constraints */
75*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconst_t	*cptr;		/* Current constraint */
76*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t		*marked;	/* Marked choice */
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker 
79*5e7646d2SAndroid Build Coastguard Worker  /*
80*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
81*5e7646d2SAndroid Build Coastguard Worker   */
82*5e7646d2SAndroid Build Coastguard Worker 
83*5e7646d2SAndroid Build Coastguard Worker   if (options)
84*5e7646d2SAndroid Build Coastguard Worker     *options = NULL;
85*5e7646d2SAndroid Build Coastguard Worker 
86*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !option || !choice || !options)
87*5e7646d2SAndroid Build Coastguard Worker     return (0);
88*5e7646d2SAndroid Build Coastguard Worker 
89*5e7646d2SAndroid Build Coastguard Worker  /*
90*5e7646d2SAndroid Build Coastguard Worker   * Test for conflicts...
91*5e7646d2SAndroid Build Coastguard Worker   */
92*5e7646d2SAndroid Build Coastguard Worker 
93*5e7646d2SAndroid Build Coastguard Worker   active = ppd_test_constraints(ppd, option, choice, 0, NULL,
94*5e7646d2SAndroid Build Coastguard Worker                                 _PPD_ALL_CONSTRAINTS);
95*5e7646d2SAndroid Build Coastguard Worker 
96*5e7646d2SAndroid Build Coastguard Worker  /*
97*5e7646d2SAndroid Build Coastguard Worker   * Loop through all of the UI constraints and add any options that conflict...
98*5e7646d2SAndroid Build Coastguard Worker   */
99*5e7646d2SAndroid Build Coastguard Worker 
100*5e7646d2SAndroid Build Coastguard Worker   for (num_options = 0, c = (_ppd_cups_uiconsts_t *)cupsArrayFirst(active);
101*5e7646d2SAndroid Build Coastguard Worker        c;
102*5e7646d2SAndroid Build Coastguard Worker        c = (_ppd_cups_uiconsts_t *)cupsArrayNext(active))
103*5e7646d2SAndroid Build Coastguard Worker   {
104*5e7646d2SAndroid Build Coastguard Worker     for (i = c->num_constraints, cptr = c->constraints;
105*5e7646d2SAndroid Build Coastguard Worker          i > 0;
106*5e7646d2SAndroid Build Coastguard Worker 	 i --, cptr ++)
107*5e7646d2SAndroid Build Coastguard Worker       if (_cups_strcasecmp(cptr->option->keyword, option))
108*5e7646d2SAndroid Build Coastguard Worker       {
109*5e7646d2SAndroid Build Coastguard Worker         if (cptr->choice)
110*5e7646d2SAndroid Build Coastguard Worker 	  num_options = cupsAddOption(cptr->option->keyword,
111*5e7646d2SAndroid Build Coastguard Worker 	                              cptr->choice->choice, num_options,
112*5e7646d2SAndroid Build Coastguard Worker 				      options);
113*5e7646d2SAndroid Build Coastguard Worker         else if ((marked = ppdFindMarkedChoice(ppd,
114*5e7646d2SAndroid Build Coastguard Worker 	                                       cptr->option->keyword)) != NULL)
115*5e7646d2SAndroid Build Coastguard Worker 	  num_options = cupsAddOption(cptr->option->keyword, marked->choice,
116*5e7646d2SAndroid Build Coastguard Worker 				      num_options, options);
117*5e7646d2SAndroid Build Coastguard Worker       }
118*5e7646d2SAndroid Build Coastguard Worker   }
119*5e7646d2SAndroid Build Coastguard Worker 
120*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(active);
121*5e7646d2SAndroid Build Coastguard Worker 
122*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
123*5e7646d2SAndroid Build Coastguard Worker }
124*5e7646d2SAndroid Build Coastguard Worker 
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker /*
127*5e7646d2SAndroid Build Coastguard Worker  * 'cupsResolveConflicts()' - Resolve conflicts in a marked PPD.
128*5e7646d2SAndroid Build Coastguard Worker  *
129*5e7646d2SAndroid Build Coastguard Worker  * This function attempts to resolve any conflicts in a marked PPD, returning
130*5e7646d2SAndroid Build Coastguard Worker  * a list of option changes that are required to resolve them.  On input,
131*5e7646d2SAndroid Build Coastguard Worker  * "num_options" and "options" contain any pending option changes that have
132*5e7646d2SAndroid Build Coastguard Worker  * not yet been marked, while "option" and "choice" contain the most recent
133*5e7646d2SAndroid Build Coastguard Worker  * selection which may or may not be in "num_options" or "options".
134*5e7646d2SAndroid Build Coastguard Worker  *
135*5e7646d2SAndroid Build Coastguard Worker  * On successful return, "num_options" and "options" are updated to contain
136*5e7646d2SAndroid Build Coastguard Worker  * "option" and "choice" along with any changes required to resolve conflicts
137*5e7646d2SAndroid Build Coastguard Worker  * specified in the PPD file and 1 is returned.
138*5e7646d2SAndroid Build Coastguard Worker  *
139*5e7646d2SAndroid Build Coastguard Worker  * If option conflicts cannot be resolved, "num_options" and "options" are not
140*5e7646d2SAndroid Build Coastguard Worker  * changed and 0 is returned.
141*5e7646d2SAndroid Build Coastguard Worker  *
142*5e7646d2SAndroid Build Coastguard Worker  * When resolving conflicts, @code cupsResolveConflicts@ does not consider
143*5e7646d2SAndroid Build Coastguard Worker  * changes to the current page size (@code media@, @code PageSize@, and
144*5e7646d2SAndroid Build Coastguard Worker  * @code PageRegion@) or to the most recent option specified in "option".
145*5e7646d2SAndroid Build Coastguard Worker  * Thus, if the only way to resolve a conflict is to change the page size
146*5e7646d2SAndroid Build Coastguard Worker  * or the option the user most recently changed, @code cupsResolveConflicts@
147*5e7646d2SAndroid Build Coastguard Worker  * will return 0 to indicate it was unable to resolve the conflicts.
148*5e7646d2SAndroid Build Coastguard Worker  *
149*5e7646d2SAndroid Build Coastguard Worker  * The @code cupsResolveConflicts@ function uses one of two sources of option
150*5e7646d2SAndroid Build Coastguard Worker  * constraint information.  The preferred constraint information is defined by
151*5e7646d2SAndroid Build Coastguard Worker  * @code cupsUIConstraints@ and @code cupsUIResolver@ attributes - in this
152*5e7646d2SAndroid Build Coastguard Worker  * case, the PPD file provides constraint resolution actions.
153*5e7646d2SAndroid Build Coastguard Worker  *
154*5e7646d2SAndroid Build Coastguard Worker  * The backup constraint information is defined by the
155*5e7646d2SAndroid Build Coastguard Worker  * @code UIConstraints@ and @code NonUIConstraints@ attributes.  These
156*5e7646d2SAndroid Build Coastguard Worker  * constraints are resolved algorithmically by first selecting the default
157*5e7646d2SAndroid Build Coastguard Worker  * choice for the conflicting option, then iterating over all possible choices
158*5e7646d2SAndroid Build Coastguard Worker  * until a non-conflicting option choice is found.
159*5e7646d2SAndroid Build Coastguard Worker  *
160*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.4/macOS 10.6@
161*5e7646d2SAndroid Build Coastguard Worker  */
162*5e7646d2SAndroid Build Coastguard Worker 
163*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 1 on success, 0 on failure */
cupsResolveConflicts(ppd_file_t * ppd,const char * option,const char * choice,int * num_options,cups_option_t ** options)164*5e7646d2SAndroid Build Coastguard Worker cupsResolveConflicts(
165*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t    *ppd,			/* I  - PPD file */
166*5e7646d2SAndroid Build Coastguard Worker     const char    *option,		/* I  - Newly selected option or @code NULL@ for none */
167*5e7646d2SAndroid Build Coastguard Worker     const char    *choice,		/* I  - Newly selected choice or @code NULL@ for none */
168*5e7646d2SAndroid Build Coastguard Worker     int           *num_options,		/* IO - Number of additional selected options */
169*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **options)		/* IO - Additional selected options */
170*5e7646d2SAndroid Build Coastguard Worker {
171*5e7646d2SAndroid Build Coastguard Worker   int			i,		/* Looping var */
172*5e7646d2SAndroid Build Coastguard Worker 			tries,		/* Number of tries */
173*5e7646d2SAndroid Build Coastguard Worker 			num_newopts;	/* Number of new options */
174*5e7646d2SAndroid Build Coastguard Worker   cups_option_t		*newopts;	/* New options */
175*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*active = NULL,	/* Active constraints */
176*5e7646d2SAndroid Build Coastguard Worker 			*pass,		/* Resolvers for this pass */
177*5e7646d2SAndroid Build Coastguard Worker 			*resolvers,	/* Resolvers we have used */
178*5e7646d2SAndroid Build Coastguard Worker 			*test;		/* Test array for conflicts */
179*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconsts_t	*consts;	/* Current constraints */
180*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
181*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t		*resolver;	/* Current resolver */
182*5e7646d2SAndroid Build Coastguard Worker   const char		*resval;	/* Pointer into resolver value */
183*5e7646d2SAndroid Build Coastguard Worker   char			resoption[PPD_MAX_NAME],
184*5e7646d2SAndroid Build Coastguard Worker 					/* Current resolver option */
185*5e7646d2SAndroid Build Coastguard Worker 			reschoice[PPD_MAX_NAME],
186*5e7646d2SAndroid Build Coastguard Worker 					/* Current resolver choice */
187*5e7646d2SAndroid Build Coastguard Worker 			*resptr,	/* Pointer into option/choice */
188*5e7646d2SAndroid Build Coastguard Worker 			firstpage[255];	/* AP_FIRSTPAGE_Keyword string */
189*5e7646d2SAndroid Build Coastguard Worker   const char		*value;		/* Selected option value */
190*5e7646d2SAndroid Build Coastguard Worker   int			changed;	/* Did we change anything? */
191*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t		*marked;	/* Marked choice */
192*5e7646d2SAndroid Build Coastguard Worker 
193*5e7646d2SAndroid Build Coastguard Worker 
194*5e7646d2SAndroid Build Coastguard Worker  /*
195*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
196*5e7646d2SAndroid Build Coastguard Worker   */
197*5e7646d2SAndroid Build Coastguard Worker 
198*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !num_options || !options || (option == NULL) != (choice == NULL))
199*5e7646d2SAndroid Build Coastguard Worker     return (0);
200*5e7646d2SAndroid Build Coastguard Worker 
201*5e7646d2SAndroid Build Coastguard Worker  /*
202*5e7646d2SAndroid Build Coastguard Worker   * Build a shadow option array...
203*5e7646d2SAndroid Build Coastguard Worker   */
204*5e7646d2SAndroid Build Coastguard Worker 
205*5e7646d2SAndroid Build Coastguard Worker   num_newopts = 0;
206*5e7646d2SAndroid Build Coastguard Worker   newopts     = NULL;
207*5e7646d2SAndroid Build Coastguard Worker 
208*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < *num_options; i ++)
209*5e7646d2SAndroid Build Coastguard Worker     num_newopts = cupsAddOption((*options)[i].name, (*options)[i].value,
210*5e7646d2SAndroid Build Coastguard Worker                                 num_newopts, &newopts);
211*5e7646d2SAndroid Build Coastguard Worker   if (option && _cups_strcasecmp(option, "Collate"))
212*5e7646d2SAndroid Build Coastguard Worker     num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);
213*5e7646d2SAndroid Build Coastguard Worker 
214*5e7646d2SAndroid Build Coastguard Worker  /*
215*5e7646d2SAndroid Build Coastguard Worker   * Loop until we have no conflicts...
216*5e7646d2SAndroid Build Coastguard Worker   */
217*5e7646d2SAndroid Build Coastguard Worker 
218*5e7646d2SAndroid Build Coastguard Worker   cupsArraySave(ppd->sorted_attrs);
219*5e7646d2SAndroid Build Coastguard Worker 
220*5e7646d2SAndroid Build Coastguard Worker   resolvers = NULL;
221*5e7646d2SAndroid Build Coastguard Worker   pass      = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);
222*5e7646d2SAndroid Build Coastguard Worker   tries     = 0;
223*5e7646d2SAndroid Build Coastguard Worker 
224*5e7646d2SAndroid Build Coastguard Worker   while (tries < 100 &&
225*5e7646d2SAndroid Build Coastguard Worker          (active = ppd_test_constraints(ppd, NULL, NULL, num_newopts, newopts,
226*5e7646d2SAndroid Build Coastguard Worker                                         _PPD_ALL_CONSTRAINTS)) != NULL)
227*5e7646d2SAndroid Build Coastguard Worker   {
228*5e7646d2SAndroid Build Coastguard Worker     tries ++;
229*5e7646d2SAndroid Build Coastguard Worker 
230*5e7646d2SAndroid Build Coastguard Worker     if (!resolvers)
231*5e7646d2SAndroid Build Coastguard Worker       resolvers = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);
232*5e7646d2SAndroid Build Coastguard Worker 
233*5e7646d2SAndroid Build Coastguard Worker     for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(active), changed = 0;
234*5e7646d2SAndroid Build Coastguard Worker          consts;
235*5e7646d2SAndroid Build Coastguard Worker 	 consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(active))
236*5e7646d2SAndroid Build Coastguard Worker     {
237*5e7646d2SAndroid Build Coastguard Worker       if (consts->resolver[0])
238*5e7646d2SAndroid Build Coastguard Worker       {
239*5e7646d2SAndroid Build Coastguard Worker        /*
240*5e7646d2SAndroid Build Coastguard Worker         * Look up the resolver...
241*5e7646d2SAndroid Build Coastguard Worker 	*/
242*5e7646d2SAndroid Build Coastguard Worker 
243*5e7646d2SAndroid Build Coastguard Worker         if (cupsArrayFind(pass, consts->resolver))
244*5e7646d2SAndroid Build Coastguard Worker 	  continue;			/* Already applied this resolver... */
245*5e7646d2SAndroid Build Coastguard Worker 
246*5e7646d2SAndroid Build Coastguard Worker         if (cupsArrayFind(resolvers, consts->resolver))
247*5e7646d2SAndroid Build Coastguard Worker 	{
248*5e7646d2SAndroid Build Coastguard Worker 	 /*
249*5e7646d2SAndroid Build Coastguard Worker 	  * Resolver loop!
250*5e7646d2SAndroid Build Coastguard Worker 	  */
251*5e7646d2SAndroid Build Coastguard Worker 
252*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("1cupsResolveConflicts: Resolver loop with %s!",
253*5e7646d2SAndroid Build Coastguard Worker 	                consts->resolver));
254*5e7646d2SAndroid Build Coastguard Worker           goto error;
255*5e7646d2SAndroid Build Coastguard Worker 	}
256*5e7646d2SAndroid Build Coastguard Worker 
257*5e7646d2SAndroid Build Coastguard Worker         if ((resolver = ppdFindAttr(ppd, "cupsUIResolver",
258*5e7646d2SAndroid Build Coastguard Worker 	                            consts->resolver)) == NULL)
259*5e7646d2SAndroid Build Coastguard Worker         {
260*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s not found!",
261*5e7646d2SAndroid Build Coastguard Worker 	                consts->resolver));
262*5e7646d2SAndroid Build Coastguard Worker 	  goto error;
263*5e7646d2SAndroid Build Coastguard Worker 	}
264*5e7646d2SAndroid Build Coastguard Worker 
265*5e7646d2SAndroid Build Coastguard Worker         if (!resolver->value)
266*5e7646d2SAndroid Build Coastguard Worker 	{
267*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s has no value!",
268*5e7646d2SAndroid Build Coastguard Worker 	                consts->resolver));
269*5e7646d2SAndroid Build Coastguard Worker 	  goto error;
270*5e7646d2SAndroid Build Coastguard Worker 	}
271*5e7646d2SAndroid Build Coastguard Worker 
272*5e7646d2SAndroid Build Coastguard Worker        /*
273*5e7646d2SAndroid Build Coastguard Worker         * Add the options from the resolver...
274*5e7646d2SAndroid Build Coastguard Worker 	*/
275*5e7646d2SAndroid Build Coastguard Worker 
276*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(pass, consts->resolver);
277*5e7646d2SAndroid Build Coastguard Worker 	cupsArrayAdd(resolvers, consts->resolver);
278*5e7646d2SAndroid Build Coastguard Worker 
279*5e7646d2SAndroid Build Coastguard Worker         for (resval = resolver->value; *resval && !changed;)
280*5e7646d2SAndroid Build Coastguard Worker 	{
281*5e7646d2SAndroid Build Coastguard Worker 	  while (_cups_isspace(*resval))
282*5e7646d2SAndroid Build Coastguard Worker 	    resval ++;
283*5e7646d2SAndroid Build Coastguard Worker 
284*5e7646d2SAndroid Build Coastguard Worker 	  if (*resval != '*')
285*5e7646d2SAndroid Build Coastguard Worker 	    break;
286*5e7646d2SAndroid Build Coastguard Worker 
287*5e7646d2SAndroid Build Coastguard Worker 	  for (resval ++, resptr = resoption;
288*5e7646d2SAndroid Build Coastguard Worker 	       *resval && !_cups_isspace(*resval);
289*5e7646d2SAndroid Build Coastguard Worker 	       resval ++)
290*5e7646d2SAndroid Build Coastguard Worker             if (resptr < (resoption + sizeof(resoption) - 1))
291*5e7646d2SAndroid Build Coastguard Worker 	      *resptr++ = *resval;
292*5e7646d2SAndroid Build Coastguard Worker 
293*5e7646d2SAndroid Build Coastguard Worker           *resptr = '\0';
294*5e7646d2SAndroid Build Coastguard Worker 
295*5e7646d2SAndroid Build Coastguard Worker 	  while (_cups_isspace(*resval))
296*5e7646d2SAndroid Build Coastguard Worker 	    resval ++;
297*5e7646d2SAndroid Build Coastguard Worker 
298*5e7646d2SAndroid Build Coastguard Worker 	  for (resptr = reschoice;
299*5e7646d2SAndroid Build Coastguard Worker 	       *resval && !_cups_isspace(*resval);
300*5e7646d2SAndroid Build Coastguard Worker 	       resval ++)
301*5e7646d2SAndroid Build Coastguard Worker             if (resptr < (reschoice + sizeof(reschoice) - 1))
302*5e7646d2SAndroid Build Coastguard Worker 	      *resptr++ = *resval;
303*5e7646d2SAndroid Build Coastguard Worker 
304*5e7646d2SAndroid Build Coastguard Worker           *resptr = '\0';
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker           if (!resoption[0] || !reschoice[0])
307*5e7646d2SAndroid Build Coastguard Worker 	    break;
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker          /*
310*5e7646d2SAndroid Build Coastguard Worker 	  * Is this the option we are changing?
311*5e7646d2SAndroid Build Coastguard Worker 	  */
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker           snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s", resoption);
314*5e7646d2SAndroid Build Coastguard Worker 
315*5e7646d2SAndroid Build Coastguard Worker 	  if (option &&
316*5e7646d2SAndroid Build Coastguard Worker 	      (!_cups_strcasecmp(resoption, option) ||
317*5e7646d2SAndroid Build Coastguard Worker 	       !_cups_strcasecmp(firstpage, option) ||
318*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "PageSize") &&
319*5e7646d2SAndroid Build Coastguard Worker 		!_cups_strcasecmp(resoption, "PageRegion")) ||
320*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
321*5e7646d2SAndroid Build Coastguard Worker 		!_cups_strcasecmp(resoption, "PageSize")) ||
322*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
323*5e7646d2SAndroid Build Coastguard Worker 		!_cups_strcasecmp(resoption, "PageRegion")) ||
324*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "PageRegion") &&
325*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(resoption, "PageSize")) ||
326*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
327*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(resoption, "PageSize")) ||
328*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
329*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(resoption, "PageRegion"))))
330*5e7646d2SAndroid Build Coastguard Worker 	    continue;
331*5e7646d2SAndroid Build Coastguard Worker 
332*5e7646d2SAndroid Build Coastguard Worker 	 /*
333*5e7646d2SAndroid Build Coastguard Worker 	  * Try this choice...
334*5e7646d2SAndroid Build Coastguard Worker 	  */
335*5e7646d2SAndroid Build Coastguard Worker 
336*5e7646d2SAndroid Build Coastguard Worker           if ((test = ppd_test_constraints(ppd, resoption, reschoice,
337*5e7646d2SAndroid Build Coastguard Worker 					   num_newopts, newopts,
338*5e7646d2SAndroid Build Coastguard Worker 					   _PPD_ALL_CONSTRAINTS)) == NULL)
339*5e7646d2SAndroid Build Coastguard Worker 	  {
340*5e7646d2SAndroid Build Coastguard Worker 	   /*
341*5e7646d2SAndroid Build Coastguard Worker 	    * That worked...
342*5e7646d2SAndroid Build Coastguard Worker 	    */
343*5e7646d2SAndroid Build Coastguard Worker 
344*5e7646d2SAndroid Build Coastguard Worker             changed = 1;
345*5e7646d2SAndroid Build Coastguard Worker 	  }
346*5e7646d2SAndroid Build Coastguard Worker 	  else
347*5e7646d2SAndroid Build Coastguard Worker             cupsArrayDelete(test);
348*5e7646d2SAndroid Build Coastguard Worker 
349*5e7646d2SAndroid Build Coastguard Worker 	 /*
350*5e7646d2SAndroid Build Coastguard Worker 	  * Add the option/choice from the resolver regardless of whether it
351*5e7646d2SAndroid Build Coastguard Worker 	  * worked; this makes sure that we can cascade several changes to
352*5e7646d2SAndroid Build Coastguard Worker 	  * make things resolve...
353*5e7646d2SAndroid Build Coastguard Worker 	  */
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker 	  num_newopts = cupsAddOption(resoption, reschoice, num_newopts,
356*5e7646d2SAndroid Build Coastguard Worker 				      &newopts);
357*5e7646d2SAndroid Build Coastguard Worker         }
358*5e7646d2SAndroid Build Coastguard Worker       }
359*5e7646d2SAndroid Build Coastguard Worker       else
360*5e7646d2SAndroid Build Coastguard Worker       {
361*5e7646d2SAndroid Build Coastguard Worker        /*
362*5e7646d2SAndroid Build Coastguard Worker         * Try resolving by choosing the default values for non-installable
363*5e7646d2SAndroid Build Coastguard Worker 	* options, then by iterating through the possible choices...
364*5e7646d2SAndroid Build Coastguard Worker 	*/
365*5e7646d2SAndroid Build Coastguard Worker 
366*5e7646d2SAndroid Build Coastguard Worker         int		j;		/* Looping var */
367*5e7646d2SAndroid Build Coastguard Worker 	ppd_choice_t	*cptr;		/* Current choice */
368*5e7646d2SAndroid Build Coastguard Worker         ppd_size_t	*size;		/* Current page size */
369*5e7646d2SAndroid Build Coastguard Worker 
370*5e7646d2SAndroid Build Coastguard Worker 
371*5e7646d2SAndroid Build Coastguard Worker         for (i = consts->num_constraints, constptr = consts->constraints;
372*5e7646d2SAndroid Build Coastguard Worker 	     i > 0 && !changed;
373*5e7646d2SAndroid Build Coastguard Worker 	     i --, constptr ++)
374*5e7646d2SAndroid Build Coastguard Worker 	{
375*5e7646d2SAndroid Build Coastguard Worker 	 /*
376*5e7646d2SAndroid Build Coastguard Worker 	  * Can't resolve by changing an installable option...
377*5e7646d2SAndroid Build Coastguard Worker 	  */
378*5e7646d2SAndroid Build Coastguard Worker 
379*5e7646d2SAndroid Build Coastguard Worker 	  if (constptr->installable)
380*5e7646d2SAndroid Build Coastguard Worker 	    continue;
381*5e7646d2SAndroid Build Coastguard Worker 
382*5e7646d2SAndroid Build Coastguard Worker          /*
383*5e7646d2SAndroid Build Coastguard Worker 	  * Is this the option we are changing?
384*5e7646d2SAndroid Build Coastguard Worker 	  */
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker 	  if (option &&
387*5e7646d2SAndroid Build Coastguard Worker 	      (!_cups_strcasecmp(constptr->option->keyword, option) ||
388*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "PageSize") &&
389*5e7646d2SAndroid Build Coastguard Worker 		!_cups_strcasecmp(constptr->option->keyword, "PageRegion")) ||
390*5e7646d2SAndroid Build Coastguard Worker 	       (!_cups_strcasecmp(option, "PageRegion") &&
391*5e7646d2SAndroid Build Coastguard Worker 		!_cups_strcasecmp(constptr->option->keyword, "PageSize"))))
392*5e7646d2SAndroid Build Coastguard Worker 	    continue;
393*5e7646d2SAndroid Build Coastguard Worker 
394*5e7646d2SAndroid Build Coastguard Worker          /*
395*5e7646d2SAndroid Build Coastguard Worker 	  * Get the current option choice...
396*5e7646d2SAndroid Build Coastguard Worker 	  */
397*5e7646d2SAndroid Build Coastguard Worker 
398*5e7646d2SAndroid Build Coastguard Worker           if ((value = cupsGetOption(constptr->option->keyword, num_newopts,
399*5e7646d2SAndroid Build Coastguard Worker 	                             newopts)) == NULL)
400*5e7646d2SAndroid Build Coastguard Worker           {
401*5e7646d2SAndroid Build Coastguard Worker 	    if (!_cups_strcasecmp(constptr->option->keyword, "PageSize") ||
402*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(constptr->option->keyword, "PageRegion"))
403*5e7646d2SAndroid Build Coastguard Worker 	    {
404*5e7646d2SAndroid Build Coastguard Worker 	      if ((value = cupsGetOption("PageSize", num_newopts,
405*5e7646d2SAndroid Build Coastguard Worker 	                                 newopts)) == NULL)
406*5e7646d2SAndroid Build Coastguard Worker                 value = cupsGetOption("PageRegion", num_newopts, newopts);
407*5e7646d2SAndroid Build Coastguard Worker 
408*5e7646d2SAndroid Build Coastguard Worker               if (!value)
409*5e7646d2SAndroid Build Coastguard Worker 	      {
410*5e7646d2SAndroid Build Coastguard Worker 	        if ((size = ppdPageSize(ppd, NULL)) != NULL)
411*5e7646d2SAndroid Build Coastguard Worker 		  value = size->name;
412*5e7646d2SAndroid Build Coastguard Worker 		else
413*5e7646d2SAndroid Build Coastguard Worker 		  value = "";
414*5e7646d2SAndroid Build Coastguard Worker 	      }
415*5e7646d2SAndroid Build Coastguard Worker 	    }
416*5e7646d2SAndroid Build Coastguard Worker 	    else
417*5e7646d2SAndroid Build Coastguard Worker 	    {
418*5e7646d2SAndroid Build Coastguard Worker 	      marked = ppdFindMarkedChoice(ppd, constptr->option->keyword);
419*5e7646d2SAndroid Build Coastguard Worker 	      value  = marked ? marked->choice : "";
420*5e7646d2SAndroid Build Coastguard Worker 	    }
421*5e7646d2SAndroid Build Coastguard Worker 	  }
422*5e7646d2SAndroid Build Coastguard Worker 
423*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strncasecmp(value, "Custom.", 7))
424*5e7646d2SAndroid Build Coastguard Worker 	    value = "Custom";
425*5e7646d2SAndroid Build Coastguard Worker 
426*5e7646d2SAndroid Build Coastguard Worker          /*
427*5e7646d2SAndroid Build Coastguard Worker 	  * Try the default choice...
428*5e7646d2SAndroid Build Coastguard Worker 	  */
429*5e7646d2SAndroid Build Coastguard Worker 
430*5e7646d2SAndroid Build Coastguard Worker           test = NULL;
431*5e7646d2SAndroid Build Coastguard Worker 
432*5e7646d2SAndroid Build Coastguard Worker           if (_cups_strcasecmp(value, constptr->option->defchoice) &&
433*5e7646d2SAndroid Build Coastguard Worker 	      (test = ppd_test_constraints(ppd, constptr->option->keyword,
434*5e7646d2SAndroid Build Coastguard Worker 	                                   constptr->option->defchoice,
435*5e7646d2SAndroid Build Coastguard Worker 					   num_newopts, newopts,
436*5e7646d2SAndroid Build Coastguard Worker 					   _PPD_OPTION_CONSTRAINTS)) == NULL)
437*5e7646d2SAndroid Build Coastguard Worker 	  {
438*5e7646d2SAndroid Build Coastguard Worker 	   /*
439*5e7646d2SAndroid Build Coastguard Worker 	    * That worked...
440*5e7646d2SAndroid Build Coastguard Worker 	    */
441*5e7646d2SAndroid Build Coastguard Worker 
442*5e7646d2SAndroid Build Coastguard Worker 	    num_newopts = cupsAddOption(constptr->option->keyword,
443*5e7646d2SAndroid Build Coastguard Worker 	                                constptr->option->defchoice,
444*5e7646d2SAndroid Build Coastguard Worker 					num_newopts, &newopts);
445*5e7646d2SAndroid Build Coastguard Worker             changed     = 1;
446*5e7646d2SAndroid Build Coastguard Worker 	  }
447*5e7646d2SAndroid Build Coastguard Worker 	  else
448*5e7646d2SAndroid Build Coastguard Worker 	  {
449*5e7646d2SAndroid Build Coastguard Worker 	   /*
450*5e7646d2SAndroid Build Coastguard Worker 	    * Try each choice instead...
451*5e7646d2SAndroid Build Coastguard Worker 	    */
452*5e7646d2SAndroid Build Coastguard Worker 
453*5e7646d2SAndroid Build Coastguard Worker             for (j = constptr->option->num_choices,
454*5e7646d2SAndroid Build Coastguard Worker 	             cptr = constptr->option->choices;
455*5e7646d2SAndroid Build Coastguard Worker 		 j > 0;
456*5e7646d2SAndroid Build Coastguard Worker 		 j --, cptr ++)
457*5e7646d2SAndroid Build Coastguard Worker             {
458*5e7646d2SAndroid Build Coastguard Worker 	      cupsArrayDelete(test);
459*5e7646d2SAndroid Build Coastguard Worker 	      test = NULL;
460*5e7646d2SAndroid Build Coastguard Worker 
461*5e7646d2SAndroid Build Coastguard Worker 	      if (_cups_strcasecmp(value, cptr->choice) &&
462*5e7646d2SAndroid Build Coastguard Worker 	          _cups_strcasecmp(constptr->option->defchoice, cptr->choice) &&
463*5e7646d2SAndroid Build Coastguard Worker 		  _cups_strcasecmp("Custom", cptr->choice) &&
464*5e7646d2SAndroid Build Coastguard Worker 	          (test = ppd_test_constraints(ppd, constptr->option->keyword,
465*5e7646d2SAndroid Build Coastguard Worker 	                                       cptr->choice, num_newopts,
466*5e7646d2SAndroid Build Coastguard Worker 					       newopts,
467*5e7646d2SAndroid Build Coastguard Worker 					       _PPD_OPTION_CONSTRAINTS)) == NULL)
468*5e7646d2SAndroid Build Coastguard Worker 	      {
469*5e7646d2SAndroid Build Coastguard Worker 	       /*
470*5e7646d2SAndroid Build Coastguard Worker 		* This choice works...
471*5e7646d2SAndroid Build Coastguard Worker 		*/
472*5e7646d2SAndroid Build Coastguard Worker 
473*5e7646d2SAndroid Build Coastguard Worker 		num_newopts = cupsAddOption(constptr->option->keyword,
474*5e7646d2SAndroid Build Coastguard Worker 					    cptr->choice, num_newopts,
475*5e7646d2SAndroid Build Coastguard Worker 					    &newopts);
476*5e7646d2SAndroid Build Coastguard Worker 		changed     = 1;
477*5e7646d2SAndroid Build Coastguard Worker 		break;
478*5e7646d2SAndroid Build Coastguard Worker 	      }
479*5e7646d2SAndroid Build Coastguard Worker 	    }
480*5e7646d2SAndroid Build Coastguard Worker 
481*5e7646d2SAndroid Build Coastguard Worker 	    cupsArrayDelete(test);
482*5e7646d2SAndroid Build Coastguard Worker           }
483*5e7646d2SAndroid Build Coastguard Worker         }
484*5e7646d2SAndroid Build Coastguard Worker       }
485*5e7646d2SAndroid Build Coastguard Worker     }
486*5e7646d2SAndroid Build Coastguard Worker 
487*5e7646d2SAndroid Build Coastguard Worker     if (!changed)
488*5e7646d2SAndroid Build Coastguard Worker     {
489*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("1cupsResolveConflicts: Unable to automatically resolve "
490*5e7646d2SAndroid Build Coastguard Worker 		 "constraint!");
491*5e7646d2SAndroid Build Coastguard Worker       goto error;
492*5e7646d2SAndroid Build Coastguard Worker     }
493*5e7646d2SAndroid Build Coastguard Worker 
494*5e7646d2SAndroid Build Coastguard Worker     cupsArrayClear(pass);
495*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(active);
496*5e7646d2SAndroid Build Coastguard Worker     active = NULL;
497*5e7646d2SAndroid Build Coastguard Worker   }
498*5e7646d2SAndroid Build Coastguard Worker 
499*5e7646d2SAndroid Build Coastguard Worker   if (tries >= 100)
500*5e7646d2SAndroid Build Coastguard Worker     goto error;
501*5e7646d2SAndroid Build Coastguard Worker 
502*5e7646d2SAndroid Build Coastguard Worker  /*
503*5e7646d2SAndroid Build Coastguard Worker   * Free the caller's option array...
504*5e7646d2SAndroid Build Coastguard Worker   */
505*5e7646d2SAndroid Build Coastguard Worker 
506*5e7646d2SAndroid Build Coastguard Worker   cupsFreeOptions(*num_options, *options);
507*5e7646d2SAndroid Build Coastguard Worker 
508*5e7646d2SAndroid Build Coastguard Worker  /*
509*5e7646d2SAndroid Build Coastguard Worker   * If Collate is the option we are testing, add it here.  Otherwise, remove
510*5e7646d2SAndroid Build Coastguard Worker   * any Collate option from the resolve list since the filters automatically
511*5e7646d2SAndroid Build Coastguard Worker   * handle manual collation...
512*5e7646d2SAndroid Build Coastguard Worker   */
513*5e7646d2SAndroid Build Coastguard Worker 
514*5e7646d2SAndroid Build Coastguard Worker   if (option && !_cups_strcasecmp(option, "Collate"))
515*5e7646d2SAndroid Build Coastguard Worker     num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);
516*5e7646d2SAndroid Build Coastguard Worker   else
517*5e7646d2SAndroid Build Coastguard Worker     num_newopts = cupsRemoveOption("Collate", num_newopts, &newopts);
518*5e7646d2SAndroid Build Coastguard Worker 
519*5e7646d2SAndroid Build Coastguard Worker  /*
520*5e7646d2SAndroid Build Coastguard Worker   * Return the new list of options to the caller...
521*5e7646d2SAndroid Build Coastguard Worker   */
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker   *num_options = num_newopts;
524*5e7646d2SAndroid Build Coastguard Worker   *options     = newopts;
525*5e7646d2SAndroid Build Coastguard Worker 
526*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pass);
527*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(resolvers);
528*5e7646d2SAndroid Build Coastguard Worker 
529*5e7646d2SAndroid Build Coastguard Worker   cupsArrayRestore(ppd->sorted_attrs);
530*5e7646d2SAndroid Build Coastguard Worker 
531*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1cupsResolveConflicts: Returning %d options:", num_newopts));
532*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
533*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < num_newopts; i ++)
534*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1cupsResolveConflicts: options[%d]: %s=%s", i,
535*5e7646d2SAndroid Build Coastguard Worker                   newopts[i].name, newopts[i].value));
536*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
537*5e7646d2SAndroid Build Coastguard Worker 
538*5e7646d2SAndroid Build Coastguard Worker   return (1);
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker  /*
541*5e7646d2SAndroid Build Coastguard Worker   * If we get here, we failed to resolve...
542*5e7646d2SAndroid Build Coastguard Worker   */
543*5e7646d2SAndroid Build Coastguard Worker 
544*5e7646d2SAndroid Build Coastguard Worker   error:
545*5e7646d2SAndroid Build Coastguard Worker 
546*5e7646d2SAndroid Build Coastguard Worker   cupsFreeOptions(num_newopts, newopts);
547*5e7646d2SAndroid Build Coastguard Worker 
548*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(active);
549*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pass);
550*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(resolvers);
551*5e7646d2SAndroid Build Coastguard Worker 
552*5e7646d2SAndroid Build Coastguard Worker   cupsArrayRestore(ppd->sorted_attrs);
553*5e7646d2SAndroid Build Coastguard Worker 
554*5e7646d2SAndroid Build Coastguard Worker   DEBUG_puts("1cupsResolveConflicts: Unable to resolve conflicts!");
555*5e7646d2SAndroid Build Coastguard Worker 
556*5e7646d2SAndroid Build Coastguard Worker   return (0);
557*5e7646d2SAndroid Build Coastguard Worker }
558*5e7646d2SAndroid Build Coastguard Worker 
559*5e7646d2SAndroid Build Coastguard Worker 
560*5e7646d2SAndroid Build Coastguard Worker /*
561*5e7646d2SAndroid Build Coastguard Worker  * 'ppdConflicts()' - Check to see if there are any conflicts among the
562*5e7646d2SAndroid Build Coastguard Worker  *                    marked option choices.
563*5e7646d2SAndroid Build Coastguard Worker  *
564*5e7646d2SAndroid Build Coastguard Worker  * The returned value is the same as returned by @link ppdMarkOption@.
565*5e7646d2SAndroid Build Coastguard Worker  */
566*5e7646d2SAndroid Build Coastguard Worker 
567*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of conflicts found */
ppdConflicts(ppd_file_t * ppd)568*5e7646d2SAndroid Build Coastguard Worker ppdConflicts(ppd_file_t *ppd)		/* I - PPD to check */
569*5e7646d2SAndroid Build Coastguard Worker {
570*5e7646d2SAndroid Build Coastguard Worker   int			i,		/* Looping variable */
571*5e7646d2SAndroid Build Coastguard Worker 			conflicts;	/* Number of conflicts */
572*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*active;	/* Active conflicts */
573*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconsts_t	*c;		/* Current constraints */
574*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconst_t	*cptr;		/* Current constraint */
575*5e7646d2SAndroid Build Coastguard Worker   ppd_option_t	*o;			/* Current option */
576*5e7646d2SAndroid Build Coastguard Worker 
577*5e7646d2SAndroid Build Coastguard Worker 
578*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
579*5e7646d2SAndroid Build Coastguard Worker     return (0);
580*5e7646d2SAndroid Build Coastguard Worker 
581*5e7646d2SAndroid Build Coastguard Worker  /*
582*5e7646d2SAndroid Build Coastguard Worker   * Clear all conflicts...
583*5e7646d2SAndroid Build Coastguard Worker   */
584*5e7646d2SAndroid Build Coastguard Worker 
585*5e7646d2SAndroid Build Coastguard Worker   cupsArraySave(ppd->options);
586*5e7646d2SAndroid Build Coastguard Worker 
587*5e7646d2SAndroid Build Coastguard Worker   for (o = ppdFirstOption(ppd); o; o = ppdNextOption(ppd))
588*5e7646d2SAndroid Build Coastguard Worker     o->conflicted = 0;
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker   cupsArrayRestore(ppd->options);
591*5e7646d2SAndroid Build Coastguard Worker 
592*5e7646d2SAndroid Build Coastguard Worker  /*
593*5e7646d2SAndroid Build Coastguard Worker   * Test for conflicts...
594*5e7646d2SAndroid Build Coastguard Worker   */
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker   active    = ppd_test_constraints(ppd, NULL, NULL, 0, NULL,
597*5e7646d2SAndroid Build Coastguard Worker                                    _PPD_ALL_CONSTRAINTS);
598*5e7646d2SAndroid Build Coastguard Worker   conflicts = cupsArrayCount(active);
599*5e7646d2SAndroid Build Coastguard Worker 
600*5e7646d2SAndroid Build Coastguard Worker  /*
601*5e7646d2SAndroid Build Coastguard Worker   * Loop through all of the UI constraints and flag any options
602*5e7646d2SAndroid Build Coastguard Worker   * that conflict...
603*5e7646d2SAndroid Build Coastguard Worker   */
604*5e7646d2SAndroid Build Coastguard Worker 
605*5e7646d2SAndroid Build Coastguard Worker   for (c = (_ppd_cups_uiconsts_t *)cupsArrayFirst(active);
606*5e7646d2SAndroid Build Coastguard Worker        c;
607*5e7646d2SAndroid Build Coastguard Worker        c = (_ppd_cups_uiconsts_t *)cupsArrayNext(active))
608*5e7646d2SAndroid Build Coastguard Worker   {
609*5e7646d2SAndroid Build Coastguard Worker     for (i = c->num_constraints, cptr = c->constraints;
610*5e7646d2SAndroid Build Coastguard Worker          i > 0;
611*5e7646d2SAndroid Build Coastguard Worker 	 i --, cptr ++)
612*5e7646d2SAndroid Build Coastguard Worker       cptr->option->conflicted = 1;
613*5e7646d2SAndroid Build Coastguard Worker   }
614*5e7646d2SAndroid Build Coastguard Worker 
615*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(active);
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker  /*
618*5e7646d2SAndroid Build Coastguard Worker   * Return the number of conflicts found...
619*5e7646d2SAndroid Build Coastguard Worker   */
620*5e7646d2SAndroid Build Coastguard Worker 
621*5e7646d2SAndroid Build Coastguard Worker   return (conflicts);
622*5e7646d2SAndroid Build Coastguard Worker }
623*5e7646d2SAndroid Build Coastguard Worker 
624*5e7646d2SAndroid Build Coastguard Worker 
625*5e7646d2SAndroid Build Coastguard Worker /*
626*5e7646d2SAndroid Build Coastguard Worker  * 'ppdInstallableConflict()' - Test whether an option choice conflicts with
627*5e7646d2SAndroid Build Coastguard Worker  *                              an installable option.
628*5e7646d2SAndroid Build Coastguard Worker  *
629*5e7646d2SAndroid Build Coastguard Worker  * This function tests whether a particular option choice is available based
630*5e7646d2SAndroid Build Coastguard Worker  * on constraints against options in the "InstallableOptions" group.
631*5e7646d2SAndroid Build Coastguard Worker  *
632*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.4/macOS 10.6@
633*5e7646d2SAndroid Build Coastguard Worker  */
634*5e7646d2SAndroid Build Coastguard Worker 
635*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 if conflicting, 0 if not conflicting */
ppdInstallableConflict(ppd_file_t * ppd,const char * option,const char * choice)636*5e7646d2SAndroid Build Coastguard Worker ppdInstallableConflict(
637*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t *ppd,			/* I - PPD file */
638*5e7646d2SAndroid Build Coastguard Worker     const char *option,			/* I - Option */
639*5e7646d2SAndroid Build Coastguard Worker     const char *choice)			/* I - Choice */
640*5e7646d2SAndroid Build Coastguard Worker {
641*5e7646d2SAndroid Build Coastguard Worker   cups_array_t	*active;		/* Active conflicts */
642*5e7646d2SAndroid Build Coastguard Worker 
643*5e7646d2SAndroid Build Coastguard Worker 
644*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ppdInstallableConflict(ppd=%p, option=\"%s\", choice=\"%s\")",
645*5e7646d2SAndroid Build Coastguard Worker                 ppd, option, choice));
646*5e7646d2SAndroid Build Coastguard Worker 
647*5e7646d2SAndroid Build Coastguard Worker  /*
648*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
649*5e7646d2SAndroid Build Coastguard Worker   */
650*5e7646d2SAndroid Build Coastguard Worker 
651*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !option || !choice)
652*5e7646d2SAndroid Build Coastguard Worker     return (0);
653*5e7646d2SAndroid Build Coastguard Worker 
654*5e7646d2SAndroid Build Coastguard Worker  /*
655*5e7646d2SAndroid Build Coastguard Worker   * Test constraints using the new option...
656*5e7646d2SAndroid Build Coastguard Worker   */
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker   active = ppd_test_constraints(ppd, option, choice, 0, NULL,
659*5e7646d2SAndroid Build Coastguard Worker 				_PPD_INSTALLABLE_CONSTRAINTS);
660*5e7646d2SAndroid Build Coastguard Worker 
661*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(active);
662*5e7646d2SAndroid Build Coastguard Worker 
663*5e7646d2SAndroid Build Coastguard Worker   return (active != NULL);
664*5e7646d2SAndroid Build Coastguard Worker }
665*5e7646d2SAndroid Build Coastguard Worker 
666*5e7646d2SAndroid Build Coastguard Worker 
667*5e7646d2SAndroid Build Coastguard Worker /*
668*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_is_installable()' - Determine whether an option is in the
669*5e7646d2SAndroid Build Coastguard Worker  *                          InstallableOptions group.
670*5e7646d2SAndroid Build Coastguard Worker  */
671*5e7646d2SAndroid Build Coastguard Worker 
672*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 if installable, 0 if normal */
ppd_is_installable(ppd_group_t * installable,const char * name)673*5e7646d2SAndroid Build Coastguard Worker ppd_is_installable(
674*5e7646d2SAndroid Build Coastguard Worker     ppd_group_t *installable,		/* I - InstallableOptions group */
675*5e7646d2SAndroid Build Coastguard Worker     const char  *name)			/* I - Option name */
676*5e7646d2SAndroid Build Coastguard Worker {
677*5e7646d2SAndroid Build Coastguard Worker   if (installable)
678*5e7646d2SAndroid Build Coastguard Worker   {
679*5e7646d2SAndroid Build Coastguard Worker     int			i;		/* Looping var */
680*5e7646d2SAndroid Build Coastguard Worker     ppd_option_t	*option;	/* Current option */
681*5e7646d2SAndroid Build Coastguard Worker 
682*5e7646d2SAndroid Build Coastguard Worker 
683*5e7646d2SAndroid Build Coastguard Worker     for (i = installable->num_options, option = installable->options;
684*5e7646d2SAndroid Build Coastguard Worker          i > 0;
685*5e7646d2SAndroid Build Coastguard Worker 	 i --, option ++)
686*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(option->keyword, name))
687*5e7646d2SAndroid Build Coastguard Worker         return (1);
688*5e7646d2SAndroid Build Coastguard Worker   }
689*5e7646d2SAndroid Build Coastguard Worker 
690*5e7646d2SAndroid Build Coastguard Worker   return (0);
691*5e7646d2SAndroid Build Coastguard Worker }
692*5e7646d2SAndroid Build Coastguard Worker 
693*5e7646d2SAndroid Build Coastguard Worker 
694*5e7646d2SAndroid Build Coastguard Worker /*
695*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_load_constraints()' - Load constraints from a PPD file.
696*5e7646d2SAndroid Build Coastguard Worker  */
697*5e7646d2SAndroid Build Coastguard Worker 
698*5e7646d2SAndroid Build Coastguard Worker static void
ppd_load_constraints(ppd_file_t * ppd)699*5e7646d2SAndroid Build Coastguard Worker ppd_load_constraints(ppd_file_t *ppd)	/* I - PPD file */
700*5e7646d2SAndroid Build Coastguard Worker {
701*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
702*5e7646d2SAndroid Build Coastguard Worker   ppd_const_t	*oldconst;		/* Current UIConstraints data */
703*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t	*constattr;		/* Current cupsUIConstraints attribute */
704*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconsts_t	*consts;	/* Current cupsUIConstraints data */
705*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
706*5e7646d2SAndroid Build Coastguard Worker   ppd_group_t	*installable;		/* Installable options group */
707*5e7646d2SAndroid Build Coastguard Worker   const char	*vptr;			/* Pointer into constraint value */
708*5e7646d2SAndroid Build Coastguard Worker   char		option[PPD_MAX_NAME],	/* Option name/MainKeyword */
709*5e7646d2SAndroid Build Coastguard Worker 		choice[PPD_MAX_NAME],	/* Choice/OptionKeyword */
710*5e7646d2SAndroid Build Coastguard Worker 		*ptr;			/* Pointer into option or choice */
711*5e7646d2SAndroid Build Coastguard Worker 
712*5e7646d2SAndroid Build Coastguard Worker 
713*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("7ppd_load_constraints(ppd=%p)", ppd));
714*5e7646d2SAndroid Build Coastguard Worker 
715*5e7646d2SAndroid Build Coastguard Worker  /*
716*5e7646d2SAndroid Build Coastguard Worker   * Create an array to hold the constraint data...
717*5e7646d2SAndroid Build Coastguard Worker   */
718*5e7646d2SAndroid Build Coastguard Worker 
719*5e7646d2SAndroid Build Coastguard Worker   ppd->cups_uiconstraints = cupsArrayNew(NULL, NULL);
720*5e7646d2SAndroid Build Coastguard Worker 
721*5e7646d2SAndroid Build Coastguard Worker  /*
722*5e7646d2SAndroid Build Coastguard Worker   * Find the installable options group if it exists...
723*5e7646d2SAndroid Build Coastguard Worker   */
724*5e7646d2SAndroid Build Coastguard Worker 
725*5e7646d2SAndroid Build Coastguard Worker   for (i = ppd->num_groups, installable = ppd->groups;
726*5e7646d2SAndroid Build Coastguard Worker        i > 0;
727*5e7646d2SAndroid Build Coastguard Worker        i --, installable ++)
728*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(installable->name, "InstallableOptions"))
729*5e7646d2SAndroid Build Coastguard Worker       break;
730*5e7646d2SAndroid Build Coastguard Worker 
731*5e7646d2SAndroid Build Coastguard Worker   if (i <= 0)
732*5e7646d2SAndroid Build Coastguard Worker     installable = NULL;
733*5e7646d2SAndroid Build Coastguard Worker 
734*5e7646d2SAndroid Build Coastguard Worker  /*
735*5e7646d2SAndroid Build Coastguard Worker   * Load old-style [Non]UIConstraints data...
736*5e7646d2SAndroid Build Coastguard Worker   */
737*5e7646d2SAndroid Build Coastguard Worker 
738*5e7646d2SAndroid Build Coastguard Worker   for (i = ppd->num_consts, oldconst = ppd->consts; i > 0; i --, oldconst ++)
739*5e7646d2SAndroid Build Coastguard Worker   {
740*5e7646d2SAndroid Build Coastguard Worker    /*
741*5e7646d2SAndroid Build Coastguard Worker     * Weed out nearby duplicates, since the PPD spec requires that you
742*5e7646d2SAndroid Build Coastguard Worker     * define both "*Foo foo *Bar bar" and "*Bar bar *Foo foo"...
743*5e7646d2SAndroid Build Coastguard Worker     */
744*5e7646d2SAndroid Build Coastguard Worker 
745*5e7646d2SAndroid Build Coastguard Worker     if (i > 1 &&
746*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(oldconst[0].option1, oldconst[1].option2) &&
747*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(oldconst[0].choice1, oldconst[1].choice2) &&
748*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(oldconst[0].option2, oldconst[1].option1) &&
749*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(oldconst[0].choice2, oldconst[1].choice1))
750*5e7646d2SAndroid Build Coastguard Worker       continue;
751*5e7646d2SAndroid Build Coastguard Worker 
752*5e7646d2SAndroid Build Coastguard Worker    /*
753*5e7646d2SAndroid Build Coastguard Worker     * Allocate memory...
754*5e7646d2SAndroid Build Coastguard Worker     */
755*5e7646d2SAndroid Build Coastguard Worker 
756*5e7646d2SAndroid Build Coastguard Worker     if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
757*5e7646d2SAndroid Build Coastguard Worker     {
758*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
759*5e7646d2SAndroid Build Coastguard Worker 		 "UIConstraints!");
760*5e7646d2SAndroid Build Coastguard Worker       return;
761*5e7646d2SAndroid Build Coastguard Worker     }
762*5e7646d2SAndroid Build Coastguard Worker 
763*5e7646d2SAndroid Build Coastguard Worker     if ((constptr = calloc(2, sizeof(_ppd_cups_uiconst_t))) == NULL)
764*5e7646d2SAndroid Build Coastguard Worker     {
765*5e7646d2SAndroid Build Coastguard Worker       free(consts);
766*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
767*5e7646d2SAndroid Build Coastguard Worker 		 "UIConstraints!");
768*5e7646d2SAndroid Build Coastguard Worker       return;
769*5e7646d2SAndroid Build Coastguard Worker     }
770*5e7646d2SAndroid Build Coastguard Worker 
771*5e7646d2SAndroid Build Coastguard Worker    /*
772*5e7646d2SAndroid Build Coastguard Worker     * Fill in the information...
773*5e7646d2SAndroid Build Coastguard Worker     */
774*5e7646d2SAndroid Build Coastguard Worker 
775*5e7646d2SAndroid Build Coastguard Worker     consts->num_constraints = 2;
776*5e7646d2SAndroid Build Coastguard Worker     consts->constraints     = constptr;
777*5e7646d2SAndroid Build Coastguard Worker 
778*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strncasecmp(oldconst->option1, "Custom", 6) &&
779*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(oldconst->choice1, "True"))
780*5e7646d2SAndroid Build Coastguard Worker     {
781*5e7646d2SAndroid Build Coastguard Worker       constptr[0].option      = ppdFindOption(ppd, oldconst->option1 + 6);
782*5e7646d2SAndroid Build Coastguard Worker       constptr[0].choice      = ppdFindChoice(constptr[0].option, "Custom");
783*5e7646d2SAndroid Build Coastguard Worker       constptr[0].installable = 0;
784*5e7646d2SAndroid Build Coastguard Worker     }
785*5e7646d2SAndroid Build Coastguard Worker     else
786*5e7646d2SAndroid Build Coastguard Worker     {
787*5e7646d2SAndroid Build Coastguard Worker       constptr[0].option      = ppdFindOption(ppd, oldconst->option1);
788*5e7646d2SAndroid Build Coastguard Worker       constptr[0].choice      = ppdFindChoice(constptr[0].option,
789*5e7646d2SAndroid Build Coastguard Worker 					      oldconst->choice1);
790*5e7646d2SAndroid Build Coastguard Worker       constptr[0].installable = ppd_is_installable(installable,
791*5e7646d2SAndroid Build Coastguard Worker 						   oldconst->option1);
792*5e7646d2SAndroid Build Coastguard Worker     }
793*5e7646d2SAndroid Build Coastguard Worker 
794*5e7646d2SAndroid Build Coastguard Worker     if (!constptr[0].option || (!constptr[0].choice && oldconst->choice1[0]))
795*5e7646d2SAndroid Build Coastguard Worker     {
796*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
797*5e7646d2SAndroid Build Coastguard Worker 		    oldconst->option1, oldconst->choice1));
798*5e7646d2SAndroid Build Coastguard Worker       free(consts->constraints);
799*5e7646d2SAndroid Build Coastguard Worker       free(consts);
800*5e7646d2SAndroid Build Coastguard Worker       continue;
801*5e7646d2SAndroid Build Coastguard Worker     }
802*5e7646d2SAndroid Build Coastguard Worker 
803*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strncasecmp(oldconst->option2, "Custom", 6) &&
804*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(oldconst->choice2, "True"))
805*5e7646d2SAndroid Build Coastguard Worker     {
806*5e7646d2SAndroid Build Coastguard Worker       constptr[1].option      = ppdFindOption(ppd, oldconst->option2 + 6);
807*5e7646d2SAndroid Build Coastguard Worker       constptr[1].choice      = ppdFindChoice(constptr[1].option, "Custom");
808*5e7646d2SAndroid Build Coastguard Worker       constptr[1].installable = 0;
809*5e7646d2SAndroid Build Coastguard Worker     }
810*5e7646d2SAndroid Build Coastguard Worker     else
811*5e7646d2SAndroid Build Coastguard Worker     {
812*5e7646d2SAndroid Build Coastguard Worker       constptr[1].option      = ppdFindOption(ppd, oldconst->option2);
813*5e7646d2SAndroid Build Coastguard Worker       constptr[1].choice      = ppdFindChoice(constptr[1].option,
814*5e7646d2SAndroid Build Coastguard Worker 					      oldconst->choice2);
815*5e7646d2SAndroid Build Coastguard Worker       constptr[1].installable = ppd_is_installable(installable,
816*5e7646d2SAndroid Build Coastguard Worker 						   oldconst->option2);
817*5e7646d2SAndroid Build Coastguard Worker     }
818*5e7646d2SAndroid Build Coastguard Worker 
819*5e7646d2SAndroid Build Coastguard Worker     if (!constptr[1].option || (!constptr[1].choice && oldconst->choice2[0]))
820*5e7646d2SAndroid Build Coastguard Worker     {
821*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
822*5e7646d2SAndroid Build Coastguard Worker 		    oldconst->option2, oldconst->choice2));
823*5e7646d2SAndroid Build Coastguard Worker       free(consts->constraints);
824*5e7646d2SAndroid Build Coastguard Worker       free(consts);
825*5e7646d2SAndroid Build Coastguard Worker       continue;
826*5e7646d2SAndroid Build Coastguard Worker     }
827*5e7646d2SAndroid Build Coastguard Worker 
828*5e7646d2SAndroid Build Coastguard Worker     consts->installable = constptr[0].installable || constptr[1].installable;
829*5e7646d2SAndroid Build Coastguard Worker 
830*5e7646d2SAndroid Build Coastguard Worker    /*
831*5e7646d2SAndroid Build Coastguard Worker     * Add it to the constraints array...
832*5e7646d2SAndroid Build Coastguard Worker     */
833*5e7646d2SAndroid Build Coastguard Worker 
834*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(ppd->cups_uiconstraints, consts);
835*5e7646d2SAndroid Build Coastguard Worker   }
836*5e7646d2SAndroid Build Coastguard Worker 
837*5e7646d2SAndroid Build Coastguard Worker  /*
838*5e7646d2SAndroid Build Coastguard Worker   * Then load new-style constraints...
839*5e7646d2SAndroid Build Coastguard Worker   */
840*5e7646d2SAndroid Build Coastguard Worker 
841*5e7646d2SAndroid Build Coastguard Worker   for (constattr = ppdFindAttr(ppd, "cupsUIConstraints", NULL);
842*5e7646d2SAndroid Build Coastguard Worker        constattr;
843*5e7646d2SAndroid Build Coastguard Worker        constattr = ppdFindNextAttr(ppd, "cupsUIConstraints", NULL))
844*5e7646d2SAndroid Build Coastguard Worker   {
845*5e7646d2SAndroid Build Coastguard Worker     if (!constattr->value)
846*5e7646d2SAndroid Build Coastguard Worker     {
847*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
848*5e7646d2SAndroid Build Coastguard Worker       continue;
849*5e7646d2SAndroid Build Coastguard Worker     }
850*5e7646d2SAndroid Build Coastguard Worker 
851*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, vptr = strchr(constattr->value, '*');
852*5e7646d2SAndroid Build Coastguard Worker 	 vptr;
853*5e7646d2SAndroid Build Coastguard Worker 	 i ++, vptr = strchr(vptr + 1, '*'));
854*5e7646d2SAndroid Build Coastguard Worker 
855*5e7646d2SAndroid Build Coastguard Worker     if (i == 0)
856*5e7646d2SAndroid Build Coastguard Worker     {
857*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
858*5e7646d2SAndroid Build Coastguard Worker       continue;
859*5e7646d2SAndroid Build Coastguard Worker     }
860*5e7646d2SAndroid Build Coastguard Worker 
861*5e7646d2SAndroid Build Coastguard Worker     if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
862*5e7646d2SAndroid Build Coastguard Worker     {
863*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
864*5e7646d2SAndroid Build Coastguard Worker 		 "cupsUIConstraints!");
865*5e7646d2SAndroid Build Coastguard Worker       return;
866*5e7646d2SAndroid Build Coastguard Worker     }
867*5e7646d2SAndroid Build Coastguard Worker 
868*5e7646d2SAndroid Build Coastguard Worker     if ((constptr = calloc((size_t)i, sizeof(_ppd_cups_uiconst_t))) == NULL)
869*5e7646d2SAndroid Build Coastguard Worker     {
870*5e7646d2SAndroid Build Coastguard Worker       free(consts);
871*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
872*5e7646d2SAndroid Build Coastguard Worker 		 "cupsUIConstraints!");
873*5e7646d2SAndroid Build Coastguard Worker       return;
874*5e7646d2SAndroid Build Coastguard Worker     }
875*5e7646d2SAndroid Build Coastguard Worker 
876*5e7646d2SAndroid Build Coastguard Worker     consts->num_constraints = i;
877*5e7646d2SAndroid Build Coastguard Worker     consts->constraints     = constptr;
878*5e7646d2SAndroid Build Coastguard Worker 
879*5e7646d2SAndroid Build Coastguard Worker     strlcpy(consts->resolver, constattr->spec, sizeof(consts->resolver));
880*5e7646d2SAndroid Build Coastguard Worker 
881*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, vptr = strchr(constattr->value, '*');
882*5e7646d2SAndroid Build Coastguard Worker 	 vptr;
883*5e7646d2SAndroid Build Coastguard Worker 	 i ++, vptr = strchr(vptr, '*'), constptr ++)
884*5e7646d2SAndroid Build Coastguard Worker     {
885*5e7646d2SAndroid Build Coastguard Worker      /*
886*5e7646d2SAndroid Build Coastguard Worker       * Extract "*Option Choice" or just "*Option"...
887*5e7646d2SAndroid Build Coastguard Worker       */
888*5e7646d2SAndroid Build Coastguard Worker 
889*5e7646d2SAndroid Build Coastguard Worker       for (vptr ++, ptr = option; *vptr && !_cups_isspace(*vptr); vptr ++)
890*5e7646d2SAndroid Build Coastguard Worker 	if (ptr < (option + sizeof(option) - 1))
891*5e7646d2SAndroid Build Coastguard Worker 	  *ptr++ = *vptr;
892*5e7646d2SAndroid Build Coastguard Worker 
893*5e7646d2SAndroid Build Coastguard Worker       *ptr = '\0';
894*5e7646d2SAndroid Build Coastguard Worker 
895*5e7646d2SAndroid Build Coastguard Worker       while (_cups_isspace(*vptr))
896*5e7646d2SAndroid Build Coastguard Worker 	vptr ++;
897*5e7646d2SAndroid Build Coastguard Worker 
898*5e7646d2SAndroid Build Coastguard Worker       if (*vptr == '*')
899*5e7646d2SAndroid Build Coastguard Worker 	choice[0] = '\0';
900*5e7646d2SAndroid Build Coastguard Worker       else
901*5e7646d2SAndroid Build Coastguard Worker       {
902*5e7646d2SAndroid Build Coastguard Worker 	for (ptr = choice; *vptr && !_cups_isspace(*vptr); vptr ++)
903*5e7646d2SAndroid Build Coastguard Worker 	  if (ptr < (choice + sizeof(choice) - 1))
904*5e7646d2SAndroid Build Coastguard Worker 	    *ptr++ = *vptr;
905*5e7646d2SAndroid Build Coastguard Worker 
906*5e7646d2SAndroid Build Coastguard Worker 	*ptr = '\0';
907*5e7646d2SAndroid Build Coastguard Worker       }
908*5e7646d2SAndroid Build Coastguard Worker 
909*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True"))
910*5e7646d2SAndroid Build Coastguard Worker       {
911*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcpy(option, option + 6);
912*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(choice, "Custom", sizeof(choice));
913*5e7646d2SAndroid Build Coastguard Worker       }
914*5e7646d2SAndroid Build Coastguard Worker 
915*5e7646d2SAndroid Build Coastguard Worker       constptr->option      = ppdFindOption(ppd, option);
916*5e7646d2SAndroid Build Coastguard Worker       constptr->choice      = ppdFindChoice(constptr->option, choice);
917*5e7646d2SAndroid Build Coastguard Worker       constptr->installable = ppd_is_installable(installable, option);
918*5e7646d2SAndroid Build Coastguard Worker       consts->installable   |= constptr->installable;
919*5e7646d2SAndroid Build Coastguard Worker 
920*5e7646d2SAndroid Build Coastguard Worker       if (!constptr->option || (!constptr->choice && choice[0]))
921*5e7646d2SAndroid Build Coastguard Worker       {
922*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
923*5e7646d2SAndroid Build Coastguard Worker 		      option, choice));
924*5e7646d2SAndroid Build Coastguard Worker 	break;
925*5e7646d2SAndroid Build Coastguard Worker       }
926*5e7646d2SAndroid Build Coastguard Worker     }
927*5e7646d2SAndroid Build Coastguard Worker 
928*5e7646d2SAndroid Build Coastguard Worker     if (!vptr)
929*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(ppd->cups_uiconstraints, consts);
930*5e7646d2SAndroid Build Coastguard Worker     else
931*5e7646d2SAndroid Build Coastguard Worker     {
932*5e7646d2SAndroid Build Coastguard Worker       free(consts->constraints);
933*5e7646d2SAndroid Build Coastguard Worker       free(consts);
934*5e7646d2SAndroid Build Coastguard Worker     }
935*5e7646d2SAndroid Build Coastguard Worker   }
936*5e7646d2SAndroid Build Coastguard Worker }
937*5e7646d2SAndroid Build Coastguard Worker 
938*5e7646d2SAndroid Build Coastguard Worker 
939*5e7646d2SAndroid Build Coastguard Worker /*
940*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_test_constraints()' - See if any constraints are active.
941*5e7646d2SAndroid Build Coastguard Worker  */
942*5e7646d2SAndroid Build Coastguard Worker 
943*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *			/* O - Array of active constraints */
ppd_test_constraints(ppd_file_t * ppd,const char * option,const char * choice,int num_options,cups_option_t * options,int which)944*5e7646d2SAndroid Build Coastguard Worker ppd_test_constraints(
945*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t    *ppd,			/* I - PPD file */
946*5e7646d2SAndroid Build Coastguard Worker     const char    *option,		/* I - Current option */
947*5e7646d2SAndroid Build Coastguard Worker     const char    *choice,		/* I - Current choice */
948*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of additional options */
949*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options,		/* I - Additional options */
950*5e7646d2SAndroid Build Coastguard Worker     int           which)		/* I - Which constraints to test */
951*5e7646d2SAndroid Build Coastguard Worker {
952*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
953*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconsts_t	*consts;	/* Current constraints */
954*5e7646d2SAndroid Build Coastguard Worker   _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
955*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t		key,		/* Search key */
956*5e7646d2SAndroid Build Coastguard Worker 			*marked;	/* Marked choice */
957*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*active = NULL;	/* Active constraints */
958*5e7646d2SAndroid Build Coastguard Worker   const char		*value,		/* Current value */
959*5e7646d2SAndroid Build Coastguard Worker 			*firstvalue;	/* AP_FIRSTPAGE_Keyword value */
960*5e7646d2SAndroid Build Coastguard Worker   char			firstpage[255];	/* AP_FIRSTPAGE_Keyword string */
961*5e7646d2SAndroid Build Coastguard Worker 
962*5e7646d2SAndroid Build Coastguard Worker 
963*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("7ppd_test_constraints(ppd=%p, option=\"%s\", choice=\"%s\", "
964*5e7646d2SAndroid Build Coastguard Worker                 "num_options=%d, options=%p, which=%d)", ppd, option, choice,
965*5e7646d2SAndroid Build Coastguard Worker 		num_options, options, which));
966*5e7646d2SAndroid Build Coastguard Worker 
967*5e7646d2SAndroid Build Coastguard Worker   if (!ppd->cups_uiconstraints)
968*5e7646d2SAndroid Build Coastguard Worker     ppd_load_constraints(ppd);
969*5e7646d2SAndroid Build Coastguard Worker 
970*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("9ppd_test_constraints: %d constraints!",
971*5e7646d2SAndroid Build Coastguard Worker 	        cupsArrayCount(ppd->cups_uiconstraints)));
972*5e7646d2SAndroid Build Coastguard Worker 
973*5e7646d2SAndroid Build Coastguard Worker   cupsArraySave(ppd->marked);
974*5e7646d2SAndroid Build Coastguard Worker 
975*5e7646d2SAndroid Build Coastguard Worker   for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(ppd->cups_uiconstraints);
976*5e7646d2SAndroid Build Coastguard Worker        consts;
977*5e7646d2SAndroid Build Coastguard Worker        consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(ppd->cups_uiconstraints))
978*5e7646d2SAndroid Build Coastguard Worker   {
979*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("9ppd_test_constraints: installable=%d, resolver=\"%s\", "
980*5e7646d2SAndroid Build Coastguard Worker                   "num_constraints=%d option1=\"%s\", choice1=\"%s\", "
981*5e7646d2SAndroid Build Coastguard Worker 		  "option2=\"%s\", choice2=\"%s\", ...",
982*5e7646d2SAndroid Build Coastguard Worker 		  consts->installable, consts->resolver, consts->num_constraints,
983*5e7646d2SAndroid Build Coastguard Worker 		  consts->constraints[0].option->keyword,
984*5e7646d2SAndroid Build Coastguard Worker 		  consts->constraints[0].choice ?
985*5e7646d2SAndroid Build Coastguard Worker 		      consts->constraints[0].choice->choice : "",
986*5e7646d2SAndroid Build Coastguard Worker 		  consts->constraints[1].option->keyword,
987*5e7646d2SAndroid Build Coastguard Worker 		  consts->constraints[1].choice ?
988*5e7646d2SAndroid Build Coastguard Worker 		      consts->constraints[1].choice->choice : ""));
989*5e7646d2SAndroid Build Coastguard Worker 
990*5e7646d2SAndroid Build Coastguard Worker     if (consts->installable && which < _PPD_INSTALLABLE_CONSTRAINTS)
991*5e7646d2SAndroid Build Coastguard Worker       continue;				/* Skip installable option constraint */
992*5e7646d2SAndroid Build Coastguard Worker 
993*5e7646d2SAndroid Build Coastguard Worker     if (!consts->installable && which == _PPD_INSTALLABLE_CONSTRAINTS)
994*5e7646d2SAndroid Build Coastguard Worker       continue;				/* Skip non-installable option constraint */
995*5e7646d2SAndroid Build Coastguard Worker 
996*5e7646d2SAndroid Build Coastguard Worker     if ((which == _PPD_OPTION_CONSTRAINTS || which == _PPD_INSTALLABLE_CONSTRAINTS) && option)
997*5e7646d2SAndroid Build Coastguard Worker     {
998*5e7646d2SAndroid Build Coastguard Worker      /*
999*5e7646d2SAndroid Build Coastguard Worker       * Skip constraints that do not involve the current option...
1000*5e7646d2SAndroid Build Coastguard Worker       */
1001*5e7646d2SAndroid Build Coastguard Worker 
1002*5e7646d2SAndroid Build Coastguard Worker       for (i = consts->num_constraints, constptr = consts->constraints;
1003*5e7646d2SAndroid Build Coastguard Worker 	   i > 0;
1004*5e7646d2SAndroid Build Coastguard Worker 	   i --, constptr ++)
1005*5e7646d2SAndroid Build Coastguard Worker       {
1006*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strcasecmp(constptr->option->keyword, option))
1007*5e7646d2SAndroid Build Coastguard Worker 	  break;
1008*5e7646d2SAndroid Build Coastguard Worker 
1009*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strncasecmp(option, "AP_FIRSTPAGE_", 13) &&
1010*5e7646d2SAndroid Build Coastguard Worker 	    !_cups_strcasecmp(constptr->option->keyword, option + 13))
1011*5e7646d2SAndroid Build Coastguard Worker 	  break;
1012*5e7646d2SAndroid Build Coastguard Worker       }
1013*5e7646d2SAndroid Build Coastguard Worker 
1014*5e7646d2SAndroid Build Coastguard Worker       if (!i)
1015*5e7646d2SAndroid Build Coastguard Worker         continue;
1016*5e7646d2SAndroid Build Coastguard Worker     }
1017*5e7646d2SAndroid Build Coastguard Worker 
1018*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("9ppd_test_constraints: Testing...");
1019*5e7646d2SAndroid Build Coastguard Worker 
1020*5e7646d2SAndroid Build Coastguard Worker     for (i = consts->num_constraints, constptr = consts->constraints;
1021*5e7646d2SAndroid Build Coastguard Worker          i > 0;
1022*5e7646d2SAndroid Build Coastguard Worker 	 i --, constptr ++)
1023*5e7646d2SAndroid Build Coastguard Worker     {
1024*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("9ppd_test_constraints: %s=%s?", constptr->option->keyword,
1025*5e7646d2SAndroid Build Coastguard Worker 		    constptr->choice ? constptr->choice->choice : ""));
1026*5e7646d2SAndroid Build Coastguard Worker 
1027*5e7646d2SAndroid Build Coastguard Worker       if (constptr->choice &&
1028*5e7646d2SAndroid Build Coastguard Worker           (!_cups_strcasecmp(constptr->option->keyword, "PageSize") ||
1029*5e7646d2SAndroid Build Coastguard Worker            !_cups_strcasecmp(constptr->option->keyword, "PageRegion")))
1030*5e7646d2SAndroid Build Coastguard Worker       {
1031*5e7646d2SAndroid Build Coastguard Worker        /*
1032*5e7646d2SAndroid Build Coastguard Worker         * PageSize and PageRegion are used depending on the selected input slot
1033*5e7646d2SAndroid Build Coastguard Worker 	* and manual feed mode.  Validate against the selected page size instead
1034*5e7646d2SAndroid Build Coastguard Worker 	* of an individual option...
1035*5e7646d2SAndroid Build Coastguard Worker 	*/
1036*5e7646d2SAndroid Build Coastguard Worker 
1037*5e7646d2SAndroid Build Coastguard Worker         if (option && choice &&
1038*5e7646d2SAndroid Build Coastguard Worker 	    (!_cups_strcasecmp(option, "PageSize") ||
1039*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(option, "PageRegion")))
1040*5e7646d2SAndroid Build Coastguard Worker 	{
1041*5e7646d2SAndroid Build Coastguard Worker 	  value = choice;
1042*5e7646d2SAndroid Build Coastguard Worker         }
1043*5e7646d2SAndroid Build Coastguard Worker 	else if ((value = cupsGetOption("PageSize", num_options,
1044*5e7646d2SAndroid Build Coastguard Worker 	                                options)) == NULL)
1045*5e7646d2SAndroid Build Coastguard Worker 	  if ((value = cupsGetOption("PageRegion", num_options,
1046*5e7646d2SAndroid Build Coastguard Worker 	                             options)) == NULL)
1047*5e7646d2SAndroid Build Coastguard Worker 	    if ((value = cupsGetOption("media", num_options, options)) == NULL)
1048*5e7646d2SAndroid Build Coastguard Worker 	    {
1049*5e7646d2SAndroid Build Coastguard Worker 	      ppd_size_t *size = ppdPageSize(ppd, NULL);
1050*5e7646d2SAndroid Build Coastguard Worker 
1051*5e7646d2SAndroid Build Coastguard Worker               if (size)
1052*5e7646d2SAndroid Build Coastguard Worker 	        value = size->name;
1053*5e7646d2SAndroid Build Coastguard Worker 	    }
1054*5e7646d2SAndroid Build Coastguard Worker 
1055*5e7646d2SAndroid Build Coastguard Worker         if (value && !_cups_strncasecmp(value, "Custom.", 7))
1056*5e7646d2SAndroid Build Coastguard Worker 	  value = "Custom";
1057*5e7646d2SAndroid Build Coastguard Worker 
1058*5e7646d2SAndroid Build Coastguard Worker         if (option && choice &&
1059*5e7646d2SAndroid Build Coastguard Worker 	    (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") ||
1060*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion")))
1061*5e7646d2SAndroid Build Coastguard Worker 	{
1062*5e7646d2SAndroid Build Coastguard Worker 	  firstvalue = choice;
1063*5e7646d2SAndroid Build Coastguard Worker         }
1064*5e7646d2SAndroid Build Coastguard Worker 	else if ((firstvalue = cupsGetOption("AP_FIRSTPAGE_PageSize",
1065*5e7646d2SAndroid Build Coastguard Worker 	                                     num_options, options)) == NULL)
1066*5e7646d2SAndroid Build Coastguard Worker 	  firstvalue = cupsGetOption("AP_FIRSTPAGE_PageRegion", num_options,
1067*5e7646d2SAndroid Build Coastguard Worker 	                             options);
1068*5e7646d2SAndroid Build Coastguard Worker 
1069*5e7646d2SAndroid Build Coastguard Worker         if (firstvalue && !_cups_strncasecmp(firstvalue, "Custom.", 7))
1070*5e7646d2SAndroid Build Coastguard Worker 	  firstvalue = "Custom";
1071*5e7646d2SAndroid Build Coastguard Worker 
1072*5e7646d2SAndroid Build Coastguard Worker         if ((!value || _cups_strcasecmp(value, constptr->choice->choice)) &&
1073*5e7646d2SAndroid Build Coastguard Worker 	    (!firstvalue || _cups_strcasecmp(firstvalue, constptr->choice->choice)))
1074*5e7646d2SAndroid Build Coastguard Worker 	{
1075*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("9ppd_test_constraints: NO");
1076*5e7646d2SAndroid Build Coastguard Worker 	  break;
1077*5e7646d2SAndroid Build Coastguard Worker 	}
1078*5e7646d2SAndroid Build Coastguard Worker       }
1079*5e7646d2SAndroid Build Coastguard Worker       else if (constptr->choice)
1080*5e7646d2SAndroid Build Coastguard Worker       {
1081*5e7646d2SAndroid Build Coastguard Worker        /*
1082*5e7646d2SAndroid Build Coastguard Worker         * Compare against the constrained choice...
1083*5e7646d2SAndroid Build Coastguard Worker 	*/
1084*5e7646d2SAndroid Build Coastguard Worker 
1085*5e7646d2SAndroid Build Coastguard Worker         if (option && choice && !_cups_strcasecmp(option, constptr->option->keyword))
1086*5e7646d2SAndroid Build Coastguard Worker 	{
1087*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strncasecmp(choice, "Custom.", 7))
1088*5e7646d2SAndroid Build Coastguard Worker 	    value = "Custom";
1089*5e7646d2SAndroid Build Coastguard Worker 	  else
1090*5e7646d2SAndroid Build Coastguard Worker 	    value = choice;
1091*5e7646d2SAndroid Build Coastguard Worker 	}
1092*5e7646d2SAndroid Build Coastguard Worker         else if ((value = cupsGetOption(constptr->option->keyword, num_options,
1093*5e7646d2SAndroid Build Coastguard Worker 	                                options)) != NULL)
1094*5e7646d2SAndroid Build Coastguard Worker         {
1095*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strncasecmp(value, "Custom.", 7))
1096*5e7646d2SAndroid Build Coastguard Worker 	    value = "Custom";
1097*5e7646d2SAndroid Build Coastguard Worker 	}
1098*5e7646d2SAndroid Build Coastguard Worker         else if (constptr->choice->marked)
1099*5e7646d2SAndroid Build Coastguard Worker 	  value = constptr->choice->choice;
1100*5e7646d2SAndroid Build Coastguard Worker 	else
1101*5e7646d2SAndroid Build Coastguard Worker 	  value = NULL;
1102*5e7646d2SAndroid Build Coastguard Worker 
1103*5e7646d2SAndroid Build Coastguard Worker        /*
1104*5e7646d2SAndroid Build Coastguard Worker         * Now check AP_FIRSTPAGE_option...
1105*5e7646d2SAndroid Build Coastguard Worker 	*/
1106*5e7646d2SAndroid Build Coastguard Worker 
1107*5e7646d2SAndroid Build Coastguard Worker         snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s",
1108*5e7646d2SAndroid Build Coastguard Worker 	         constptr->option->keyword);
1109*5e7646d2SAndroid Build Coastguard Worker 
1110*5e7646d2SAndroid Build Coastguard Worker         if (option && choice && !_cups_strcasecmp(option, firstpage))
1111*5e7646d2SAndroid Build Coastguard Worker 	{
1112*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strncasecmp(choice, "Custom.", 7))
1113*5e7646d2SAndroid Build Coastguard Worker 	    firstvalue = "Custom";
1114*5e7646d2SAndroid Build Coastguard Worker 	  else
1115*5e7646d2SAndroid Build Coastguard Worker 	    firstvalue = choice;
1116*5e7646d2SAndroid Build Coastguard Worker 	}
1117*5e7646d2SAndroid Build Coastguard Worker         else if ((firstvalue = cupsGetOption(firstpage, num_options,
1118*5e7646d2SAndroid Build Coastguard Worker 	                                     options)) != NULL)
1119*5e7646d2SAndroid Build Coastguard Worker         {
1120*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strncasecmp(firstvalue, "Custom.", 7))
1121*5e7646d2SAndroid Build Coastguard Worker 	    firstvalue = "Custom";
1122*5e7646d2SAndroid Build Coastguard Worker 	}
1123*5e7646d2SAndroid Build Coastguard Worker 	else
1124*5e7646d2SAndroid Build Coastguard Worker 	  firstvalue = NULL;
1125*5e7646d2SAndroid Build Coastguard Worker 
1126*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("9ppd_test_constraints: value=%s, firstvalue=%s", value,
1127*5e7646d2SAndroid Build Coastguard Worker 	              firstvalue));
1128*5e7646d2SAndroid Build Coastguard Worker 
1129*5e7646d2SAndroid Build Coastguard Worker         if ((!value || _cups_strcasecmp(value, constptr->choice->choice)) &&
1130*5e7646d2SAndroid Build Coastguard Worker 	    (!firstvalue || _cups_strcasecmp(firstvalue, constptr->choice->choice)))
1131*5e7646d2SAndroid Build Coastguard Worker 	{
1132*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("9ppd_test_constraints: NO");
1133*5e7646d2SAndroid Build Coastguard Worker 	  break;
1134*5e7646d2SAndroid Build Coastguard Worker 	}
1135*5e7646d2SAndroid Build Coastguard Worker       }
1136*5e7646d2SAndroid Build Coastguard Worker       else if (option && choice &&
1137*5e7646d2SAndroid Build Coastguard Worker                !_cups_strcasecmp(option, constptr->option->keyword))
1138*5e7646d2SAndroid Build Coastguard Worker       {
1139*5e7646d2SAndroid Build Coastguard Worker 	if (!_cups_strcasecmp(choice, "None") || !_cups_strcasecmp(choice, "Off") ||
1140*5e7646d2SAndroid Build Coastguard Worker 	    !_cups_strcasecmp(choice, "False"))
1141*5e7646d2SAndroid Build Coastguard Worker 	{
1142*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("9ppd_test_constraints: NO");
1143*5e7646d2SAndroid Build Coastguard Worker 	  break;
1144*5e7646d2SAndroid Build Coastguard Worker 	}
1145*5e7646d2SAndroid Build Coastguard Worker       }
1146*5e7646d2SAndroid Build Coastguard Worker       else if ((value = cupsGetOption(constptr->option->keyword, num_options,
1147*5e7646d2SAndroid Build Coastguard Worker 				      options)) != NULL)
1148*5e7646d2SAndroid Build Coastguard Worker       {
1149*5e7646d2SAndroid Build Coastguard Worker 	if (!_cups_strcasecmp(value, "None") || !_cups_strcasecmp(value, "Off") ||
1150*5e7646d2SAndroid Build Coastguard Worker 	    !_cups_strcasecmp(value, "False"))
1151*5e7646d2SAndroid Build Coastguard Worker 	{
1152*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("9ppd_test_constraints: NO");
1153*5e7646d2SAndroid Build Coastguard Worker 	  break;
1154*5e7646d2SAndroid Build Coastguard Worker 	}
1155*5e7646d2SAndroid Build Coastguard Worker       }
1156*5e7646d2SAndroid Build Coastguard Worker       else
1157*5e7646d2SAndroid Build Coastguard Worker       {
1158*5e7646d2SAndroid Build Coastguard Worker 	key.option = constptr->option;
1159*5e7646d2SAndroid Build Coastguard Worker 
1160*5e7646d2SAndroid Build Coastguard Worker 	if ((marked = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key))
1161*5e7646d2SAndroid Build Coastguard Worker 		== NULL ||
1162*5e7646d2SAndroid Build Coastguard Worker 	    (!_cups_strcasecmp(marked->choice, "None") ||
1163*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(marked->choice, "Off") ||
1164*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(marked->choice, "False")))
1165*5e7646d2SAndroid Build Coastguard Worker 	{
1166*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("9ppd_test_constraints: NO");
1167*5e7646d2SAndroid Build Coastguard Worker 	  break;
1168*5e7646d2SAndroid Build Coastguard Worker 	}
1169*5e7646d2SAndroid Build Coastguard Worker       }
1170*5e7646d2SAndroid Build Coastguard Worker     }
1171*5e7646d2SAndroid Build Coastguard Worker 
1172*5e7646d2SAndroid Build Coastguard Worker     if (i <= 0)
1173*5e7646d2SAndroid Build Coastguard Worker     {
1174*5e7646d2SAndroid Build Coastguard Worker       if (!active)
1175*5e7646d2SAndroid Build Coastguard Worker         active = cupsArrayNew(NULL, NULL);
1176*5e7646d2SAndroid Build Coastguard Worker 
1177*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(active, consts);
1178*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("9ppd_test_constraints: Added...");
1179*5e7646d2SAndroid Build Coastguard Worker     }
1180*5e7646d2SAndroid Build Coastguard Worker   }
1181*5e7646d2SAndroid Build Coastguard Worker 
1182*5e7646d2SAndroid Build Coastguard Worker   cupsArrayRestore(ppd->marked);
1183*5e7646d2SAndroid Build Coastguard Worker 
1184*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("8ppd_test_constraints: Found %d active constraints!",
1185*5e7646d2SAndroid Build Coastguard Worker                 cupsArrayCount(active)));
1186*5e7646d2SAndroid Build Coastguard Worker 
1187*5e7646d2SAndroid Build Coastguard Worker   return (active);
1188*5e7646d2SAndroid Build Coastguard Worker }
1189