]>
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-2009 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"
39 #include <cups/globals.h>
43 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
46 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
49 ppdcGroup
*g
; // Current group
56 // Bump the use count of any strings we inherit...
58 d
->manufacturer
->retain();
62 d
->default_font
->retain();
64 d
->default_size
->retain();
65 if (d
->custom_size_code
)
66 d
->custom_size_code
->retain();
68 // Copy all of the data from the driver template...
69 copyright
= new ppdcArray(d
->copyright
);
70 manufacturer
= d
->manufacturer
;
76 model_number
= d
->model_number
;
77 manual_copies
= d
->manual_copies
;
78 color_device
= d
->color_device
;
79 throughput
= d
->throughput
;
80 attrs
= new ppdcArray(d
->attrs
);
81 constraints
= new ppdcArray(d
->constraints
);
82 filters
= new ppdcArray(d
->filters
);
83 fonts
= new ppdcArray(d
->fonts
);
84 profiles
= new ppdcArray(d
->profiles
);
85 sizes
= new ppdcArray(d
->sizes
);
86 default_font
= d
->default_font
;
87 default_size
= d
->default_size
;
88 variable_paper_size
= d
->variable_paper_size
;
89 custom_size_code
= d
->custom_size_code
;
90 left_margin
= d
->left_margin
;
91 bottom_margin
= d
->bottom_margin
;
92 right_margin
= d
->right_margin
;
93 top_margin
= d
->top_margin
;
94 max_width
= d
->max_width
;
95 max_length
= d
->max_length
;
96 min_width
= d
->min_width
;
97 min_length
= d
->min_length
;
99 // Then copy the groups manually, since we want separate copies
100 // of the groups and options...
101 groups
= new ppdcArray();
103 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
104 groups
->add(new ppdcGroup(g
));
108 // Zero all of the data in the driver...
109 copyright
= new ppdcArray();
115 type
= PPDC_DRIVER_CUSTOM
;
120 attrs
= new ppdcArray();
121 constraints
= new ppdcArray();
122 fonts
= new ppdcArray();
123 filters
= new ppdcArray();
124 groups
= new ppdcArray();
125 profiles
= new ppdcArray();
126 sizes
= new ppdcArray();
129 variable_paper_size
= 0;
130 custom_size_code
= 0;
144 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
147 ppdcDriver::~ppdcDriver()
151 copyright
->release();
154 manufacturer
->release();
156 model_name
->release();
158 file_name
->release();
160 pc_file_name
->release();
164 default_font
->release();
166 default_size
->release();
167 if (custom_size_code
)
168 custom_size_code
->release();
171 constraints
->release();
181 // 'ppdcDriver::find_attr()' - Find an attribute.
184 ppdcAttr
* // O - Attribute or NULL
185 ppdcDriver::find_attr(const char *k
, // I - Keyword string
186 const char *s
) // I - Spec string
188 ppdcAttr
*a
; // Current attribute
191 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
192 if (!strcmp(a
->name
->value
, k
) &&
193 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
194 (s
&& a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
202 // 'ppdcDriver::find_group()' - Find a group.
205 ppdcGroup
* // O - Matching group or NULL
206 ppdcDriver::find_group(const char *n
) // I - Group name
208 ppdcGroup
*g
; // Current group
211 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
212 if (!strcasecmp(n
, g
->name
->value
))
220 // 'ppdcDriver::find_option()' - Find an option.
223 ppdcOption
* // O - Matching option or NULL
224 ppdcDriver::find_option(const char *n
) // I - Option name
226 return (find_option_group(n
, (ppdcGroup
**)0));
231 // 'ppdcDriver::find_option_group()' - Find an option and its group.
234 ppdcOption
* // O - Matching option or NULL
235 ppdcDriver::find_option_group(
236 const char *n
, // I - Option name
237 ppdcGroup
**mg
) // O - Matching group or NULL
239 ppdcGroup
*g
; // Current group
240 ppdcOption
*o
; // Current option
243 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
244 for (o
= (ppdcOption
*)g
->options
->first(); o
; o
= (ppdcOption
*)g
->options
->next())
245 if (!strcasecmp(n
, o
->name
->value
))
254 *mg
= (ppdcGroup
*)0;
261 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
265 ppdcDriver::set_custom_size_code(
266 const char *c
) // I - CustomPageSize code
268 if (custom_size_code
)
269 custom_size_code
->release();
271 custom_size_code
= new ppdcString(c
);
276 // 'ppdcDriver::set_default_font()' - Set the default font name.
280 ppdcDriver::set_default_font(
281 ppdcFont
*f
) // I - Font
284 default_font
->release();
289 default_font
= f
->name
;
297 // 'ppdcDriver::set_default_size()' - Set the default size name.
301 ppdcDriver::set_default_size(
302 ppdcMediaSize
*m
) // I - Media size
305 default_size
->release();
310 default_size
= m
->name
;
318 // 'ppdcDriver::set_file_name()' - Set the full filename.
322 ppdcDriver::set_file_name(const char *f
)// I - Filename
325 file_name
->release();
327 file_name
= new ppdcString(f
);
332 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
336 ppdcDriver::set_manufacturer(
337 const char *m
) // I - Model name
340 manufacturer
->release();
342 manufacturer
= new ppdcString(m
);
347 // 'ppdcDriver::set_model_name()' - Set the model name.
351 ppdcDriver::set_model_name(
352 const char *m
) // I - Model name
355 model_name
->release();
357 model_name
= new ppdcString(m
);
362 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
366 ppdcDriver::set_pc_file_name(
367 const char *f
) // I - Filename
370 pc_file_name
->release();
372 pc_file_name
= new ppdcString(f
);
377 // 'ppdcDriver::set_version()' - Set the version string.
381 ppdcDriver::set_version(const char *v
) // I - Version
386 version
= new ppdcString(v
);
391 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
394 int // O - 0 on success, -1 on failure
395 ppdcDriver::write_ppd_file(
396 cups_file_t
*fp
, // I - PPD file
397 ppdcCatalog
*catalog
, // I - Message catalog
398 ppdcArray
*locales
, // I - Additional languages to add
399 ppdcSource
*src
, // I - Driver source
400 ppdcLineEnding le
) // I - Line endings to use
402 bool delete_cat
; // Delete the catalog when we are done?
403 char query
[42], // Query attribute
404 custom
[42]; // Custom attribute
405 ppdcString
*s
; // Copyright string
406 ppdcGroup
*g
; // Current group
407 ppdcOption
*o
; // Current option
408 ppdcChoice
*c
; // Current choice
409 ppdcMediaSize
*m
; // Current media size
410 ppdcProfile
*p
; // Current color profile
411 ppdcFilter
*f
; // Current filter
412 ppdcFont
*fn
, // Current font
413 *bfn
; // Current base font
414 ppdcConstraint
*cn
; // Current constraint
415 ppdcAttr
*a
; // Current attribute
416 const char *lf
; // Linefeed character to use
419 // If we don't have a message catalog, use an empty (English) one...
422 catalog
= new ppdcCatalog("en");
428 // Figure out the end-of-line string...
429 if (le
== PPDC_LFONLY
)
431 else if (le
== PPDC_CRONLY
)
436 // Write the standard header stuff...
437 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
438 cupsFilePrintf(fp
, "*%%%%%%%% PPD file for %s with CUPS.%s",
439 model_name
->value
, lf
);
441 "*%%%%%%%% Created by the CUPS PPD Compiler " CUPS_SVERSION
443 for (s
= (ppdcString
*)copyright
->first();
445 s
= (ppdcString
*)copyright
->next())
446 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
447 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
448 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
450 a
= find_attr("LanguageVersion", NULL
);
451 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
452 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
454 a
= find_attr("LanguageEncoding", NULL
);
455 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
456 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
458 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
460 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
461 if (!strcmp(a
->name
->value
, "Product"))
466 for (; a
; a
= (ppdcAttr
*)attrs
->next())
467 if (!strcmp(a
->name
->value
, "Product"))
468 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
471 cupsFilePrintf(fp
, "*Product: \"(%s)\"%s", model_name
->value
, lf
);
473 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
474 catalog
->find_message(manufacturer
->value
), lf
);
476 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
477 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
478 catalog
->find_message(a
->value
->value
), lf
);
479 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
480 strlen(manufacturer
->value
)))
481 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
482 catalog
->find_message(manufacturer
->value
),
483 catalog
->find_message(model_name
->value
), lf
);
485 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
486 catalog
->find_message(model_name
->value
), lf
);
488 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
489 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
490 catalog
->find_message(a
->value
->value
), lf
);
491 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
492 strlen(manufacturer
->value
)))
493 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
494 catalog
->find_message(manufacturer
->value
),
495 catalog
->find_message(model_name
->value
), lf
);
497 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
498 catalog
->find_message(model_name
->value
), lf
);
500 if ((a
= find_attr("NickName", NULL
)) != NULL
)
501 cupsFilePrintf(fp
, "*NickName: \"%s\"%s",
502 catalog
->find_message(a
->value
->value
), lf
);
503 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
504 strlen(manufacturer
->value
)))
505 cupsFilePrintf(fp
, "*NickName: \"%s %s, %s\"%s",
506 catalog
->find_message(manufacturer
->value
),
507 catalog
->find_message(model_name
->value
), version
->value
,
510 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
511 catalog
->find_message(model_name
->value
), version
->value
,
514 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
515 if (!strcmp(a
->name
->value
, "PSVersion"))
520 for (; a
; a
= (ppdcAttr
*)attrs
->next())
521 if (!strcmp(a
->name
->value
, "PSVersion"))
522 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
525 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 0\"%s", lf
);
527 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
528 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
530 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
532 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
534 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
535 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
537 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
538 color_device
? "RGB" : "Gray", lf
);
540 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
541 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
543 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
545 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
547 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
548 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
550 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
552 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
553 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
554 else if (type
!= PPDC_DRIVER_PS
)
555 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
557 struct lconv
*loc
= localeconv();
561 // Write driver-defined attributes...
562 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
563 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
565 if (!strcmp(a
->name
->value
, "Product") ||
566 !strcmp(a
->name
->value
, "PSVersion") ||
567 !strcmp(a
->name
->value
, "LanguageLevel") ||
568 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
569 !strcmp(a
->name
->value
, "FileSystem") ||
570 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
571 !strcmp(a
->name
->value
, "TTRasterizer") ||
572 !strcmp(a
->name
->value
, "LanguageVersion") ||
573 !strcmp(a
->name
->value
, "LanguageEncoding") ||
574 !strcmp(a
->name
->value
, "ModelName") ||
575 !strcmp(a
->name
->value
, "NickName") ||
576 !strcmp(a
->name
->value
, "ShortNickName") ||
577 !strcmp(a
->name
->value
, "cupsVersion"))
580 if (a
->name
->value
[0] == '?' &&
581 (find_option(a
->name
->value
+ 1) ||
582 !strcmp(a
->name
->value
, "?ImageableArea") ||
583 !strcmp(a
->name
->value
, "?PageRegion") ||
584 !strcmp(a
->name
->value
, "?PageSize") ||
585 !strcmp(a
->name
->value
, "?PaperDimension")))
588 if (!strncmp(a
->name
->value
, "Custom", 6) &&
589 find_option(a
->name
->value
+ 6))
592 if (!strncmp(a
->name
->value
, "ParamCustom", 11) &&
593 find_option(a
->name
->value
+ 11))
596 if (!a
->selector
->value
|| !a
->selector
->value
[0])
597 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
598 else if (!a
->text
->value
|| !a
->text
->value
[0])
599 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
601 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
604 if (strcmp(a
->value
->value
, "False") &&
605 strcmp(a
->value
->value
, "True") &&
606 strcmp(a
->name
->value
, "1284Modes") &&
607 strcmp(a
->name
->value
, "InkName") &&
608 strcmp(a
->name
->value
, "PageStackOrder") &&
609 strncmp(a
->name
->value
, "ParamCustom", 11) &&
610 strcmp(a
->name
->value
, "Protocols") &&
611 strcmp(a
->name
->value
, "ReferencePunch") &&
612 strncmp(a
->name
->value
, "Default", 7))
614 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
616 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
617 cupsFilePrintf(fp
, "*End%s", lf
);
620 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
624 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
626 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
627 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
629 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
630 CUPS_VERSION_MINOR
, lf
);
631 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
632 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
633 manual_copies
? "True" : "False", lf
);
637 for (f
= (ppdcFilter
*)filters
->first();
639 f
= (ppdcFilter
*)filters
->next())
640 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
641 f
->cost
, f
->program
->value
, lf
);
647 case PPDC_DRIVER_LABEL
:
648 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
649 "rastertolabel\"%s", lf
);
652 case PPDC_DRIVER_EPSON
:
653 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
654 "rastertoepson\"%s", lf
);
657 case PPDC_DRIVER_ESCP
:
658 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
659 "commandtoescpx\"%s", lf
);
660 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
661 "rastertoescpx\"%s", lf
);
664 case PPDC_DRIVER_HP
:
665 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
666 "rastertohp\"%s", lf
);
669 case PPDC_DRIVER_PCL
:
670 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
671 "commandtopclx\"%s", lf
);
672 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
673 "rastertopclx\"%s", lf
);
681 for (p
= (ppdcProfile
*)profiles
->first();
683 p
= (ppdcProfile
*)profiles
->next())
685 char density
[255], gamma
[255], profile
[9][255];
687 _cupsStrFormatd(density
, density
+ sizeof(density
), p
->density
, loc
);
688 _cupsStrFormatd(gamma
, gamma
+ sizeof(gamma
), p
->gamma
, loc
);
690 for (int i
= 0; i
< 9; i
++)
691 _cupsStrFormatd(profile
[i
], profile
[i
] + sizeof(profile
[0]),
695 "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
696 "%s\"%s", p
->resolution
->value
, p
->media_type
->value
,
697 density
, gamma
, profile
[0], profile
[1], profile
[2],
698 profile
[3], profile
[4], profile
[5], profile
[6], profile
[7],
705 // Add localizations for additional languages...
706 ppdcString
*locale
; // Locale name
707 ppdcCatalog
*locatalog
; // Message catalog for locale
710 // Write the list of languages...
711 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
713 for (locale
= (ppdcString
*)locales
->first();
715 locale
= (ppdcString
*)locales
->next())
717 // Skip (US) English...
718 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
721 // See if we have a po file for this language...
722 if (!src
->find_po(locale
->value
))
724 // No, see if we can use the base file?
725 locatalog
= new ppdcCatalog(locale
->value
);
727 if (locatalog
->messages
->count
== 0)
729 // No, skip this one...
730 _cupsLangPrintf(stderr
,
731 _("ppdc: No message catalog provided for locale "
732 "%s!\n"), locale
->value
);
736 // Add the base file to the list...
737 src
->po_files
->add(locatalog
);
740 cupsFilePrintf(fp
, " %s", locale
->value
);
743 cupsFilePrintf(fp
, "\"%s", lf
);
746 for (cn
= (ppdcConstraint
*)constraints
->first();
748 cn
= (ppdcConstraint
*)constraints
->next())
750 // First constrain 1 against 2...
751 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
752 !strncmp(cn
->option2
->value
, "*Custom", 7))
753 cupsFilePuts(fp
, "*NonUIConstraints: ");
755 cupsFilePuts(fp
, "*UIConstraints: ");
757 if (cn
->option1
->value
[0] != '*')
758 cupsFilePutChar(fp
, '*');
760 cupsFilePuts(fp
, cn
->option1
->value
);
762 if (cn
->choice1
->value
)
763 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
765 cupsFilePutChar(fp
, ' ');
767 if (cn
->option2
->value
[0] != '*')
768 cupsFilePutChar(fp
, '*');
770 cupsFilePuts(fp
, cn
->option2
->value
);
772 if (cn
->choice2
->value
)
773 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
775 cupsFilePuts(fp
, lf
);
777 // Then constrain 2 against 1...
778 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
779 !strncmp(cn
->option2
->value
, "*Custom", 7))
780 cupsFilePuts(fp
, "*NonUIConstraints: ");
782 cupsFilePuts(fp
, "*UIConstraints: ");
784 if (cn
->option2
->value
[0] != '*')
785 cupsFilePutChar(fp
, '*');
787 cupsFilePuts(fp
, cn
->option2
->value
);
789 if (cn
->choice2
->value
)
790 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
792 cupsFilePutChar(fp
, ' ');
794 if (cn
->option1
->value
[0] != '*')
795 cupsFilePutChar(fp
, '*');
797 cupsFilePuts(fp
, cn
->option1
->value
);
799 if (cn
->choice1
->value
)
800 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
802 cupsFilePuts(fp
, lf
);
805 // PageSize option...
806 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
807 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
808 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
809 default_size
? default_size
->value
: "Letter", lf
);
811 for (m
= (ppdcMediaSize
*)sizes
->first();
813 m
= (ppdcMediaSize
*)sizes
->next())
814 if (m
->size_code
->value
)
816 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
817 m
->name
->value
, catalog
->find_message(m
->text
->value
),
818 m
->size_code
->value
, lf
);
820 if (strchr(m
->size_code
->value
, '\n') ||
821 strchr(m
->size_code
->value
, '\r'))
822 cupsFilePrintf(fp
, "*End%s", lf
);
826 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
827 "/ImagingBBox null>>setpagedevice\"%s",
828 m
->name
->value
, catalog
->find_message(m
->text
->value
),
829 m
->width
, m
->length
, lf
);
831 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
833 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
835 if (strchr(a
->value
->value
, '\n') ||
836 strchr(a
->value
->value
, '\r'))
837 cupsFilePrintf(fp
, "*End%s", lf
);
840 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
842 // PageRegion option...
843 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
844 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
845 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
846 default_size
? default_size
->value
: "Letter", lf
);
848 for (m
= (ppdcMediaSize
*)sizes
->first();
850 m
= (ppdcMediaSize
*)sizes
->next())
851 if (m
->region_code
->value
)
853 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
854 m
->name
->value
, catalog
->find_message(m
->text
->value
),
855 m
->region_code
->value
, lf
);
857 if (strchr(m
->region_code
->value
, '\n') ||
858 strchr(m
->region_code
->value
, '\r'))
859 cupsFilePrintf(fp
, "*End%s", lf
);
863 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
864 "/ImagingBBox null>>setpagedevice\"%s",
865 m
->name
->value
, catalog
->find_message(m
->text
->value
),
866 m
->width
, m
->length
, lf
);
868 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
870 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
872 if (strchr(a
->value
->value
, '\n') ||
873 strchr(a
->value
->value
, '\r'))
874 cupsFilePrintf(fp
, "*End%s", lf
);
877 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
879 // ImageableArea info...
880 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
881 default_size
? default_size
->value
: "Letter", lf
);
883 char left
[255], right
[255], bottom
[255], top
[255];
885 for (m
= (ppdcMediaSize
*)sizes
->first();
887 m
= (ppdcMediaSize
*)sizes
->next())
889 _cupsStrFormatd(left
, left
+ sizeof(left
), m
->left
, loc
);
890 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), m
->bottom
, loc
);
891 _cupsStrFormatd(right
, right
+ sizeof(right
), m
->width
- m
->right
, loc
);
892 _cupsStrFormatd(top
, top
+ sizeof(top
), m
->length
- m
->top
, loc
);
894 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
895 m
->name
->value
, catalog
->find_message(m
->text
->value
),
896 left
, bottom
, right
, top
, lf
);
899 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
901 cupsFilePrintf(fp
, "*?ImageableArea: \"%s\"%s", a
->value
->value
, lf
);
903 if (strchr(a
->value
->value
, '\n') ||
904 strchr(a
->value
->value
, '\r'))
905 cupsFilePrintf(fp
, "*End%s", lf
);
908 // PaperDimension info...
909 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
910 default_size
? default_size
->value
: "Letter", lf
);
912 char width
[255], length
[255];
914 for (m
= (ppdcMediaSize
*)sizes
->first();
916 m
= (ppdcMediaSize
*)sizes
->next())
918 _cupsStrFormatd(width
, width
+ sizeof(width
), m
->width
, loc
);
919 _cupsStrFormatd(length
, length
+ sizeof(length
), m
->length
, loc
);
921 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%s %s\"%s",
922 m
->name
->value
, catalog
->find_message(m
->text
->value
),
926 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
928 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
930 if (strchr(a
->value
->value
, '\n') ||
931 strchr(a
->value
->value
, '\r'))
932 cupsFilePrintf(fp
, "*End%s", lf
);
935 // Custom size support...
936 if (variable_paper_size
)
938 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
939 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
941 _cupsStrFormatd(left
, left
+ sizeof(left
), left_margin
, loc
);
942 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), bottom_margin
, loc
);
943 _cupsStrFormatd(right
, right
+ sizeof(right
), right_margin
, loc
);
944 _cupsStrFormatd(top
, top
+ sizeof(top
), top_margin
, loc
);
946 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%s\"%s", width
, lf
);
947 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%s\"%s", length
, lf
);
948 cupsFilePrintf(fp
, "*HWMargins: %s %s %s %s%s", left
, bottom
, right
, top
,
951 if (custom_size_code
&& custom_size_code
->value
)
953 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
954 custom_size_code
->value
, lf
);
956 if (strchr(custom_size_code
->value
, '\n') ||
957 strchr(custom_size_code
->value
, '\r'))
958 cupsFilePrintf(fp
, "*End%s", lf
);
962 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
963 "/ImagingBBox null>>setpagedevice\"%s", lf
);
965 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
966 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
972 _cupsStrFormatd(width0
, width0
+ sizeof(width0
), min_width
, loc
);
973 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
975 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %s %s%s",
979 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
980 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
986 _cupsStrFormatd(length0
, length0
+ sizeof(length0
), min_length
, loc
);
987 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
989 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %s %s%s",
990 length0
, length
, lf
);
993 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
994 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
995 a
->value
->value
, lf
);
997 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
999 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
1000 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
1001 a
->value
->value
, lf
);
1003 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
1005 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
1006 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
1007 a
->value
->value
, lf
);
1009 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
1012 // All other options...
1013 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1015 if (!g
->options
->count
)
1018 if (strcasecmp(g
->name
->value
, "General"))
1019 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
1020 catalog
->find_message(g
->text
->value
), lf
);
1022 for (o
= (ppdcOption
*)g
->options
->first();
1024 o
= (ppdcOption
*)g
->options
->next())
1026 if (!o
->choices
->count
)
1029 if (!o
->text
->value
|| !strcmp(o
->name
->value
, o
->text
->value
))
1030 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1031 catalog
->find_message(o
->name
->value
));
1033 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1034 catalog
->find_message(o
->text
->value
));
1039 cupsFilePrintf(fp
, "Boolean%s", lf
);
1042 cupsFilePrintf(fp
, "PickOne%s", lf
);
1044 case PPDC_PICKMANY
:
1045 cupsFilePrintf(fp
, "PickMany%s", lf
);
1050 _cupsStrFormatd(order
, order
+ sizeof(order
), o
->order
, loc
);
1052 cupsFilePrintf(fp
, "*OrderDependency: %s ", order
);
1056 cupsFilePrintf(fp
, "AnySetup");
1058 case PPDC_SECTION_DOCUMENT
:
1059 cupsFilePrintf(fp
, "DocumentSetup");
1061 case PPDC_SECTION_EXIT
:
1062 cupsFilePrintf(fp
, "ExitServer");
1064 case PPDC_SECTION_JCL
:
1065 cupsFilePrintf(fp
, "JCLSetup");
1067 case PPDC_SECTION_PAGE
:
1068 cupsFilePrintf(fp
, "PageSetup");
1070 case PPDC_SECTION_PROLOG
:
1071 cupsFilePrintf(fp
, "Prolog");
1075 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
1079 // Use the programmer-supplied default...
1080 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
1081 o
->defchoice
->value
, lf
);
1085 // Make the first choice the default...
1086 c
= (ppdcChoice
*)o
->choices
->first();
1087 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
1091 for (c
= (ppdcChoice
*)o
->choices
->first();
1093 c
= (ppdcChoice
*)o
->choices
->next())
1095 // Write this choice...
1096 if (!c
->text
->value
|| !strcmp(c
->name
->value
, c
->text
->value
))
1097 cupsFilePrintf(fp
, "*%s %s: \"%s\"%s", o
->name
->value
,
1098 catalog
->find_message(c
->name
->value
),
1099 c
->code
->value
, lf
);
1101 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1102 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1103 c
->code
->value
, lf
);
1105 // Multi-line commands need a *End line to terminate them.
1106 if (strchr(c
->code
->value
, '\n') ||
1107 strchr(c
->code
->value
, '\r'))
1108 cupsFilePrintf(fp
, "*End%s", lf
);
1111 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1113 if ((a
= find_attr(query
, NULL
)) != NULL
)
1115 cupsFilePrintf(fp
, "*%s: \"%s\"%s", query
, a
->value
->value
, lf
);
1117 if (strchr(a
->value
->value
, '\n') ||
1118 strchr(a
->value
->value
, '\r'))
1119 cupsFilePrintf(fp
, "*End%s", lf
);
1122 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1124 snprintf(custom
, sizeof(custom
), "Custom%s", o
->name
->value
);
1125 if ((a
= find_attr(custom
, "True")) != NULL
)
1127 // Output custom option information...
1128 cupsFilePrintf(fp
, "*%s True: \"%s\"%s", custom
, a
->value
->value
, lf
);
1129 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
1130 cupsFilePrintf(fp
, "*End%s", lf
);
1132 snprintf(custom
, sizeof(custom
), "ParamCustom%s", o
->name
->value
);
1133 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1135 if (strcmp(a
->name
->value
, custom
))
1138 if (!a
->selector
->value
|| !a
->selector
->value
[0])
1139 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
1140 else if (!a
->text
->value
|| !a
->text
->value
[0])
1141 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
1143 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1146 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
1151 if (strcasecmp(g
->name
->value
, "General"))
1152 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1157 // Add localizations for additional languages...
1158 ppdcString
*locale
; // Locale name
1159 ppdcCatalog
*locatalog
; // Message catalog for locale
1162 // Write the translation strings for each language...
1163 for (locale
= (ppdcString
*)locales
->first();
1165 locale
= (ppdcString
*)locales
->next())
1167 // Skip (US) English...
1168 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1171 // Skip missing languages...
1172 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1175 // Do the core stuff first...
1176 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1178 locatalog
->find_message(manufacturer
->value
), lf
);
1180 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1181 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1183 locatalog
->find_message(a
->value
->value
), lf
);
1184 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1185 strlen(manufacturer
->value
)))
1186 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1188 locatalog
->find_message(manufacturer
->value
),
1189 locatalog
->find_message(model_name
->value
), lf
);
1191 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1193 locatalog
->find_message(model_name
->value
), lf
);
1195 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1196 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1198 locatalog
->find_message(a
->value
->value
), lf
);
1199 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1200 strlen(manufacturer
->value
)))
1201 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1203 locatalog
->find_message(manufacturer
->value
),
1204 locatalog
->find_message(model_name
->value
), lf
);
1206 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1208 locatalog
->find_message(model_name
->value
), lf
);
1210 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1211 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1213 locatalog
->find_message(a
->value
->value
), lf
);
1214 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1215 strlen(manufacturer
->value
)))
1216 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1218 locatalog
->find_message(manufacturer
->value
),
1219 locatalog
->find_message(model_name
->value
),
1220 version
->value
, lf
);
1222 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1224 locatalog
->find_message(model_name
->value
),
1225 version
->value
, lf
);
1227 // Then the page sizes...
1228 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1229 locatalog
->find_message("Media Size"), lf
);
1231 for (m
= (ppdcMediaSize
*)sizes
->first();
1233 m
= (ppdcMediaSize
*)sizes
->next())
1235 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1236 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1240 // Next the groups and options...
1241 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1243 if (!g
->options
->count
)
1246 if (strcasecmp(g
->name
->value
, "General"))
1247 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1249 locatalog
->find_message(g
->text
->value
), lf
);
1251 for (o
= (ppdcOption
*)g
->options
->first();
1253 o
= (ppdcOption
*)g
->options
->next())
1255 if (!o
->choices
->count
)
1258 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1260 locatalog
->find_message(o
->text
->value
?
1262 o
->name
->value
), lf
);
1264 for (c
= (ppdcChoice
*)o
->choices
->first();
1266 c
= (ppdcChoice
*)o
->choices
->next())
1268 // Write this choice...
1269 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1270 o
->name
->value
, c
->name
->value
,
1271 locatalog
->find_message(c
->text
->value
?
1273 c
->name
->value
), lf
);
1278 // Finally the localizable attributes...
1279 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1281 if ((!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1282 strncmp(a
->name
->value
, "Custom", 6) &&
1283 strncmp(a
->name
->value
, "ParamCustom", 11))
1286 if (!a
->localizable
&&
1287 strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1288 strcmp(a
->name
->value
, "APPrinterPreset") &&
1289 strcmp(a
->name
->value
, "cupsICCProfile") &&
1290 strcmp(a
->name
->value
, "cupsIPPReason") &&
1291 strcmp(a
->name
->value
, "cupsMarkerName") &&
1292 strncmp(a
->name
->value
, "Custom", 6) &&
1293 strncmp(a
->name
->value
, "ParamCustom", 11))
1296 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1297 a
->name
->value
, a
->selector
->value
,
1298 locatalog
->find_message(a
->text
&& a
->text
->value
?
1299 a
->text
->value
: a
->name
->value
),
1300 ((a
->localizable
&& a
->value
->value
[0]) ||
1301 !strcmp(a
->name
->value
, "cupsIPPReason")) ?
1302 locatalog
->find_message(a
->value
->value
) : "",
1308 if (default_font
&& default_font
->value
)
1309 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1311 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1313 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1314 if (!strcmp(fn
->name
->value
, "*"))
1316 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1318 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1319 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1320 bfn
->name
->value
, bfn
->encoding
->value
,
1321 bfn
->version
->value
, bfn
->charset
->value
,
1322 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1325 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1326 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1328 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1330 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1331 (int)(cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),