]>
git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-driver.cxx
4 // PPD file compiler definitions for the CUPS PPD Compiler.
6 // Copyright 2007-2011 by Apple Inc.
7 // Copyright 2002-2006 by Easy Software Products.
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/".
17 // ppdcDriver::ppdcDriver() - Create a new printer driver.
18 // ppdcDriver::~ppdcDriver() - Destroy a printer driver.
19 // ppdcDriver::find_attr() - Find an attribute.
20 // ppdcDriver::find_group() - Find a group.
21 // ppdcDriver::find_option() - Find an option.
22 // ppdcDriver::find_option_group() - Find an option and its group.
23 // ppdcDriver::set_custom_size_code() - Set the custom page size code.
24 // ppdcDriver::set_default_font() - Set the default font name.
25 // ppdcDriver::set_default_size() - Set the default size name.
26 // ppdcDriver::set_file_name() - Set the full filename.
27 // ppdcDriver::set_manufacturer() - Set the manufacturer name.
28 // ppdcDriver::set_model_name() - Set the model name.
29 // ppdcDriver::set_pc_file_name() - Set the PC filename.
30 // ppdcDriver::set_version() - Set the version string.
31 // ppdcDriver::write_ppd_file() - Write a PPD file...
35 // Include necessary headers...
38 #include "ppdc-private.h"
42 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
45 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
48 ppdcGroup
*g
; // Current group
55 // Bump the use count of any strings we inherit...
57 d
->manufacturer
->retain();
61 d
->default_font
->retain();
63 d
->default_size
->retain();
64 if (d
->custom_size_code
)
65 d
->custom_size_code
->retain();
67 // Copy all of the data from the driver template...
68 copyright
= new ppdcArray(d
->copyright
);
69 manufacturer
= d
->manufacturer
;
75 model_number
= d
->model_number
;
76 manual_copies
= d
->manual_copies
;
77 color_device
= d
->color_device
;
78 throughput
= d
->throughput
;
79 attrs
= new ppdcArray(d
->attrs
);
80 constraints
= new ppdcArray(d
->constraints
);
81 filters
= new ppdcArray(d
->filters
);
82 fonts
= new ppdcArray(d
->fonts
);
83 profiles
= new ppdcArray(d
->profiles
);
84 sizes
= new ppdcArray(d
->sizes
);
85 default_font
= d
->default_font
;
86 default_size
= d
->default_size
;
87 variable_paper_size
= d
->variable_paper_size
;
88 custom_size_code
= d
->custom_size_code
;
89 left_margin
= d
->left_margin
;
90 bottom_margin
= d
->bottom_margin
;
91 right_margin
= d
->right_margin
;
92 top_margin
= d
->top_margin
;
93 max_width
= d
->max_width
;
94 max_length
= d
->max_length
;
95 min_width
= d
->min_width
;
96 min_length
= d
->min_length
;
98 // Then copy the groups manually, since we want separate copies
99 // of the groups and options...
100 groups
= new ppdcArray();
102 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
103 groups
->add(new ppdcGroup(g
));
107 // Zero all of the data in the driver...
108 copyright
= new ppdcArray();
114 type
= PPDC_DRIVER_CUSTOM
;
119 attrs
= new ppdcArray();
120 constraints
= new ppdcArray();
121 fonts
= new ppdcArray();
122 filters
= new ppdcArray();
123 groups
= new ppdcArray();
124 profiles
= new ppdcArray();
125 sizes
= new ppdcArray();
128 variable_paper_size
= 0;
129 custom_size_code
= 0;
143 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
146 ppdcDriver::~ppdcDriver()
150 copyright
->release();
153 manufacturer
->release();
155 model_name
->release();
157 file_name
->release();
159 pc_file_name
->release();
163 default_font
->release();
165 default_size
->release();
166 if (custom_size_code
)
167 custom_size_code
->release();
170 constraints
->release();
180 // 'ppdcDriver::find_attr()' - Find an attribute.
183 ppdcAttr
* // O - Attribute or NULL
184 ppdcDriver::find_attr(const char *k
, // I - Keyword string
185 const char *s
) // I - Spec string
187 ppdcAttr
*a
; // Current attribute
190 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
191 if (!strcmp(a
->name
->value
, k
) &&
192 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
193 (s
&& a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
201 // 'ppdcDriver::find_group()' - Find a group.
204 ppdcGroup
* // O - Matching group or NULL
205 ppdcDriver::find_group(const char *n
) // I - Group name
207 ppdcGroup
*g
; // Current group
210 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
211 if (!_cups_strcasecmp(n
, g
->name
->value
))
219 // 'ppdcDriver::find_option()' - Find an option.
222 ppdcOption
* // O - Matching option or NULL
223 ppdcDriver::find_option(const char *n
) // I - Option name
225 return (find_option_group(n
, (ppdcGroup
**)0));
230 // 'ppdcDriver::find_option_group()' - Find an option and its group.
233 ppdcOption
* // O - Matching option or NULL
234 ppdcDriver::find_option_group(
235 const char *n
, // I - Option name
236 ppdcGroup
**mg
) // O - Matching group or NULL
238 ppdcGroup
*g
; // Current group
239 ppdcOption
*o
; // Current option
242 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
243 for (o
= (ppdcOption
*)g
->options
->first(); o
; o
= (ppdcOption
*)g
->options
->next())
244 if (!_cups_strcasecmp(n
, o
->name
->value
))
253 *mg
= (ppdcGroup
*)0;
260 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
264 ppdcDriver::set_custom_size_code(
265 const char *c
) // I - CustomPageSize code
267 if (custom_size_code
)
268 custom_size_code
->release();
270 custom_size_code
= new ppdcString(c
);
275 // 'ppdcDriver::set_default_font()' - Set the default font name.
279 ppdcDriver::set_default_font(
280 ppdcFont
*f
) // I - Font
283 default_font
->release();
288 default_font
= f
->name
;
296 // 'ppdcDriver::set_default_size()' - Set the default size name.
300 ppdcDriver::set_default_size(
301 ppdcMediaSize
*m
) // I - Media size
304 default_size
->release();
309 default_size
= m
->name
;
317 // 'ppdcDriver::set_file_name()' - Set the full filename.
321 ppdcDriver::set_file_name(const char *f
)// I - Filename
324 file_name
->release();
326 file_name
= new ppdcString(f
);
331 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
335 ppdcDriver::set_manufacturer(
336 const char *m
) // I - Model name
339 manufacturer
->release();
341 manufacturer
= new ppdcString(m
);
346 // 'ppdcDriver::set_model_name()' - Set the model name.
350 ppdcDriver::set_model_name(
351 const char *m
) // I - Model name
354 model_name
->release();
356 model_name
= new ppdcString(m
);
361 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
365 ppdcDriver::set_pc_file_name(
366 const char *f
) // I - Filename
369 pc_file_name
->release();
371 pc_file_name
= new ppdcString(f
);
376 // 'ppdcDriver::set_version()' - Set the version string.
380 ppdcDriver::set_version(const char *v
) // I - Version
385 version
= new ppdcString(v
);
390 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
393 int // O - 0 on success, -1 on failure
394 ppdcDriver::write_ppd_file(
395 cups_file_t
*fp
, // I - PPD file
396 ppdcCatalog
*catalog
, // I - Message catalog
397 ppdcArray
*locales
, // I - Additional languages to add
398 ppdcSource
*src
, // I - Driver source
399 ppdcLineEnding le
) // I - Line endings to use
401 bool delete_cat
; // Delete the catalog when we are done?
402 char query
[42], // Query attribute
403 custom
[42]; // Custom attribute
404 ppdcString
*s
; // Copyright string
405 ppdcGroup
*g
; // Current group
406 ppdcOption
*o
; // Current option
407 ppdcChoice
*c
; // Current choice
408 ppdcMediaSize
*m
; // Current media size
409 ppdcProfile
*p
; // Current color profile
410 ppdcFilter
*f
; // Current filter
411 ppdcFont
*fn
, // Current font
412 *bfn
; // Current base font
413 ppdcConstraint
*cn
; // Current constraint
414 ppdcAttr
*a
; // Current attribute
415 const char *lf
; // Linefeed character to use
418 // If we don't have a message catalog, use an empty (English) one...
421 catalog
= new ppdcCatalog("en");
427 // Figure out the end-of-line string...
428 if (le
== PPDC_LFONLY
)
430 else if (le
== PPDC_CRONLY
)
435 // Write the standard header stuff...
436 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
437 cupsFilePrintf(fp
, "*%%%%%%%% PPD file for %s with CUPS.%s",
438 model_name
->value
, lf
);
440 "*%%%%%%%% Created by the CUPS PPD Compiler " CUPS_SVERSION
442 for (s
= (ppdcString
*)copyright
->first();
444 s
= (ppdcString
*)copyright
->next())
445 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
446 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
447 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
449 a
= find_attr("LanguageVersion", NULL
);
450 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
451 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
453 a
= find_attr("LanguageEncoding", NULL
);
454 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
455 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
457 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
459 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
460 if (!strcmp(a
->name
->value
, "Product"))
465 for (; a
; a
= (ppdcAttr
*)attrs
->next())
466 if (!strcmp(a
->name
->value
, "Product"))
467 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
470 cupsFilePrintf(fp
, "*Product: \"(%s)\"%s", model_name
->value
, lf
);
472 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
473 catalog
->find_message(manufacturer
->value
), lf
);
475 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
476 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
477 catalog
->find_message(a
->value
->value
), lf
);
478 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
479 strlen(manufacturer
->value
)))
480 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
481 catalog
->find_message(manufacturer
->value
),
482 catalog
->find_message(model_name
->value
), lf
);
484 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
485 catalog
->find_message(model_name
->value
), lf
);
487 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
488 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
489 catalog
->find_message(a
->value
->value
), lf
);
490 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
491 strlen(manufacturer
->value
)))
492 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
493 catalog
->find_message(manufacturer
->value
),
494 catalog
->find_message(model_name
->value
), lf
);
496 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
497 catalog
->find_message(model_name
->value
), lf
);
499 if ((a
= find_attr("NickName", NULL
)) != NULL
)
500 cupsFilePrintf(fp
, "*NickName: \"%s\"%s",
501 catalog
->find_message(a
->value
->value
), lf
);
502 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
503 strlen(manufacturer
->value
)))
504 cupsFilePrintf(fp
, "*NickName: \"%s %s, %s\"%s",
505 catalog
->find_message(manufacturer
->value
),
506 catalog
->find_message(model_name
->value
), version
->value
,
509 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
510 catalog
->find_message(model_name
->value
), version
->value
,
513 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
514 if (!strcmp(a
->name
->value
, "PSVersion"))
519 for (; a
; a
= (ppdcAttr
*)attrs
->next())
520 if (!strcmp(a
->name
->value
, "PSVersion"))
521 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
524 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 0\"%s", lf
);
526 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
527 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
529 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
531 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
533 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
534 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
536 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
537 color_device
? "RGB" : "Gray", lf
);
539 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
540 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
542 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
544 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
546 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
547 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
549 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
551 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
552 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
553 else if (type
!= PPDC_DRIVER_PS
)
554 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
556 struct lconv
*loc
= localeconv();
560 // Write driver-defined attributes...
561 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
562 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
564 if (!strcmp(a
->name
->value
, "Product") ||
565 !strcmp(a
->name
->value
, "PSVersion") ||
566 !strcmp(a
->name
->value
, "LanguageLevel") ||
567 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
568 !strcmp(a
->name
->value
, "FileSystem") ||
569 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
570 !strcmp(a
->name
->value
, "TTRasterizer") ||
571 !strcmp(a
->name
->value
, "LanguageVersion") ||
572 !strcmp(a
->name
->value
, "LanguageEncoding") ||
573 !strcmp(a
->name
->value
, "ModelName") ||
574 !strcmp(a
->name
->value
, "NickName") ||
575 !strcmp(a
->name
->value
, "ShortNickName") ||
576 !strcmp(a
->name
->value
, "cupsVersion"))
579 if (a
->name
->value
[0] == '?' &&
580 (find_option(a
->name
->value
+ 1) ||
581 !strcmp(a
->name
->value
, "?ImageableArea") ||
582 !strcmp(a
->name
->value
, "?PageRegion") ||
583 !strcmp(a
->name
->value
, "?PageSize") ||
584 !strcmp(a
->name
->value
, "?PaperDimension")))
587 if (!strncmp(a
->name
->value
, "Custom", 6) &&
588 find_option(a
->name
->value
+ 6))
591 if (!strncmp(a
->name
->value
, "ParamCustom", 11) &&
592 find_option(a
->name
->value
+ 11))
595 if (!a
->selector
->value
|| !a
->selector
->value
[0])
596 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
597 else if (!a
->text
->value
|| !a
->text
->value
[0])
598 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
600 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
603 if (strcmp(a
->value
->value
, "False") &&
604 strcmp(a
->value
->value
, "True") &&
605 strcmp(a
->name
->value
, "1284Modes") &&
606 strcmp(a
->name
->value
, "InkName") &&
607 strcmp(a
->name
->value
, "PageStackOrder") &&
608 strncmp(a
->name
->value
, "ParamCustom", 11) &&
609 strcmp(a
->name
->value
, "Protocols") &&
610 strcmp(a
->name
->value
, "ReferencePunch") &&
611 strncmp(a
->name
->value
, "Default", 7))
613 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
615 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
616 cupsFilePrintf(fp
, "*End%s", lf
);
619 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
623 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
625 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
626 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
628 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
629 CUPS_VERSION_MINOR
, lf
);
630 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
631 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
632 manual_copies
? "True" : "False", lf
);
636 for (f
= (ppdcFilter
*)filters
->first();
638 f
= (ppdcFilter
*)filters
->next())
639 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
640 f
->cost
, f
->program
->value
, lf
);
646 case PPDC_DRIVER_LABEL
:
647 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
648 "rastertolabel\"%s", lf
);
651 case PPDC_DRIVER_EPSON
:
652 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
653 "rastertoepson\"%s", lf
);
656 case PPDC_DRIVER_ESCP
:
657 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
658 "commandtoescpx\"%s", lf
);
659 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
660 "rastertoescpx\"%s", lf
);
663 case PPDC_DRIVER_HP
:
664 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
665 "rastertohp\"%s", lf
);
668 case PPDC_DRIVER_PCL
:
669 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
670 "commandtopclx\"%s", lf
);
671 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
672 "rastertopclx\"%s", lf
);
680 for (p
= (ppdcProfile
*)profiles
->first();
682 p
= (ppdcProfile
*)profiles
->next())
684 char density
[255], gamma
[255], profile
[9][255];
686 _cupsStrFormatd(density
, density
+ sizeof(density
), p
->density
, loc
);
687 _cupsStrFormatd(gamma
, gamma
+ sizeof(gamma
), p
->gamma
, loc
);
689 for (int i
= 0; i
< 9; i
++)
690 _cupsStrFormatd(profile
[i
], profile
[i
] + sizeof(profile
[0]),
694 "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
695 "%s\"%s", p
->resolution
->value
, p
->media_type
->value
,
696 density
, gamma
, profile
[0], profile
[1], profile
[2],
697 profile
[3], profile
[4], profile
[5], profile
[6], profile
[7],
704 // Add localizations for additional languages...
705 ppdcString
*locale
; // Locale name
706 ppdcCatalog
*locatalog
; // Message catalog for locale
709 // Write the list of languages...
710 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
712 for (locale
= (ppdcString
*)locales
->first();
714 locale
= (ppdcString
*)locales
->next())
716 // Skip (US) English...
717 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
720 // See if we have a po file for this language...
721 if (!src
->find_po(locale
->value
))
723 // No, see if we can use the base file?
724 locatalog
= new ppdcCatalog(locale
->value
);
726 if (locatalog
->messages
->count
== 0)
728 // No, skip this one...
729 _cupsLangPrintf(stderr
,
730 _("ppdc: No message catalog provided for locale "
731 "%s."), locale
->value
);
735 // Add the base file to the list...
736 src
->po_files
->add(locatalog
);
739 cupsFilePrintf(fp
, " %s", locale
->value
);
742 cupsFilePrintf(fp
, "\"%s", lf
);
745 for (cn
= (ppdcConstraint
*)constraints
->first();
747 cn
= (ppdcConstraint
*)constraints
->next())
749 // First constrain 1 against 2...
750 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
751 !strncmp(cn
->option2
->value
, "*Custom", 7))
752 cupsFilePuts(fp
, "*NonUIConstraints: ");
754 cupsFilePuts(fp
, "*UIConstraints: ");
756 if (cn
->option1
->value
[0] != '*')
757 cupsFilePutChar(fp
, '*');
759 cupsFilePuts(fp
, cn
->option1
->value
);
761 if (cn
->choice1
->value
)
762 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
764 cupsFilePutChar(fp
, ' ');
766 if (cn
->option2
->value
[0] != '*')
767 cupsFilePutChar(fp
, '*');
769 cupsFilePuts(fp
, cn
->option2
->value
);
771 if (cn
->choice2
->value
)
772 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
774 cupsFilePuts(fp
, lf
);
776 // Then constrain 2 against 1...
777 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
778 !strncmp(cn
->option2
->value
, "*Custom", 7))
779 cupsFilePuts(fp
, "*NonUIConstraints: ");
781 cupsFilePuts(fp
, "*UIConstraints: ");
783 if (cn
->option2
->value
[0] != '*')
784 cupsFilePutChar(fp
, '*');
786 cupsFilePuts(fp
, cn
->option2
->value
);
788 if (cn
->choice2
->value
)
789 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
791 cupsFilePutChar(fp
, ' ');
793 if (cn
->option1
->value
[0] != '*')
794 cupsFilePutChar(fp
, '*');
796 cupsFilePuts(fp
, cn
->option1
->value
);
798 if (cn
->choice1
->value
)
799 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
801 cupsFilePuts(fp
, lf
);
804 // PageSize option...
805 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
806 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
807 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
808 default_size
? default_size
->value
: "Letter", lf
);
810 for (m
= (ppdcMediaSize
*)sizes
->first();
812 m
= (ppdcMediaSize
*)sizes
->next())
813 if (m
->size_code
->value
)
815 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
816 m
->name
->value
, catalog
->find_message(m
->text
->value
),
817 m
->size_code
->value
, lf
);
819 if (strchr(m
->size_code
->value
, '\n') ||
820 strchr(m
->size_code
->value
, '\r'))
821 cupsFilePrintf(fp
, "*End%s", lf
);
825 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
826 "/ImagingBBox null>>setpagedevice\"%s",
827 m
->name
->value
, catalog
->find_message(m
->text
->value
),
828 m
->width
, m
->length
, lf
);
830 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
832 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
834 if (strchr(a
->value
->value
, '\n') ||
835 strchr(a
->value
->value
, '\r'))
836 cupsFilePrintf(fp
, "*End%s", lf
);
839 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
841 // PageRegion option...
842 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
843 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
844 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
845 default_size
? default_size
->value
: "Letter", lf
);
847 for (m
= (ppdcMediaSize
*)sizes
->first();
849 m
= (ppdcMediaSize
*)sizes
->next())
850 if (m
->region_code
->value
)
852 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
853 m
->name
->value
, catalog
->find_message(m
->text
->value
),
854 m
->region_code
->value
, lf
);
856 if (strchr(m
->region_code
->value
, '\n') ||
857 strchr(m
->region_code
->value
, '\r'))
858 cupsFilePrintf(fp
, "*End%s", lf
);
862 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
863 "/ImagingBBox null>>setpagedevice\"%s",
864 m
->name
->value
, catalog
->find_message(m
->text
->value
),
865 m
->width
, m
->length
, lf
);
867 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
869 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
871 if (strchr(a
->value
->value
, '\n') ||
872 strchr(a
->value
->value
, '\r'))
873 cupsFilePrintf(fp
, "*End%s", lf
);
876 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
878 // ImageableArea info...
879 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
880 default_size
? default_size
->value
: "Letter", lf
);
882 char left
[255], right
[255], bottom
[255], top
[255];
884 for (m
= (ppdcMediaSize
*)sizes
->first();
886 m
= (ppdcMediaSize
*)sizes
->next())
888 _cupsStrFormatd(left
, left
+ sizeof(left
), m
->left
, loc
);
889 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), m
->bottom
, loc
);
890 _cupsStrFormatd(right
, right
+ sizeof(right
), m
->width
- m
->right
, loc
);
891 _cupsStrFormatd(top
, top
+ sizeof(top
), m
->length
- m
->top
, loc
);
893 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
894 m
->name
->value
, catalog
->find_message(m
->text
->value
),
895 left
, bottom
, right
, top
, lf
);
898 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
900 cupsFilePrintf(fp
, "*?ImageableArea: \"%s\"%s", a
->value
->value
, lf
);
902 if (strchr(a
->value
->value
, '\n') ||
903 strchr(a
->value
->value
, '\r'))
904 cupsFilePrintf(fp
, "*End%s", lf
);
907 // PaperDimension info...
908 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
909 default_size
? default_size
->value
: "Letter", lf
);
911 char width
[255], length
[255];
913 for (m
= (ppdcMediaSize
*)sizes
->first();
915 m
= (ppdcMediaSize
*)sizes
->next())
917 _cupsStrFormatd(width
, width
+ sizeof(width
), m
->width
, loc
);
918 _cupsStrFormatd(length
, length
+ sizeof(length
), m
->length
, loc
);
920 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%s %s\"%s",
921 m
->name
->value
, catalog
->find_message(m
->text
->value
),
925 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
927 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
929 if (strchr(a
->value
->value
, '\n') ||
930 strchr(a
->value
->value
, '\r'))
931 cupsFilePrintf(fp
, "*End%s", lf
);
934 // Custom size support...
935 if (variable_paper_size
)
937 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
938 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
940 _cupsStrFormatd(left
, left
+ sizeof(left
), left_margin
, loc
);
941 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), bottom_margin
, loc
);
942 _cupsStrFormatd(right
, right
+ sizeof(right
), right_margin
, loc
);
943 _cupsStrFormatd(top
, top
+ sizeof(top
), top_margin
, loc
);
945 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%s\"%s", width
, lf
);
946 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%s\"%s", length
, lf
);
947 cupsFilePrintf(fp
, "*HWMargins: %s %s %s %s%s", left
, bottom
, right
, top
,
950 if (custom_size_code
&& custom_size_code
->value
)
952 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
953 custom_size_code
->value
, lf
);
955 if (strchr(custom_size_code
->value
, '\n') ||
956 strchr(custom_size_code
->value
, '\r'))
957 cupsFilePrintf(fp
, "*End%s", lf
);
961 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
962 "/ImagingBBox null>>setpagedevice\"%s", lf
);
964 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
965 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
971 _cupsStrFormatd(width0
, width0
+ sizeof(width0
), min_width
, loc
);
972 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
974 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %s %s%s",
978 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
979 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
985 _cupsStrFormatd(length0
, length0
+ sizeof(length0
), min_length
, loc
);
986 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
988 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %s %s%s",
989 length0
, length
, lf
);
992 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
993 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
994 a
->value
->value
, lf
);
996 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
998 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
999 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
1000 a
->value
->value
, lf
);
1002 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
1004 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
1005 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
1006 a
->value
->value
, lf
);
1008 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
1011 // All other options...
1012 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1014 if (!g
->options
->count
)
1017 if (_cups_strcasecmp(g
->name
->value
, "General"))
1018 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
1019 catalog
->find_message(g
->text
->value
), lf
);
1021 for (o
= (ppdcOption
*)g
->options
->first();
1023 o
= (ppdcOption
*)g
->options
->next())
1025 if (!o
->choices
->count
)
1028 if (o
->section
== PPDC_SECTION_JCL
)
1030 if (!o
->text
->value
)
1031 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1032 catalog
->find_message(o
->name
->value
));
1034 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1035 catalog
->find_message(o
->text
->value
));
1037 else if (!o
->text
->value
)
1038 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1039 catalog
->find_message(o
->name
->value
));
1041 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1042 catalog
->find_message(o
->text
->value
));
1047 cupsFilePrintf(fp
, "Boolean%s", lf
);
1050 cupsFilePrintf(fp
, "PickOne%s", lf
);
1052 case PPDC_PICKMANY
:
1053 cupsFilePrintf(fp
, "PickMany%s", lf
);
1058 _cupsStrFormatd(order
, order
+ sizeof(order
), o
->order
, loc
);
1060 cupsFilePrintf(fp
, "*OrderDependency: %s ", order
);
1064 cupsFilePrintf(fp
, "AnySetup");
1066 case PPDC_SECTION_DOCUMENT
:
1067 cupsFilePrintf(fp
, "DocumentSetup");
1069 case PPDC_SECTION_EXIT
:
1070 cupsFilePrintf(fp
, "ExitServer");
1072 case PPDC_SECTION_JCL
:
1073 cupsFilePrintf(fp
, "JCLSetup");
1075 case PPDC_SECTION_PAGE
:
1076 cupsFilePrintf(fp
, "PageSetup");
1078 case PPDC_SECTION_PROLOG
:
1079 cupsFilePrintf(fp
, "Prolog");
1083 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
1087 // Use the programmer-supplied default...
1088 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
1089 o
->defchoice
->value
, lf
);
1093 // Make the first choice the default...
1094 c
= (ppdcChoice
*)o
->choices
->first();
1095 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
1099 for (c
= (ppdcChoice
*)o
->choices
->first();
1101 c
= (ppdcChoice
*)o
->choices
->next())
1103 // Write this choice...
1104 if (!c
->text
->value
)
1105 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1106 c
->name
->value
, catalog
->find_message(c
->name
->value
),
1107 c
->code
->value
, lf
);
1109 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1110 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1111 c
->code
->value
, lf
);
1113 // Multi-line commands need a *End line to terminate them.
1114 if (strchr(c
->code
->value
, '\n') ||
1115 strchr(c
->code
->value
, '\r'))
1116 cupsFilePrintf(fp
, "*End%s", lf
);
1119 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1121 if ((a
= find_attr(query
, NULL
)) != NULL
)
1123 cupsFilePrintf(fp
, "*%s: \"%s\"%s", query
, a
->value
->value
, lf
);
1125 if (strchr(a
->value
->value
, '\n') ||
1126 strchr(a
->value
->value
, '\r'))
1127 cupsFilePrintf(fp
, "*End%s", lf
);
1130 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1132 snprintf(custom
, sizeof(custom
), "Custom%s", o
->name
->value
);
1133 if ((a
= find_attr(custom
, "True")) != NULL
)
1135 // Output custom option information...
1136 cupsFilePrintf(fp
, "*%s True: \"%s\"%s", custom
, a
->value
->value
, lf
);
1137 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
1138 cupsFilePrintf(fp
, "*End%s", lf
);
1140 snprintf(custom
, sizeof(custom
), "ParamCustom%s", o
->name
->value
);
1141 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1143 if (strcmp(a
->name
->value
, custom
))
1146 if (!a
->selector
->value
|| !a
->selector
->value
[0])
1147 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
1148 else if (!a
->text
->value
|| !a
->text
->value
[0])
1149 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1150 catalog
->find_message(a
->selector
->value
));
1152 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1153 catalog
->find_message(a
->text
->value
));
1155 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
1160 if (_cups_strcasecmp(g
->name
->value
, "General"))
1161 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1166 // Add localizations for additional languages...
1167 ppdcString
*locale
; // Locale name
1168 ppdcCatalog
*locatalog
; // Message catalog for locale
1171 // Write the translation strings for each language...
1172 for (locale
= (ppdcString
*)locales
->first();
1174 locale
= (ppdcString
*)locales
->next())
1176 // Skip (US) English...
1177 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1180 // Skip missing languages...
1181 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1184 // Do the core stuff first...
1185 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1187 locatalog
->find_message(manufacturer
->value
), lf
);
1189 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1190 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1192 locatalog
->find_message(a
->value
->value
), lf
);
1193 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1194 strlen(manufacturer
->value
)))
1195 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1197 locatalog
->find_message(manufacturer
->value
),
1198 locatalog
->find_message(model_name
->value
), lf
);
1200 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1202 locatalog
->find_message(model_name
->value
), lf
);
1204 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1205 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1207 locatalog
->find_message(a
->value
->value
), lf
);
1208 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1209 strlen(manufacturer
->value
)))
1210 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1212 locatalog
->find_message(manufacturer
->value
),
1213 locatalog
->find_message(model_name
->value
), lf
);
1215 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1217 locatalog
->find_message(model_name
->value
), lf
);
1219 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1220 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1222 locatalog
->find_message(a
->value
->value
), lf
);
1223 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1224 strlen(manufacturer
->value
)))
1225 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1227 locatalog
->find_message(manufacturer
->value
),
1228 locatalog
->find_message(model_name
->value
),
1229 version
->value
, lf
);
1231 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1233 locatalog
->find_message(model_name
->value
),
1234 version
->value
, lf
);
1236 // Then the page sizes...
1237 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1238 locatalog
->find_message("Media Size"), lf
);
1240 for (m
= (ppdcMediaSize
*)sizes
->first();
1242 m
= (ppdcMediaSize
*)sizes
->next())
1244 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1245 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1249 // Next the groups and options...
1250 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1252 if (!g
->options
->count
)
1255 if (_cups_strcasecmp(g
->name
->value
, "General"))
1256 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1258 locatalog
->find_message(g
->text
->value
), lf
);
1260 for (o
= (ppdcOption
*)g
->options
->first();
1262 o
= (ppdcOption
*)g
->options
->next())
1264 if (!o
->choices
->count
)
1267 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1269 locatalog
->find_message(o
->text
->value
?
1271 o
->name
->value
), lf
);
1273 for (c
= (ppdcChoice
*)o
->choices
->first();
1275 c
= (ppdcChoice
*)o
->choices
->next())
1277 // Write this choice...
1278 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1279 o
->name
->value
, c
->name
->value
,
1280 locatalog
->find_message(c
->text
->value
?
1282 c
->name
->value
), lf
);
1287 // Finally the localizable attributes...
1288 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1290 if (!a
->localizable
&&
1291 (!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1292 strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1293 strcmp(a
->name
->value
, "APPrinterPreset") &&
1294 strcmp(a
->name
->value
, "cupsICCProfile") &&
1295 strcmp(a
->name
->value
, "cupsIPPReason") &&
1296 strcmp(a
->name
->value
, "cupsMarkerName") &&
1297 strncmp(a
->name
->value
, "Custom", 6) &&
1298 strncmp(a
->name
->value
, "ParamCustom", 11))
1301 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1302 a
->name
->value
, a
->selector
->value
,
1303 locatalog
->find_message(a
->text
&& a
->text
->value
?
1304 a
->text
->value
: a
->name
->value
),
1305 ((a
->localizable
&& a
->value
->value
[0]) ||
1306 !strcmp(a
->name
->value
, "cupsIPPReason")) ?
1307 locatalog
->find_message(a
->value
->value
) : "",
1313 if (default_font
&& default_font
->value
)
1314 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1316 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1318 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1319 if (!strcmp(fn
->name
->value
, "*"))
1321 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1323 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1324 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1325 bfn
->name
->value
, bfn
->encoding
->value
,
1326 bfn
->version
->value
, bfn
->charset
->value
,
1327 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1330 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1331 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1333 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1335 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1336 (int)(cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),