]>
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 the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2009 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 * 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
37 * ppd_mark_size() - Quickly mark a page size without checking for
42 * Include necessary headers...
56 static void debug_marked(ppd_file_t
*ppd
, const char *title
);
58 # define debug_marked(ppd,title)
60 static void ppd_defaults(ppd_file_t
*ppd
, ppd_group_t
*g
);
61 static void ppd_mark_choices(ppd_file_t
*ppd
, const char *s
);
62 static void ppd_mark_option(ppd_file_t
*ppd
, const char *option
,
64 static void ppd_mark_size(ppd_file_t
*ppd
, const char *size
);
68 * 'cupsMarkOptions()' - Mark command-line options in a PPD file.
70 * This function maps the IPP "finishings", "media", "mirror",
71 * "multiple-document-handling", "output-bin", "printer-resolution", and
72 * "sides" attributes to their corresponding PPD options and choices.
75 int /* O - 1 if conflicts exist, 0 otherwise */
77 ppd_file_t
*ppd
, /* I - PPD file */
78 int num_options
, /* I - Number of options */
79 cups_option_t
*options
) /* I - Options */
81 int i
, j
, k
; /* Looping vars */
82 char *ptr
, /* Pointer into string */
83 s
[255]; /* Temporary string */
84 const char *val
, /* Pointer into value */
85 *media
, /* media option */
86 *media_col
, /* media-col option */
87 *page_size
; /* PageSize option */
88 cups_option_t
*optptr
; /* Current option */
89 ppd_option_t
*option
; /* PPD option */
90 ppd_attr_t
*attr
; /* PPD attribute */
91 static const char * const duplex_options
[] =
92 { /* Duplex option names */
95 "EFDuplexing", /* EFI */
96 "KD03Duplex", /* Kodak */
97 "JCLDuplex" /* Samsung */
99 static const char * const duplex_one
[] =
100 { /* one-sided names */
104 static const char * const duplex_two_long
[] =
105 { /* two-sided-long-edge names */
106 "DuplexNoTumble", /* Adobe */
107 "LongEdge", /* EFI */
110 static const char * const duplex_two_short
[] =
111 { /* two-sided-long-edge names */
112 "DuplexTumble", /* Adobe */
113 "ShortEdge", /* EFI */
122 if (!ppd
|| num_options
<= 0 || !options
)
125 debug_marked(ppd
, "Before...");
128 * Do special handling for media, media-col, and PageSize...
131 media
= cupsGetOption("media", num_options
, options
);
132 media_col
= cupsGetOption("media-col", num_options
, options
);
133 page_size
= cupsGetOption("PageSize", num_options
, options
);
135 if (media_col
&& (!page_size
|| !page_size
[0]))
138 * Pull out the corresponding media size from the media-col value...
141 int num_media_cols
, /* Number of media-col values */
142 num_media_sizes
;/* Number of media-size values */
143 cups_option_t
*media_cols
, /* media-col values */
144 *media_sizes
; /* media-size values */
147 num_media_cols
= cupsParseOptions(media_col
, 0, &media_cols
);
149 if ((val
= cupsGetOption("media-key", num_media_cols
, media_cols
)) != NULL
)
151 else if ((val
= cupsGetOption("media-size", num_media_cols
,
152 media_cols
)) != NULL
)
155 * Lookup by dimensions...
158 double width
, /* Width in points */
159 length
; /* Length in points */
160 struct lconv
*loc
; /* Locale data */
161 _cups_pwg_media_t
*pwgmedia
; /* PWG media name */
164 num_media_sizes
= cupsParseOptions(val
, 0, &media_sizes
);
167 if ((val
= cupsGetOption("x-dimension", num_media_sizes
,
168 media_sizes
)) != NULL
)
169 width
= _cupsStrScand(val
, NULL
, loc
) * 2540.0 / 72.0;
173 if ((val
= cupsGetOption("y-dimension", num_media_sizes
,
174 media_sizes
)) != NULL
)
175 length
= _cupsStrScand(val
, NULL
, loc
) * 2540.0 / 72.0;
179 if ((pwgmedia
= _cupsPWGMediaBySize(width
, length
)) != NULL
)
180 media
= pwgmedia
->pwg
;
182 cupsFreeOptions(num_media_sizes
, media_sizes
);
185 cupsFreeOptions(num_media_cols
, media_cols
);
191 * Loop through the option string, separating it at commas and
192 * marking each individual option as long as the corresponding
193 * PPD option (PageSize, InputSlot, etc.) is not also set.
195 * For PageSize, we also check for an empty option value since
196 * some versions of MacOS X use it to specify auto-selection
197 * of the media based solely on the size.
200 for (val
= media
; *val
;)
203 * Extract the sub-option from the string...
206 for (ptr
= s
; *val
&& *val
!= ',' && (ptr
- s
) < (sizeof(s
) - 1);)
217 if (!page_size
|| !page_size
[0])
218 ppd_mark_size(ppd
, s
);
220 if (cupsGetOption("InputSlot", num_options
, options
) == NULL
)
221 ppd_mark_option(ppd
, "InputSlot", s
);
223 if (cupsGetOption("MediaType", num_options
, options
) == NULL
)
224 ppd_mark_option(ppd
, "MediaType", s
);
226 if (cupsGetOption("EFMediaType", num_options
, options
) == NULL
)
227 ppd_mark_option(ppd
, "EFMediaType", s
); /* EFI */
229 if (cupsGetOption("EFMediaQualityMode", num_options
, options
) == NULL
)
230 ppd_mark_option(ppd
, "EFMediaQualityMode", s
); /* EFI */
232 if (!strcasecmp(s
, "manual") &&
233 !cupsGetOption("ManualFeed", num_options
, options
))
234 ppd_mark_option(ppd
, "ManualFeed", "True");
239 * Mark other options...
242 for (i
= num_options
, optptr
= options
; i
> 0; i
--, optptr
++)
243 if (!strcasecmp(optptr
->name
, "media") ||
244 !strcasecmp(optptr
->name
, "media-col"))
246 else if (!strcasecmp(optptr
->name
, "sides"))
249 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
251 if (cupsGetOption(duplex_options
[j
], num_options
, options
))
254 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
257 * Don't override the PPD option with the IPP attribute...
263 if (!strcasecmp(optptr
->value
, "one-sided"))
266 * Mark the appropriate duplex option for one-sided output...
270 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
272 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
275 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
278 k
< (int)(sizeof(duplex_one
) / sizeof(duplex_one
[0]));
280 if (ppdFindChoice(option
, duplex_one
[k
]))
282 ppd_mark_option(ppd
, duplex_options
[j
], duplex_one
[k
]);
287 else if (!strcasecmp(optptr
->value
, "two-sided-long-edge"))
290 * Mark the appropriate duplex option for two-sided-long-edge output...
294 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
296 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
299 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
302 k
< (int)(sizeof(duplex_two_long
) / sizeof(duplex_two_long
[0]));
304 if (ppdFindChoice(option
, duplex_two_long
[k
]))
306 ppd_mark_option(ppd
, duplex_options
[j
], duplex_two_long
[k
]);
311 else if (!strcasecmp(optptr
->value
, "two-sided-short-edge"))
314 * Mark the appropriate duplex option for two-sided-short-edge output...
318 j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0]));
320 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
323 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
326 k
< (int)(sizeof(duplex_two_short
) / sizeof(duplex_two_short
[0]));
328 if (ppdFindChoice(option
, duplex_two_short
[k
]))
330 ppd_mark_option(ppd
, duplex_options
[j
], duplex_two_short
[k
]);
336 else if (!strcasecmp(optptr
->name
, "resolution") ||
337 !strcasecmp(optptr
->name
, "printer-resolution"))
339 ppd_mark_option(ppd
, "Resolution", optptr
->value
);
340 ppd_mark_option(ppd
, "SetResolution", optptr
->value
);
341 /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
342 ppd_mark_option(ppd
, "JCLResolution", optptr
->value
);
344 ppd_mark_option(ppd
, "CNRes_PGP", optptr
->value
);
347 else if (!strcasecmp(optptr
->name
, "output-bin"))
349 if (!cupsGetOption("OutputBin", num_options
, options
))
350 ppd_mark_option(ppd
, "OutputBin", optptr
->value
);
352 else if (!strcasecmp(optptr
->name
, "multiple-document-handling"))
354 if (!cupsGetOption("Collate", num_options
, options
) &&
355 ppdFindOption(ppd
, "Collate"))
357 if (strcasecmp(optptr
->value
, "separate-documents-uncollated-copies"))
358 ppd_mark_option(ppd
, "Collate", "True");
360 ppd_mark_option(ppd
, "Collate", "False");
363 else if (!strcasecmp(optptr
->name
, "finishings"))
366 * Lookup cupsIPPFinishings attributes for each value...
369 for (ptr
= optptr
->value
; *ptr
;)
372 * Get the next finishings number...
375 if (!isdigit(*ptr
& 255))
378 if ((j
= strtol(ptr
, &ptr
, 10)) < 3)
382 * Skip separator as needed...
389 * Look it up in the PPD file...
394 if ((attr
= ppdFindAttr(ppd
, "cupsIPPFinishings", s
)) == NULL
)
398 * Apply "*Option Choice" settings from the attribute value...
401 ppd_mark_choices(ppd
, attr
->value
);
404 else if (!strcasecmp(optptr
->name
, "APPrinterPreset"))
407 * Lookup APPrinterPreset value...
410 if ((attr
= ppdFindAttr(ppd
, "APPrinterPreset", optptr
->value
)) != NULL
)
413 * Apply "*Option Choice" settings from the attribute value...
416 ppd_mark_choices(ppd
, attr
->value
);
419 else if (!strcasecmp(optptr
->name
, "mirror"))
420 ppd_mark_option(ppd
, "MirrorPrint", optptr
->value
);
422 ppd_mark_option(ppd
, optptr
->name
, optptr
->value
);
424 debug_marked(ppd
, "After...");
426 return (ppdConflicts(ppd
) > 0);
431 * 'ppdFindChoice()' - Return a pointer to an option choice.
434 ppd_choice_t
* /* O - Choice pointer or @code NULL@ */
435 ppdFindChoice(ppd_option_t
*o
, /* I - Pointer to option */
436 const char *choice
) /* I - Name of choice */
438 int i
; /* Looping var */
439 ppd_choice_t
*c
; /* Current choice */
445 if (choice
[0] == '{' || !strncasecmp(choice
, "Custom.", 7))
448 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
449 if (!strcasecmp(c
->choice
, choice
))
457 * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
460 ppd_choice_t
* /* O - Pointer to choice or @code NULL@ */
461 ppdFindMarkedChoice(ppd_file_t
*ppd
, /* I - PPD file */
462 const char *option
) /* I - Keyword/option name */
464 ppd_choice_t key
, /* Search key for choice */
465 *marked
; /* Marked choice */
468 DEBUG_printf(("2ppdFindMarkedChoice(ppd=%p, option=\"%s\")", ppd
, option
));
470 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
472 DEBUG_puts("3ppdFindMarkedChoice: Option not found, returning NULL");
476 marked
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
);
478 DEBUG_printf(("3ppdFindMarkedChoice: Returning %p(%s)...", marked
,
479 marked
? marked
->choice
: "NULL"));
486 * 'ppdFindOption()' - Return a pointer to the specified option.
489 ppd_option_t
* /* O - Pointer to option or @code NULL@ */
490 ppdFindOption(ppd_file_t
*ppd
, /* I - PPD file data */
491 const char *option
) /* I - Option/Keyword name */
494 * Range check input...
503 * Search in the array...
506 ppd_option_t key
; /* Option search key */
509 strlcpy(key
.keyword
, option
, sizeof(key
.keyword
));
511 return ((ppd_option_t
*)cupsArrayFind(ppd
->options
, &key
));
516 * Search in each group...
519 int i
, j
; /* Looping vars */
520 ppd_group_t
*group
; /* Current group */
521 ppd_option_t
*optptr
; /* Current option */
524 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
525 for (j
= group
->num_options
, optptr
= group
->options
;
528 if (!strcasecmp(optptr
->keyword
, option
))
537 * 'ppdIsMarked()' - Check to see if an option is marked.
540 int /* O - Non-zero if option is marked */
541 ppdIsMarked(ppd_file_t
*ppd
, /* I - PPD file data */
542 const char *option
, /* I - Option/Keyword name */
543 const char *choice
) /* I - Choice name */
545 ppd_choice_t key
, /* Search key */
546 *c
; /* Choice pointer */
552 if ((key
.option
= ppdFindOption(ppd
, option
)) == NULL
)
555 if ((c
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) == NULL
)
558 return (!strcmp(c
->choice
, choice
));
563 * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
567 ppdMarkDefaults(ppd_file_t
*ppd
) /* I - PPD file record */
569 int i
; /* Looping variables */
570 ppd_group_t
*g
; /* Current group */
571 ppd_choice_t
*c
; /* Current choice */
578 * Clean out the marked array...
581 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
583 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
584 cupsArrayRemove(ppd
->marked
, c
);
587 * Then repopulate it with the defaults...
590 for (i
= ppd
->num_groups
, g
= ppd
->groups
; i
> 0; i
--, g
++)
591 ppd_defaults(ppd
, g
);
596 * 'ppdMarkOption()' - Mark an option in a PPD file and return the number of
600 int /* O - Number of conflicts */
601 ppdMarkOption(ppd_file_t
*ppd
, /* I - PPD file record */
602 const char *option
, /* I - Keyword */
603 const char *choice
) /* I - Option name */
605 DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")",
606 ppd
, option
, choice
));
609 * Range check input...
612 if (!ppd
|| !option
|| !choice
)
619 ppd_mark_option(ppd
, option
, choice
);
622 * Return the number of conflicts...
625 return (ppdConflicts(ppd
));
630 * 'ppdFirstOption()' - Return the first option in the PPD file.
632 * Options are returned from all groups in ascending alphanumeric order.
634 * @since CUPS 1.2/Mac OS X 10.5@
637 ppd_option_t
* /* O - First option or @code NULL@ */
638 ppdFirstOption(ppd_file_t
*ppd
) /* I - PPD file */
643 return ((ppd_option_t
*)cupsArrayFirst(ppd
->options
));
648 * 'ppdNextOption()' - Return the next option in the PPD file.
650 * Options are returned from all groups in ascending alphanumeric order.
652 * @since CUPS 1.2/Mac OS X 10.5@
655 ppd_option_t
* /* O - Next option or @code NULL@ */
656 ppdNextOption(ppd_file_t
*ppd
) /* I - PPD file */
661 return ((ppd_option_t
*)cupsArrayNext(ppd
->options
));
666 * '_ppdParseOptions()' - Parse options from a PPD file.
668 * This function looks for strings of the form:
670 * *option choice ... *optionN choiceN
672 * It stops when it finds a string that doesn't match this format.
675 int /* O - Number of options */
677 const char *s
, /* I - String to parse */
678 int num_options
, /* I - Number of options */
679 cups_option_t
**options
) /* IO - Options */
681 char option
[PPD_MAX_NAME
], /* Current option */
682 choice
[PPD_MAX_NAME
], /* Current choice */
683 *ptr
; /* Pointer into option or choice */
687 return (num_options
);
690 * Read all of the "*Option Choice" pairs from the string, marking PPD
691 * options as we go...
697 * Skip leading whitespace...
700 while (isspace(*s
& 255))
707 * Get the option name...
712 while (*s
&& !isspace(*s
& 255) && ptr
< (option
+ sizeof(option
) - 1))
724 while (isspace(*s
& 255))
731 while (*s
&& !isspace(*s
& 255) && ptr
< (choice
+ sizeof(choice
) - 1))
737 * Add it to the options array...
740 num_options
= cupsAddOption(option
, choice
, num_options
, options
);
743 return (num_options
);
749 * 'debug_marked()' - Output the marked array to stdout...
753 debug_marked(ppd_file_t
*ppd
, /* I - PPD file data */
754 const char *title
) /* I - Title for list */
756 ppd_choice_t
*c
; /* Current choice */
759 DEBUG_printf(("2cupsMarkOptions: %s", title
));
761 for (c
= (ppd_choice_t
*)cupsArrayFirst(ppd
->marked
);
763 c
= (ppd_choice_t
*)cupsArrayNext(ppd
->marked
))
764 DEBUG_printf(("2cupsMarkOptions: %s=%s", c
->option
->keyword
, c
->choice
));
770 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
774 ppd_defaults(ppd_file_t
*ppd
, /* I - PPD file */
775 ppd_group_t
*g
) /* I - Group to default */
777 int i
; /* Looping var */
778 ppd_option_t
*o
; /* Current option */
779 ppd_group_t
*sg
; /* Current sub-group */
782 for (i
= g
->num_options
, o
= g
->options
; i
> 0; i
--, o
++)
783 if (strcasecmp(o
->keyword
, "PageRegion") != 0)
784 ppdMarkOption(ppd
, o
->keyword
, o
->defchoice
);
786 for (i
= g
->num_subgroups
, sg
= g
->subgroups
; i
> 0; i
--, sg
++)
787 ppd_defaults(ppd
, sg
);
792 * 'ppd_mark_choices()' - Mark one or more option choices from a string.
796 ppd_mark_choices(ppd_file_t
*ppd
, /* I - PPD file */
797 const char *s
) /* I - "*Option Choice ..." string */
799 int i
, /* Looping var */
800 num_options
; /* Number of options */
801 cups_option_t
*options
, /* Options */
802 *option
; /* Current option */
809 num_options
= _ppdParseOptions(s
, 0, &options
);
811 for (i
= num_options
, option
= options
; i
> 0; i
--, option
++)
812 ppd_mark_option(ppd
, option
->name
, option
->value
);
814 cupsFreeOptions(num_options
, options
);
819 * 'ppd_mark_option()' - Quick mark an option without checking for conflicts.
823 ppd_mark_option(ppd_file_t
*ppd
, /* I - PPD file */
824 const char *option
, /* I - Option name */
825 const char *choice
) /* I - Choice name */
827 int i
, j
; /* Looping vars */
828 ppd_option_t
*o
; /* Option pointer */
829 ppd_choice_t
*c
, /* Choice pointer */
830 *oldc
, /* Old choice pointer */
831 key
; /* Search key for choice */
832 struct lconv
*loc
; /* Locale data */
835 DEBUG_printf(("7ppd_mark_option(ppd=%p, option=\"%s\", choice=\"%s\")",
836 ppd
, option
, choice
));
839 * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
840 * it clears the regular InputSlot choices...
843 if (!strcasecmp(option
, "AP_D_InputSlot"))
845 cupsArraySave(ppd
->options
);
847 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
850 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
853 cupsArrayRemove(ppd
->marked
, oldc
);
857 cupsArrayRestore(ppd
->options
);
861 * Check for custom options...
864 cupsArraySave(ppd
->options
);
866 o
= ppdFindOption(ppd
, option
);
868 cupsArrayRestore(ppd
->options
);
875 if (!strncasecmp(choice
, "Custom.", 7))
878 * Handle a custom option...
881 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
884 if (!strcasecmp(option
, "PageSize"))
887 * Handle custom page sizes...
890 ppdPageSize(ppd
, choice
);
895 * Handle other custom options...
898 ppd_coption_t
*coption
; /* Custom option */
899 ppd_cparam_t
*cparam
; /* Custom parameter */
900 char *units
; /* Custom points units */
903 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
905 if ((cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
)) == NULL
)
908 switch (cparam
->type
)
910 case PPD_CUSTOM_CURVE
:
911 case PPD_CUSTOM_INVCURVE
:
912 case PPD_CUSTOM_REAL
:
913 cparam
->current
.custom_real
= (float)_cupsStrScand(choice
+ 7,
917 case PPD_CUSTOM_POINTS
:
918 cparam
->current
.custom_points
= (float)_cupsStrScand(choice
+ 7,
924 if (!strcasecmp(units
, "cm"))
925 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
926 else if (!strcasecmp(units
, "mm"))
927 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
928 else if (!strcasecmp(units
, "m"))
929 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
930 else if (!strcasecmp(units
, "in"))
931 cparam
->current
.custom_points
*= 72.0f
;
932 else if (!strcasecmp(units
, "ft"))
933 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
937 case PPD_CUSTOM_INT
:
938 cparam
->current
.custom_int
= atoi(choice
+ 7);
941 case PPD_CUSTOM_PASSCODE
:
942 case PPD_CUSTOM_PASSWORD
:
943 case PPD_CUSTOM_STRING
:
944 if (cparam
->current
.custom_string
)
945 _cupsStrFree(cparam
->current
.custom_string
);
947 cparam
->current
.custom_string
= _cupsStrAlloc(choice
+ 7);
954 * Make sure that we keep the option marked below...
959 else if (choice
[0] == '{')
962 * Handle multi-value custom options...
965 ppd_coption_t
*coption
; /* Custom option */
966 ppd_cparam_t
*cparam
; /* Custom parameter */
967 char *units
; /* Custom points units */
968 int num_vals
; /* Number of values */
969 cups_option_t
*vals
, /* Values */
973 if ((c
= ppdFindChoice(o
, "Custom")) == NULL
)
976 if ((coption
= ppdFindCustomOption(ppd
, option
)) != NULL
)
978 num_vals
= cupsParseOptions(choice
, 0, &vals
);
980 for (i
= 0, val
= vals
; i
< num_vals
; i
++, val
++)
982 if ((cparam
= ppdFindCustomParam(coption
, val
->name
)) == NULL
)
985 switch (cparam
->type
)
987 case PPD_CUSTOM_CURVE
:
988 case PPD_CUSTOM_INVCURVE
:
989 case PPD_CUSTOM_REAL
:
990 cparam
->current
.custom_real
= (float)_cupsStrScand(val
->value
,
994 case PPD_CUSTOM_POINTS
:
995 cparam
->current
.custom_points
= (float)_cupsStrScand(val
->value
,
1001 if (!strcasecmp(units
, "cm"))
1002 cparam
->current
.custom_points
*= 72.0f
/ 2.54f
;
1003 else if (!strcasecmp(units
, "mm"))
1004 cparam
->current
.custom_points
*= 72.0f
/ 25.4f
;
1005 else if (!strcasecmp(units
, "m"))
1006 cparam
->current
.custom_points
*= 72.0f
/ 0.0254f
;
1007 else if (!strcasecmp(units
, "in"))
1008 cparam
->current
.custom_points
*= 72.0f
;
1009 else if (!strcasecmp(units
, "ft"))
1010 cparam
->current
.custom_points
*= 12.0f
* 72.0f
;
1014 case PPD_CUSTOM_INT
:
1015 cparam
->current
.custom_int
= atoi(val
->value
);
1018 case PPD_CUSTOM_PASSCODE
:
1019 case PPD_CUSTOM_PASSWORD
:
1020 case PPD_CUSTOM_STRING
:
1021 if (cparam
->current
.custom_string
)
1022 _cupsStrFree(cparam
->current
.custom_string
);
1024 cparam
->current
.custom_string
= _cupsStrRetain(val
->value
);
1029 cupsFreeOptions(num_vals
, vals
);
1034 for (i
= o
->num_choices
, c
= o
->choices
; i
> 0; i
--, c
++)
1035 if (!strcasecmp(c
->choice
, choice
))
1043 * Option found; mark it and then handle unmarking any other options.
1046 if (o
->ui
!= PPD_UI_PICKMANY
)
1049 * Unmark all other choices...
1052 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, c
)) != NULL
)
1055 cupsArrayRemove(ppd
->marked
, oldc
);
1058 if (!strcasecmp(option
, "PageSize") || !strcasecmp(option
, "PageRegion"))
1061 * Mark current page size...
1064 for (j
= 0; j
< ppd
->num_sizes
; j
++)
1065 ppd
->sizes
[j
].marked
= !strcasecmp(ppd
->sizes
[j
].name
,
1069 * Unmark the current PageSize or PageRegion setting, as
1073 cupsArraySave(ppd
->options
);
1075 if (!strcasecmp(option
, "PageSize"))
1077 if ((o
= ppdFindOption(ppd
, "PageRegion")) != NULL
)
1080 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1083 cupsArrayRemove(ppd
->marked
, oldc
);
1089 if ((o
= ppdFindOption(ppd
, "PageSize")) != NULL
)
1092 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1095 cupsArrayRemove(ppd
->marked
, oldc
);
1100 cupsArrayRestore(ppd
->options
);
1102 else if (!strcasecmp(option
, "InputSlot"))
1105 * Unmark ManualFeed option...
1108 cupsArraySave(ppd
->options
);
1110 if ((o
= ppdFindOption(ppd
, "ManualFeed")) != NULL
)
1113 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1116 cupsArrayRemove(ppd
->marked
, oldc
);
1120 cupsArrayRestore(ppd
->options
);
1122 else if (!strcasecmp(option
, "ManualFeed") &&
1123 !strcasecmp(choice
, "True"))
1126 * Unmark InputSlot option...
1129 cupsArraySave(ppd
->options
);
1131 if ((o
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1134 if ((oldc
= (ppd_choice_t
*)cupsArrayFind(ppd
->marked
, &key
)) != NULL
)
1137 cupsArrayRemove(ppd
->marked
, oldc
);
1141 cupsArrayRestore(ppd
->options
);
1147 cupsArrayAdd(ppd
->marked
, c
);
1152 * 'ppd_mark_size()' - Quickly mark a page size without checking for conflicts.
1154 * This function is also responsible for mapping PWG/ISO/IPP size names to the
1159 ppd_mark_size(ppd_file_t
*ppd
, /* I - PPD file */
1160 const char *size
) /* I - Size name */
1162 int i
; /* Looping var */
1163 _cups_pwg_media_t
*pwgmedia
; /* PWG media information */
1164 ppd_size_t
*ppdsize
; /* Current PPD size */
1165 double dw
, dl
; /* Difference in width and height */
1166 double width
, /* Width to find */
1167 length
; /* Length to find */
1168 char width_str
[256], /* Width in size name */
1169 length_str
[256],/* Length in size name */
1170 units
[256], /* Units in size name */
1171 custom
[256]; /* Custom size */
1172 struct lconv
*loc
; /* Localization data */
1176 * See if this is a PPD size...
1179 if (!strncasecmp(size
, "Custom.", 7) || ppdPageSize(ppd
, size
))
1181 ppd_mark_option(ppd
, "PageSize", size
);
1186 * Nope, try looking up the PWG or legacy (IPP/ISO) size name...
1189 if ((pwgmedia
= _cupsPWGMediaByName(size
)) == NULL
)
1190 pwgmedia
= _cupsPWGMediaByLegacy(size
);
1194 width
= pwgmedia
->width
;
1195 length
= pwgmedia
->length
;
1197 else if (sscanf(size
, "%*[^_]_%*[^_]_%255[0-9.]x%255[0-9.]%s", width_str
,
1198 length_str
, units
) == 3)
1201 * Got a "self-describing" name that isn't in our table...
1205 width
= _cupsStrScand(width_str
, NULL
, loc
);
1206 length
= _cupsStrScand(length_str
, NULL
, loc
);
1208 if (!strcmp(units
, "in"))
1213 else if (!strcmp(units
, "mm"))
1215 width
*= 25.4 / 72.0;
1216 length
*= 25.4 / 72.0;
1225 * Search the PPD file for a matching size...
1228 for (i
= ppd
->num_sizes
, ppdsize
= ppd
->sizes
; i
> 0; i
--, ppdsize
++)
1230 dw
= ppdsize
->width
- width
;
1231 dl
= ppdsize
->length
- length
;
1233 if (dw
> -5.0 && dw
< 5.0 && dl
> -5.0 && dl
< 5.0)
1235 ppd_mark_option(ppd
, "PageSize", ppdsize
->name
);
1241 * No match found; if custom sizes are supported, set a custom size...
1244 if (ppd
->variable_sizes
)
1246 snprintf(custom
, sizeof(custom
), "Custom.%dx%d", (int)width
, (int)length
);
1247 ppd_mark_option(ppd
, "PageSize", custom
);
1253 * End of "$Id: mark.c 8210 2009-01-09 02:30:26Z mike $".