]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/mark.c
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
, k
; /* 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 *page_size
, /* PageSize option */
81 *ppd_keyword
; /* PPD keyword */
82 cups_option_t
*optptr
; /* Current option */
83 ppd_option_t
*option
; /* PPD option */
84 ppd_attr_t
*attr
; /* PPD attribute */
85 static const char * const duplex_options
[] =
86 { /* Duplex option names */
89 "EFDuplexing", /* EFI */
90 "KD03Duplex", /* Kodak */
91 "JCLDuplex" /* Samsung */
93 static const char * const duplex_one
[] =
94 { /* one-sided names */
98 static const char * const duplex_two_long
[] =
99 { /* two-sided-long-edge names */
100 "DuplexNoTumble", /* Adobe */
101 "LongEdge", /* EFI */
104 static const char * const duplex_two_short
[] =
105 { /* two-sided-long-edge names */
106 "DuplexTumble", /* Adobe */
107 "ShortEdge", /* EFI */
116 if (!ppd
|| num_options
<= 0 || !options
)
119 ppd_debug_marked(ppd
, "Before...");
122 * Do special handling for media and PageSize...
125 media
= cupsGetOption("media", num_options
, options
);
126 page_size
= cupsGetOption("PageSize", num_options
, options
);
131 * Load PWG mapping data as needed...
135 ppd
->pwg
= _pwgCreateWithPPD(ppd
);
138 * Loop through the option string, separating it at commas and
139 * marking each individual option as long as the corresponding
140 * PPD option (PageSize, InputSlot, etc.) is not also set.
142 * For PageSize, we also check for an empty option value since
143 * some versions of MacOS X use it to specify auto-selection
144 * of the media based solely on the size.
147 for (val
= media
; *val
;)
150 * Extract the sub-option from the string...
153 for (ptr
= s
; *val
&& *val
!= ',' && (ptr
- s
) < (sizeof(s
) - 1);)
164 if ((!page_size
|| !page_size
[0]) &&
165 (ppd_keyword
= _pwgGetPageSize((_pwg_t
*)ppd
->pwg
, NULL
, s
,
167 ppd_mark_option(ppd
, "PageSize", ppd_keyword
);
169 if (!cupsGetOption("InputSlot", num_options
, options
) &&
170 (ppd_keyword
= _pwgGetInputSlot((_pwg_t
*)ppd
->pwg
, NULL
, s
)) != NULL
)
171 ppd_mark_option(ppd
, "InputSlot", ppd_keyword
);
173 if (!cupsGetOption("MediaType", num_options
, options
) &&
174 (ppd_keyword
= _pwgGetMediaType((_pwg_t
*)ppd
->pwg
, NULL
, s
)) != NULL
)
175 ppd_mark_option(ppd
, "MediaType", ppd_keyword
);
180 * Mark other options...
183 for (i
= num_options
, optptr
= options
; i
> 0; i
--, optptr
++)
184 if (!strcasecmp(optptr
->name
, "media"))
186 else if (!strcasecmp(optptr
->name
, "sides"))
189 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
191 if (cupsGetOption(duplex_options
[j
], num_options
, options
))
194 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
197 * Don't override the PPD option with the IPP attribute...
203 if (!strcasecmp(optptr
->value
, "one-sided"))
206 * Mark the appropriate duplex option for one-sided output...
210 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
212 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
215 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
218 k
< (int)(sizeof(duplex_one
) / sizeof(duplex_one
[0]));
220 if (ppdFindChoice(option
, duplex_one
[k
]))
222 ppd_mark_option(ppd
, duplex_options
[j
], duplex_one
[k
]);
227 else if (!strcasecmp(optptr
->value
, "two-sided-long-edge"))
230 * Mark the appropriate duplex option for two-sided-long-edge output...
234 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
236 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
239 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
242 k
< (int)(sizeof(duplex_two_long
) / sizeof(duplex_two_long
[0]));
244 if (ppdFindChoice(option
, duplex_two_long
[k
]))
246 ppd_mark_option(ppd
, duplex_options
[j
], duplex_two_long
[k
]);
251 else if (!strcasecmp(optptr
->value
, "two-sided-short-edge"))
254 * Mark the appropriate duplex option for two-sided-short-edge output...
258 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
260 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
263 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
266 k
< (int)(sizeof(duplex_two_short
) / sizeof(duplex_two_short
[0]));
268 if (ppdFindChoice(option
, duplex_two_short
[k
]))
270 ppd_mark_option(ppd
, duplex_options
[j
], duplex_two_short
[k
]);
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
, "output-bin"))
289 if (!cupsGetOption("OutputBin", num_options
, options
))
290 ppd_mark_option(ppd
, "OutputBin", optptr
->value
);
292 else if (!strcasecmp(optptr
->name
, "multiple-document-handling"))
294 if (!cupsGetOption("Collate", num_options
, options
) &&
295 ppdFindOption(ppd
, "Collate"))
297 if (strcasecmp(optptr
->value
, "separate-documents-uncollated-copies"))
298 ppd_mark_option(ppd
, "Collate", "True");
300 ppd_mark_option(ppd
, "Collate", "False");
303 else if (!strcasecmp(optptr
->name
, "finishings"))
306 * Lookup cupsIPPFinishings attributes for each value...
309 for (ptr
= optptr
->value
; *ptr
;)
312 * Get the next finishings number...
315 if (!isdigit(*ptr
& 255))
318 if ((j
= strtol(ptr
, &ptr
, 10)) < 3)
322 * Skip separator as needed...
329 * Look it up in the PPD file...
334 if ((attr
= ppdFindAttr(ppd
, "cupsIPPFinishings", s
)) == NULL
)
338 * Apply "*Option Choice" settings from the attribute value...
341 ppd_mark_choices(ppd
, attr
->value
);
344 else if (!strcasecmp(optptr
->name
, "print-quality"))
346 ppd_option_t
*output_mode
= ppdFindOption(ppd
, "OutputMode");
347 /* OutputMode option */
349 if (!strcmp(optptr
->value
, "3"))
355 if (ppdFindChoice(output_mode
, "Draft"))
356 ppd_mark_option(ppd
, "OutputMode", "Draft");
357 else if (ppdFindChoice(output_mode
, "Fast"))
358 ppd_mark_option(ppd
, "OutputMode", "Fast");
360 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
361 "DraftGray_with_Paper_Auto-Detect")) != NULL
)
362 ppd_mark_choices(ppd
, attr
->value
);
364 else if (!strcmp(optptr
->value
, "4"))
370 if (ppdFindChoice(output_mode
, "Normal"))
371 ppd_mark_option(ppd
, "OutputMode", "Normal");
372 else if (ppdFindChoice(output_mode
, "Good"))
373 ppd_mark_option(ppd
, "OutputMode", "Good");
375 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
376 "Color_with_Paper_Auto-Detect")) != NULL
)
377 ppd_mark_choices(ppd
, attr
->value
);
378 else if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
379 "Gray_with_Paper_Auto-Detect")) != NULL
)
380 ppd_mark_choices(ppd
, attr
->value
);
382 else if (!strcmp(optptr
->value
, "5"))
385 * High/best/photo quality...
388 if (ppdFindChoice(output_mode
, "Best"))
389 ppd_mark_option(ppd
, "OutputMode", "Best");
390 else if (ppdFindChoice(output_mode
, "High"))
391 ppd_mark_option(ppd
, "OutputMode", "High");
393 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
394 "Photo_on_Photo_Paper")) != NULL
)
395 ppd_mark_choices(ppd
, attr
->value
);
398 else if (!strcasecmp(optptr
->name
, "APPrinterPreset"))
401 * Lookup APPrinterPreset value...
404 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset", optptr
->value
)) != NULL
)
407 * Apply "*Option Choice" settings from the attribute value...
410 ppd_mark_choices(ppd
, attr
->value
);
413 else if (!strcasecmp(optptr
->name
, "mirror"))
414 ppd_mark_option(ppd
, "MirrorPrint", optptr
->value
);
416 ppd_mark_option(ppd
, optptr
->name
, optptr
->value
);
418 ppd_debug_marked(ppd
, "After...");
420 return (ppdConflicts(ppd
) > 0);
425 * 'ppdFindChoice()' - Return a pointer to an option choice.
428 ppd_choice_t
* /* O - Choice pointer or @code NULL@ */
429 ppdFindChoice(ppd_option_t
*o
, /* I - Pointer to option */
430 const char *choice
) /* I - Name of choice */
432 int i
; /* Looping var */
433 ppd_choice_t
*c
; /* Current choice */
439 if (choice
[0] == '{' || !strncasecmp(choice
, "Custom.", 7))
442 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
443 if (!strcasecmp(c
->choice
, choice
))
451 * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
454 ppd_choice_t
* /* O - Pointer to choice or @code NULL@ */
455 ppdFindMarkedChoice(ppd_file_t
*ppd
, /* I - PPD file */
456 const char *option
) /* I - Keyword/option name */
458 ppd_choice_t key
, /* Search key for choice */
459 *marked
; /* Marked choice */
462 DEBUG_printf(("2ppdFindMarkedChoice(ppd=%p, option=\"%s\")", ppd
, option
));
464 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
466 DEBUG_puts("3ppdFindMarkedChoice: Option not found, returning NULL");
470 marked
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
);
472 DEBUG_printf(("3ppdFindMarkedChoice: Returning %p(%s)...", marked
,
473 marked
? marked
->choice
: "NULL"));
480 * 'ppdFindOption()' - Return a pointer to the specified option.
483 ppd_option_t
* /* O - Pointer to option or @code NULL@ */
484 ppdFindOption(ppd_file_t
*ppd
, /* I - PPD file data */
485 const char *option
) /* I - Option/Keyword name */
488 * Range check input...
497 * Search in the array...
500 ppd_option_t key
; /* Option search key */
503 strlcpy(key
.keyword
, option
, sizeof(key
.keyword
));
505 return ((ppd_option_t
*)cupsArrayFind(ppd
->options
, &key
));
510 * Search in each group...
513 int i
, j
; /* Looping vars */
514 ppd_group_t
*group
; /* Current group */
515 ppd_option_t
*optptr
; /* Current option */
518 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
519 for (j
= group
->num_options
, optptr
= group
->options
;
522 if (!strcasecmp(optptr
->keyword
, option
))
531 * 'ppdIsMarked()' - Check to see if an option is marked.
534 int /* O - Non-zero if option is marked */
535 ppdIsMarked(ppd_file_t
*ppd
, /* I - PPD file data */
536 const char *option
, /* I - Option/Keyword name */
537 const char *choice
) /* I - Choice name */
539 ppd_choice_t key
, /* Search key */
540 *c
; /* Choice pointer */
546 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
549 if ((c
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) == NULL
)
552 return (!strcmp(c
->choice
, choice
));
557 * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
561 ppdMarkDefaults(ppd_file_t
*ppd
) /* I - PPD file record */
563 int i
; /* Looping variables */
564 ppd_group_t
*g
; /* Current group */
565 ppd_choice_t
*c
; /* Current choice */
572 * Clean out the marked array...
575 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
577 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
578 cupsArrayRemove(ppd
->marked
, c
);
581 * Then repopulate it with the defaults...
584 for (i
= ppd
->num_groups
, g
= ppd
->groups
; i
> 0; i
--, g
++)
585 ppd_defaults(ppd
, g
);
590 * 'ppdMarkOption()' - Mark an option in a PPD file and return the number of
594 int /* O - Number of conflicts */
595 ppdMarkOption(ppd_file_t
*ppd
, /* I - PPD file record */
596 const char *option
, /* I - Keyword */
597 const char *choice
) /* I - Option name */
599 DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")",
600 ppd
, option
, choice
));
603 * Range check input...
606 if (!ppd
|| !option
|| !choice
)
613 ppd_mark_option(ppd
, option
, choice
);
616 * Return the number of conflicts...
619 return (ppdConflicts(ppd
));
624 * 'ppdFirstOption()' - Return the first option in the PPD file.
626 * Options are returned from all groups in ascending alphanumeric order.
628 * @since CUPS 1.2/Mac OS X 10.5@
631 ppd_option_t
* /* O - First option or @code NULL@ */
632 ppdFirstOption(ppd_file_t
*ppd
) /* I - PPD file */
637 return ((ppd_option_t
*)cupsArrayFirst(ppd
->options
));
642 * 'ppdNextOption()' - Return the next option in the PPD file.
644 * Options are returned from all groups in ascending alphanumeric order.
646 * @since CUPS 1.2/Mac OS X 10.5@
649 ppd_option_t
* /* O - Next option or @code NULL@ */
650 ppdNextOption(ppd_file_t
*ppd
) /* I - PPD file */
655 return ((ppd_option_t
*)cupsArrayNext(ppd
->options
));
660 * '_ppdParseOptions()' - Parse options from a PPD file.
662 * This function looks for strings of the form:
664 * *option choice ... *optionN choiceN
666 * It stops when it finds a string that doesn't match this format.
669 int /* O - Number of options */
671 const char *s
, /* I - String to parse */
672 int num_options
, /* I - Number of options */
673 cups_option_t
**options
) /* IO - Options */
675 char option
[PPD_MAX_NAME
], /* Current option */
676 choice
[PPD_MAX_NAME
], /* Current choice */
677 *ptr
; /* Pointer into option or choice */
681 return (num_options
);
684 * Read all of the "*Option Choice" pairs from the string, marking PPD
685 * options as we go...
691 * Skip leading whitespace...
694 while (isspace(*s
& 255))
701 * Get the option name...
706 while (*s
&& !isspace(*s
& 255) && ptr
< (option
+ sizeof(option
) - 1))
718 while (isspace(*s
& 255))
725 while (*s
&& !isspace(*s
& 255) && ptr
< (choice
+ sizeof(choice
) - 1))
731 * Add it to the options array...
734 num_options
= cupsAddOption(option
, choice
, num_options
, options
);
737 return (num_options
);
743 * 'ppd_debug_marked()' - Output the marked array to stdout...
747 ppd_debug_marked(ppd_file_t
*ppd
, /* I - PPD file data */
748 const char *title
) /* I - Title for list */
750 ppd_choice_t
*c
; /* Current choice */
753 DEBUG_printf(("2cupsMarkOptions: %s", title
));
755 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
757 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
758 DEBUG_printf(("2cupsMarkOptions: %s=%s", c
->option
->keyword
, c
->choice
));
764 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
768 ppd_defaults(ppd_file_t
*ppd
, /* I - PPD file */
769 ppd_group_t
*g
) /* I - Group to default */
771 int i
; /* Looping var */
772 ppd_option_t
*o
; /* Current option */
773 ppd_group_t
*sg
; /* Current sub-group */
776 for (i
= g
->num_options
, o
= g
->options
; i
> 0; i
--, o
++)
777 if (strcasecmp(o
->keyword
, "PageRegion") != 0)
778 ppdMarkOption(ppd
, o
->keyword
, o
->defchoice
);
780 for (i
= g
->num_subgroups
, sg
= g
->subgroups
; i
> 0; i
--, sg
++)
781 ppd_defaults(ppd
, sg
);
786 * 'ppd_mark_choices()' - Mark one or more option choices from a string.
790 ppd_mark_choices(ppd_file_t
*ppd
, /* I - PPD file */
791 const char *s
) /* I - "*Option Choice ..." string */
793 int i
, /* Looping var */
794 num_options
; /* Number of options */
795 cups_option_t
*options
, /* Options */
796 *option
; /* Current option */
803 num_options
= _ppdParseOptions(s
, 0, &options
);
805 for (i
= num_options
, option
= options
; i
> 0; i
--, option
++)
806 ppd_mark_option(ppd
, option
->name
, option
->value
);
808 cupsFreeOptions(num_options
, options
);
813 * 'ppd_mark_option()' - Quick mark an option without checking for conflicts.
817 ppd_mark_option(ppd_file_t
*ppd
, /* I - PPD file */
818 const char *option
, /* I - Option name */
819 const char *choice
) /* I - Choice name */
821 int i
, j
; /* Looping vars */
822 ppd_option_t
*o
; /* Option pointer */
823 ppd_choice_t
*c
, /* Choice pointer */
824 *oldc
, /* Old choice pointer */
825 key
; /* Search key for choice */
826 struct lconv
*loc
; /* Locale data */
829 DEBUG_printf(("7ppd_mark_option(ppd=%p, option=\"%s\", choice=\"%s\")",
830 ppd
, option
, choice
));
833 * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
834 * it clears the regular InputSlot choices...
837 if (!strcasecmp(option
, "AP_D_InputSlot"))
839 cupsArraySave(ppd
->options
);
841 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
844 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
847 cupsArrayRemove(ppd
->marked
, oldc
);
851 cupsArrayRestore(ppd
->options
);
855 * Check for custom options...
858 cupsArraySave(ppd
->options
);
860 o
= ppdFindOption(ppd
, option
);
862 cupsArrayRestore(ppd
->options
);
869 if (!strncasecmp(choice
, "Custom.", 7))
872 * Handle a custom option...
875 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
878 if (!strcasecmp(option
, "PageSize"))
881 * Handle custom page sizes...
884 ppdPageSize(ppd
, choice
);
889 * Handle other custom options...
892 ppd_coption_t
*coption
; /* Custom option */
893 ppd_cparam_t
*cparam
; /* Custom parameter */
894 char *units
; /* Custom points units */
897 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
899 if ((cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
)) == NULL
)
902 switch (cparam
->type
)
904 case PPD_CUSTOM_CURVE
:
905 case PPD_CUSTOM_INVCURVE
:
906 case PPD_CUSTOM_REAL
:
907 cparam
->current
.custom_real
= (float)_cupsStrScand(choice
+ 7,
911 case PPD_CUSTOM_POINTS
:
912 cparam
->current
.custom_points
= (float)_cupsStrScand(choice
+ 7,
918 if (!strcasecmp(units
, "cm"))
919 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
920 else if (!strcasecmp(units
, "mm"))
921 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
922 else if (!strcasecmp(units
, "m"))
923 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
924 else if (!strcasecmp(units
, "in"))
925 cparam
->current
.custom_points
*= 72.0f
;
926 else if (!strcasecmp(units
, "ft"))
927 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
931 case PPD_CUSTOM_INT
:
932 cparam
->current
.custom_int
= atoi(choice
+ 7);
935 case PPD_CUSTOM_PASSCODE
:
936 case PPD_CUSTOM_PASSWORD
:
937 case PPD_CUSTOM_STRING
:
938 if (cparam
->current
.custom_string
)
939 _cupsStrFree(cparam
->current
.custom_string
);
941 cparam
->current
.custom_string
= _cupsStrAlloc(choice
+ 7);
948 * Make sure that we keep the option marked below...
953 else if (choice
[0] == '{')
956 * Handle multi-value custom options...
959 ppd_coption_t
*coption
; /* Custom option */
960 ppd_cparam_t
*cparam
; /* Custom parameter */
961 char *units
; /* Custom points units */
962 int num_vals
; /* Number of values */
963 cups_option_t
*vals
, /* Values */
967 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
970 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
972 num_vals
= cupsParseOptions(choice
, 0, &vals
);
974 for (i
= 0, val
= vals
; i
< num_vals
; i
++, val
++)
976 if ((cparam
= ppdFindCustomParam(coption
, val
->name
)) == NULL
)
979 switch (cparam
->type
)
981 case PPD_CUSTOM_CURVE
:
982 case PPD_CUSTOM_INVCURVE
:
983 case PPD_CUSTOM_REAL
:
984 cparam
->current
.custom_real
= (float)_cupsStrScand(val
->value
,
988 case PPD_CUSTOM_POINTS
:
989 cparam
->current
.custom_points
= (float)_cupsStrScand(val
->value
,
995 if (!strcasecmp(units
, "cm"))
996 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
997 else if (!strcasecmp(units
, "mm"))
998 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
999 else if (!strcasecmp(units
, "m"))
1000 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
1001 else if (!strcasecmp(units
, "in"))
1002 cparam
->current
.custom_points
*= 72.0f
;
1003 else if (!strcasecmp(units
, "ft"))
1004 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
1008 case PPD_CUSTOM_INT
:
1009 cparam
->current
.custom_int
= atoi(val
->value
);
1012 case PPD_CUSTOM_PASSCODE
:
1013 case PPD_CUSTOM_PASSWORD
:
1014 case PPD_CUSTOM_STRING
:
1015 if (cparam
->current
.custom_string
)
1016 _cupsStrFree(cparam
->current
.custom_string
);
1018 cparam
->current
.custom_string
= _cupsStrRetain(val
->value
);
1023 cupsFreeOptions(num_vals
, vals
);
1028 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
1029 if (!strcasecmp(c
->choice
, choice
))
1037 * Option found; mark it and then handle unmarking any other options.
1040 if (o
->ui
!= PPD_UI_PICKMANY
)
1043 * Unmark all other choices...
1046 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, c
)) != NULL
)
1049 cupsArrayRemove(ppd
->marked
, oldc
);
1052 if (!strcasecmp(option
, "PageSize") || !strcasecmp(option
, "PageRegion"))
1055 * Mark current page size...
1058 for (j
= 0; j
< ppd
->num_sizes
; j
++)
1059 ppd
->sizes
[j
].marked
= !strcasecmp(ppd
->sizes
[j
].name
,
1063 * Unmark the current PageSize or PageRegion setting, as
1067 cupsArraySave(ppd
->options
);
1069 if (!strcasecmp(option
, "PageSize"))
1071 if ((o
= ppdFindOption(ppd
, "PageRegion")) != NULL
)
1074 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1077 cupsArrayRemove(ppd
->marked
, oldc
);
1083 if ((o
= ppdFindOption(ppd
, "PageSize")) != NULL
)
1086 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1089 cupsArrayRemove(ppd
->marked
, oldc
);
1094 cupsArrayRestore(ppd
->options
);
1096 else if (!strcasecmp(option
, "InputSlot"))
1099 * Unmark ManualFeed option...
1102 cupsArraySave(ppd
->options
);
1104 if ((o
= ppdFindOption(ppd
, "ManualFeed")) != NULL
)
1107 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1110 cupsArrayRemove(ppd
->marked
, oldc
);
1114 cupsArrayRestore(ppd
->options
);
1116 else if (!strcasecmp(option
, "ManualFeed") &&
1117 !strcasecmp(choice
, "True"))
1120 * Unmark InputSlot option...
1123 cupsArraySave(ppd
->options
);
1125 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1128 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1131 cupsArrayRemove(ppd
->marked
, oldc
);
1135 cupsArrayRestore(ppd
->options
);
1141 cupsArrayAdd(ppd
->marked
, c
);
1146 * End of "$Id: mark.c 9042 2010-03-24 00:45:34Z mike $".