]>
git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-driver.cxx
2 // PPD file compiler definitions for the CUPS PPD Compiler.
4 // Copyright © 2007-2019 by Apple Inc.
5 // Copyright © 2002-2006 by Easy Software Products.
7 // Licensed under Apache License v2.0. See the file "LICENSE" for more
12 // Include necessary headers...
15 #include "ppdc-private.h"
19 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
22 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
25 ppdcGroup
*g
; // Current group
32 // Bump the use count of any strings we inherit...
34 d
->manufacturer
->retain();
38 d
->default_font
->retain();
40 d
->default_size
->retain();
41 if (d
->custom_size_code
)
42 d
->custom_size_code
->retain();
44 // Copy all of the data from the driver template...
45 copyright
= new ppdcArray(d
->copyright
);
46 manufacturer
= d
->manufacturer
;
52 model_number
= d
->model_number
;
53 manual_copies
= d
->manual_copies
;
54 color_device
= d
->color_device
;
55 throughput
= d
->throughput
;
56 attrs
= new ppdcArray(d
->attrs
);
57 constraints
= new ppdcArray(d
->constraints
);
58 filters
= new ppdcArray(d
->filters
);
59 fonts
= new ppdcArray(d
->fonts
);
60 profiles
= new ppdcArray(d
->profiles
);
61 sizes
= new ppdcArray(d
->sizes
);
62 default_font
= d
->default_font
;
63 default_size
= d
->default_size
;
64 variable_paper_size
= d
->variable_paper_size
;
65 custom_size_code
= d
->custom_size_code
;
66 left_margin
= d
->left_margin
;
67 bottom_margin
= d
->bottom_margin
;
68 right_margin
= d
->right_margin
;
69 top_margin
= d
->top_margin
;
70 max_width
= d
->max_width
;
71 max_length
= d
->max_length
;
72 min_width
= d
->min_width
;
73 min_length
= d
->min_length
;
75 // Then copy the groups manually, since we want separate copies
76 // of the groups and options...
77 groups
= new ppdcArray();
79 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
80 groups
->add(new ppdcGroup(g
));
84 // Zero all of the data in the driver...
85 copyright
= new ppdcArray();
91 type
= PPDC_DRIVER_CUSTOM
;
96 attrs
= new ppdcArray();
97 constraints
= new ppdcArray();
98 fonts
= new ppdcArray();
99 filters
= new ppdcArray();
100 groups
= new ppdcArray();
101 profiles
= new ppdcArray();
102 sizes
= new ppdcArray();
105 variable_paper_size
= 0;
106 custom_size_code
= 0;
120 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
123 ppdcDriver::~ppdcDriver()
127 copyright
->release();
130 manufacturer
->release();
132 model_name
->release();
134 file_name
->release();
136 pc_file_name
->release();
140 default_font
->release();
142 default_size
->release();
143 if (custom_size_code
)
144 custom_size_code
->release();
147 constraints
->release();
157 // 'ppdcDriver::find_attr()' - Find an attribute.
160 ppdcAttr
* // O - Attribute or NULL
161 ppdcDriver::find_attr(const char *k
, // I - Keyword string
162 const char *s
) // I - Spec string
164 ppdcAttr
*a
; // Current attribute
167 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
168 if (!strcmp(a
->name
->value
, k
) &&
169 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
170 (s
&& a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
178 // 'ppdcDriver::find_group()' - Find a group.
181 ppdcGroup
* // O - Matching group or NULL
182 ppdcDriver::find_group(const char *n
) // I - Group name
184 ppdcGroup
*g
; // Current group
187 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
188 if (!_cups_strcasecmp(n
, g
->name
->value
))
196 // 'ppdcDriver::find_option()' - Find an option.
199 ppdcOption
* // O - Matching option or NULL
200 ppdcDriver::find_option(const char *n
) // I - Option name
202 return (find_option_group(n
, (ppdcGroup
**)0));
207 // 'ppdcDriver::find_option_group()' - Find an option and its group.
210 ppdcOption
* // O - Matching option or NULL
211 ppdcDriver::find_option_group(
212 const char *n
, // I - Option name
213 ppdcGroup
**mg
) // O - Matching group or NULL
215 ppdcGroup
*g
; // Current group
216 ppdcOption
*o
; // Current option
219 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
220 for (o
= (ppdcOption
*)g
->options
->first(); o
; o
= (ppdcOption
*)g
->options
->next())
221 if (!_cups_strcasecmp(n
, o
->name
->value
))
230 *mg
= (ppdcGroup
*)0;
237 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
241 ppdcDriver::set_custom_size_code(
242 const char *c
) // I - CustomPageSize code
244 if (custom_size_code
)
245 custom_size_code
->release();
247 custom_size_code
= new ppdcString(c
);
252 // 'ppdcDriver::set_default_font()' - Set the default font name.
256 ppdcDriver::set_default_font(
257 ppdcFont
*f
) // I - Font
260 default_font
->release();
265 default_font
= f
->name
;
273 // 'ppdcDriver::set_default_size()' - Set the default size name.
277 ppdcDriver::set_default_size(
278 ppdcMediaSize
*m
) // I - Media size
281 default_size
->release();
286 default_size
= m
->name
;
294 // 'ppdcDriver::set_file_name()' - Set the full filename.
298 ppdcDriver::set_file_name(const char *f
)// I - Filename
301 file_name
->release();
303 file_name
= new ppdcString(f
);
308 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
312 ppdcDriver::set_manufacturer(
313 const char *m
) // I - Model name
316 manufacturer
->release();
318 manufacturer
= new ppdcString(m
);
323 // 'ppdcDriver::set_model_name()' - Set the model name.
327 ppdcDriver::set_model_name(
328 const char *m
) // I - Model name
331 model_name
->release();
333 model_name
= new ppdcString(m
);
338 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
342 ppdcDriver::set_pc_file_name(
343 const char *f
) // I - Filename
346 pc_file_name
->release();
348 pc_file_name
= new ppdcString(f
);
353 // 'ppdcDriver::set_version()' - Set the version string.
357 ppdcDriver::set_version(const char *v
) // I - Version
362 version
= new ppdcString(v
);
367 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
370 int // O - 0 on success, -1 on failure
371 ppdcDriver::write_ppd_file(
372 cups_file_t
*fp
, // I - PPD file
373 ppdcCatalog
*catalog
, // I - Message catalog
374 ppdcArray
*locales
, // I - Additional languages to add
375 ppdcSource
*src
, // I - Driver source
376 ppdcLineEnding le
) // I - Line endings to use
378 bool delete_cat
; // Delete the catalog when we are done?
379 char query
[42], // Query attribute
380 custom
[42]; // Custom attribute
381 ppdcString
*s
; // Copyright string
382 ppdcGroup
*g
; // Current group
383 ppdcOption
*o
; // Current option
384 ppdcChoice
*c
; // Current choice
385 ppdcMediaSize
*m
; // Current media size
386 ppdcProfile
*p
; // Current color profile
387 ppdcFilter
*f
; // Current filter
388 ppdcFont
*fn
, // Current font
389 *bfn
; // Current base font
390 ppdcConstraint
*cn
; // Current constraint
391 ppdcAttr
*a
; // Current attribute
392 const char *lf
; // Linefeed character to use
395 // If we don't have a message catalog, use an empty (English) one...
398 catalog
= new ppdcCatalog(NULL
);
404 // Figure out the end-of-line string...
405 if (le
== PPDC_LFONLY
)
407 else if (le
== PPDC_CRONLY
)
412 // Write the standard header stuff...
413 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
414 cupsFilePrintf(fp
, "*%%%%%%%% PPD file for %s with CUPS.%s",
415 model_name
->value
, lf
);
417 "*%%%%%%%% Created by the CUPS PPD Compiler " CUPS_SVERSION
419 for (s
= (ppdcString
*)copyright
->first();
421 s
= (ppdcString
*)copyright
->next())
422 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
423 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
424 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
426 a
= find_attr("LanguageVersion", NULL
);
427 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
428 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
430 a
= find_attr("LanguageEncoding", NULL
);
431 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
432 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
434 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
436 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
437 if (!strcmp(a
->name
->value
, "Product"))
442 for (; a
; a
= (ppdcAttr
*)attrs
->next())
443 if (!strcmp(a
->name
->value
, "Product"))
444 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
447 cupsFilePrintf(fp
, "*Product: \"(%s)\"%s", model_name
->value
, lf
);
449 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
450 catalog
->find_message(manufacturer
->value
), lf
);
452 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
453 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
454 catalog
->find_message(a
->value
->value
), lf
);
455 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
456 strlen(manufacturer
->value
)))
457 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
458 catalog
->find_message(manufacturer
->value
),
459 catalog
->find_message(model_name
->value
), lf
);
461 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
462 catalog
->find_message(model_name
->value
), lf
);
464 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
465 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
466 catalog
->find_message(a
->value
->value
), lf
);
467 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
468 strlen(manufacturer
->value
)))
469 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
470 catalog
->find_message(manufacturer
->value
),
471 catalog
->find_message(model_name
->value
), lf
);
473 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
474 catalog
->find_message(model_name
->value
), lf
);
476 if ((a
= find_attr("NickName", NULL
)) != NULL
)
477 cupsFilePrintf(fp
, "*NickName: \"%s\"%s",
478 catalog
->find_message(a
->value
->value
), lf
);
479 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
480 strlen(manufacturer
->value
)))
481 cupsFilePrintf(fp
, "*NickName: \"%s %s, %s\"%s",
482 catalog
->find_message(manufacturer
->value
),
483 catalog
->find_message(model_name
->value
), version
->value
,
486 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
487 catalog
->find_message(model_name
->value
), version
->value
,
490 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
491 if (!strcmp(a
->name
->value
, "PSVersion"))
496 for (; a
; a
= (ppdcAttr
*)attrs
->next())
497 if (!strcmp(a
->name
->value
, "PSVersion"))
498 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
501 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 0\"%s", lf
);
503 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
504 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
506 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
508 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
510 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
511 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
513 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
514 color_device
? "RGB" : "Gray", lf
);
516 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
517 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
519 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
521 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
523 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
524 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
526 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
528 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
529 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
530 else if (type
!= PPDC_DRIVER_PS
)
531 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
533 struct lconv
*loc
= localeconv();
537 // Write driver-defined attributes...
538 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
539 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
541 if (!strcmp(a
->name
->value
, "Product") ||
542 !strcmp(a
->name
->value
, "PSVersion") ||
543 !strcmp(a
->name
->value
, "LanguageLevel") ||
544 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
545 !strcmp(a
->name
->value
, "FileSystem") ||
546 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
547 !strcmp(a
->name
->value
, "TTRasterizer") ||
548 !strcmp(a
->name
->value
, "LanguageVersion") ||
549 !strcmp(a
->name
->value
, "LanguageEncoding") ||
550 !strcmp(a
->name
->value
, "ModelName") ||
551 !strcmp(a
->name
->value
, "NickName") ||
552 !strcmp(a
->name
->value
, "ShortNickName") ||
553 !strcmp(a
->name
->value
, "cupsVersion"))
556 if (a
->name
->value
[0] == '?' &&
557 (find_option(a
->name
->value
+ 1) ||
558 !strcmp(a
->name
->value
, "?ImageableArea") ||
559 !strcmp(a
->name
->value
, "?PageRegion") ||
560 !strcmp(a
->name
->value
, "?PageSize") ||
561 !strcmp(a
->name
->value
, "?PaperDimension")))
564 if (!strncmp(a
->name
->value
, "Custom", 6) &&
565 find_option(a
->name
->value
+ 6))
568 if (!strncmp(a
->name
->value
, "ParamCustom", 11) &&
569 find_option(a
->name
->value
+ 11))
572 if (!a
->selector
->value
|| !a
->selector
->value
[0])
573 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
574 else if (!a
->text
->value
|| !a
->text
->value
[0])
575 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
577 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
580 if (strcmp(a
->value
->value
, "False") &&
581 strcmp(a
->value
->value
, "True") &&
582 strcmp(a
->name
->value
, "1284Modes") &&
583 strcmp(a
->name
->value
, "InkName") &&
584 strcmp(a
->name
->value
, "PageStackOrder") &&
585 strncmp(a
->name
->value
, "ParamCustom", 11) &&
586 strcmp(a
->name
->value
, "Protocols") &&
587 strcmp(a
->name
->value
, "ReferencePunch") &&
588 strncmp(a
->name
->value
, "Default", 7))
590 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
592 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
593 cupsFilePrintf(fp
, "*End%s", lf
);
596 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
600 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
602 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
603 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
605 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
606 CUPS_VERSION_MINOR
, lf
);
607 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
608 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
609 manual_copies
? "True" : "False", lf
);
613 for (f
= (ppdcFilter
*)filters
->first();
615 f
= (ppdcFilter
*)filters
->next())
616 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
617 f
->cost
, f
->program
->value
, lf
);
623 case PPDC_DRIVER_LABEL
:
624 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
625 "rastertolabel\"%s", lf
);
628 case PPDC_DRIVER_EPSON
:
629 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
630 "rastertoepson\"%s", lf
);
633 case PPDC_DRIVER_ESCP
:
634 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
635 "commandtoescpx\"%s", lf
);
636 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
637 "rastertoescpx\"%s", lf
);
640 case PPDC_DRIVER_HP
:
641 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
642 "rastertohp\"%s", lf
);
645 case PPDC_DRIVER_PCL
:
646 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
647 "commandtopclx\"%s", lf
);
648 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
649 "rastertopclx\"%s", lf
);
657 for (p
= (ppdcProfile
*)profiles
->first();
659 p
= (ppdcProfile
*)profiles
->next())
661 char density
[255], gamma
[255], profile
[9][255];
663 _cupsStrFormatd(density
, density
+ sizeof(density
), p
->density
, loc
);
664 _cupsStrFormatd(gamma
, gamma
+ sizeof(gamma
), p
->gamma
, loc
);
666 for (int i
= 0; i
< 9; i
++)
667 _cupsStrFormatd(profile
[i
], profile
[i
] + sizeof(profile
[0]),
671 "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
672 "%s\"%s", p
->resolution
->value
, p
->media_type
->value
,
673 density
, gamma
, profile
[0], profile
[1], profile
[2],
674 profile
[3], profile
[4], profile
[5], profile
[6], profile
[7],
681 // Add localizations for additional languages...
682 ppdcString
*locale
; // Locale name
683 ppdcCatalog
*locatalog
; // Message catalog for locale
686 // Write the list of languages...
687 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
689 for (locale
= (ppdcString
*)locales
->first();
691 locale
= (ppdcString
*)locales
->next())
693 // Skip (US) English...
694 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
697 // See if we have a po file for this language...
698 if (!src
->find_po(locale
->value
))
700 // No, see if we can use the base file?
701 locatalog
= new ppdcCatalog(locale
->value
);
703 if (locatalog
->messages
->count
== 0)
705 // No, skip this one...
706 _cupsLangPrintf(stderr
,
707 _("ppdc: No message catalog provided for locale "
708 "%s."), locale
->value
);
713 // Add the base file to the list...
714 src
->po_files
->add(locatalog
);
717 cupsFilePrintf(fp
, " %s", locale
->value
);
720 cupsFilePrintf(fp
, "\"%s", lf
);
723 for (cn
= (ppdcConstraint
*)constraints
->first();
725 cn
= (ppdcConstraint
*)constraints
->next())
727 // First constrain 1 against 2...
728 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
729 !strncmp(cn
->option2
->value
, "*Custom", 7))
730 cupsFilePuts(fp
, "*NonUIConstraints: ");
732 cupsFilePuts(fp
, "*UIConstraints: ");
734 if (cn
->option1
->value
[0] != '*')
735 cupsFilePutChar(fp
, '*');
737 cupsFilePuts(fp
, cn
->option1
->value
);
739 if (cn
->choice1
->value
)
740 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
742 cupsFilePutChar(fp
, ' ');
744 if (cn
->option2
->value
[0] != '*')
745 cupsFilePutChar(fp
, '*');
747 cupsFilePuts(fp
, cn
->option2
->value
);
749 if (cn
->choice2
->value
)
750 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
752 cupsFilePuts(fp
, lf
);
754 // Then constrain 2 against 1...
755 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
756 !strncmp(cn
->option2
->value
, "*Custom", 7))
757 cupsFilePuts(fp
, "*NonUIConstraints: ");
759 cupsFilePuts(fp
, "*UIConstraints: ");
761 if (cn
->option2
->value
[0] != '*')
762 cupsFilePutChar(fp
, '*');
764 cupsFilePuts(fp
, cn
->option2
->value
);
766 if (cn
->choice2
->value
)
767 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
769 cupsFilePutChar(fp
, ' ');
771 if (cn
->option1
->value
[0] != '*')
772 cupsFilePutChar(fp
, '*');
774 cupsFilePuts(fp
, cn
->option1
->value
);
776 if (cn
->choice1
->value
)
777 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
779 cupsFilePuts(fp
, lf
);
782 // PageSize option...
783 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
784 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
785 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
786 default_size
? default_size
->value
: "Letter", lf
);
788 for (m
= (ppdcMediaSize
*)sizes
->first();
790 m
= (ppdcMediaSize
*)sizes
->next())
791 if (m
->size_code
->value
)
793 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
794 m
->name
->value
, catalog
->find_message(m
->text
->value
),
795 m
->size_code
->value
, lf
);
797 if (strchr(m
->size_code
->value
, '\n') ||
798 strchr(m
->size_code
->value
, '\r'))
799 cupsFilePrintf(fp
, "*End%s", lf
);
803 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
804 "/ImagingBBox null>>setpagedevice\"%s",
805 m
->name
->value
, catalog
->find_message(m
->text
->value
),
806 m
->width
, m
->length
, lf
);
808 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
810 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
812 if (strchr(a
->value
->value
, '\n') ||
813 strchr(a
->value
->value
, '\r'))
814 cupsFilePrintf(fp
, "*End%s", lf
);
817 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
819 // PageRegion option...
820 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
821 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
822 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
823 default_size
? default_size
->value
: "Letter", lf
);
825 for (m
= (ppdcMediaSize
*)sizes
->first();
827 m
= (ppdcMediaSize
*)sizes
->next())
828 if (m
->region_code
->value
)
830 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
831 m
->name
->value
, catalog
->find_message(m
->text
->value
),
832 m
->region_code
->value
, lf
);
834 if (strchr(m
->region_code
->value
, '\n') ||
835 strchr(m
->region_code
->value
, '\r'))
836 cupsFilePrintf(fp
, "*End%s", lf
);
840 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
841 "/ImagingBBox null>>setpagedevice\"%s",
842 m
->name
->value
, catalog
->find_message(m
->text
->value
),
843 m
->width
, m
->length
, lf
);
845 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
847 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
849 if (strchr(a
->value
->value
, '\n') ||
850 strchr(a
->value
->value
, '\r'))
851 cupsFilePrintf(fp
, "*End%s", lf
);
854 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
856 // ImageableArea info...
857 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
858 default_size
? default_size
->value
: "Letter", lf
);
860 char left
[255], right
[255], bottom
[255], top
[255];
862 for (m
= (ppdcMediaSize
*)sizes
->first();
864 m
= (ppdcMediaSize
*)sizes
->next())
866 _cupsStrFormatd(left
, left
+ sizeof(left
), m
->left
, loc
);
867 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), m
->bottom
, loc
);
868 _cupsStrFormatd(right
, right
+ sizeof(right
), m
->width
- m
->right
, loc
);
869 _cupsStrFormatd(top
, top
+ sizeof(top
), m
->length
- m
->top
, loc
);
871 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
872 m
->name
->value
, catalog
->find_message(m
->text
->value
),
873 left
, bottom
, right
, top
, lf
);
876 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
878 cupsFilePrintf(fp
, "*?ImageableArea: \"%s\"%s", a
->value
->value
, lf
);
880 if (strchr(a
->value
->value
, '\n') ||
881 strchr(a
->value
->value
, '\r'))
882 cupsFilePrintf(fp
, "*End%s", lf
);
885 // PaperDimension info...
886 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
887 default_size
? default_size
->value
: "Letter", lf
);
889 char width
[255], length
[255];
891 for (m
= (ppdcMediaSize
*)sizes
->first();
893 m
= (ppdcMediaSize
*)sizes
->next())
895 _cupsStrFormatd(width
, width
+ sizeof(width
), m
->width
, loc
);
896 _cupsStrFormatd(length
, length
+ sizeof(length
), m
->length
, loc
);
898 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%s %s\"%s",
899 m
->name
->value
, catalog
->find_message(m
->text
->value
),
903 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
905 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
907 if (strchr(a
->value
->value
, '\n') ||
908 strchr(a
->value
->value
, '\r'))
909 cupsFilePrintf(fp
, "*End%s", lf
);
912 // Custom size support...
913 if (variable_paper_size
)
915 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
916 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
918 _cupsStrFormatd(left
, left
+ sizeof(left
), left_margin
, loc
);
919 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), bottom_margin
, loc
);
920 _cupsStrFormatd(right
, right
+ sizeof(right
), right_margin
, loc
);
921 _cupsStrFormatd(top
, top
+ sizeof(top
), top_margin
, loc
);
923 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%s\"%s", width
, lf
);
924 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%s\"%s", length
, lf
);
925 cupsFilePrintf(fp
, "*HWMargins: %s %s %s %s%s", left
, bottom
, right
, top
,
928 if (custom_size_code
&& custom_size_code
->value
)
930 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
931 custom_size_code
->value
, lf
);
933 if (strchr(custom_size_code
->value
, '\n') ||
934 strchr(custom_size_code
->value
, '\r'))
935 cupsFilePrintf(fp
, "*End%s", lf
);
939 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
940 "/ImagingBBox null>>setpagedevice\"%s", lf
);
942 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
943 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
949 _cupsStrFormatd(width0
, width0
+ sizeof(width0
), min_width
, loc
);
950 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
952 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %s %s%s",
956 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
957 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
963 _cupsStrFormatd(length0
, length0
+ sizeof(length0
), min_length
, loc
);
964 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
966 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %s %s%s",
967 length0
, length
, lf
);
970 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
971 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
972 a
->value
->value
, lf
);
974 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
976 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
977 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
978 a
->value
->value
, lf
);
980 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
982 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
983 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
984 a
->value
->value
, lf
);
986 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
989 // All other options...
990 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
992 if (!g
->options
->count
)
995 if (_cups_strcasecmp(g
->name
->value
, "General"))
996 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
997 catalog
->find_message(g
->text
->value
), lf
);
999 for (o
= (ppdcOption
*)g
->options
->first();
1001 o
= (ppdcOption
*)g
->options
->next())
1003 if (!o
->choices
->count
)
1006 if (o
->section
== PPDC_SECTION_JCL
)
1008 if (!o
->text
->value
)
1009 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1010 catalog
->find_message(o
->name
->value
));
1012 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1013 catalog
->find_message(o
->text
->value
));
1015 else if (!o
->text
->value
)
1016 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1017 catalog
->find_message(o
->name
->value
));
1019 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1020 catalog
->find_message(o
->text
->value
));
1025 cupsFilePrintf(fp
, "Boolean%s", lf
);
1028 cupsFilePrintf(fp
, "PickOne%s", lf
);
1030 case PPDC_PICKMANY
:
1031 cupsFilePrintf(fp
, "PickMany%s", lf
);
1036 _cupsStrFormatd(order
, order
+ sizeof(order
), o
->order
, loc
);
1038 cupsFilePrintf(fp
, "*OrderDependency: %s ", order
);
1042 cupsFilePrintf(fp
, "AnySetup");
1044 case PPDC_SECTION_DOCUMENT
:
1045 cupsFilePrintf(fp
, "DocumentSetup");
1047 case PPDC_SECTION_EXIT
:
1048 cupsFilePrintf(fp
, "ExitServer");
1050 case PPDC_SECTION_JCL
:
1051 cupsFilePrintf(fp
, "JCLSetup");
1053 case PPDC_SECTION_PAGE
:
1054 cupsFilePrintf(fp
, "PageSetup");
1056 case PPDC_SECTION_PROLOG
:
1057 cupsFilePrintf(fp
, "Prolog");
1061 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
1065 // Use the programmer-supplied default...
1066 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
1067 o
->defchoice
->value
, lf
);
1071 // Make the first choice the default...
1072 c
= (ppdcChoice
*)o
->choices
->first();
1073 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
1077 for (c
= (ppdcChoice
*)o
->choices
->first();
1079 c
= (ppdcChoice
*)o
->choices
->next())
1081 // Write this choice...
1082 if (!c
->text
->value
)
1083 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1084 c
->name
->value
, catalog
->find_message(c
->name
->value
),
1085 c
->code
->value
, lf
);
1087 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1088 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1089 c
->code
->value
, lf
);
1091 // Multi-line commands need a *End line to terminate them.
1092 if (strchr(c
->code
->value
, '\n') ||
1093 strchr(c
->code
->value
, '\r'))
1094 cupsFilePrintf(fp
, "*End%s", lf
);
1097 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1099 if ((a
= find_attr(query
, NULL
)) != NULL
)
1101 cupsFilePrintf(fp
, "*%s: \"%s\"%s", query
, a
->value
->value
, lf
);
1103 if (strchr(a
->value
->value
, '\n') ||
1104 strchr(a
->value
->value
, '\r'))
1105 cupsFilePrintf(fp
, "*End%s", lf
);
1108 if (o
->section
== PPDC_SECTION_JCL
)
1109 cupsFilePrintf(fp
, "*JCLCloseUI: *%s%s", o
->name
->value
, lf
);
1111 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1113 snprintf(custom
, sizeof(custom
), "Custom%s", o
->name
->value
);
1114 if ((a
= find_attr(custom
, "True")) != NULL
)
1116 // Output custom option information...
1117 cupsFilePrintf(fp
, "*%s True: \"%s\"%s", custom
, a
->value
->value
, lf
);
1118 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
1119 cupsFilePrintf(fp
, "*End%s", lf
);
1121 snprintf(custom
, sizeof(custom
), "ParamCustom%s", o
->name
->value
);
1122 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1124 if (strcmp(a
->name
->value
, custom
))
1127 if (!a
->selector
->value
|| !a
->selector
->value
[0])
1128 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
1129 else if (!a
->text
->value
|| !a
->text
->value
[0])
1130 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1131 catalog
->find_message(a
->selector
->value
));
1133 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1134 catalog
->find_message(a
->text
->value
));
1136 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
1141 if (_cups_strcasecmp(g
->name
->value
, "General"))
1142 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1147 // Add localizations for additional languages...
1148 ppdcString
*locale
; // Locale name
1149 ppdcCatalog
*locatalog
; // Message catalog for locale
1152 // Write the translation strings for each language...
1153 for (locale
= (ppdcString
*)locales
->first();
1155 locale
= (ppdcString
*)locales
->next())
1157 // Skip (US) English...
1158 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1161 // Skip missing languages...
1162 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1165 // Do the core stuff first...
1166 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1168 locatalog
->find_message(manufacturer
->value
), lf
);
1170 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1171 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1173 locatalog
->find_message(a
->value
->value
), lf
);
1174 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1175 strlen(manufacturer
->value
)))
1176 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1178 locatalog
->find_message(manufacturer
->value
),
1179 locatalog
->find_message(model_name
->value
), lf
);
1181 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1183 locatalog
->find_message(model_name
->value
), lf
);
1185 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1186 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1188 locatalog
->find_message(a
->value
->value
), lf
);
1189 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1190 strlen(manufacturer
->value
)))
1191 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1193 locatalog
->find_message(manufacturer
->value
),
1194 locatalog
->find_message(model_name
->value
), lf
);
1196 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1198 locatalog
->find_message(model_name
->value
), lf
);
1200 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1201 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1203 locatalog
->find_message(a
->value
->value
), lf
);
1204 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1205 strlen(manufacturer
->value
)))
1206 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1208 locatalog
->find_message(manufacturer
->value
),
1209 locatalog
->find_message(model_name
->value
),
1210 version
->value
, lf
);
1212 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1214 locatalog
->find_message(model_name
->value
),
1215 version
->value
, lf
);
1217 // Then the page sizes...
1218 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1219 locatalog
->find_message("Media Size"), lf
);
1221 for (m
= (ppdcMediaSize
*)sizes
->first();
1223 m
= (ppdcMediaSize
*)sizes
->next())
1225 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1226 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1230 // Next the groups and options...
1231 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1233 if (!g
->options
->count
)
1236 if (_cups_strcasecmp(g
->name
->value
, "General"))
1237 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1239 locatalog
->find_message(g
->text
->value
), lf
);
1241 for (o
= (ppdcOption
*)g
->options
->first();
1243 o
= (ppdcOption
*)g
->options
->next())
1245 if (!o
->choices
->count
)
1248 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1250 locatalog
->find_message(o
->text
->value
?
1252 o
->name
->value
), lf
);
1254 for (c
= (ppdcChoice
*)o
->choices
->first();
1256 c
= (ppdcChoice
*)o
->choices
->next())
1258 // Write this choice...
1259 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1260 o
->name
->value
, c
->name
->value
,
1261 locatalog
->find_message(c
->text
->value
?
1263 c
->name
->value
), lf
);
1268 // Finally the localizable attributes...
1269 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1271 if (!a
->localizable
&&
1272 (!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1273 strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1274 strcmp(a
->name
->value
, "APPrinterPreset") &&
1275 strcmp(a
->name
->value
, "cupsICCProfile") &&
1276 strcmp(a
->name
->value
, "cupsIPPReason") &&
1277 strcmp(a
->name
->value
, "cupsMarkerName") &&
1278 strncmp(a
->name
->value
, "Custom", 6) &&
1279 strncmp(a
->name
->value
, "ParamCustom", 11))
1282 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1283 a
->name
->value
, a
->selector
->value
,
1284 locatalog
->find_message(a
->text
&& a
->text
->value
?
1285 a
->text
->value
: a
->name
->value
),
1286 ((a
->localizable
&& a
->value
->value
[0]) ||
1287 !strcmp(a
->name
->value
, "cupsIPPReason")) ?
1288 locatalog
->find_message(a
->value
->value
) : "",
1294 if (default_font
&& default_font
->value
)
1295 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1297 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1299 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1300 if (!strcmp(fn
->name
->value
, "*"))
1302 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1304 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1305 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1306 bfn
->name
->value
, bfn
->encoding
->value
,
1307 bfn
->version
->value
, bfn
->charset
->value
,
1308 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1311 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1312 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1314 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1316 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1317 (int)((size_t)cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),