]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/mark.c
2 * "$Id: mark.c 8210 2009-01-09 02:30:26Z 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...
46 #include "pwg-private.h"
54 static void ppd_debug_marked(ppd_file_t
*ppd
, const char *title
);
56 # define ppd_debug_marked(ppd,title)
58 static void ppd_defaults(ppd_file_t
*ppd
, ppd_group_t
*g
);
59 static void ppd_mark_choices(ppd_file_t
*ppd
, const char *s
);
60 static void ppd_mark_option(ppd_file_t
*ppd
, const char *option
,
65 * 'cupsMarkOptions()' - Mark command-line options in a PPD file.
67 * This function maps the IPP "finishings", "media", "mirror",
68 * "multiple-document-handling", "output-bin", "printer-resolution", and
69 * "sides" attributes to their corresponding PPD options and choices.
72 int /* O - 1 if conflicts exist, 0 otherwise */
74 ppd_file_t
*ppd
, /* I - PPD file */
75 int num_options
, /* I - Number of options */
76 cups_option_t
*options
) /* I - Options */
78 int i
, j
, k
; /* Looping vars */
79 char *ptr
, /* Pointer into string */
80 s
[255]; /* Temporary string */
81 const char *val
, /* Pointer into value */
82 *media
, /* media option */
83 *page_size
, /* PageSize option */
84 *ppd_keyword
; /* PPD keyword */
85 cups_option_t
*optptr
; /* Current option */
86 ppd_option_t
*option
; /* PPD option */
87 ppd_attr_t
*attr
; /* PPD attribute */
88 static const char * const duplex_options
[] =
89 { /* Duplex option names */
92 "EFDuplexing", /* EFI */
93 "KD03Duplex", /* Kodak */
94 "JCLDuplex" /* Samsung */
96 static const char * const duplex_one
[] =
97 { /* one-sided names */
101 static const char * const duplex_two_long
[] =
102 { /* two-sided-long-edge names */
103 "DuplexNoTumble", /* Adobe */
104 "LongEdge", /* EFI */
107 static const char * const duplex_two_short
[] =
108 { /* two-sided-long-edge names */
109 "DuplexTumble", /* Adobe */
110 "ShortEdge", /* EFI */
119 if (!ppd
|| num_options
<= 0 || !options
)
122 ppd_debug_marked(ppd
, "Before...");
125 * Do special handling for media and PageSize...
128 media
= cupsGetOption("media", num_options
, options
);
129 page_size
= cupsGetOption("PageSize", num_options
, options
);
134 * Load PWG mapping data as needed...
138 ppd
->pwg
= _pwgCreateWithPPD(ppd
);
141 * Loop through the option string, separating it at commas and
142 * marking each individual option as long as the corresponding
143 * PPD option (PageSize, InputSlot, etc.) is not also set.
145 * For PageSize, we also check for an empty option value since
146 * some versions of MacOS X use it to specify auto-selection
147 * of the media based solely on the size.
150 for (val
= media
; *val
;)
153 * Extract the sub-option from the string...
156 for (ptr
= s
; *val
&& *val
!= ',' && (ptr
- s
) < (sizeof(s
) - 1);)
167 if ((!page_size
|| !page_size
[0]) &&
168 (ppd_keyword
= _pwgGetPageSize((_pwg_t
*)ppd
->pwg
, NULL
, s
,
170 ppd_mark_option(ppd
, "PageSize", ppd_keyword
);
172 if (!cupsGetOption("InputSlot", num_options
, options
) &&
173 (ppd_keyword
= _pwgGetInputSlot((_pwg_t
*)ppd
->pwg
, NULL
, s
)) != NULL
)
174 ppd_mark_option(ppd
, "InputSlot", ppd_keyword
);
176 if (!cupsGetOption("MediaType", num_options
, options
) &&
177 (ppd_keyword
= _pwgGetMediaType((_pwg_t
*)ppd
->pwg
, NULL
, s
)) != NULL
)
178 ppd_mark_option(ppd
, "MediaType", ppd_keyword
);
183 * Mark other options...
186 for (i
= num_options
, optptr
= options
; i
> 0; i
--, optptr
++)
187 if (!strcasecmp(optptr
->name
, "media"))
189 else if (!strcasecmp(optptr
->name
, "sides"))
192 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
194 if (cupsGetOption(duplex_options
[j
], num_options
, options
))
197 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
200 * Don't override the PPD option with the IPP attribute...
206 if (!strcasecmp(optptr
->value
, "one-sided"))
209 * Mark the appropriate duplex option for one-sided output...
213 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
215 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
218 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
221 k
< (int)(sizeof(duplex_one
) / sizeof(duplex_one
[0]));
223 if (ppdFindChoice(option
, duplex_one
[k
]))
225 ppd_mark_option(ppd
, duplex_options
[j
], duplex_one
[k
]);
230 else if (!strcasecmp(optptr
->value
, "two-sided-long-edge"))
233 * Mark the appropriate duplex option for two-sided-long-edge output...
237 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
239 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
242 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
245 k
< (int)(sizeof(duplex_two_long
) / sizeof(duplex_two_long
[0]));
247 if (ppdFindChoice(option
, duplex_two_long
[k
]))
249 ppd_mark_option(ppd
, duplex_options
[j
], duplex_two_long
[k
]);
254 else if (!strcasecmp(optptr
->value
, "two-sided-short-edge"))
257 * Mark the appropriate duplex option for two-sided-short-edge output...
261 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
263 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
266 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
269 k
< (int)(sizeof(duplex_two_short
) / sizeof(duplex_two_short
[0]));
271 if (ppdFindChoice(option
, duplex_two_short
[k
]))
273 ppd_mark_option(ppd
, duplex_options
[j
], duplex_two_short
[k
]);
279 else if (!strcasecmp(optptr
->name
, "resolution") ||
280 !strcasecmp(optptr
->name
, "printer-resolution"))
282 ppd_mark_option(ppd
, "Resolution", optptr
->value
);
283 ppd_mark_option(ppd
, "SetResolution", optptr
->value
);
284 /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
285 ppd_mark_option(ppd
, "JCLResolution", optptr
->value
);
287 ppd_mark_option(ppd
, "CNRes_PGP", optptr
->value
);
290 else if (!strcasecmp(optptr
->name
, "output-bin"))
292 if (!cupsGetOption("OutputBin", num_options
, options
))
293 ppd_mark_option(ppd
, "OutputBin", optptr
->value
);
295 else if (!strcasecmp(optptr
->name
, "multiple-document-handling"))
297 if (!cupsGetOption("Collate", num_options
, options
) &&
298 ppdFindOption(ppd
, "Collate"))
300 if (strcasecmp(optptr
->value
, "separate-documents-uncollated-copies"))
301 ppd_mark_option(ppd
, "Collate", "True");
303 ppd_mark_option(ppd
, "Collate", "False");
306 else if (!strcasecmp(optptr
->name
, "finishings"))
309 * Lookup cupsIPPFinishings attributes for each value...
312 for (ptr
= optptr
->value
; *ptr
;)
315 * Get the next finishings number...
318 if (!isdigit(*ptr
& 255))
321 if ((j
= strtol(ptr
, &ptr
, 10)) < 3)
325 * Skip separator as needed...
332 * Look it up in the PPD file...
337 if ((attr
= ppdFindAttr(ppd
, "cupsIPPFinishings", s
)) == NULL
)
341 * Apply "*Option Choice" settings from the attribute value...
344 ppd_mark_choices(ppd
, attr
->value
);
347 else if (!strcasecmp(optptr
->name
, "print-quality"))
349 ppd_option_t
*output_mode
= ppdFindOption(ppd
, "OutputMode");
350 /* OutputMode option */
352 if (!strcmp(optptr
->value
, "3"))
358 if (ppdFindChoice(output_mode
, "Draft"))
359 ppd_mark_option(ppd
, "OutputMode", "Draft");
360 else if (ppdFindChoice(output_mode
, "Fast"))
361 ppd_mark_option(ppd
, "OutputMode", "Fast");
363 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
364 "DraftGray_with_Paper_Auto-Detect")) != NULL
)
365 ppd_mark_choices(ppd
, attr
->value
);
367 else if (!strcmp(optptr
->value
, "4"))
373 if (ppdFindChoice(output_mode
, "Normal"))
374 ppd_mark_option(ppd
, "OutputMode", "Normal");
375 else if (ppdFindChoice(output_mode
, "Good"))
376 ppd_mark_option(ppd
, "OutputMode", "Good");
378 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
379 "Color_with_Paper_Auto-Detect")) != NULL
)
380 ppd_mark_choices(ppd
, attr
->value
);
381 else if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
382 "Gray_with_Paper_Auto-Detect")) != NULL
)
383 ppd_mark_choices(ppd
, attr
->value
);
385 else if (!strcmp(optptr
->value
, "5"))
388 * High/best/photo quality...
391 if (ppdFindChoice(output_mode
, "Best"))
392 ppd_mark_option(ppd
, "OutputMode", "Best");
393 else if (ppdFindChoice(output_mode
, "High"))
394 ppd_mark_option(ppd
, "OutputMode", "High");
396 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset",
397 "Photo_on_Photo_Paper")) != NULL
)
398 ppd_mark_choices(ppd
, attr
->value
);
401 else if (!strcasecmp(optptr
->name
, "APPrinterPreset"))
404 * Lookup APPrinterPreset value...
407 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset", optptr
->value
)) != NULL
)
410 * Apply "*Option Choice" settings from the attribute value...
413 ppd_mark_choices(ppd
, attr
->value
);
416 else if (!strcasecmp(optptr
->name
, "mirror"))
417 ppd_mark_option(ppd
, "MirrorPrint", optptr
->value
);
419 ppd_mark_option(ppd
, optptr
->name
, optptr
->value
);
421 ppd_debug_marked(ppd
, "After...");
423 return (ppdConflicts(ppd
) > 0);
428 * 'ppdFindChoice()' - Return a pointer to an option choice.
431 ppd_choice_t
* /* O - Choice pointer or @code NULL@ */
432 ppdFindChoice(ppd_option_t
*o
, /* I - Pointer to option */
433 const char *choice
) /* I - Name of choice */
435 int i
; /* Looping var */
436 ppd_choice_t
*c
; /* Current choice */
442 if (choice
[0] == '{' || !strncasecmp(choice
, "Custom.", 7))
445 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
446 if (!strcasecmp(c
->choice
, choice
))
454 * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
457 ppd_choice_t
* /* O - Pointer to choice or @code NULL@ */
458 ppdFindMarkedChoice(ppd_file_t
*ppd
, /* I - PPD file */
459 const char *option
) /* I - Keyword/option name */
461 ppd_choice_t key
, /* Search key for choice */
462 *marked
; /* Marked choice */
465 DEBUG_printf(("2ppdFindMarkedChoice(ppd=%p, option=\"%s\")", ppd
, option
));
467 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
469 DEBUG_puts("3ppdFindMarkedChoice: Option not found, returning NULL");
473 marked
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
);
475 DEBUG_printf(("3ppdFindMarkedChoice: Returning %p(%s)...", marked
,
476 marked
? marked
->choice
: "NULL"));
483 * 'ppdFindOption()' - Return a pointer to the specified option.
486 ppd_option_t
* /* O - Pointer to option or @code NULL@ */
487 ppdFindOption(ppd_file_t
*ppd
, /* I - PPD file data */
488 const char *option
) /* I - Option/Keyword name */
491 * Range check input...
500 * Search in the array...
503 ppd_option_t key
; /* Option search key */
506 strlcpy(key
.keyword
, option
, sizeof(key
.keyword
));
508 return ((ppd_option_t
*)cupsArrayFind(ppd
->options
, &key
));
513 * Search in each group...
516 int i
, j
; /* Looping vars */
517 ppd_group_t
*group
; /* Current group */
518 ppd_option_t
*optptr
; /* Current option */
521 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
522 for (j
= group
->num_options
, optptr
= group
->options
;
525 if (!strcasecmp(optptr
->keyword
, option
))
534 * 'ppdIsMarked()' - Check to see if an option is marked.
537 int /* O - Non-zero if option is marked */
538 ppdIsMarked(ppd_file_t
*ppd
, /* I - PPD file data */
539 const char *option
, /* I - Option/Keyword name */
540 const char *choice
) /* I - Choice name */
542 ppd_choice_t key
, /* Search key */
543 *c
; /* Choice pointer */
549 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
552 if ((c
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) == NULL
)
555 return (!strcmp(c
->choice
, choice
));
560 * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
564 ppdMarkDefaults(ppd_file_t
*ppd
) /* I - PPD file record */
566 int i
; /* Looping variables */
567 ppd_group_t
*g
; /* Current group */
568 ppd_choice_t
*c
; /* Current choice */
575 * Clean out the marked array...
578 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
580 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
581 cupsArrayRemove(ppd
->marked
, c
);
584 * Then repopulate it with the defaults...
587 for (i
= ppd
->num_groups
, g
= ppd
->groups
; i
> 0; i
--, g
++)
588 ppd_defaults(ppd
, g
);
593 * 'ppdMarkOption()' - Mark an option in a PPD file and return the number of
597 int /* O - Number of conflicts */
598 ppdMarkOption(ppd_file_t
*ppd
, /* I - PPD file record */
599 const char *option
, /* I - Keyword */
600 const char *choice
) /* I - Option name */
602 DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")",
603 ppd
, option
, choice
));
606 * Range check input...
609 if (!ppd
|| !option
|| !choice
)
616 ppd_mark_option(ppd
, option
, choice
);
619 * Return the number of conflicts...
622 return (ppdConflicts(ppd
));
627 * 'ppdFirstOption()' - Return the first option in the PPD file.
629 * Options are returned from all groups in ascending alphanumeric order.
631 * @since CUPS 1.2/Mac OS X 10.5@
634 ppd_option_t
* /* O - First option or @code NULL@ */
635 ppdFirstOption(ppd_file_t
*ppd
) /* I - PPD file */
640 return ((ppd_option_t
*)cupsArrayFirst(ppd
->options
));
645 * 'ppdNextOption()' - Return the next option in the PPD file.
647 * Options are returned from all groups in ascending alphanumeric order.
649 * @since CUPS 1.2/Mac OS X 10.5@
652 ppd_option_t
* /* O - Next option or @code NULL@ */
653 ppdNextOption(ppd_file_t
*ppd
) /* I - PPD file */
658 return ((ppd_option_t
*)cupsArrayNext(ppd
->options
));
663 * '_ppdParseOptions()' - Parse options from a PPD file.
665 * This function looks for strings of the form:
667 * *option choice ... *optionN choiceN
669 * It stops when it finds a string that doesn't match this format.
672 int /* O - Number of options */
674 const char *s
, /* I - String to parse */
675 int num_options
, /* I - Number of options */
676 cups_option_t
**options
) /* IO - Options */
678 char option
[PPD_MAX_NAME
], /* Current option */
679 choice
[PPD_MAX_NAME
], /* Current choice */
680 *ptr
; /* Pointer into option or choice */
684 return (num_options
);
687 * Read all of the "*Option Choice" pairs from the string, marking PPD
688 * options as we go...
694 * Skip leading whitespace...
697 while (isspace(*s
& 255))
704 * Get the option name...
709 while (*s
&& !isspace(*s
& 255) && ptr
< (option
+ sizeof(option
) - 1))
721 while (isspace(*s
& 255))
728 while (*s
&& !isspace(*s
& 255) && ptr
< (choice
+ sizeof(choice
) - 1))
734 * Add it to the options array...
737 num_options
= cupsAddOption(option
, choice
, num_options
, options
);
740 return (num_options
);
746 * 'ppd_debug_marked()' - Output the marked array to stdout...
750 ppd_debug_marked(ppd_file_t
*ppd
, /* I - PPD file data */
751 const char *title
) /* I - Title for list */
753 ppd_choice_t
*c
; /* Current choice */
756 DEBUG_printf(("2cupsMarkOptions: %s", title
));
758 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
760 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
761 DEBUG_printf(("2cupsMarkOptions: %s=%s", c
->option
->keyword
, c
->choice
));
767 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
771 ppd_defaults(ppd_file_t
*ppd
, /* I - PPD file */
772 ppd_group_t
*g
) /* I - Group to default */
774 int i
; /* Looping var */
775 ppd_option_t
*o
; /* Current option */
776 ppd_group_t
*sg
; /* Current sub-group */
779 for (i
= g
->num_options
, o
= g
->options
; i
> 0; i
--, o
++)
780 if (strcasecmp(o
->keyword
, "PageRegion") != 0)
781 ppdMarkOption(ppd
, o
->keyword
, o
->defchoice
);
783 for (i
= g
->num_subgroups
, sg
= g
->subgroups
; i
> 0; i
--, sg
++)
784 ppd_defaults(ppd
, sg
);
789 * 'ppd_mark_choices()' - Mark one or more option choices from a string.
793 ppd_mark_choices(ppd_file_t
*ppd
, /* I - PPD file */
794 const char *s
) /* I - "*Option Choice ..." string */
796 int i
, /* Looping var */
797 num_options
; /* Number of options */
798 cups_option_t
*options
, /* Options */
799 *option
; /* Current option */
806 num_options
= _ppdParseOptions(s
, 0, &options
);
808 for (i
= num_options
, option
= options
; i
> 0; i
--, option
++)
809 ppd_mark_option(ppd
, option
->name
, option
->value
);
811 cupsFreeOptions(num_options
, options
);
816 * 'ppd_mark_option()' - Quick mark an option without checking for conflicts.
820 ppd_mark_option(ppd_file_t
*ppd
, /* I - PPD file */
821 const char *option
, /* I - Option name */
822 const char *choice
) /* I - Choice name */
824 int i
, j
; /* Looping vars */
825 ppd_option_t
*o
; /* Option pointer */
826 ppd_choice_t
*c
, /* Choice pointer */
827 *oldc
, /* Old choice pointer */
828 key
; /* Search key for choice */
829 struct lconv
*loc
; /* Locale data */
832 DEBUG_printf(("7ppd_mark_option(ppd=%p, option=\"%s\", choice=\"%s\")",
833 ppd
, option
, choice
));
836 * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
837 * it clears the regular InputSlot choices...
840 if (!strcasecmp(option
, "AP_D_InputSlot"))
842 cupsArraySave(ppd
->options
);
844 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
847 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
850 cupsArrayRemove(ppd
->marked
, oldc
);
854 cupsArrayRestore(ppd
->options
);
858 * Check for custom options...
861 cupsArraySave(ppd
->options
);
863 o
= ppdFindOption(ppd
, option
);
865 cupsArrayRestore(ppd
->options
);
872 if (!strncasecmp(choice
, "Custom.", 7))
875 * Handle a custom option...
878 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
881 if (!strcasecmp(option
, "PageSize"))
884 * Handle custom page sizes...
887 ppdPageSize(ppd
, choice
);
892 * Handle other custom options...
895 ppd_coption_t
*coption
; /* Custom option */
896 ppd_cparam_t
*cparam
; /* Custom parameter */
897 char *units
; /* Custom points units */
900 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
902 if ((cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
)) == NULL
)
905 switch (cparam
->type
)
907 case PPD_CUSTOM_CURVE
:
908 case PPD_CUSTOM_INVCURVE
:
909 case PPD_CUSTOM_REAL
:
910 cparam
->current
.custom_real
= (float)_cupsStrScand(choice
+ 7,
914 case PPD_CUSTOM_POINTS
:
915 cparam
->current
.custom_points
= (float)_cupsStrScand(choice
+ 7,
921 if (!strcasecmp(units
, "cm"))
922 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
923 else if (!strcasecmp(units
, "mm"))
924 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
925 else if (!strcasecmp(units
, "m"))
926 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
927 else if (!strcasecmp(units
, "in"))
928 cparam
->current
.custom_points
*= 72.0f
;
929 else if (!strcasecmp(units
, "ft"))
930 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
934 case PPD_CUSTOM_INT
:
935 cparam
->current
.custom_int
= atoi(choice
+ 7);
938 case PPD_CUSTOM_PASSCODE
:
939 case PPD_CUSTOM_PASSWORD
:
940 case PPD_CUSTOM_STRING
:
941 if (cparam
->current
.custom_string
)
942 _cupsStrFree(cparam
->current
.custom_string
);
944 cparam
->current
.custom_string
= _cupsStrAlloc(choice
+ 7);
951 * Make sure that we keep the option marked below...
956 else if (choice
[0] == '{')
959 * Handle multi-value custom options...
962 ppd_coption_t
*coption
; /* Custom option */
963 ppd_cparam_t
*cparam
; /* Custom parameter */
964 char *units
; /* Custom points units */
965 int num_vals
; /* Number of values */
966 cups_option_t
*vals
, /* Values */
970 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
973 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
975 num_vals
= cupsParseOptions(choice
, 0, &vals
);
977 for (i
= 0, val
= vals
; i
< num_vals
; i
++, val
++)
979 if ((cparam
= ppdFindCustomParam(coption
, val
->name
)) == NULL
)
982 switch (cparam
->type
)
984 case PPD_CUSTOM_CURVE
:
985 case PPD_CUSTOM_INVCURVE
:
986 case PPD_CUSTOM_REAL
:
987 cparam
->current
.custom_real
= (float)_cupsStrScand(val
->value
,
991 case PPD_CUSTOM_POINTS
:
992 cparam
->current
.custom_points
= (float)_cupsStrScand(val
->value
,
998 if (!strcasecmp(units
, "cm"))
999 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
1000 else if (!strcasecmp(units
, "mm"))
1001 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
1002 else if (!strcasecmp(units
, "m"))
1003 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
1004 else if (!strcasecmp(units
, "in"))
1005 cparam
->current
.custom_points
*= 72.0f
;
1006 else if (!strcasecmp(units
, "ft"))
1007 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
1011 case PPD_CUSTOM_INT
:
1012 cparam
->current
.custom_int
= atoi(val
->value
);
1015 case PPD_CUSTOM_PASSCODE
:
1016 case PPD_CUSTOM_PASSWORD
:
1017 case PPD_CUSTOM_STRING
:
1018 if (cparam
->current
.custom_string
)
1019 _cupsStrFree(cparam
->current
.custom_string
);
1021 cparam
->current
.custom_string
= _cupsStrRetain(val
->value
);
1026 cupsFreeOptions(num_vals
, vals
);
1031 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
1032 if (!strcasecmp(c
->choice
, choice
))
1040 * Option found; mark it and then handle unmarking any other options.
1043 if (o
->ui
!= PPD_UI_PICKMANY
)
1046 * Unmark all other choices...
1049 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, c
)) != NULL
)
1052 cupsArrayRemove(ppd
->marked
, oldc
);
1055 if (!strcasecmp(option
, "PageSize") || !strcasecmp(option
, "PageRegion"))
1058 * Mark current page size...
1061 for (j
= 0; j
< ppd
->num_sizes
; j
++)
1062 ppd
->sizes
[j
].marked
= !strcasecmp(ppd
->sizes
[j
].name
,
1066 * Unmark the current PageSize or PageRegion setting, as
1070 cupsArraySave(ppd
->options
);
1072 if (!strcasecmp(option
, "PageSize"))
1074 if ((o
= ppdFindOption(ppd
, "PageRegion")) != NULL
)
1077 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1080 cupsArrayRemove(ppd
->marked
, oldc
);
1086 if ((o
= ppdFindOption(ppd
, "PageSize")) != NULL
)
1089 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1092 cupsArrayRemove(ppd
->marked
, oldc
);
1097 cupsArrayRestore(ppd
->options
);
1099 else if (!strcasecmp(option
, "InputSlot"))
1102 * Unmark ManualFeed option...
1105 cupsArraySave(ppd
->options
);
1107 if ((o
= ppdFindOption(ppd
, "ManualFeed")) != NULL
)
1110 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1113 cupsArrayRemove(ppd
->marked
, oldc
);
1117 cupsArrayRestore(ppd
->options
);
1119 else if (!strcasecmp(option
, "ManualFeed") &&
1120 !strcasecmp(choice
, "True"))
1123 * Unmark InputSlot option...
1126 cupsArraySave(ppd
->options
);
1128 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1131 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1134 cupsArrayRemove(ppd
->marked
, oldc
);
1138 cupsArrayRestore(ppd
->options
);
1144 cupsArrayAdd(ppd
->marked
, c
);
1149 * 'ppd_mark_size()' - Quickly mark a page size without checking for conflicts.
1151 * This function is also responsible for mapping PWG/ISO/IPP size names to the
1156 ppd_mark_size(ppd_file_t
*ppd
, /* I - PPD file */
1157 const char *size
) /* I - Size name */
1159 int i
; /* Looping var */
1160 _cups_pwg_media_t
*pwgmedia
; /* PWG media information */
1161 ppd_size_t
*ppdsize
; /* Current PPD size */
1162 double dw
, dl
; /* Difference in width and height */
1163 double width
, /* Width to find */
1164 length
; /* Length to find */
1165 char width_str
[256], /* Width in size name */
1166 length_str
[256],/* Length in size name */
1167 units
[256], /* Units in size name */
1168 custom
[256]; /* Custom size */
1169 struct lconv
*loc
; /* Localization data */
1173 * See if this is a PPD size...
1176 if (!strncasecmp(size
, "Custom.", 7) || ppdPageSize(ppd
, size
))
1178 ppd_mark_option(ppd
, "PageSize", size
);
1183 * Nope, try looking up the PWG or legacy (IPP/ISO) size name...
1186 if ((pwgmedia
= _cupsPWGMediaByName(size
)) == NULL
)
1187 pwgmedia
= _cupsPWGMediaByLegacy(size
);
1191 width
= pwgmedia
->width
;
1192 length
= pwgmedia
->length
;
1194 else if (sscanf(size
, "%*[^_]_%*[^_]_%255[0-9.]x%255[0-9.]%s", width_str
,
1195 length_str
, units
) == 3)
1198 * Got a "self-describing" name that isn't in our table...
1202 width
= _cupsStrScand(width_str
, NULL
, loc
);
1203 length
= _cupsStrScand(length_str
, NULL
, loc
);
1205 if (!strcmp(units
, "in"))
1210 else if (!strcmp(units
, "mm"))
1212 width
*= 25.4 / 72.0;
1213 length
*= 25.4 / 72.0;
1222 * Search the PPD file for a matching size...
1225 for (i
= ppd
->num_sizes
, ppdsize
= ppd
->sizes
; i
> 0; i
--, ppdsize
++)
1227 dw
= ppdsize
->width
- width
;
1228 dl
= ppdsize
->length
- length
;
1230 if (dw
> -5.0 && dw
< 5.0 && dl
> -5.0 && dl
< 5.0)
1232 ppd_mark_option(ppd
, "PageSize", ppdsize
->name
);
1238 * No match found; if custom sizes are supported, set a custom size...
1241 if (ppd
->variable_sizes
)
1243 snprintf(custom
, sizeof(custom
), "Custom.%dx%d", (int)width
, (int)length
);
1244 ppd_mark_option(ppd
, "PageSize", custom
);
1250 * End of "$Id: mark.c 8210 2009-01-09 02:30:26Z mike $".