]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/options.c
2 * "$Id: options.c 6310 2007-02-27 14:20:39Z mike $"
4 * Option routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2007 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * cupsAddOption() - Add an option to an option array.
29 * cupsFreeOptions() - Free all memory used by options.
30 * cupsGetOption() - Get an option value.
31 * cupsMarkOptions() - Mark command-line options in a PPD file.
32 * cupsParseOptions() - Parse options from a command-line argument.
33 * cupsRemoveOptions() - Remove an option from an option array.
37 * Include necessary headers...
48 * 'cupsAddOption()' - Add an option to an option array.
51 int /* O - Number of options */
52 cupsAddOption(const char *name
, /* I - Name of option */
53 const char *value
, /* I - Value of option */
54 int num_options
,/* I - Number of options */
55 cups_option_t
**options
) /* IO - Pointer to options */
57 int i
; /* Looping var */
58 cups_option_t
*temp
; /* Pointer to new option */
61 if (name
== NULL
|| !name
[0] || value
== NULL
||
62 options
== NULL
|| num_options
< 0)
66 * Look for an existing option with the same name...
69 for (i
= 0, temp
= *options
; i
< num_options
; i
++, temp
++)
70 if (strcasecmp(temp
->name
, name
) == 0)
76 * No matching option name...
80 temp
= (cups_option_t
*)malloc(sizeof(cups_option_t
));
82 temp
= (cups_option_t
*)realloc(*options
, sizeof(cups_option_t
) *
90 temp
->name
= strdup(name
);
96 * Match found; free the old value...
102 temp
->value
= strdup(value
);
104 return (num_options
);
109 * 'cupsFreeOptions()' - Free all memory used by options.
114 int num_options
, /* I - Number of options */
115 cups_option_t
*options
) /* I - Pointer to options */
117 int i
; /* Looping var */
120 if (num_options
<= 0 || options
== NULL
)
123 for (i
= 0; i
< num_options
; i
++)
125 free(options
[i
].name
);
126 free(options
[i
].value
);
134 * 'cupsGetOption()' - Get an option value.
137 const char * /* O - Option value or NULL */
138 cupsGetOption(const char *name
, /* I - Name of option */
139 int num_options
,/* I - Number of options */
140 cups_option_t
*options
) /* I - Options */
142 int i
; /* Looping var */
145 if (name
== NULL
|| num_options
<= 0 || options
== NULL
)
148 for (i
= 0; i
< num_options
; i
++)
149 if (strcasecmp(options
[i
].name
, name
) == 0)
150 return (options
[i
].value
);
157 * 'cupsMarkOptions()' - Mark command-line options in a PPD file.
160 int /* O - 1 if conflicting */
162 ppd_file_t
*ppd
, /* I - PPD file */
163 int num_options
, /* I - Number of options */
164 cups_option_t
*options
) /* I - Options */
166 int i
, j
, k
; /* Looping vars */
167 int conflict
; /* Option conflicts */
168 char *val
, /* Pointer into value */
169 *ptr
, /* Pointer into string */
170 s
[255]; /* Temporary string */
171 const char *page_size
; /* PageSize option */
172 cups_option_t
*optptr
; /* Current option */
173 ppd_option_t
*option
; /* PPD option */
174 static const char * const duplex_options
[] =
175 { /* Duplex option names */
176 "Duplex", /* Adobe */
177 "EFDuplex", /* EFI */
178 "EFDuplexing", /* EFI */
179 "KD03Duplex", /* Kodak */
180 "JCLDuplex" /* Samsung */
182 static const char * const duplex_one
[] =
183 { /* one-sided names */
187 static const char * const duplex_two_long
[] =
188 { /* two-sided-long-edge names */
189 "DuplexNoTumble", /* Adobe */
190 "LongEdge", /* EFI */
193 static const char * const duplex_two_short
[] =
194 { /* two-sided-long-edge names */
195 "DuplexTumble", /* Adobe */
196 "ShortEdge", /* EFI */
205 if (ppd
== NULL
|| num_options
<= 0 || options
== NULL
)
214 for (i
= num_options
, optptr
= options
; i
> 0; i
--, optptr
++)
215 if (!strcasecmp(optptr
->name
, "media"))
218 * Loop through the option string, separating it at commas and
219 * marking each individual option as long as the corresponding
220 * PPD option (PageSize, InputSlot, etc.) is not also set.
222 * For PageSize, we also check for an empty option value since
223 * some versions of MacOS X use it to specify auto-selection
224 * of the media based solely on the size.
227 page_size
= cupsGetOption("PageSize", num_options
, options
);
229 for (val
= optptr
->value
; *val
;)
232 * Extract the sub-option from the string...
235 for (ptr
= s
; *val
&& *val
!= ',' && (ptr
- s
) < (sizeof(s
) - 1);)
246 if (!page_size
|| !page_size
[0])
247 if (ppdMarkOption(ppd
, "PageSize", s
))
250 if (cupsGetOption("InputSlot", num_options
, options
) == NULL
)
251 if (ppdMarkOption(ppd
, "InputSlot", s
))
254 if (cupsGetOption("MediaType", num_options
, options
) == NULL
)
255 if (ppdMarkOption(ppd
, "MediaType", s
))
258 if (cupsGetOption("EFMediaType", num_options
, options
) == NULL
)
259 if (ppdMarkOption(ppd
, "EFMediaType", s
))
262 if (cupsGetOption("EFMediaQualityMode", num_options
, options
) == NULL
)
263 if (ppdMarkOption(ppd
, "EFMediaQualityMode", s
)) /* EFI */
266 if (strcasecmp(s
, "manual") == 0 &&
267 cupsGetOption("ManualFeed", num_options
, options
) == NULL
)
268 if (ppdMarkOption(ppd
, "ManualFeed", "True"))
272 else if (!strcasecmp(optptr
->name
, "sides"))
274 for (j
= 0; j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])); j
++)
275 if (cupsGetOption(duplex_options
[j
], num_options
, options
) != NULL
)
278 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
281 * Don't override the PPD option with the IPP attribute...
287 if (!strcasecmp(optptr
->value
, "one-sided"))
290 * Mark the appropriate duplex option for one-sided output...
293 for (j
= 0; j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])); j
++)
294 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
297 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
299 for (k
= 0; k
< (int)(sizeof(duplex_one
) / sizeof(duplex_one
[0])); k
++)
300 if (ppdFindChoice(option
, duplex_one
[k
]))
302 if (ppdMarkOption(ppd
, duplex_options
[j
], duplex_one
[k
]))
309 else if (!strcasecmp(optptr
->value
, "two-sided-long-edge"))
312 * Mark the appropriate duplex option for two-sided-long-edge output...
315 for (j
= 0; j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])); j
++)
316 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
319 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
321 for (k
= 0; k
< (int)(sizeof(duplex_two_long
) / sizeof(duplex_two_long
[0])); k
++)
322 if (ppdFindChoice(option
, duplex_two_long
[k
]))
324 if (ppdMarkOption(ppd
, duplex_options
[j
], duplex_two_long
[k
]))
331 else if (!strcasecmp(optptr
->value
, "two-sided-short-edge"))
334 * Mark the appropriate duplex option for two-sided-short-edge output...
337 for (j
= 0; j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])); j
++)
338 if ((option
= ppdFindOption(ppd
, duplex_options
[j
])) != NULL
)
341 if (j
< (int)(sizeof(duplex_options
) / sizeof(duplex_options
[0])))
343 for (k
= 0; k
< (int)(sizeof(duplex_two_short
) / sizeof(duplex_two_short
[0])); k
++)
344 if (ppdFindChoice(option
, duplex_two_short
[k
]))
346 if (ppdMarkOption(ppd
, duplex_options
[j
], duplex_two_short
[k
]))
354 else if (!strcasecmp(optptr
->name
, "resolution") ||
355 !strcasecmp(optptr
->name
, "printer-resolution"))
357 if (ppdMarkOption(ppd
, "Resolution", optptr
->value
))
359 if (ppdMarkOption(ppd
, "SetResolution", optptr
->value
))
360 /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
362 if (ppdMarkOption(ppd
, "JCLResolution", optptr
->value
)) /* HP */
364 if (ppdMarkOption(ppd
, "CNRes_PGP", optptr
->value
)) /* Canon */
367 else if (!strcasecmp(optptr
->name
, "output-bin"))
369 if (!cupsGetOption("OutputBin", num_options
, options
))
370 if (ppdMarkOption(ppd
, "OutputBin", optptr
->value
))
373 else if (!strcasecmp(optptr
->name
, "multiple-document-handling"))
375 if (!cupsGetOption("Collate", num_options
, options
) &&
376 ppdFindOption(ppd
, "Collate"))
378 if (strcasecmp(optptr
->value
, "separate-documents-uncollated-copies"))
380 if (ppdMarkOption(ppd
, "Collate", "True"))
385 if (ppdMarkOption(ppd
, "Collate", "False"))
390 else if (ppdMarkOption(ppd
, optptr
->name
, optptr
->value
))
398 * 'cupsParseOptions()' - Parse options from a command-line argument.
400 * This function converts space-delimited name/value pairs according
401 * to the PAPI text option ABNF specification. Collection values
402 * ("name={a=... b=... c=...}") are stored with the curley brackets
403 * intact - use cupsParseOptions() on the value to extract the collection
407 int /* O - Number of options found */
409 const char *arg
, /* I - Argument to parse */
410 int num_options
, /* I - Number of options */
411 cups_option_t
**options
) /* O - Options found */
413 char *copyarg
, /* Copy of input string */
414 *ptr
, /* Pointer into string */
415 *name
, /* Pointer to name */
416 *value
; /* Pointer to value */
419 if (arg
== NULL
|| options
== NULL
|| num_options
< 0)
423 * Make a copy of the argument string and then divide it up...
426 copyarg
= strdup(arg
);
430 * Skip leading spaces...
433 while (isspace(*ptr
& 255))
437 * Loop through the string...
443 * Get the name up to a SPACE, =, or end-of-string...
447 while (!isspace(*ptr
& 255) && *ptr
!= '=' && *ptr
!= '\0')
451 * Avoid an empty name...
458 * Skip trailing spaces...
461 while (isspace(*ptr
& 255))
467 * Start of another option...
470 if (strncasecmp(name
, "no", 2) == 0)
471 num_options
= cupsAddOption(name
+ 2, "false", num_options
,
474 num_options
= cupsAddOption(name
, "true", num_options
, options
);
480 * Remove = and parse the value...
488 * Quoted string constant...
494 while (*ptr
!= '\'' && *ptr
!= '\0')
497 _cups_strcpy(ptr
, ptr
+ 1);
505 else if (*ptr
== '\"')
508 * Double-quoted string constant...
514 while (*ptr
!= '\"' && *ptr
!= '\0')
517 _cups_strcpy(ptr
, ptr
+ 1);
525 else if (*ptr
== '{')
528 * Collection value...
535 for (depth
= 1; *ptr
; ptr
++)
538 else if (*ptr
== '}')
549 else if (*ptr
== '\\')
550 _cups_strcpy(ptr
, ptr
+ 1);
558 * Normal space-delimited string...
563 while (!isspace(*ptr
& 255) && *ptr
!= '\0')
566 _cups_strcpy(ptr
, ptr
+ 1);
573 * Skip trailing whitespace...
576 while (isspace(*ptr
& 255))
580 * Add the string value...
583 num_options
= cupsAddOption(name
, value
, num_options
, options
);
587 * Free the copy of the argument we made and return the number of options
593 return (num_options
);
598 * 'cupsRemoveOption()' - Remove an option from an option array.
603 int /* O - New number of options */
605 const char *name
, /* I - Option name */
606 int num_options
, /* I - Current number of options */
607 cups_option_t
**options
) /* IO - Options */
609 int i
; /* Looping var */
610 cups_option_t
*option
; /* Current option */
614 * Range check input...
617 if (!name
|| num_options
< 1 || !options
)
618 return (num_options
);
621 * Loop for the option...
624 for (i
= num_options
, option
= *options
; i
> 0; i
--, option
++)
625 if (!strcasecmp(name
, option
->name
))
631 * Remove this option from the array...
642 memmove(option
, option
+ 1, i
* sizeof(cups_option_t
));
646 * Return the new number of options...
649 return (num_options
);
654 * End of "$Id: options.c 6310 2007-02-27 14:20:39Z mike $".