2 * "$Id: mark.c 9042 2010-03-24 00:45:34Z mike $"
4 * Option marking routines for CUPS.
6 * Copyright 2007-2010 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 * cupsMarkOptions() - Mark command-line options in a PPD file.
22 * ppdFindChoice() - Return a pointer to an option choice.
23 * ppdFindMarkedChoice() - Return the marked choice for the specified option.
24 * ppdFindOption() - Return a pointer to the specified option.
25 * ppdIsMarked() - Check to see if an option is marked.
26 * ppdMarkDefaults() - Mark all default options in the PPD file.
27 * ppdMarkOption() - Mark an option in a PPD file and return the number
29 * ppdFirstOption() - Return the first option in the PPD file.
30 * ppdNextOption() - Return the next option in the PPD file.
31 * _ppdParseOptions() - Parse options from a PPD file.
32 * ppd_debug_marked() - Output the marked array to stdout...
33 * ppd_defaults() - Set the defaults for this group and all sub-groups.
34 * ppd_mark_choices() - Mark one or more option choices from a string.
35 * ppd_mark_option() - Quickly mark an option without checking for
40 * Include necessary headers...
43 #include "cups-private.h"
51 static void ppd_debug_marked(ppd_file_t
*ppd
, const char *title
);
53 # define ppd_debug_marked(ppd,title)
55 static void ppd_defaults(ppd_file_t
*ppd
, ppd_group_t
*g
);
56 static void ppd_mark_choices(ppd_file_t
*ppd
, const char *s
);
57 static void ppd_mark_option(ppd_file_t
*ppd
, const char *option
,
62 * 'cupsMarkOptions()' - Mark command-line options in a PPD file.
64 * This function maps the IPP "finishings", "media", "mirror",
65 * "multiple-document-handling", "output-bin", "printer-resolution", and
66 * "sides" attributes to their corresponding PPD options and choices.
69 int /* O - 1 if conflicts exist, 0 otherwise */
71 ppd_file_t
*ppd
, /* I - PPD file */
72 int num_options
, /* I - Number of options */
73 cups_option_t
*options
) /* I - Options */
75 int i
, j
; /* Looping vars */
76 char *ptr
, /* Pointer into string */
77 s
[255]; /* Temporary string */
78 const char *val
, /* Pointer into value */
79 *media
, /* media option */
80 *output_bin
, /* output-bin option */
81 *output_mode
, /* output-mode option */
82 *page_size
, /* PageSize option */
83 *ppd_keyword
, /* PPD keyword */
84 *print_quality
, /* print-quality option */
85 *sides
; /* sides option */
86 cups_option_t
*optptr
; /* Current option */
87 ppd_attr_t
*attr
; /* PPD attribute */
88 _pwg_t
*pwg
; /* PWG mapping data */
95 if (!ppd
|| num_options
<= 0 || !options
)
98 ppd_debug_marked(ppd
, "Before...");
101 * Do special handling for finishings, media, output-bin, output-mode,
102 * print-color-mode, print-quality, and PageSize...
105 media
= cupsGetOption("media", num_options
, options
);
106 output_bin
= cupsGetOption("output-bin", num_options
, options
);
107 output_mode
= cupsGetOption("output-mode", num_options
, options
);
108 page_size
= cupsGetOption("PageSize", num_options
, options
);
109 print_quality
= cupsGetOption("print-quality", num_options
, options
);
110 sides
= cupsGetOption("sides", num_options
, options
);
112 if ((media
|| output_bin
|| output_mode
|| print_quality
|| sides
) &&
116 * Load PWG mapping data as needed...
119 ppd
->pwg
= _pwgCreateWithPPD(ppd
);
122 pwg
= (_pwg_t
*)ppd
->pwg
;
127 * Loop through the option string, separating it at commas and marking each
128 * individual option as long as the corresponding PPD option (PageSize,
129 * InputSlot, etc.) is not also set.
131 * For PageSize, we also check for an empty option value since some versions
132 * of MacOS X use it to specify auto-selection of the media based solely on
136 for (val
= media
; *val
;)
139 * Extract the sub-option from the string...
142 for (ptr
= s
; *val
&& *val
!= ',' && (ptr
- s
) < (sizeof(s
) - 1);)
153 if (!page_size
|| !page_size
[0])
155 if (!strncasecmp(s
, "Custom.", 7) || ppdPageSize(ppd
, s
))
156 ppd_mark_option(ppd
, "PageSize", s
);
157 else if ((ppd_keyword
= _pwgGetPageSize(pwg
, NULL
, s
, NULL
)) != NULL
)
158 ppd_mark_option(ppd
, "PageSize", ppd_keyword
);
161 if (pwg
&& pwg
->source_option
&&
162 !cupsGetOption(pwg
->source_option
, num_options
, options
) &&
163 (ppd_keyword
= _pwgGetInputSlot(pwg
, NULL
, s
)) != NULL
)
164 ppd_mark_option(ppd
, pwg
->source_option
, ppd_keyword
);
166 if (!cupsGetOption("MediaType", num_options
, options
) &&
167 (ppd_keyword
= _pwgGetMediaType(pwg
, NULL
, s
)) != NULL
)
168 ppd_mark_option(ppd
, "MediaType", ppd_keyword
);
174 if (!cupsGetOption("com.apple.print.DocumentTicket.PMSpoolFormat",
175 num_options
, options
) &&
176 !cupsGetOption("APPrinterPreset", num_options
, options
) &&
177 (output_mode
|| print_quality
))
180 * Map output-mode and print-quality to a preset...
183 _pwg_output_mode_t pwg_om
; /* output-mode index */
184 _pwg_print_quality_t pwg_pq
; /* print-quality index */
185 cups_option_t
*preset
;/* Current preset option */
187 if (output_mode
&& !strcmp(output_mode
, "monochrome"))
188 pwg_om
= _PWG_OUTPUT_MODE_MONOCHROME
;
190 pwg_om
= _PWG_OUTPUT_MODE_COLOR
;
194 pwg_pq
= atoi(print_quality
) - IPP_QUALITY_DRAFT
;
195 if (pwg_pq
< _PWG_PRINT_QUALITY_DRAFT
)
196 pwg_pq
= _PWG_PRINT_QUALITY_DRAFT
;
197 else if (pwg_pq
> _PWG_PRINT_QUALITY_HIGH
)
198 pwg_pq
= _PWG_PRINT_QUALITY_HIGH
;
201 pwg_pq
= _PWG_PRINT_QUALITY_NORMAL
;
203 if (pwg
->num_presets
[pwg_om
][pwg_pq
] == 0)
206 * Try to find a preset that works so that we maximize the chances of us
207 * getting a good print using IPP attributes.
210 if (pwg
->num_presets
[pwg_om
][_PWG_PRINT_QUALITY_NORMAL
] > 0)
211 pwg_pq
= _PWG_PRINT_QUALITY_NORMAL
;
212 else if (pwg
->num_presets
[_PWG_OUTPUT_MODE_COLOR
][pwg_pq
] > 0)
213 pwg_om
= _PWG_OUTPUT_MODE_COLOR
;
216 pwg_pq
= _PWG_PRINT_QUALITY_NORMAL
;
217 pwg_om
= _PWG_OUTPUT_MODE_COLOR
;
221 if (pwg
->num_presets
[pwg_om
][pwg_pq
] > 0)
224 * Copy the preset options as long as the corresponding names are not
225 * already defined in the IPP request...
228 for (i
= pwg
->num_presets
[pwg_om
][pwg_pq
],
229 preset
= pwg
->presets
[pwg_om
][pwg_pq
];
233 if (!cupsGetOption(preset
->name
, num_options
, options
))
234 ppd_mark_option(ppd
, preset
->name
, preset
->value
);
239 if (output_bin
&& !cupsGetOption("OutputBin", num_options
, options
) &&
240 (ppd_keyword
= _pwgGetOutputBin(pwg
, output_bin
)) != NULL
)
243 * Map output-bin to OutputBin...
246 ppd_mark_option(ppd
, "OutputBin", ppd_keyword
);
249 if (sides
&& pwg
->sides_option
&&
250 !cupsGetOption(pwg
->sides_option
, num_options
, options
))
253 * Map sides to duplex option...
256 if (!strcmp(sides
, "one-sided"))
257 ppd_mark_option(ppd
, pwg
->sides_option
, pwg
->sides_1sided
);
258 else if (!strcmp(sides
, "two-sided-long-edge"))
259 ppd_mark_option(ppd
, pwg
->sides_option
, pwg
->sides_2sided_long
);
260 else if (!strcmp(sides
, "two-sided-short-edge"))
261 ppd_mark_option(ppd
, pwg
->sides_option
, pwg
->sides_2sided_short
);
266 * Mark other options...
269 for (i
= num_options
, optptr
= options
; i
> 0; i
--, optptr
++)
270 if (!strcasecmp(optptr
->name
, "media") ||
271 !strcasecmp(optptr
->name
, "output-bin") ||
272 !strcasecmp(optptr
->name
, "output-mode") ||
273 !strcasecmp(optptr
->name
, "print-quality") ||
274 !strcasecmp(optptr
->name
, "sides"))
276 else if (!strcasecmp(optptr
->name
, "resolution") ||
277 !strcasecmp(optptr
->name
, "printer-resolution"))
279 ppd_mark_option(ppd
, "Resolution", optptr
->value
);
280 ppd_mark_option(ppd
, "SetResolution", optptr
->value
);
281 /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
282 ppd_mark_option(ppd
, "JCLResolution", optptr
->value
);
284 ppd_mark_option(ppd
, "CNRes_PGP", optptr
->value
);
287 else if (!strcasecmp(optptr
->name
, "multiple-document-handling"))
289 if (!cupsGetOption("Collate", num_options
, options
) &&
290 ppdFindOption(ppd
, "Collate"))
292 if (strcasecmp(optptr
->value
, "separate-documents-uncollated-copies"))
293 ppd_mark_option(ppd
, "Collate", "True");
295 ppd_mark_option(ppd
, "Collate", "False");
298 else if (!strcasecmp(optptr
->name
, "finishings"))
301 * Lookup cupsIPPFinishings attributes for each value...
304 for (ptr
= optptr
->value
; *ptr
;)
307 * Get the next finishings number...
310 if (!isdigit(*ptr
& 255))
313 if ((j
= strtol(ptr
, &ptr
, 10)) < 3)
317 * Skip separator as needed...
324 * Look it up in the PPD file...
329 if ((attr
= ppdFindAttr(ppd
, "cupsIPPFinishings", s
)) == NULL
)
333 * Apply "*Option Choice" settings from the attribute value...
336 ppd_mark_choices(ppd
, attr
->value
);
339 else if (!strcasecmp(optptr
->name
, "APPrinterPreset"))
342 * Lookup APPrinterPreset value...
345 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset", optptr
->value
)) != NULL
)
348 * Apply "*Option Choice" settings from the attribute value...
351 ppd_mark_choices(ppd
, attr
->value
);
354 else if (!strcasecmp(optptr
->name
, "mirror"))
355 ppd_mark_option(ppd
, "MirrorPrint", optptr
->value
);
357 ppd_mark_option(ppd
, optptr
->name
, optptr
->value
);
359 ppd_debug_marked(ppd
, "After...");
361 return (ppdConflicts(ppd
) > 0);
366 * 'ppdFindChoice()' - Return a pointer to an option choice.
369 ppd_choice_t
* /* O - Choice pointer or @code NULL@ */
370 ppdFindChoice(ppd_option_t
*o
, /* I - Pointer to option */
371 const char *choice
) /* I - Name of choice */
373 int i
; /* Looping var */
374 ppd_choice_t
*c
; /* Current choice */
380 if (choice
[0] == '{' || !strncasecmp(choice
, "Custom.", 7))
383 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
384 if (!strcasecmp(c
->choice
, choice
))
392 * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
395 ppd_choice_t
* /* O - Pointer to choice or @code NULL@ */
396 ppdFindMarkedChoice(ppd_file_t
*ppd
, /* I - PPD file */
397 const char *option
) /* I - Keyword/option name */
399 ppd_choice_t key
, /* Search key for choice */
400 *marked
; /* Marked choice */
403 DEBUG_printf(("2ppdFindMarkedChoice(ppd=%p, option=\"%s\")", ppd
, option
));
405 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
407 DEBUG_puts("3ppdFindMarkedChoice: Option not found, returning NULL");
411 marked
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
);
413 DEBUG_printf(("3ppdFindMarkedChoice: Returning %p(%s)...", marked
,
414 marked
? marked
->choice
: "NULL"));
421 * 'ppdFindOption()' - Return a pointer to the specified option.
424 ppd_option_t
* /* O - Pointer to option or @code NULL@ */
425 ppdFindOption(ppd_file_t
*ppd
, /* I - PPD file data */
426 const char *option
) /* I - Option/Keyword name */
429 * Range check input...
438 * Search in the array...
441 ppd_option_t key
; /* Option search key */
444 strlcpy(key
.keyword
, option
, sizeof(key
.keyword
));
446 return ((ppd_option_t
*)cupsArrayFind(ppd
->options
, &key
));
451 * Search in each group...
454 int i
, j
; /* Looping vars */
455 ppd_group_t
*group
; /* Current group */
456 ppd_option_t
*optptr
; /* Current option */
459 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
460 for (j
= group
->num_options
, optptr
= group
->options
;
463 if (!strcasecmp(optptr
->keyword
, option
))
472 * 'ppdIsMarked()' - Check to see if an option is marked.
475 int /* O - Non-zero if option is marked */
476 ppdIsMarked(ppd_file_t
*ppd
, /* I - PPD file data */
477 const char *option
, /* I - Option/Keyword name */
478 const char *choice
) /* I - Choice name */
480 ppd_choice_t key
, /* Search key */
481 *c
; /* Choice pointer */
487 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
490 if ((c
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) == NULL
)
493 return (!strcmp(c
->choice
, choice
));
498 * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
502 ppdMarkDefaults(ppd_file_t
*ppd
) /* I - PPD file record */
504 int i
; /* Looping variables */
505 ppd_group_t
*g
; /* Current group */
506 ppd_choice_t
*c
; /* Current choice */
513 * Clean out the marked array...
516 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
518 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
520 cupsArrayRemove(ppd
->marked
, c
);
525 * Then repopulate it with the defaults...
528 for (i
= ppd
->num_groups
, g
= ppd
->groups
; i
> 0; i
--, g
++)
529 ppd_defaults(ppd
, g
);
534 * 'ppdMarkOption()' - Mark an option in a PPD file and return the number of
538 int /* O - Number of conflicts */
539 ppdMarkOption(ppd_file_t
*ppd
, /* I - PPD file record */
540 const char *option
, /* I - Keyword */
541 const char *choice
) /* I - Option name */
543 DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")",
544 ppd
, option
, choice
));
547 * Range check input...
550 if (!ppd
|| !option
|| !choice
)
557 ppd_mark_option(ppd
, option
, choice
);
560 * Return the number of conflicts...
563 return (ppdConflicts(ppd
));
568 * 'ppdFirstOption()' - Return the first option in the PPD file.
570 * Options are returned from all groups in ascending alphanumeric order.
572 * @since CUPS 1.2/Mac OS X 10.5@
575 ppd_option_t
* /* O - First option or @code NULL@ */
576 ppdFirstOption(ppd_file_t
*ppd
) /* I - PPD file */
581 return ((ppd_option_t
*)cupsArrayFirst(ppd
->options
));
586 * 'ppdNextOption()' - Return the next option in the PPD file.
588 * Options are returned from all groups in ascending alphanumeric order.
590 * @since CUPS 1.2/Mac OS X 10.5@
593 ppd_option_t
* /* O - Next option or @code NULL@ */
594 ppdNextOption(ppd_file_t
*ppd
) /* I - PPD file */
599 return ((ppd_option_t
*)cupsArrayNext(ppd
->options
));
604 * '_ppdParseOptions()' - Parse options from a PPD file.
606 * This function looks for strings of the form:
608 * *option choice ... *optionN choiceN
609 * property value ... propertyN valueN
611 * It stops when it finds a string that doesn't match this format.
614 int /* O - Number of options */
616 const char *s
, /* I - String to parse */
617 int num_options
, /* I - Number of options */
618 cups_option_t
**options
, /* IO - Options */
619 _ppd_parse_t which
) /* I - What to parse */
621 char option
[PPD_MAX_NAME
* 2 + 1], /* Current option/property */
622 choice
[PPD_MAX_NAME
], /* Current choice/value */
623 *ptr
; /* Pointer into option or choice */
627 return (num_options
);
630 * Read all of the "*Option Choice" and "property value" pairs from the
631 * string, add them to an options array as we go...
637 * Skip leading whitespace...
640 while (_cups_isspace(*s
))
644 * Get the option/property name...
648 while (*s
&& !_cups_isspace(*s
) && ptr
< (option
+ sizeof(option
) - 1))
651 if (ptr
== s
|| !_cups_isspace(*s
))
660 while (_cups_isspace(*s
))
667 while (*s
&& !_cups_isspace(*s
) && ptr
< (choice
+ sizeof(choice
) - 1))
670 if (*s
&& !_cups_isspace(*s
))
676 * Add it to the options array...
679 if (option
[0] == '*' && which
!= _PPD_PARSE_PROPERTIES
)
680 num_options
= cupsAddOption(option
+ 1, choice
, num_options
, options
);
681 else if (option
[0] != '*' && which
!= _PPD_PARSE_OPTIONS
)
682 num_options
= cupsAddOption(option
, choice
, num_options
, options
);
685 return (num_options
);
691 * 'ppd_debug_marked()' - Output the marked array to stdout...
695 ppd_debug_marked(ppd_file_t
*ppd
, /* I - PPD file data */
696 const char *title
) /* I - Title for list */
698 ppd_choice_t
*c
; /* Current choice */
701 DEBUG_printf(("2cupsMarkOptions: %s", title
));
703 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
705 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
706 DEBUG_printf(("2cupsMarkOptions: %s=%s", c
->option
->keyword
, c
->choice
));
712 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
716 ppd_defaults(ppd_file_t
*ppd
, /* I - PPD file */
717 ppd_group_t
*g
) /* I - Group to default */
719 int i
; /* Looping var */
720 ppd_option_t
*o
; /* Current option */
721 ppd_group_t
*sg
; /* Current sub-group */
724 for (i
= g
->num_options
, o
= g
->options
; i
> 0; i
--, o
++)
725 if (strcasecmp(o
->keyword
, "PageRegion") != 0)
726 ppdMarkOption(ppd
, o
->keyword
, o
->defchoice
);
728 for (i
= g
->num_subgroups
, sg
= g
->subgroups
; i
> 0; i
--, sg
++)
729 ppd_defaults(ppd
, sg
);
734 * 'ppd_mark_choices()' - Mark one or more option choices from a string.
738 ppd_mark_choices(ppd_file_t
*ppd
, /* I - PPD file */
739 const char *s
) /* I - "*Option Choice ..." string */
741 int i
, /* Looping var */
742 num_options
; /* Number of options */
743 cups_option_t
*options
, /* Options */
744 *option
; /* Current option */
751 num_options
= _ppdParseOptions(s
, 0, &options
, 0);
753 for (i
= num_options
, option
= options
; i
> 0; i
--, option
++)
754 ppd_mark_option(ppd
, option
->name
, option
->value
);
756 cupsFreeOptions(num_options
, options
);
761 * 'ppd_mark_option()' - Quick mark an option without checking for conflicts.
765 ppd_mark_option(ppd_file_t
*ppd
, /* I - PPD file */
766 const char *option
, /* I - Option name */
767 const char *choice
) /* I - Choice name */
769 int i
, j
; /* Looping vars */
770 ppd_option_t
*o
; /* Option pointer */
771 ppd_choice_t
*c
, /* Choice pointer */
772 *oldc
, /* Old choice pointer */
773 key
; /* Search key for choice */
774 struct lconv
*loc
; /* Locale data */
777 DEBUG_printf(("7ppd_mark_option(ppd=%p, option=\"%s\", choice=\"%s\")",
778 ppd
, option
, choice
));
781 * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
782 * it clears the regular InputSlot choices...
785 if (!strcasecmp(option
, "AP_D_InputSlot"))
787 cupsArraySave(ppd
->options
);
789 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
792 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
795 cupsArrayRemove(ppd
->marked
, oldc
);
799 cupsArrayRestore(ppd
->options
);
803 * Check for custom options...
806 cupsArraySave(ppd
->options
);
808 o
= ppdFindOption(ppd
, option
);
810 cupsArrayRestore(ppd
->options
);
817 if (!strncasecmp(choice
, "Custom.", 7))
820 * Handle a custom option...
823 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
826 if (!strcasecmp(option
, "PageSize"))
829 * Handle custom page sizes...
832 ppdPageSize(ppd
, choice
);
837 * Handle other custom options...
840 ppd_coption_t
*coption
; /* Custom option */
841 ppd_cparam_t
*cparam
; /* Custom parameter */
842 char *units
; /* Custom points units */
845 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
847 if ((cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
)) == NULL
)
850 switch (cparam
->type
)
852 case PPD_CUSTOM_CURVE
:
853 case PPD_CUSTOM_INVCURVE
:
854 case PPD_CUSTOM_REAL
:
855 cparam
->current
.custom_real
= (float)_cupsStrScand(choice
+ 7,
859 case PPD_CUSTOM_POINTS
:
860 cparam
->current
.custom_points
= (float)_cupsStrScand(choice
+ 7,
866 if (!strcasecmp(units
, "cm"))
867 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
868 else if (!strcasecmp(units
, "mm"))
869 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
870 else if (!strcasecmp(units
, "m"))
871 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
872 else if (!strcasecmp(units
, "in"))
873 cparam
->current
.custom_points
*= 72.0f
;
874 else if (!strcasecmp(units
, "ft"))
875 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
879 case PPD_CUSTOM_INT
:
880 cparam
->current
.custom_int
= atoi(choice
+ 7);
883 case PPD_CUSTOM_PASSCODE
:
884 case PPD_CUSTOM_PASSWORD
:
885 case PPD_CUSTOM_STRING
:
886 if (cparam
->current
.custom_string
)
887 _cupsStrFree(cparam
->current
.custom_string
);
889 cparam
->current
.custom_string
= _cupsStrAlloc(choice
+ 7);
896 * Make sure that we keep the option marked below...
901 else if (choice
[0] == '{')
904 * Handle multi-value custom options...
907 ppd_coption_t
*coption
; /* Custom option */
908 ppd_cparam_t
*cparam
; /* Custom parameter */
909 char *units
; /* Custom points units */
910 int num_vals
; /* Number of values */
911 cups_option_t
*vals
, /* Values */
915 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
918 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
920 num_vals
= cupsParseOptions(choice
, 0, &vals
);
922 for (i
= 0, val
= vals
; i
< num_vals
; i
++, val
++)
924 if ((cparam
= ppdFindCustomParam(coption
, val
->name
)) == NULL
)
927 switch (cparam
->type
)
929 case PPD_CUSTOM_CURVE
:
930 case PPD_CUSTOM_INVCURVE
:
931 case PPD_CUSTOM_REAL
:
932 cparam
->current
.custom_real
= (float)_cupsStrScand(val
->value
,
936 case PPD_CUSTOM_POINTS
:
937 cparam
->current
.custom_points
= (float)_cupsStrScand(val
->value
,
943 if (!strcasecmp(units
, "cm"))
944 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
945 else if (!strcasecmp(units
, "mm"))
946 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
947 else if (!strcasecmp(units
, "m"))
948 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
949 else if (!strcasecmp(units
, "in"))
950 cparam
->current
.custom_points
*= 72.0f
;
951 else if (!strcasecmp(units
, "ft"))
952 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
956 case PPD_CUSTOM_INT
:
957 cparam
->current
.custom_int
= atoi(val
->value
);
960 case PPD_CUSTOM_PASSCODE
:
961 case PPD_CUSTOM_PASSWORD
:
962 case PPD_CUSTOM_STRING
:
963 if (cparam
->current
.custom_string
)
964 _cupsStrFree(cparam
->current
.custom_string
);
966 cparam
->current
.custom_string
= _cupsStrRetain(val
->value
);
971 cupsFreeOptions(num_vals
, vals
);
976 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
977 if (!strcasecmp(c
->choice
, choice
))
985 * Option found; mark it and then handle unmarking any other options.
988 if (o
->ui
!= PPD_UI_PICKMANY
)
991 * Unmark all other choices...
994 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, c
)) != NULL
)
997 cupsArrayRemove(ppd
->marked
, oldc
);
1000 if (!strcasecmp(option
, "PageSize") || !strcasecmp(option
, "PageRegion"))
1003 * Mark current page size...
1006 for (j
= 0; j
< ppd
->num_sizes
; j
++)
1007 ppd
->sizes
[j
].marked
= !strcasecmp(ppd
->sizes
[j
].name
,
1011 * Unmark the current PageSize or PageRegion setting, as
1015 cupsArraySave(ppd
->options
);
1017 if (!strcasecmp(option
, "PageSize"))
1019 if ((o
= ppdFindOption(ppd
, "PageRegion")) != NULL
)
1022 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1025 cupsArrayRemove(ppd
->marked
, oldc
);
1031 if ((o
= ppdFindOption(ppd
, "PageSize")) != NULL
)
1034 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1037 cupsArrayRemove(ppd
->marked
, oldc
);
1042 cupsArrayRestore(ppd
->options
);
1044 else if (!strcasecmp(option
, "InputSlot"))
1047 * Unmark ManualFeed option...
1050 cupsArraySave(ppd
->options
);
1052 if ((o
= ppdFindOption(ppd
, "ManualFeed")) != NULL
)
1055 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1058 cupsArrayRemove(ppd
->marked
, oldc
);
1062 cupsArrayRestore(ppd
->options
);
1064 else if (!strcasecmp(option
, "ManualFeed") &&
1065 !strcasecmp(choice
, "True"))
1068 * Unmark InputSlot option...
1071 cupsArraySave(ppd
->options
);
1073 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1076 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1079 cupsArrayRemove(ppd
->marked
, oldc
);
1083 cupsArrayRestore(ppd
->options
);
1089 cupsArrayAdd(ppd
->marked
, c
);
1094 * End of "$Id: mark.c 9042 2010-03-24 00:45:34Z mike $".