4 * PWG load/save API implementation for CUPS.
6 * Copyright 2010 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * _pwgCreateWithFile() - Create PWG mapping data from a written file.
19 * _pwgDestroy() - Free all memory used for PWG mapping data.
20 * _pwgWriteFile() - Write PWG mapping data to a file.
24 * Include necessary headers...
27 #include "cups-private.h"
32 * '_pwgCreateWithFile()' - Create PWG mapping data from a written file.
34 * Use the @link _pwgWriteFile@ function to write PWG mapping data to a file.
37 _pwg_t
* /* O - PWG mapping data */
38 _pwgCreateWithFile(const char *filename
)/* I - File to read */
40 cups_file_t
*fp
; /* File */
41 _pwg_t
*pwg
; /* PWG mapping data */
42 _pwg_size_t
*size
; /* Current size */
43 _pwg_map_t
*map
; /* Current map */
44 int linenum
, /* Current line number */
45 num_bins
, /* Number of bins in file */
46 num_sizes
, /* Number of sizes in file */
47 num_sources
, /* Number of sources in file */
48 num_types
; /* Number of types in file */
49 char line
[2048], /* Current line */
50 *value
, /* Pointer to value in line */
51 *valueptr
, /* Pointer into value */
52 pwg_keyword
[128], /* PWG keyword */
53 ppd_keyword
[PPD_MAX_NAME
];
55 _pwg_output_mode_t output_mode
; /* Output mode for preset */
56 _pwg_print_quality_t print_quality
; /* Print quality for preset */
59 DEBUG_printf(("_pwgCreateWithFile(filename=\"%s\")", filename
));
62 * Range check input...
67 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(EINVAL
), 0);
75 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
77 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
82 * Allocate the mapping data structure...
85 if ((pwg
= calloc(1, sizeof(_pwg_t
))) == NULL
)
87 DEBUG_puts("_pwgCreateWithFile: Unable to allocate pwg_t.");
88 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
102 while (cupsFileGetConf(fp
, line
, sizeof(line
), &value
, &linenum
))
104 DEBUG_printf(("_pwgCreateWithFile: line=\"%s\", value=\"%s\", linenum=%d",
105 line
, value
, linenum
));
109 DEBUG_printf(("_pwgCreateWithFile: Missing value on line %d.", linenum
));
110 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
113 else if (!strcasecmp(line
, "NumBins"))
117 DEBUG_puts("_pwgCreateWithFile: NumBins listed multiple times.");
118 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
122 if ((num_bins
= atoi(value
)) <= 0 || num_bins
> 65536)
124 DEBUG_printf(("_pwgCreateWithFile: Bad NumBins value %d on line %d.",
125 num_sizes
, linenum
));
126 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
130 if ((pwg
->bins
= calloc(num_bins
, sizeof(_pwg_map_t
))) == NULL
)
132 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d bins.",
134 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
138 else if (!strcasecmp(line
, "Bin"))
140 if (sscanf(value
, "%127s%40s", pwg_keyword
, ppd_keyword
) != 2)
142 DEBUG_printf(("_pwgCreateWithFile: Bad Bin on line %d.", linenum
));
143 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
147 if (pwg
->num_bins
>= num_bins
)
149 DEBUG_printf(("_pwgCreateWithFile: Too many Bin's on line %d.",
151 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
155 map
= pwg
->bins
+ pwg
->num_bins
;
156 map
->pwg
= _cupsStrAlloc(pwg_keyword
);
157 map
->ppd
= _cupsStrAlloc(ppd_keyword
);
161 else if (!strcasecmp(line
, "NumSizes"))
165 DEBUG_puts("_pwgCreateWithFile: NumSizes listed multiple times.");
166 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
170 if ((num_sizes
= atoi(value
)) <= 0 || num_sizes
> 65536)
172 DEBUG_printf(("_pwgCreateWithFile: Bad NumSizes value %d on line %d.",
173 num_sizes
, linenum
));
174 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
178 if ((pwg
->sizes
= calloc(num_sizes
, sizeof(_pwg_size_t
))) == NULL
)
180 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sizes.",
182 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
186 else if (!strcasecmp(line
, "Size"))
188 if (pwg
->num_sizes
>= num_sizes
)
190 DEBUG_printf(("_pwgCreateWithFile: Too many Size's on line %d.",
192 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
196 size
= pwg
->sizes
+ pwg
->num_sizes
;
198 if (sscanf(value
, "%127s%40s%d%d%d%d%d%d", pwg_keyword
, ppd_keyword
,
199 &(size
->width
), &(size
->length
), &(size
->left
),
200 &(size
->bottom
), &(size
->right
), &(size
->top
)) != 8)
202 DEBUG_printf(("_pwgCreateWithFile: Bad Size on line %d.", linenum
));
203 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
207 size
->map
.pwg
= _cupsStrAlloc(pwg_keyword
);
208 size
->map
.ppd
= _cupsStrAlloc(ppd_keyword
);
212 else if (!strcasecmp(line
, "CustomSize"))
214 if (pwg
->custom_max_width
> 0)
216 DEBUG_printf(("_pwgCreateWithFile: Too many CustomSize's on line %d.",
218 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
222 if (sscanf(value
, "%d%d%d%d%d%d%d%d", &(pwg
->custom_max_width
),
223 &(pwg
->custom_max_length
), &(pwg
->custom_min_width
),
224 &(pwg
->custom_min_length
), &(pwg
->custom_size
.left
),
225 &(pwg
->custom_size
.bottom
), &(pwg
->custom_size
.right
),
226 &(pwg
->custom_size
.top
)) != 8)
228 DEBUG_printf(("_pwgCreateWithFile: Bad CustomSize on line %d.", linenum
));
229 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
233 _pwgGenerateSize(pwg_keyword
, sizeof(pwg_keyword
), "custom", "max",
234 pwg
->custom_max_width
, pwg
->custom_max_length
);
235 pwg
->custom_max_keyword
= _cupsStrAlloc(pwg_keyword
);
237 _pwgGenerateSize(pwg_keyword
, sizeof(pwg_keyword
), "custom", "min",
238 pwg
->custom_min_width
, pwg
->custom_min_length
);
239 pwg
->custom_min_keyword
= _cupsStrAlloc(pwg_keyword
);
241 else if (!strcasecmp(line
, "NumSources"))
245 DEBUG_puts("_pwgCreateWithFile: NumSources listed multiple times.");
246 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
250 if ((num_sources
= atoi(value
)) <= 0 || num_sources
> 65536)
252 DEBUG_printf(("_pwgCreateWithFile: Bad NumSources value %d on line %d.",
253 num_sources
, linenum
));
254 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
258 if ((pwg
->sources
= calloc(num_sources
, sizeof(_pwg_map_t
))) == NULL
)
260 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sources.",
262 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
266 else if (!strcasecmp(line
, "Source"))
268 if (sscanf(value
, "%127s%40s", pwg_keyword
, ppd_keyword
) != 2)
270 DEBUG_printf(("_pwgCreateWithFile: Bad Source on line %d.", linenum
));
271 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
275 if (pwg
->num_sources
>= num_sources
)
277 DEBUG_printf(("_pwgCreateWithFile: Too many Source's on line %d.",
279 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
283 map
= pwg
->sources
+ pwg
->num_sources
;
284 map
->pwg
= _cupsStrAlloc(pwg_keyword
);
285 map
->ppd
= _cupsStrAlloc(ppd_keyword
);
289 else if (!strcasecmp(line
, "NumTypes"))
293 DEBUG_puts("_pwgCreateWithFile: NumTypes listed multiple times.");
294 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
298 if ((num_types
= atoi(value
)) <= 0 || num_types
> 65536)
300 DEBUG_printf(("_pwgCreateWithFile: Bad NumTypes value %d on line %d.",
301 num_types
, linenum
));
302 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
306 if ((pwg
->types
= calloc(num_types
, sizeof(_pwg_map_t
))) == NULL
)
308 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d types.",
310 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
314 else if (!strcasecmp(line
, "Type"))
316 if (sscanf(value
, "%127s%40s", pwg_keyword
, ppd_keyword
) != 2)
318 DEBUG_printf(("_pwgCreateWithFile: Bad Type on line %d.", linenum
));
319 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
323 if (pwg
->num_types
>= num_types
)
325 DEBUG_printf(("_pwgCreateWithFile: Too many Type's on line %d.",
327 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
331 map
= pwg
->types
+ pwg
->num_types
;
332 map
->pwg
= _cupsStrAlloc(pwg_keyword
);
333 map
->ppd
= _cupsStrAlloc(ppd_keyword
);
337 else if (!strcasecmp(line
, "Preset"))
340 * Preset output-mode print-quality name=value ...
343 output_mode
= (_pwg_output_mode_t
)strtol(value
, &valueptr
, 10);
344 print_quality
= (_pwg_print_quality_t
)strtol(valueptr
, &valueptr
, 10);
346 if (output_mode
< _PWG_OUTPUT_MODE_MONOCHROME
||
347 output_mode
>= _PWG_OUTPUT_MODE_MAX
||
348 print_quality
< _PWG_PRINT_QUALITY_DRAFT
||
349 print_quality
>= _PWG_PRINT_QUALITY_MAX
||
350 valueptr
== value
|| !*valueptr
)
352 DEBUG_printf(("_pwgCreateWithFile: Bad Preset on line %d.", linenum
));
353 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
357 pwg
->num_presets
[output_mode
][print_quality
] =
358 cupsParseOptions(valueptr
, 0,
359 pwg
->presets
[output_mode
] + print_quality
);
361 else if (!strcasecmp(line
, "SidesOption"))
362 pwg
->sides_option
= _cupsStrAlloc(value
);
363 else if (!strcasecmp(line
, "Sides1Sided"))
364 pwg
->sides_1sided
= _cupsStrAlloc(value
);
365 else if (!strcasecmp(line
, "Sides2SidedLong"))
366 pwg
->sides_2sided_long
= _cupsStrAlloc(value
);
367 else if (!strcasecmp(line
, "Sides2SidedShort"))
368 pwg
->sides_2sided_short
= _cupsStrAlloc(value
);
371 DEBUG_printf(("_pwgCreateWithFile: Unknown %s on line %d.", line
,
373 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
378 if (pwg
->num_sizes
< num_sizes
)
380 DEBUG_printf(("_pwgCreateWithFile: Not enough sizes (%d < %d).",
381 pwg
->num_sizes
, num_sizes
));
382 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
386 if (pwg
->num_sources
< num_sources
)
388 DEBUG_printf(("_pwgCreateWithFile: Not enough sources (%d < %d).",
389 pwg
->num_sources
, num_sources
));
390 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
394 if (pwg
->num_types
< num_types
)
396 DEBUG_printf(("_pwgCreateWithFile: Not enough types (%d < %d).",
397 pwg
->num_types
, num_types
));
398 _cupsSetError(IPP_INTERNAL_ERROR
, _("Bad PWG mapping file."), 1);
407 * If we get here the file was bad - free any data and return...
420 * '_pwgDestroy()' - Free all memory used for PWG mapping data.
424 _pwgDestroy(_pwg_t
*pwg
) /* I - PWG mapping data */
426 int i
; /* Looping var */
427 _pwg_map_t
*map
; /* Current map */
428 _pwg_size_t
*size
; /* Current size */
432 * Range check input...
439 * Free memory as needed...
444 for (i
= pwg
->num_bins
, map
= pwg
->bins
; i
> 0; i
--, map
++)
446 _cupsStrFree(map
->pwg
);
447 _cupsStrFree(map
->ppd
);
455 for (i
= pwg
->num_sizes
, size
= pwg
->sizes
; i
> 0; i
--, size
++)
457 _cupsStrFree(size
->map
.pwg
);
458 _cupsStrFree(size
->map
.ppd
);
466 for (i
= pwg
->num_sources
, map
= pwg
->sources
; i
> 0; i
--, map
++)
468 _cupsStrFree(map
->pwg
);
469 _cupsStrFree(map
->ppd
);
477 for (i
= pwg
->num_types
, map
= pwg
->types
; i
> 0; i
--, map
++)
479 _cupsStrFree(map
->pwg
);
480 _cupsStrFree(map
->ppd
);
486 if (pwg
->custom_max_keyword
)
487 _cupsStrFree(pwg
->custom_max_keyword
);
489 if (pwg
->custom_min_keyword
)
490 _cupsStrFree(pwg
->custom_min_keyword
);
497 * '_pwgWriteFile()' - Write PWG mapping data to a file.
500 int /* O - 1 on success, 0 on failure */
501 _pwgWriteFile(_pwg_t
*pwg
, /* I - PWG mapping data */
502 const char *filename
) /* I - File to write */
504 int i
, j
, k
; /* Looping vars */
505 cups_file_t
*fp
; /* Output file */
506 _pwg_size_t
*size
; /* Current size */
507 _pwg_map_t
*map
; /* Current map */
508 cups_option_t
*option
; /* Current option */
512 * Range check input...
515 if (!pwg
|| !filename
)
517 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(EINVAL
), 0);
522 * Open the file and write with compression...
525 if ((fp
= cupsFileOpen(filename
, "w9")) == NULL
)
527 _cupsSetError(IPP_INTERNAL_ERROR
, strerror(errno
), 0);
535 cupsFilePuts(fp
, "#CUPS-PWGPPD\n");
541 if (pwg
->num_bins
> 0)
543 cupsFilePrintf(fp
, "NumBins %d\n", pwg
->num_bins
);
544 for (i
= pwg
->num_bins
, map
= pwg
->bins
; i
> 0; i
--, map
++)
545 cupsFilePrintf(fp
, "Bin %s %s\n", map
->pwg
, map
->ppd
);
552 cupsFilePrintf(fp
, "NumSizes %d\n", pwg
->num_sizes
);
553 for (i
= pwg
->num_sizes
, size
= pwg
->sizes
; i
> 0; i
--, size
++)
554 cupsFilePrintf(fp
, "Size %s %s %d %d %d %d %d %d\n", size
->map
.pwg
,
555 size
->map
.ppd
, size
->width
, size
->length
, size
->left
,
556 size
->bottom
, size
->right
, size
->top
);
557 if (pwg
->custom_max_width
> 0)
558 cupsFilePrintf(fp
, "CustomSize %d %d %d %d %d %d %d %d\n",
559 pwg
->custom_max_width
, pwg
->custom_max_length
,
560 pwg
->custom_min_width
, pwg
->custom_min_length
,
561 pwg
->custom_size
.left
, pwg
->custom_size
.bottom
,
562 pwg
->custom_size
.right
, pwg
->custom_size
.top
);
568 if (pwg
->num_sources
> 0)
570 cupsFilePrintf(fp
, "NumSources %d\n", pwg
->num_sources
);
571 for (i
= pwg
->num_sources
, map
= pwg
->sources
; i
> 0; i
--, map
++)
572 cupsFilePrintf(fp
, "Source %s %s\n", map
->pwg
, map
->ppd
);
579 if (pwg
->num_types
> 0)
581 cupsFilePrintf(fp
, "NumTypes %d\n", pwg
->num_types
);
582 for (i
= pwg
->num_types
, map
= pwg
->types
; i
> 0; i
--, map
++)
583 cupsFilePrintf(fp
, "Type %s %s\n", map
->pwg
, map
->ppd
);
590 for (i
= _PWG_OUTPUT_MODE_MONOCHROME
; i
< _PWG_OUTPUT_MODE_MAX
; i
++)
591 for (j
= _PWG_PRINT_QUALITY_DRAFT
; i
< _PWG_PRINT_QUALITY_MAX
; i
++)
592 if (pwg
->num_presets
[i
][j
])
594 cupsFilePrintf(fp
, "Preset %d %d", i
, j
);
595 for (k
= pwg
->num_presets
[i
][j
], option
= pwg
->presets
[i
][j
];
598 cupsFilePrintf(fp
, " %s=%s", option
->name
, option
->value
);
599 cupsFilePutChar(fp
, '\n');
606 if (pwg
->sides_option
)
607 cupsFilePrintf(fp
, "SidesOption %s\n", pwg
->sides_option
);
609 if (pwg
->sides_1sided
)
610 cupsFilePrintf(fp
, "Sides1Sided %s\n", pwg
->sides_1sided
);
612 if (pwg
->sides_2sided_long
)
613 cupsFilePrintf(fp
, "Sides2SidedLong %s\n", pwg
->sides_2sided_long
);
615 if (pwg
->sides_2sided_short
)
616 cupsFilePrintf(fp
, "Sides2SidedShort %s\n", pwg
->sides_2sided_short
);
619 * Close and return...
622 return (!cupsFileClose(fp
));