]>
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-2014 by Apple Inc.
5 // Copyright 2002-2006 by Easy Software Products.
7 // Licensed under Apache License v2.0. See the file "LICENSE" for more information.
11 // Include necessary headers...
14 #include "ppdc-private.h"
18 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
21 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
24 ppdcGroup
*g
; // Current group
31 // Bump the use count of any strings we inherit...
33 d
->manufacturer
->retain();
37 d
->default_font
->retain();
39 d
->default_size
->retain();
40 if (d
->custom_size_code
)
41 d
->custom_size_code
->retain();
43 // Copy all of the data from the driver template...
44 copyright
= new ppdcArray(d
->copyright
);
45 manufacturer
= d
->manufacturer
;
51 model_number
= d
->model_number
;
52 manual_copies
= d
->manual_copies
;
53 color_device
= d
->color_device
;
54 throughput
= d
->throughput
;
55 attrs
= new ppdcArray(d
->attrs
);
56 constraints
= new ppdcArray(d
->constraints
);
57 filters
= new ppdcArray(d
->filters
);
58 fonts
= new ppdcArray(d
->fonts
);
59 profiles
= new ppdcArray(d
->profiles
);
60 sizes
= new ppdcArray(d
->sizes
);
61 default_font
= d
->default_font
;
62 default_size
= d
->default_size
;
63 variable_paper_size
= d
->variable_paper_size
;
64 custom_size_code
= d
->custom_size_code
;
65 left_margin
= d
->left_margin
;
66 bottom_margin
= d
->bottom_margin
;
67 right_margin
= d
->right_margin
;
68 top_margin
= d
->top_margin
;
69 max_width
= d
->max_width
;
70 max_length
= d
->max_length
;
71 min_width
= d
->min_width
;
72 min_length
= d
->min_length
;
74 // Then copy the groups manually, since we want separate copies
75 // of the groups and options...
76 groups
= new ppdcArray();
78 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
79 groups
->add(new ppdcGroup(g
));
83 // Zero all of the data in the driver...
84 copyright
= new ppdcArray();
90 type
= PPDC_DRIVER_CUSTOM
;
95 attrs
= new ppdcArray();
96 constraints
= new ppdcArray();
97 fonts
= new ppdcArray();
98 filters
= new ppdcArray();
99 groups
= new ppdcArray();
100 profiles
= new ppdcArray();
101 sizes
= new ppdcArray();
104 variable_paper_size
= 0;
105 custom_size_code
= 0;
119 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
122 ppdcDriver::~ppdcDriver()
126 copyright
->release();
129 manufacturer
->release();
131 model_name
->release();
133 file_name
->release();
135 pc_file_name
->release();
139 default_font
->release();
141 default_size
->release();
142 if (custom_size_code
)
143 custom_size_code
->release();
146 constraints
->release();
156 // 'ppdcDriver::find_attr()' - Find an attribute.
159 ppdcAttr
* // O - Attribute or NULL
160 ppdcDriver::find_attr(const char *k
, // I - Keyword string
161 const char *s
) // I - Spec string
163 ppdcAttr
*a
; // Current attribute
166 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
167 if (!strcmp(a
->name
->value
, k
) &&
168 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
169 (s
&& a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
177 // 'ppdcDriver::find_group()' - Find a group.
180 ppdcGroup
* // O - Matching group or NULL
181 ppdcDriver::find_group(const char *n
) // I - Group name
183 ppdcGroup
*g
; // Current group
186 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
187 if (!_cups_strcasecmp(n
, g
->name
->value
))
195 // 'ppdcDriver::find_option()' - Find an option.
198 ppdcOption
* // O - Matching option or NULL
199 ppdcDriver::find_option(const char *n
) // I - Option name
201 return (find_option_group(n
, (ppdcGroup
**)0));
206 // 'ppdcDriver::find_option_group()' - Find an option and its group.
209 ppdcOption
* // O - Matching option or NULL
210 ppdcDriver::find_option_group(
211 const char *n
, // I - Option name
212 ppdcGroup
**mg
) // O - Matching group or NULL
214 ppdcGroup
*g
; // Current group
215 ppdcOption
*o
; // Current option
218 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
219 for (o
= (ppdcOption
*)g
->options
->first(); o
; o
= (ppdcOption
*)g
->options
->next())
220 if (!_cups_strcasecmp(n
, o
->name
->value
))
229 *mg
= (ppdcGroup
*)0;
236 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
240 ppdcDriver::set_custom_size_code(
241 const char *c
) // I - CustomPageSize code
243 if (custom_size_code
)
244 custom_size_code
->release();
246 custom_size_code
= new ppdcString(c
);
251 // 'ppdcDriver::set_default_font()' - Set the default font name.
255 ppdcDriver::set_default_font(
256 ppdcFont
*f
) // I - Font
259 default_font
->release();
264 default_font
= f
->name
;
272 // 'ppdcDriver::set_default_size()' - Set the default size name.
276 ppdcDriver::set_default_size(
277 ppdcMediaSize
*m
) // I - Media size
280 default_size
->release();
285 default_size
= m
->name
;
293 // 'ppdcDriver::set_file_name()' - Set the full filename.
297 ppdcDriver::set_file_name(const char *f
)// I - Filename
300 file_name
->release();
302 file_name
= new ppdcString(f
);
307 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
311 ppdcDriver::set_manufacturer(
312 const char *m
) // I - Model name
315 manufacturer
->release();
317 manufacturer
= new ppdcString(m
);
322 // 'ppdcDriver::set_model_name()' - Set the model name.
326 ppdcDriver::set_model_name(
327 const char *m
) // I - Model name
330 model_name
->release();
332 model_name
= new ppdcString(m
);
337 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
341 ppdcDriver::set_pc_file_name(
342 const char *f
) // I - Filename
345 pc_file_name
->release();
347 pc_file_name
= new ppdcString(f
);
352 // 'ppdcDriver::set_version()' - Set the version string.
356 ppdcDriver::set_version(const char *v
) // I - Version
361 version
= new ppdcString(v
);
366 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
369 int // O - 0 on success, -1 on failure
370 ppdcDriver::write_ppd_file(
371 cups_file_t
*fp
, // I - PPD file
372 ppdcCatalog
*catalog
, // I - Message catalog
373 ppdcArray
*locales
, // I - Additional languages to add
374 ppdcSource
*src
, // I - Driver source
375 ppdcLineEnding le
) // I - Line endings to use
377 bool delete_cat
; // Delete the catalog when we are done?
378 char query
[42], // Query attribute
379 custom
[42]; // Custom attribute
380 ppdcString
*s
; // Copyright string
381 ppdcGroup
*g
; // Current group
382 ppdcOption
*o
; // Current option
383 ppdcChoice
*c
; // Current choice
384 ppdcMediaSize
*m
; // Current media size
385 ppdcProfile
*p
; // Current color profile
386 ppdcFilter
*f
; // Current filter
387 ppdcFont
*fn
, // Current font
388 *bfn
; // Current base font
389 ppdcConstraint
*cn
; // Current constraint
390 ppdcAttr
*a
; // Current attribute
391 const char *lf
; // Linefeed character to use
394 // If we don't have a message catalog, use an empty (English) one...
397 catalog
= new ppdcCatalog(NULL
);
403 // Figure out the end-of-line string...
404 if (le
== PPDC_LFONLY
)
406 else if (le
== PPDC_CRONLY
)
411 // Write the standard header stuff...
412 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
413 cupsFilePrintf(fp
, "*%%%%%%%% PPD file for %s with CUPS.%s",
414 model_name
->value
, lf
);
416 "*%%%%%%%% Created by the CUPS PPD Compiler " CUPS_SVERSION
418 for (s
= (ppdcString
*)copyright
->first();
420 s
= (ppdcString
*)copyright
->next())
421 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
422 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
423 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
425 a
= find_attr("LanguageVersion", NULL
);
426 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
427 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
429 a
= find_attr("LanguageEncoding", NULL
);
430 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
431 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
433 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
435 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
436 if (!strcmp(a
->name
->value
, "Product"))
441 for (; a
; a
= (ppdcAttr
*)attrs
->next())
442 if (!strcmp(a
->name
->value
, "Product"))
443 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
446 cupsFilePrintf(fp
, "*Product: \"(%s)\"%s", model_name
->value
, lf
);
448 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
449 catalog
->find_message(manufacturer
->value
), lf
);
451 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
452 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
453 catalog
->find_message(a
->value
->value
), lf
);
454 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
455 strlen(manufacturer
->value
)))
456 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
457 catalog
->find_message(manufacturer
->value
),
458 catalog
->find_message(model_name
->value
), lf
);
460 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
461 catalog
->find_message(model_name
->value
), lf
);
463 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
464 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
465 catalog
->find_message(a
->value
->value
), lf
);
466 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
467 strlen(manufacturer
->value
)))
468 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
469 catalog
->find_message(manufacturer
->value
),
470 catalog
->find_message(model_name
->value
), lf
);
472 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
473 catalog
->find_message(model_name
->value
), lf
);
475 if ((a
= find_attr("NickName", NULL
)) != NULL
)
476 cupsFilePrintf(fp
, "*NickName: \"%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
, "*NickName: \"%s %s, %s\"%s",
481 catalog
->find_message(manufacturer
->value
),
482 catalog
->find_message(model_name
->value
), version
->value
,
485 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
486 catalog
->find_message(model_name
->value
), version
->value
,
489 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
490 if (!strcmp(a
->name
->value
, "PSVersion"))
495 for (; a
; a
= (ppdcAttr
*)attrs
->next())
496 if (!strcmp(a
->name
->value
, "PSVersion"))
497 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
500 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 0\"%s", lf
);
502 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
503 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
505 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
507 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
509 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
510 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
512 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
513 color_device
? "RGB" : "Gray", lf
);
515 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
516 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
518 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
520 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
522 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
523 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
525 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
527 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
528 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
529 else if (type
!= PPDC_DRIVER_PS
)
530 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
532 struct lconv
*loc
= localeconv();
536 // Write driver-defined attributes...
537 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
538 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
540 if (!strcmp(a
->name
->value
, "Product") ||
541 !strcmp(a
->name
->value
, "PSVersion") ||
542 !strcmp(a
->name
->value
, "LanguageLevel") ||
543 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
544 !strcmp(a
->name
->value
, "FileSystem") ||
545 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
546 !strcmp(a
->name
->value
, "TTRasterizer") ||
547 !strcmp(a
->name
->value
, "LanguageVersion") ||
548 !strcmp(a
->name
->value
, "LanguageEncoding") ||
549 !strcmp(a
->name
->value
, "ModelName") ||
550 !strcmp(a
->name
->value
, "NickName") ||
551 !strcmp(a
->name
->value
, "ShortNickName") ||
552 !strcmp(a
->name
->value
, "cupsVersion"))
555 if (a
->name
->value
[0] == '?' &&
556 (find_option(a
->name
->value
+ 1) ||
557 !strcmp(a
->name
->value
, "?ImageableArea") ||
558 !strcmp(a
->name
->value
, "?PageRegion") ||
559 !strcmp(a
->name
->value
, "?PageSize") ||
560 !strcmp(a
->name
->value
, "?PaperDimension")))
563 if (!strncmp(a
->name
->value
, "Custom", 6) &&
564 find_option(a
->name
->value
+ 6))
567 if (!strncmp(a
->name
->value
, "ParamCustom", 11) &&
568 find_option(a
->name
->value
+ 11))
571 if (!a
->selector
->value
|| !a
->selector
->value
[0])
572 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
573 else if (!a
->text
->value
|| !a
->text
->value
[0])
574 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
576 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
579 if (strcmp(a
->value
->value
, "False") &&
580 strcmp(a
->value
->value
, "True") &&
581 strcmp(a
->name
->value
, "1284Modes") &&
582 strcmp(a
->name
->value
, "InkName") &&
583 strcmp(a
->name
->value
, "PageStackOrder") &&
584 strncmp(a
->name
->value
, "ParamCustom", 11) &&
585 strcmp(a
->name
->value
, "Protocols") &&
586 strcmp(a
->name
->value
, "ReferencePunch") &&
587 strncmp(a
->name
->value
, "Default", 7))
589 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
591 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
592 cupsFilePrintf(fp
, "*End%s", lf
);
595 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
599 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
601 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
602 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
604 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
605 CUPS_VERSION_MINOR
, lf
);
606 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
607 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
608 manual_copies
? "True" : "False", lf
);
612 for (f
= (ppdcFilter
*)filters
->first();
614 f
= (ppdcFilter
*)filters
->next())
615 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
616 f
->cost
, f
->program
->value
, lf
);
622 case PPDC_DRIVER_LABEL
:
623 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
624 "rastertolabel\"%s", lf
);
627 case PPDC_DRIVER_EPSON
:
628 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
629 "rastertoepson\"%s", lf
);
632 case PPDC_DRIVER_ESCP
:
633 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
634 "commandtoescpx\"%s", lf
);
635 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
636 "rastertoescpx\"%s", lf
);
639 case PPDC_DRIVER_HP
:
640 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
641 "rastertohp\"%s", lf
);
644 case PPDC_DRIVER_PCL
:
645 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
646 "commandtopclx\"%s", lf
);
647 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
648 "rastertopclx\"%s", lf
);
656 for (p
= (ppdcProfile
*)profiles
->first();
658 p
= (ppdcProfile
*)profiles
->next())
660 char density
[255], gamma
[255], profile
[9][255];
662 _cupsStrFormatd(density
, density
+ sizeof(density
), p
->density
, loc
);
663 _cupsStrFormatd(gamma
, gamma
+ sizeof(gamma
), p
->gamma
, loc
);
665 for (int i
= 0; i
< 9; i
++)
666 _cupsStrFormatd(profile
[i
], profile
[i
] + sizeof(profile
[0]),
670 "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
671 "%s\"%s", p
->resolution
->value
, p
->media_type
->value
,
672 density
, gamma
, profile
[0], profile
[1], profile
[2],
673 profile
[3], profile
[4], profile
[5], profile
[6], profile
[7],
680 // Add localizations for additional languages...
681 ppdcString
*locale
; // Locale name
682 ppdcCatalog
*locatalog
; // Message catalog for locale
685 // Write the list of languages...
686 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
688 for (locale
= (ppdcString
*)locales
->first();
690 locale
= (ppdcString
*)locales
->next())
692 // Skip (US) English...
693 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
696 // See if we have a po file for this language...
697 if (!src
->find_po(locale
->value
))
699 // No, see if we can use the base file?
700 locatalog
= new ppdcCatalog(locale
->value
);
702 if (locatalog
->messages
->count
== 0)
704 // No, skip this one...
705 _cupsLangPrintf(stderr
,
706 _("ppdc: No message catalog provided for locale "
707 "%s."), locale
->value
);
711 // Add the base file to the list...
712 src
->po_files
->add(locatalog
);
715 cupsFilePrintf(fp
, " %s", locale
->value
);
718 cupsFilePrintf(fp
, "\"%s", lf
);
721 for (cn
= (ppdcConstraint
*)constraints
->first();
723 cn
= (ppdcConstraint
*)constraints
->next())
725 // First constrain 1 against 2...
726 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
727 !strncmp(cn
->option2
->value
, "*Custom", 7))
728 cupsFilePuts(fp
, "*NonUIConstraints: ");
730 cupsFilePuts(fp
, "*UIConstraints: ");
732 if (cn
->option1
->value
[0] != '*')
733 cupsFilePutChar(fp
, '*');
735 cupsFilePuts(fp
, cn
->option1
->value
);
737 if (cn
->choice1
->value
)
738 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
740 cupsFilePutChar(fp
, ' ');
742 if (cn
->option2
->value
[0] != '*')
743 cupsFilePutChar(fp
, '*');
745 cupsFilePuts(fp
, cn
->option2
->value
);
747 if (cn
->choice2
->value
)
748 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
750 cupsFilePuts(fp
, lf
);
752 // Then constrain 2 against 1...
753 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
754 !strncmp(cn
->option2
->value
, "*Custom", 7))
755 cupsFilePuts(fp
, "*NonUIConstraints: ");
757 cupsFilePuts(fp
, "*UIConstraints: ");
759 if (cn
->option2
->value
[0] != '*')
760 cupsFilePutChar(fp
, '*');
762 cupsFilePuts(fp
, cn
->option2
->value
);
764 if (cn
->choice2
->value
)
765 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
767 cupsFilePutChar(fp
, ' ');
769 if (cn
->option1
->value
[0] != '*')
770 cupsFilePutChar(fp
, '*');
772 cupsFilePuts(fp
, cn
->option1
->value
);
774 if (cn
->choice1
->value
)
775 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
777 cupsFilePuts(fp
, lf
);
780 // PageSize option...
781 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
782 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
783 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
784 default_size
? default_size
->value
: "Letter", lf
);
786 for (m
= (ppdcMediaSize
*)sizes
->first();
788 m
= (ppdcMediaSize
*)sizes
->next())
789 if (m
->size_code
->value
)
791 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
792 m
->name
->value
, catalog
->find_message(m
->text
->value
),
793 m
->size_code
->value
, lf
);
795 if (strchr(m
->size_code
->value
, '\n') ||
796 strchr(m
->size_code
->value
, '\r'))
797 cupsFilePrintf(fp
, "*End%s", lf
);
801 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
802 "/ImagingBBox null>>setpagedevice\"%s",
803 m
->name
->value
, catalog
->find_message(m
->text
->value
),
804 m
->width
, m
->length
, lf
);
806 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
808 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
810 if (strchr(a
->value
->value
, '\n') ||
811 strchr(a
->value
->value
, '\r'))
812 cupsFilePrintf(fp
, "*End%s", lf
);
815 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
817 // PageRegion option...
818 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
819 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
820 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
821 default_size
? default_size
->value
: "Letter", lf
);
823 for (m
= (ppdcMediaSize
*)sizes
->first();
825 m
= (ppdcMediaSize
*)sizes
->next())
826 if (m
->region_code
->value
)
828 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
829 m
->name
->value
, catalog
->find_message(m
->text
->value
),
830 m
->region_code
->value
, lf
);
832 if (strchr(m
->region_code
->value
, '\n') ||
833 strchr(m
->region_code
->value
, '\r'))
834 cupsFilePrintf(fp
, "*End%s", lf
);
838 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
839 "/ImagingBBox null>>setpagedevice\"%s",
840 m
->name
->value
, catalog
->find_message(m
->text
->value
),
841 m
->width
, m
->length
, lf
);
843 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
845 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
847 if (strchr(a
->value
->value
, '\n') ||
848 strchr(a
->value
->value
, '\r'))
849 cupsFilePrintf(fp
, "*End%s", lf
);
852 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
854 // ImageableArea info...
855 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
856 default_size
? default_size
->value
: "Letter", lf
);
858 char left
[255], right
[255], bottom
[255], top
[255];
860 for (m
= (ppdcMediaSize
*)sizes
->first();
862 m
= (ppdcMediaSize
*)sizes
->next())
864 _cupsStrFormatd(left
, left
+ sizeof(left
), m
->left
, loc
);
865 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), m
->bottom
, loc
);
866 _cupsStrFormatd(right
, right
+ sizeof(right
), m
->width
- m
->right
, loc
);
867 _cupsStrFormatd(top
, top
+ sizeof(top
), m
->length
- m
->top
, loc
);
869 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
870 m
->name
->value
, catalog
->find_message(m
->text
->value
),
871 left
, bottom
, right
, top
, lf
);
874 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
876 cupsFilePrintf(fp
, "*?ImageableArea: \"%s\"%s", a
->value
->value
, lf
);
878 if (strchr(a
->value
->value
, '\n') ||
879 strchr(a
->value
->value
, '\r'))
880 cupsFilePrintf(fp
, "*End%s", lf
);
883 // PaperDimension info...
884 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
885 default_size
? default_size
->value
: "Letter", lf
);
887 char width
[255], length
[255];
889 for (m
= (ppdcMediaSize
*)sizes
->first();
891 m
= (ppdcMediaSize
*)sizes
->next())
893 _cupsStrFormatd(width
, width
+ sizeof(width
), m
->width
, loc
);
894 _cupsStrFormatd(length
, length
+ sizeof(length
), m
->length
, loc
);
896 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%s %s\"%s",
897 m
->name
->value
, catalog
->find_message(m
->text
->value
),
901 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
903 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
905 if (strchr(a
->value
->value
, '\n') ||
906 strchr(a
->value
->value
, '\r'))
907 cupsFilePrintf(fp
, "*End%s", lf
);
910 // Custom size support...
911 if (variable_paper_size
)
913 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
914 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
916 _cupsStrFormatd(left
, left
+ sizeof(left
), left_margin
, loc
);
917 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), bottom_margin
, loc
);
918 _cupsStrFormatd(right
, right
+ sizeof(right
), right_margin
, loc
);
919 _cupsStrFormatd(top
, top
+ sizeof(top
), top_margin
, loc
);
921 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%s\"%s", width
, lf
);
922 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%s\"%s", length
, lf
);
923 cupsFilePrintf(fp
, "*HWMargins: %s %s %s %s%s", left
, bottom
, right
, top
,
926 if (custom_size_code
&& custom_size_code
->value
)
928 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
929 custom_size_code
->value
, lf
);
931 if (strchr(custom_size_code
->value
, '\n') ||
932 strchr(custom_size_code
->value
, '\r'))
933 cupsFilePrintf(fp
, "*End%s", lf
);
937 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
938 "/ImagingBBox null>>setpagedevice\"%s", lf
);
940 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
941 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
947 _cupsStrFormatd(width0
, width0
+ sizeof(width0
), min_width
, loc
);
948 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
950 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %s %s%s",
954 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
955 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
961 _cupsStrFormatd(length0
, length0
+ sizeof(length0
), min_length
, loc
);
962 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
964 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %s %s%s",
965 length0
, length
, lf
);
968 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
969 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
970 a
->value
->value
, lf
);
972 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
974 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
975 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
976 a
->value
->value
, lf
);
978 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
980 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
981 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
982 a
->value
->value
, lf
);
984 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
987 // All other options...
988 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
990 if (!g
->options
->count
)
993 if (_cups_strcasecmp(g
->name
->value
, "General"))
994 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
995 catalog
->find_message(g
->text
->value
), lf
);
997 for (o
= (ppdcOption
*)g
->options
->first();
999 o
= (ppdcOption
*)g
->options
->next())
1001 if (!o
->choices
->count
)
1004 if (o
->section
== PPDC_SECTION_JCL
)
1006 if (!o
->text
->value
)
1007 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1008 catalog
->find_message(o
->name
->value
));
1010 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1011 catalog
->find_message(o
->text
->value
));
1013 else if (!o
->text
->value
)
1014 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1015 catalog
->find_message(o
->name
->value
));
1017 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1018 catalog
->find_message(o
->text
->value
));
1023 cupsFilePrintf(fp
, "Boolean%s", lf
);
1026 cupsFilePrintf(fp
, "PickOne%s", lf
);
1028 case PPDC_PICKMANY
:
1029 cupsFilePrintf(fp
, "PickMany%s", lf
);
1034 _cupsStrFormatd(order
, order
+ sizeof(order
), o
->order
, loc
);
1036 cupsFilePrintf(fp
, "*OrderDependency: %s ", order
);
1040 cupsFilePrintf(fp
, "AnySetup");
1042 case PPDC_SECTION_DOCUMENT
:
1043 cupsFilePrintf(fp
, "DocumentSetup");
1045 case PPDC_SECTION_EXIT
:
1046 cupsFilePrintf(fp
, "ExitServer");
1048 case PPDC_SECTION_JCL
:
1049 cupsFilePrintf(fp
, "JCLSetup");
1051 case PPDC_SECTION_PAGE
:
1052 cupsFilePrintf(fp
, "PageSetup");
1054 case PPDC_SECTION_PROLOG
:
1055 cupsFilePrintf(fp
, "Prolog");
1059 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
1063 // Use the programmer-supplied default...
1064 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
1065 o
->defchoice
->value
, lf
);
1069 // Make the first choice the default...
1070 c
= (ppdcChoice
*)o
->choices
->first();
1071 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
1075 for (c
= (ppdcChoice
*)o
->choices
->first();
1077 c
= (ppdcChoice
*)o
->choices
->next())
1079 // Write this choice...
1080 if (!c
->text
->value
)
1081 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1082 c
->name
->value
, catalog
->find_message(c
->name
->value
),
1083 c
->code
->value
, lf
);
1085 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1086 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1087 c
->code
->value
, lf
);
1089 // Multi-line commands need a *End line to terminate them.
1090 if (strchr(c
->code
->value
, '\n') ||
1091 strchr(c
->code
->value
, '\r'))
1092 cupsFilePrintf(fp
, "*End%s", lf
);
1095 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1097 if ((a
= find_attr(query
, NULL
)) != NULL
)
1099 cupsFilePrintf(fp
, "*%s: \"%s\"%s", query
, a
->value
->value
, lf
);
1101 if (strchr(a
->value
->value
, '\n') ||
1102 strchr(a
->value
->value
, '\r'))
1103 cupsFilePrintf(fp
, "*End%s", lf
);
1106 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1108 snprintf(custom
, sizeof(custom
), "Custom%s", o
->name
->value
);
1109 if ((a
= find_attr(custom
, "True")) != NULL
)
1111 // Output custom option information...
1112 cupsFilePrintf(fp
, "*%s True: \"%s\"%s", custom
, a
->value
->value
, lf
);
1113 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
1114 cupsFilePrintf(fp
, "*End%s", lf
);
1116 snprintf(custom
, sizeof(custom
), "ParamCustom%s", o
->name
->value
);
1117 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1119 if (strcmp(a
->name
->value
, custom
))
1122 if (!a
->selector
->value
|| !a
->selector
->value
[0])
1123 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
1124 else if (!a
->text
->value
|| !a
->text
->value
[0])
1125 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1126 catalog
->find_message(a
->selector
->value
));
1128 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1129 catalog
->find_message(a
->text
->value
));
1131 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
1136 if (_cups_strcasecmp(g
->name
->value
, "General"))
1137 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1142 // Add localizations for additional languages...
1143 ppdcString
*locale
; // Locale name
1144 ppdcCatalog
*locatalog
; // Message catalog for locale
1147 // Write the translation strings for each language...
1148 for (locale
= (ppdcString
*)locales
->first();
1150 locale
= (ppdcString
*)locales
->next())
1152 // Skip (US) English...
1153 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1156 // Skip missing languages...
1157 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1160 // Do the core stuff first...
1161 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1163 locatalog
->find_message(manufacturer
->value
), lf
);
1165 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1166 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1168 locatalog
->find_message(a
->value
->value
), lf
);
1169 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1170 strlen(manufacturer
->value
)))
1171 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1173 locatalog
->find_message(manufacturer
->value
),
1174 locatalog
->find_message(model_name
->value
), lf
);
1176 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1178 locatalog
->find_message(model_name
->value
), lf
);
1180 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1181 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1183 locatalog
->find_message(a
->value
->value
), lf
);
1184 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1185 strlen(manufacturer
->value
)))
1186 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1188 locatalog
->find_message(manufacturer
->value
),
1189 locatalog
->find_message(model_name
->value
), lf
);
1191 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1193 locatalog
->find_message(model_name
->value
), lf
);
1195 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1196 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1198 locatalog
->find_message(a
->value
->value
), lf
);
1199 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1200 strlen(manufacturer
->value
)))
1201 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1203 locatalog
->find_message(manufacturer
->value
),
1204 locatalog
->find_message(model_name
->value
),
1205 version
->value
, lf
);
1207 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1209 locatalog
->find_message(model_name
->value
),
1210 version
->value
, lf
);
1212 // Then the page sizes...
1213 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1214 locatalog
->find_message("Media Size"), lf
);
1216 for (m
= (ppdcMediaSize
*)sizes
->first();
1218 m
= (ppdcMediaSize
*)sizes
->next())
1220 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1221 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1225 // Next the groups and options...
1226 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1228 if (!g
->options
->count
)
1231 if (_cups_strcasecmp(g
->name
->value
, "General"))
1232 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1234 locatalog
->find_message(g
->text
->value
), lf
);
1236 for (o
= (ppdcOption
*)g
->options
->first();
1238 o
= (ppdcOption
*)g
->options
->next())
1240 if (!o
->choices
->count
)
1243 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1245 locatalog
->find_message(o
->text
->value
?
1247 o
->name
->value
), lf
);
1249 for (c
= (ppdcChoice
*)o
->choices
->first();
1251 c
= (ppdcChoice
*)o
->choices
->next())
1253 // Write this choice...
1254 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1255 o
->name
->value
, c
->name
->value
,
1256 locatalog
->find_message(c
->text
->value
?
1258 c
->name
->value
), lf
);
1263 // Finally the localizable attributes...
1264 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1266 if (!a
->localizable
&&
1267 (!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1268 strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1269 strcmp(a
->name
->value
, "APPrinterPreset") &&
1270 strcmp(a
->name
->value
, "cupsICCProfile") &&
1271 strcmp(a
->name
->value
, "cupsIPPReason") &&
1272 strcmp(a
->name
->value
, "cupsMarkerName") &&
1273 strncmp(a
->name
->value
, "Custom", 6) &&
1274 strncmp(a
->name
->value
, "ParamCustom", 11))
1277 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1278 a
->name
->value
, a
->selector
->value
,
1279 locatalog
->find_message(a
->text
&& a
->text
->value
?
1280 a
->text
->value
: a
->name
->value
),
1281 ((a
->localizable
&& a
->value
->value
[0]) ||
1282 !strcmp(a
->name
->value
, "cupsIPPReason")) ?
1283 locatalog
->find_message(a
->value
->value
) : "",
1289 if (default_font
&& default_font
->value
)
1290 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1292 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1294 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1295 if (!strcmp(fn
->name
->value
, "*"))
1297 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1299 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1300 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1301 bfn
->name
->value
, bfn
->encoding
->value
,
1302 bfn
->version
->value
, bfn
->charset
->value
,
1303 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1306 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1307 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1309 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1311 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1312 (int)((size_t)cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),