4 * Option marking routines for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * PostScript is a trademark of Adobe Systems, Inc.
17 * This file is subject to the Apple OS-Developed Software exception.
21 * cupsResolveConflicts() - Resolve conflicts in a marked PPD.
22 * ppdConflicts() - Check to see if there are any conflicts among
23 * the marked option choices.
24 * ppdInstallableConflict() - Test whether an option choice conflicts with an
26 * ppd_is_installable() - Determine whether an option is in the
27 * InstallableOptions group.
28 * ppd_load_constraints() - Load constraints from a PPD file.
29 * ppd_test_constraints() - See if any constraints are active.
33 * Include necessary headers...
36 #include "ppd-private.h"
47 _PPD_NORMAL_CONSTRAINTS
,
48 _PPD_INSTALLABLE_CONSTRAINTS
,
57 static int ppd_is_installable(ppd_group_t
*installable
,
59 static void ppd_load_constraints(ppd_file_t
*ppd
);
60 static cups_array_t
*ppd_test_constraints(ppd_file_t
*ppd
,
64 cups_option_t
*options
,
69 * 'cupsResolveConflicts()' - Resolve conflicts in a marked PPD.
71 * This function attempts to resolve any conflicts in a marked PPD, returning
72 * a list of option changes that are required to resolve them. On input,
73 * "num_options" and "options" contain any pending option changes that have
74 * not yet been marked, while "option" and "choice" contain the most recent
75 * selection which may or may not be in "num_options" or "options".
77 * On successful return, "num_options" and "options" are updated to contain
78 * "option" and "choice" along with any changes required to resolve conflicts
79 * specified in the PPD file and 1 is returned.
81 * If option conflicts cannot be resolved, "num_options" and "options" are not
82 * changed and 0 is returned.
84 * When resolving conflicts, @code cupsResolveConflicts@ does not consider
85 * changes to the current page size (@code media@, @code PageSize@, and
86 * @code PageRegion@) or to the most recent option specified in "option".
87 * Thus, if the only way to resolve a conflict is to change the page size
88 * or the option the user most recently changed, @code cupsResolveConflicts@
89 * will return 0 to indicate it was unable to resolve the conflicts.
91 * The @code cupsResolveConflicts@ function uses one of two sources of option
92 * constraint information. The preferred constraint information is defined by
93 * @code cupsUIConstraints@ and @code cupsUIResolver@ attributes - in this
94 * case, the PPD file provides constraint resolution actions.
96 * The backup constraint information is defined by the
97 * @code UIConstraints@ and @code NonUIConstraints@ attributes. These
98 * constraints are resolved algorithmically by first selecting the default
99 * choice for the conflicting option, then iterating over all possible choices
100 * until a non-conflicting option choice is found.
105 int /* O - 1 on success, 0 on failure */
106 cupsResolveConflicts(
107 ppd_file_t
*ppd
, /* I - PPD file */
108 const char *option
, /* I - Newly selected option or @code NULL@ for none */
109 const char *choice
, /* I - Newly selected choice or @code NULL@ for none */
110 int *num_options
, /* IO - Number of additional selected options */
111 cups_option_t
**options
) /* IO - Additional selected options */
113 int i
, /* Looping var */
114 num_newopts
, /* Number of new options */
115 num_resopts
; /* Number of resolver options */
116 cups_option_t
*newopts
, /* New options */
117 *resopts
; /* Resolver options */
118 cups_array_t
*active
, /* Active constraints */
119 *pass
, /* Resolvers for this pass */
120 *resolvers
; /* Resolvers we have used */
121 _ppd_cups_uiconsts_t
*consts
; /* Current constraints */
122 _ppd_cups_uiconst_t
*constptr
; /* Current constraint */
123 ppd_attr_t
*resolver
; /* Current resolver */
124 const char *value
; /* Selected option value */
125 int changed
; /* Did we change anything? */
126 ppd_choice_t
*marked
; /* Marked choice */
130 * Range check input...
133 if (!ppd
|| !num_options
|| !options
|| (option
== NULL
) != (choice
== NULL
))
137 * Build a shadow option array...
143 for (i
= 0; i
< *num_options
; i
++)
144 num_newopts
= cupsAddOption((*options
)[i
].name
, (*options
)[i
].value
,
145 num_newopts
, &newopts
);
146 if (option
&& strcasecmp(option
, "Collate"))
147 num_newopts
= cupsAddOption(option
, choice
, num_newopts
, &newopts
);
150 * Loop until we have no conflicts...
153 cupsArraySave(ppd
->sorted_attrs
);
156 pass
= cupsArrayNew((cups_array_func_t
)strcasecmp
, NULL
);
158 while ((active
= ppd_test_constraints(ppd
, NULL
, NULL
, num_newopts
, newopts
,
159 _PPD_ALL_CONSTRAINTS
)) != NULL
)
162 resolvers
= cupsArrayNew((cups_array_func_t
)strcasecmp
, NULL
);
164 for (consts
= (_ppd_cups_uiconsts_t
*)cupsArrayFirst(active
), changed
= 0;
166 consts
= (_ppd_cups_uiconsts_t
*)cupsArrayNext(active
))
168 if (consts
->resolver
[0])
171 * Look up the resolver...
174 if (cupsArrayFind(pass
, consts
->resolver
))
175 continue; /* Already applied this resolver... */
177 if (cupsArrayFind(resolvers
, consts
->resolver
))
183 DEBUG_printf(("ppdResolveConflicts: Resolver loop with %s!\n",
188 if ((resolver
= ppdFindAttr(ppd
, "cupsUIResolver",
189 consts
->resolver
)) == NULL
)
191 DEBUG_printf(("ppdResolveConflicts: Resolver %s not found!\n",
196 if (!resolver
->value
)
198 DEBUG_printf(("ppdResolveConflicts: Resolver %s has no value!\n",
204 * Add the options from the resolver...
207 cupsArrayAdd(pass
, consts
->resolver
);
208 cupsArrayAdd(resolvers
, consts
->resolver
);
210 if (option
&& choice
)
213 num_resopts
= _ppdParseOptions(resolver
->value
, 0, &resopts
);
215 if ((value
= cupsGetOption(option
, num_newopts
, newopts
)) != NULL
&&
216 !strcasecmp(value
, choice
))
218 DEBUG_printf(("cupsResolveConflicts: Resolver %s changes %s!\n",
219 consts
->resolver
, option
));
220 cupsFreeOptions(num_resopts
, resopts
);
224 cupsFreeOptions(num_resopts
, resopts
);
227 num_newopts
= _ppdParseOptions(resolver
->value
, num_newopts
, &newopts
);
233 * Try resolving by choosing the default values for non-installable
234 * options, then by iterating through the possible choices...
237 int j
; /* Looping var */
238 ppd_choice_t
*cptr
; /* Current choice */
239 cups_array_t
*test
; /* Test array for conflicts */
242 for (i
= consts
->num_constraints
, constptr
= consts
->constraints
;
246 if (constptr
->installable
||
247 !strcasecmp(constptr
->option
->keyword
, "PageSize") ||
248 !strcasecmp(constptr
->option
->keyword
, "PageRegion"))
251 if (option
&& !strcasecmp(constptr
->option
->keyword
, option
))
254 if ((value
= cupsGetOption(constptr
->option
->keyword
, num_newopts
,
257 marked
= ppdFindMarkedChoice(ppd
, constptr
->option
->keyword
);
258 value
= marked
? marked
->choice
: "";
262 * Try the default choice...
267 if (strcasecmp(value
, constptr
->option
->defchoice
) &&
268 (test
= ppd_test_constraints(ppd
, constptr
->option
->keyword
,
269 constptr
->option
->defchoice
,
270 num_newopts
, newopts
,
271 _PPD_ALL_CONSTRAINTS
)) == NULL
)
277 num_newopts
= cupsAddOption(constptr
->option
->keyword
,
278 constptr
->option
->defchoice
,
279 num_newopts
, &newopts
);
285 * Try each choice instead...
288 cupsArrayDelete(test
);
290 for (j
= constptr
->option
->num_choices
,
291 cptr
= constptr
->option
->choices
;
297 if (strcasecmp(value
, cptr
->choice
) &&
298 strcasecmp(constptr
->option
->defchoice
, cptr
->choice
) &&
299 (test
= ppd_test_constraints(ppd
, constptr
->option
->keyword
,
300 cptr
->choice
, num_newopts
,
302 _PPD_ALL_CONSTRAINTS
)) == NULL
)
305 * This choice works...
308 num_newopts
= cupsAddOption(constptr
->option
->keyword
,
309 cptr
->choice
, num_newopts
,
315 cupsArrayDelete(test
);
323 DEBUG_puts("ppdResolveConflicts: Unable to automatically resolve "
329 cupsArrayClear(pass
);
330 cupsArrayDelete(active
);
334 * Free the caller's option array...
337 cupsFreeOptions(*num_options
, *options
);
340 * If Collate is the option we are testing, add it here. Otherwise, remove
341 * any Collate option from the resolve list since the filters automatically
342 * handle manual collation...
345 if (option
&& !strcasecmp(option
, "Collate"))
346 num_newopts
= cupsAddOption(option
, choice
, num_newopts
, &newopts
);
348 num_newopts
= cupsRemoveOption("Collate", num_newopts
, &newopts
);
351 * Return the new list of options to the caller...
354 *num_options
= num_newopts
;
357 cupsArrayDelete(pass
);
358 cupsArrayDelete(resolvers
);
360 cupsArrayRestore(ppd
->sorted_attrs
);
365 * If we get here, we failed to resolve...
370 cupsFreeOptions(num_newopts
, newopts
);
372 cupsArrayDelete(pass
);
373 cupsArrayDelete(resolvers
);
375 cupsArrayRestore(ppd
->sorted_attrs
);
382 * 'ppdConflicts()' - Check to see if there are any conflicts among the
383 * marked option choices.
385 * The returned value is the same as returned by @link ppdMarkOption@.
388 int /* O - Number of conflicts found */
389 ppdConflicts(ppd_file_t
*ppd
) /* I - PPD to check */
391 int i
, /* Looping variable */
392 conflicts
; /* Number of conflicts */
393 cups_array_t
*active
; /* Active conflicts */
394 _ppd_cups_uiconsts_t
*c
; /* Current constraints */
395 _ppd_cups_uiconst_t
*cptr
; /* Current constraint */
396 ppd_option_t
*o
; /* Current option */
403 * Clear all conflicts...
406 for (o
= ppdFirstOption(ppd
); o
; o
= ppdNextOption(ppd
))
410 * Test for conflicts...
413 active
= ppd_test_constraints(ppd
, NULL
, NULL
, 0, NULL
,
414 _PPD_ALL_CONSTRAINTS
);
415 conflicts
= cupsArrayCount(active
);
418 * Loop through all of the UI constraints and flag any options
422 for (c
= (_ppd_cups_uiconsts_t
*)cupsArrayFirst(active
);
424 c
= (_ppd_cups_uiconsts_t
*)cupsArrayNext(active
))
426 for (i
= c
->num_constraints
, cptr
= c
->constraints
;
429 cptr
->option
->conflicted
= 1;
432 cupsArrayDelete(active
);
435 * Return the number of conflicts found...
443 * 'ppdInstallableConflict()' - Test whether an option choice conflicts with
444 * an installable option.
446 * This function tests whether a particular option choice is available based
447 * on constraints against options in the "InstallableOptions" group.
452 int /* O - 1 if conflicting, 0 if not conflicting */
453 ppdInstallableConflict(
454 ppd_file_t
*ppd
, /* I - PPD file */
455 const char *option
, /* I - Option */
456 const char *choice
) /* I - Choice */
458 cups_array_t
*active
; /* Active conflicts */
462 * Range check input...
465 if (!ppd
|| !option
|| !choice
)
469 * Test constraints using the new option...
472 active
= ppd_test_constraints(ppd
, option
, choice
, 0, NULL
,
473 _PPD_INSTALLABLE_CONSTRAINTS
);
475 cupsArrayDelete(active
);
477 return (active
!= NULL
);
482 * 'ppd_is_installable()' - Determine whether an option is in the
483 * InstallableOptions group.
486 static int /* O - 1 if installable, 0 if normal */
488 ppd_group_t
*installable
, /* I - InstallableOptions group */
489 const char *name
) /* I - Option name */
493 int i
; /* Looping var */
494 ppd_option_t
*option
; /* Current option */
497 for (i
= installable
->num_options
, option
= installable
->options
;
500 if (!strcasecmp(option
->keyword
, name
))
509 * 'ppd_load_constraints()' - Load constraints from a PPD file.
513 ppd_load_constraints(ppd_file_t
*ppd
) /* I - PPD file */
515 int i
; /* Looping var */
516 ppd_const_t
*oldconst
; /* Current UIConstraints data */
517 ppd_attr_t
*constattr
; /* Current cupsUIConstraints attribute */
518 _ppd_cups_uiconsts_t
*consts
; /* Current cupsUIConstraints data */
519 _ppd_cups_uiconst_t
*constptr
; /* Current constraint */
520 ppd_group_t
*installable
; /* Installable options group */
521 const char *vptr
; /* Pointer into constraint value */
522 char option
[PPD_MAX_NAME
], /* Option name/MainKeyword */
523 choice
[PPD_MAX_NAME
], /* Choice/OptionKeyword */
524 *ptr
; /* Pointer into option or choice */
528 * Create an array to hold the constraint data...
531 ppd
->cups_uiconstraints
= cupsArrayNew(NULL
, NULL
);
534 * Find the installable options group if it exists...
537 for (i
= ppd
->num_groups
, installable
= ppd
->groups
;
539 i
--, installable
++)
540 if (!strcasecmp(installable
->name
, "InstallableOptions"))
547 * Load old-style [Non]UIConstraints data...
550 for (i
= ppd
->num_consts
, oldconst
= ppd
->consts
; i
> 0; i
--, oldconst
++)
553 * Weed out nearby duplicates, since the PPD spec requires that you
554 * define both "*Foo foo *Bar bar" and "*Bar bar *Foo foo"...
558 !strcasecmp(oldconst
[0].option1
, oldconst
[1].option2
) &&
559 !strcasecmp(oldconst
[0].choice1
, oldconst
[1].choice2
) &&
560 !strcasecmp(oldconst
[0].option2
, oldconst
[1].option1
) &&
561 !strcasecmp(oldconst
[0].choice2
, oldconst
[1].choice1
))
568 if ((consts
= calloc(1, sizeof(_ppd_cups_uiconsts_t
))) == NULL
)
570 DEBUG_puts("ppd_load_constraints: Unable to allocate memory for "
575 if ((constptr
= calloc(2, sizeof(_ppd_cups_uiconst_t
))) == NULL
)
578 DEBUG_puts("ppd_load_constraints: Unable to allocate memory for "
584 * Fill in the information...
587 consts
->num_constraints
= 2;
588 consts
->constraints
= constptr
;
590 if (!strncasecmp(oldconst
->option1
, "Custom", 6) &&
591 !strcasecmp(oldconst
->choice1
, "True"))
593 constptr
[0].option
= ppdFindOption(ppd
, oldconst
->option1
+ 6);
594 constptr
[0].choice
= ppdFindChoice(constptr
[0].option
, "Custom");
595 constptr
[0].installable
= 0;
599 constptr
[0].option
= ppdFindOption(ppd
, oldconst
->option1
);
600 constptr
[0].choice
= ppdFindChoice(constptr
[0].option
,
602 constptr
[0].installable
= ppd_is_installable(installable
,
606 if (!constptr
[0].option
|| (!constptr
[0].choice
&& oldconst
->choice1
[0]))
608 DEBUG_printf(("ppd_load_constraints: Unknown option *%s %s!\n",
609 oldconst
->option1
, oldconst
->choice1
));
610 free(consts
->constraints
);
615 if (!strncasecmp(oldconst
->option2
, "Custom", 6) &&
616 !strcasecmp(oldconst
->choice2
, "True"))
618 constptr
[1].option
= ppdFindOption(ppd
, oldconst
->option2
+ 6);
619 constptr
[1].choice
= ppdFindChoice(constptr
[1].option
, "Custom");
620 constptr
[1].installable
= 0;
624 constptr
[1].option
= ppdFindOption(ppd
, oldconst
->option2
);
625 constptr
[1].choice
= ppdFindChoice(constptr
[1].option
,
627 constptr
[1].installable
= ppd_is_installable(installable
,
631 if (!constptr
[1].option
|| (!constptr
[1].choice
&& oldconst
->choice2
[0]))
633 DEBUG_printf(("ppd_load_constraints: Unknown option *%s %s!\n",
634 oldconst
->option2
, oldconst
->choice2
));
635 free(consts
->constraints
);
640 consts
->installable
= constptr
[0].installable
|| constptr
[1].installable
;
643 * Add it to the constraints array...
646 cupsArrayAdd(ppd
->cups_uiconstraints
, consts
);
650 * Then load new-style constraints...
653 for (constattr
= ppdFindAttr(ppd
, "cupsUIConstraints", NULL
);
655 constattr
= ppdFindNextAttr(ppd
, "cupsUIConstraints", NULL
))
657 if (!constattr
->value
)
659 DEBUG_puts("ppd_load_constraints: Bad cupsUIConstraints value!");
663 for (i
= 0, vptr
= strchr(constattr
->value
, '*');
665 i
++, vptr
= strchr(vptr
+ 1, '*'));
669 DEBUG_puts("ppd_load_constraints: Bad cupsUIConstraints value!");
673 if ((consts
= calloc(1, sizeof(_ppd_cups_uiconsts_t
))) == NULL
)
675 DEBUG_puts("ppd_load_constraints: Unable to allocate memory for "
676 "cupsUIConstraints!");
680 if ((constptr
= calloc(i
, sizeof(_ppd_cups_uiconst_t
))) == NULL
)
683 DEBUG_puts("ppd_load_constraints: Unable to allocate memory for "
684 "cupsUIConstraints!");
688 consts
->num_constraints
= i
;
689 consts
->constraints
= constptr
;
691 strlcpy(consts
->resolver
, constattr
->spec
, sizeof(consts
->resolver
));
693 for (i
= 0, vptr
= strchr(constattr
->value
, '*');
695 i
++, vptr
= strchr(vptr
, '*'), constptr
++)
698 * Extract "*Option Choice" or just "*Option"...
701 for (vptr
++, ptr
= option
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
702 if (ptr
< (option
+ sizeof(option
) - 1))
707 while (isspace(*vptr
& 255))
714 for (ptr
= choice
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
715 if (ptr
< (choice
+ sizeof(choice
) - 1))
721 if (!strncasecmp(option
, "Custom", 6) && !strcasecmp(choice
, "True"))
723 _cups_strcpy(option
, option
+ 6);
724 strcpy(choice
, "Custom");
727 constptr
->option
= ppdFindOption(ppd
, option
);
728 constptr
->choice
= ppdFindChoice(constptr
->option
, choice
);
729 constptr
->installable
= ppd_is_installable(installable
, option
);
730 consts
->installable
|= constptr
->installable
;
732 if (!constptr
->option
|| (!constptr
->choice
&& choice
[0]))
734 DEBUG_printf(("ppd_load_constraints: Unknown option *%s %s!\n",
741 cupsArrayAdd(ppd
->cups_uiconstraints
, consts
);
744 free(consts
->constraints
);
752 * 'ppd_test_constraints()' - See if any constraints are active.
755 static cups_array_t
* /* O - Array of active constraints */
756 ppd_test_constraints(
757 ppd_file_t
*ppd
, /* I - PPD file */
758 const char *option
, /* I - Current option */
759 const char *choice
, /* I - Current choice */
760 int num_options
, /* I - Number of additional options */
761 cups_option_t
*options
, /* I - Additional options */
762 int which
) /* I - Which constraints to test */
764 int i
; /* Looping var */
765 _ppd_cups_uiconsts_t
*consts
; /* Current constraints */
766 _ppd_cups_uiconst_t
*constptr
; /* Current constraint */
767 ppd_choice_t key
, /* Search key */
768 *marked
; /* Marked choice */
769 cups_array_t
*active
= NULL
; /* Active constraints */
770 const char *value
; /* Current value */
771 int option_conflict
;/* Conflict with current option? */
774 DEBUG_printf(("ppd_test_constraints(ppd=%p, num_options=%d, options=%p, "
775 "which=%d)\n", ppd
, num_options
, options
, which
));
777 if (!ppd
->cups_uiconstraints
)
778 ppd_load_constraints(ppd
);
780 DEBUG_printf(("ppd_test_constraints: %d constraints!\n",
781 cupsArrayCount(ppd
->cups_uiconstraints
)));
783 cupsArraySave(ppd
->marked
);
785 for (consts
= (_ppd_cups_uiconsts_t
*)cupsArrayFirst(ppd
->cups_uiconstraints
);
787 consts
= (_ppd_cups_uiconsts_t
*)cupsArrayNext(ppd
->cups_uiconstraints
))
789 DEBUG_printf(("ppd_test_constraints: installable=%d, resolver=\"%s\", "
790 "num_constraints=%d option1=\"%s\", choice1=\"%s\", "
791 "option2=\"%s\", choice2=\"%s\", ...\n",
792 consts
->installable
, consts
->resolver
, consts
->num_constraints
,
793 consts
->constraints
[0].option
->keyword
,
794 consts
->constraints
[0].choice
?
795 consts
->constraints
[0].choice
->choice
: "",
796 consts
->constraints
[1].option
->keyword
,
797 consts
->constraints
[1].choice
?
798 consts
->constraints
[1].choice
->choice
: ""));
800 if (which
!= _PPD_ALL_CONSTRAINTS
&& which
!= consts
->installable
)
803 DEBUG_puts("ppd_test_constraints: Testing...");
805 for (i
= consts
->num_constraints
, constptr
= consts
->constraints
,
810 DEBUG_printf(("ppd_test_constraints: %s=%s?\n", constptr
->option
->keyword
,
811 constptr
->choice
? constptr
->choice
->choice
: ""));
813 if (constptr
->choice
&&
814 (!strcasecmp(constptr
->option
->keyword
, "PageSize") ||
815 !strcasecmp(constptr
->option
->keyword
, "PageRegion")))
818 * PageSize and PageRegion are used depending on the selected input slot
819 * and manual feed mode. Validate against the selected page size instead
820 * of an individual option...
823 if (option
&& choice
&&
824 (!strcasecmp(option
, "PageSize") ||
825 !strcasecmp(option
, "PageRegion")))
829 if (!strcasecmp(value
, constptr
->choice
->choice
))
832 else if ((value
= cupsGetOption("PageSize", num_options
,
834 if ((value
= cupsGetOption("PageRegion", num_options
,
836 if ((value
= cupsGetOption("media", num_options
, options
)) == NULL
)
838 ppd_size_t
*size
= ppdPageSize(ppd
, NULL
);
844 if (!value
|| strcasecmp(value
, constptr
->choice
->choice
))
846 DEBUG_puts("ppd_test_constraints: NO");
850 else if (constptr
->choice
)
852 if (option
&& choice
&& !strcasecmp(option
, constptr
->option
->keyword
))
854 if (strcasecmp(choice
, constptr
->choice
->choice
))
859 else if ((value
= cupsGetOption(constptr
->option
->keyword
, num_options
,
862 if (strcasecmp(value
, constptr
->choice
->choice
))
864 DEBUG_puts("ppd_test_constraints: NO");
868 else if (!constptr
->choice
->marked
)
870 DEBUG_puts("ppd_test_constraints: NO");
874 else if (option
&& choice
&&
875 !strcasecmp(option
, constptr
->option
->keyword
))
877 if (!strcasecmp(choice
, "None") || !strcasecmp(choice
, "Off") ||
878 !strcasecmp(choice
, "False"))
883 else if ((value
= cupsGetOption(constptr
->option
->keyword
, num_options
,
886 if (!strcasecmp(value
, "None") || !strcasecmp(value
, "Off") ||
887 !strcasecmp(value
, "False"))
889 DEBUG_puts("ppd_test_constraints: NO");
895 key
.option
= constptr
->option
;
897 if ((marked
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
))
899 (!strcasecmp(marked
->choice
, "None") ||
900 !strcasecmp(marked
->choice
, "Off") ||
901 !strcasecmp(marked
->choice
, "False")))
903 DEBUG_puts("ppd_test_constraints: NO");
909 if (i
<= 0 && (!option
|| option_conflict
))
912 active
= cupsArrayNew(NULL
, NULL
);
914 cupsArrayAdd(active
, consts
);
915 DEBUG_puts("ppd_test_constraints: Added...");
919 cupsArrayRestore(ppd
->marked
);
921 DEBUG_printf(("ppd_test_constraints: Found %d active constraints!\n",
922 cupsArrayCount(active
)));