]>
git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-driver.cxx
6d1596343216c89aa160b1e0df7e8b6f75352959
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 // These coded instructions, statements, and computer programs are the
8 // property of Apple Inc. and are protected by Federal copyright
9 // law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 // which should have been included with this file. If this file is
11 // file is missing or damaged, see the license at "http://www.cups.org/".
15 // Include necessary headers...
18 #include "ppdc-private.h"
22 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
25 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
28 ppdcGroup
*g
; // Current group
35 // Bump the use count of any strings we inherit...
37 d
->manufacturer
->retain();
41 d
->default_font
->retain();
43 d
->default_size
->retain();
44 if (d
->custom_size_code
)
45 d
->custom_size_code
->retain();
47 // Copy all of the data from the driver template...
48 copyright
= new ppdcArray(d
->copyright
);
49 manufacturer
= d
->manufacturer
;
55 model_number
= d
->model_number
;
56 manual_copies
= d
->manual_copies
;
57 color_device
= d
->color_device
;
58 throughput
= d
->throughput
;
59 attrs
= new ppdcArray(d
->attrs
);
60 constraints
= new ppdcArray(d
->constraints
);
61 filters
= new ppdcArray(d
->filters
);
62 fonts
= new ppdcArray(d
->fonts
);
63 profiles
= new ppdcArray(d
->profiles
);
64 sizes
= new ppdcArray(d
->sizes
);
65 default_font
= d
->default_font
;
66 default_size
= d
->default_size
;
67 variable_paper_size
= d
->variable_paper_size
;
68 custom_size_code
= d
->custom_size_code
;
69 left_margin
= d
->left_margin
;
70 bottom_margin
= d
->bottom_margin
;
71 right_margin
= d
->right_margin
;
72 top_margin
= d
->top_margin
;
73 max_width
= d
->max_width
;
74 max_length
= d
->max_length
;
75 min_width
= d
->min_width
;
76 min_length
= d
->min_length
;
78 // Then copy the groups manually, since we want separate copies
79 // of the groups and options...
80 groups
= new ppdcArray();
82 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
83 groups
->add(new ppdcGroup(g
));
87 // Zero all of the data in the driver...
88 copyright
= new ppdcArray();
94 type
= PPDC_DRIVER_CUSTOM
;
99 attrs
= new ppdcArray();
100 constraints
= new ppdcArray();
101 fonts
= new ppdcArray();
102 filters
= new ppdcArray();
103 groups
= new ppdcArray();
104 profiles
= new ppdcArray();
105 sizes
= new ppdcArray();
108 variable_paper_size
= 0;
109 custom_size_code
= 0;
123 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
126 ppdcDriver::~ppdcDriver()
130 copyright
->release();
133 manufacturer
->release();
135 model_name
->release();
137 file_name
->release();
139 pc_file_name
->release();
143 default_font
->release();
145 default_size
->release();
146 if (custom_size_code
)
147 custom_size_code
->release();
150 constraints
->release();
160 // 'ppdcDriver::find_attr()' - Find an attribute.
163 ppdcAttr
* // O - Attribute or NULL
164 ppdcDriver::find_attr(const char *k
, // I - Keyword string
165 const char *s
) // I - Spec string
167 ppdcAttr
*a
; // Current attribute
170 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
171 if (!strcmp(a
->name
->value
, k
) &&
172 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
173 (s
&& a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
181 // 'ppdcDriver::find_group()' - Find a group.
184 ppdcGroup
* // O - Matching group or NULL
185 ppdcDriver::find_group(const char *n
) // I - Group name
187 ppdcGroup
*g
; // Current group
190 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
191 if (!_cups_strcasecmp(n
, g
->name
->value
))
199 // 'ppdcDriver::find_option()' - Find an option.
202 ppdcOption
* // O - Matching option or NULL
203 ppdcDriver::find_option(const char *n
) // I - Option name
205 return (find_option_group(n
, (ppdcGroup
**)0));
210 // 'ppdcDriver::find_option_group()' - Find an option and its group.
213 ppdcOption
* // O - Matching option or NULL
214 ppdcDriver::find_option_group(
215 const char *n
, // I - Option name
216 ppdcGroup
**mg
) // O - Matching group or NULL
218 ppdcGroup
*g
; // Current group
219 ppdcOption
*o
; // Current option
222 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
223 for (o
= (ppdcOption
*)g
->options
->first(); o
; o
= (ppdcOption
*)g
->options
->next())
224 if (!_cups_strcasecmp(n
, o
->name
->value
))
233 *mg
= (ppdcGroup
*)0;
240 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
244 ppdcDriver::set_custom_size_code(
245 const char *c
) // I - CustomPageSize code
247 if (custom_size_code
)
248 custom_size_code
->release();
250 custom_size_code
= new ppdcString(c
);
255 // 'ppdcDriver::set_default_font()' - Set the default font name.
259 ppdcDriver::set_default_font(
260 ppdcFont
*f
) // I - Font
263 default_font
->release();
268 default_font
= f
->name
;
276 // 'ppdcDriver::set_default_size()' - Set the default size name.
280 ppdcDriver::set_default_size(
281 ppdcMediaSize
*m
) // I - Media size
284 default_size
->release();
289 default_size
= m
->name
;
297 // 'ppdcDriver::set_file_name()' - Set the full filename.
301 ppdcDriver::set_file_name(const char *f
)// I - Filename
304 file_name
->release();
306 file_name
= new ppdcString(f
);
311 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
315 ppdcDriver::set_manufacturer(
316 const char *m
) // I - Model name
319 manufacturer
->release();
321 manufacturer
= new ppdcString(m
);
326 // 'ppdcDriver::set_model_name()' - Set the model name.
330 ppdcDriver::set_model_name(
331 const char *m
) // I - Model name
334 model_name
->release();
336 model_name
= new ppdcString(m
);
341 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
345 ppdcDriver::set_pc_file_name(
346 const char *f
) // I - Filename
349 pc_file_name
->release();
351 pc_file_name
= new ppdcString(f
);
356 // 'ppdcDriver::set_version()' - Set the version string.
360 ppdcDriver::set_version(const char *v
) // I - Version
365 version
= new ppdcString(v
);
370 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
373 int // O - 0 on success, -1 on failure
374 ppdcDriver::write_ppd_file(
375 cups_file_t
*fp
, // I - PPD file
376 ppdcCatalog
*catalog
, // I - Message catalog
377 ppdcArray
*locales
, // I - Additional languages to add
378 ppdcSource
*src
, // I - Driver source
379 ppdcLineEnding le
) // I - Line endings to use
381 bool delete_cat
; // Delete the catalog when we are done?
382 char query
[42], // Query attribute
383 custom
[42]; // Custom attribute
384 ppdcString
*s
; // Copyright string
385 ppdcGroup
*g
; // Current group
386 ppdcOption
*o
; // Current option
387 ppdcChoice
*c
; // Current choice
388 ppdcMediaSize
*m
; // Current media size
389 ppdcProfile
*p
; // Current color profile
390 ppdcFilter
*f
; // Current filter
391 ppdcFont
*fn
, // Current font
392 *bfn
; // Current base font
393 ppdcConstraint
*cn
; // Current constraint
394 ppdcAttr
*a
; // Current attribute
395 const char *lf
; // Linefeed character to use
398 // If we don't have a message catalog, use an empty (English) one...
401 catalog
= new ppdcCatalog("en");
407 // Figure out the end-of-line string...
408 if (le
== PPDC_LFONLY
)
410 else if (le
== PPDC_CRONLY
)
415 // Write the standard header stuff...
416 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
417 cupsFilePrintf(fp
, "*%%%%%%%% PPD file for %s with CUPS.%s",
418 model_name
->value
, lf
);
420 "*%%%%%%%% Created by the CUPS PPD Compiler " CUPS_SVERSION
422 for (s
= (ppdcString
*)copyright
->first();
424 s
= (ppdcString
*)copyright
->next())
425 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
426 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
427 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
429 a
= find_attr("LanguageVersion", NULL
);
430 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
431 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
433 a
= find_attr("LanguageEncoding", NULL
);
434 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
435 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
437 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
439 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
440 if (!strcmp(a
->name
->value
, "Product"))
445 for (; a
; a
= (ppdcAttr
*)attrs
->next())
446 if (!strcmp(a
->name
->value
, "Product"))
447 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
450 cupsFilePrintf(fp
, "*Product: \"(%s)\"%s", model_name
->value
, lf
);
452 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
453 catalog
->find_message(manufacturer
->value
), lf
);
455 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
456 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
457 catalog
->find_message(a
->value
->value
), lf
);
458 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
459 strlen(manufacturer
->value
)))
460 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
461 catalog
->find_message(manufacturer
->value
),
462 catalog
->find_message(model_name
->value
), lf
);
464 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
465 catalog
->find_message(model_name
->value
), lf
);
467 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
468 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
469 catalog
->find_message(a
->value
->value
), lf
);
470 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
471 strlen(manufacturer
->value
)))
472 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
473 catalog
->find_message(manufacturer
->value
),
474 catalog
->find_message(model_name
->value
), lf
);
476 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
477 catalog
->find_message(model_name
->value
), lf
);
479 if ((a
= find_attr("NickName", NULL
)) != NULL
)
480 cupsFilePrintf(fp
, "*NickName: \"%s\"%s",
481 catalog
->find_message(a
->value
->value
), lf
);
482 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
483 strlen(manufacturer
->value
)))
484 cupsFilePrintf(fp
, "*NickName: \"%s %s, %s\"%s",
485 catalog
->find_message(manufacturer
->value
),
486 catalog
->find_message(model_name
->value
), version
->value
,
489 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
490 catalog
->find_message(model_name
->value
), version
->value
,
493 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
494 if (!strcmp(a
->name
->value
, "PSVersion"))
499 for (; a
; a
= (ppdcAttr
*)attrs
->next())
500 if (!strcmp(a
->name
->value
, "PSVersion"))
501 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
504 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 0\"%s", lf
);
506 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
507 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
509 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
511 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
513 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
514 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
516 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
517 color_device
? "RGB" : "Gray", lf
);
519 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
520 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
522 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
524 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
526 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
527 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
529 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
531 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
532 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
533 else if (type
!= PPDC_DRIVER_PS
)
534 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
536 struct lconv
*loc
= localeconv();
540 // Write driver-defined attributes...
541 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
542 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
544 if (!strcmp(a
->name
->value
, "Product") ||
545 !strcmp(a
->name
->value
, "PSVersion") ||
546 !strcmp(a
->name
->value
, "LanguageLevel") ||
547 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
548 !strcmp(a
->name
->value
, "FileSystem") ||
549 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
550 !strcmp(a
->name
->value
, "TTRasterizer") ||
551 !strcmp(a
->name
->value
, "LanguageVersion") ||
552 !strcmp(a
->name
->value
, "LanguageEncoding") ||
553 !strcmp(a
->name
->value
, "ModelName") ||
554 !strcmp(a
->name
->value
, "NickName") ||
555 !strcmp(a
->name
->value
, "ShortNickName") ||
556 !strcmp(a
->name
->value
, "cupsVersion"))
559 if (a
->name
->value
[0] == '?' &&
560 (find_option(a
->name
->value
+ 1) ||
561 !strcmp(a
->name
->value
, "?ImageableArea") ||
562 !strcmp(a
->name
->value
, "?PageRegion") ||
563 !strcmp(a
->name
->value
, "?PageSize") ||
564 !strcmp(a
->name
->value
, "?PaperDimension")))
567 if (!strncmp(a
->name
->value
, "Custom", 6) &&
568 find_option(a
->name
->value
+ 6))
571 if (!strncmp(a
->name
->value
, "ParamCustom", 11) &&
572 find_option(a
->name
->value
+ 11))
575 if (!a
->selector
->value
|| !a
->selector
->value
[0])
576 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
577 else if (!a
->text
->value
|| !a
->text
->value
[0])
578 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
580 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
583 if (strcmp(a
->value
->value
, "False") &&
584 strcmp(a
->value
->value
, "True") &&
585 strcmp(a
->name
->value
, "1284Modes") &&
586 strcmp(a
->name
->value
, "InkName") &&
587 strcmp(a
->name
->value
, "PageStackOrder") &&
588 strncmp(a
->name
->value
, "ParamCustom", 11) &&
589 strcmp(a
->name
->value
, "Protocols") &&
590 strcmp(a
->name
->value
, "ReferencePunch") &&
591 strncmp(a
->name
->value
, "Default", 7))
593 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
595 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
596 cupsFilePrintf(fp
, "*End%s", lf
);
599 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
603 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
605 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
606 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
608 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
609 CUPS_VERSION_MINOR
, lf
);
610 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
611 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
612 manual_copies
? "True" : "False", lf
);
616 for (f
= (ppdcFilter
*)filters
->first();
618 f
= (ppdcFilter
*)filters
->next())
619 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
620 f
->cost
, f
->program
->value
, lf
);
626 case PPDC_DRIVER_LABEL
:
627 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
628 "rastertolabel\"%s", lf
);
631 case PPDC_DRIVER_EPSON
:
632 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
633 "rastertoepson\"%s", lf
);
636 case PPDC_DRIVER_ESCP
:
637 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
638 "commandtoescpx\"%s", lf
);
639 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
640 "rastertoescpx\"%s", lf
);
643 case PPDC_DRIVER_HP
:
644 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
645 "rastertohp\"%s", lf
);
648 case PPDC_DRIVER_PCL
:
649 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
650 "commandtopclx\"%s", lf
);
651 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
652 "rastertopclx\"%s", lf
);
660 for (p
= (ppdcProfile
*)profiles
->first();
662 p
= (ppdcProfile
*)profiles
->next())
664 char density
[255], gamma
[255], profile
[9][255];
666 _cupsStrFormatd(density
, density
+ sizeof(density
), p
->density
, loc
);
667 _cupsStrFormatd(gamma
, gamma
+ sizeof(gamma
), p
->gamma
, loc
);
669 for (int i
= 0; i
< 9; i
++)
670 _cupsStrFormatd(profile
[i
], profile
[i
] + sizeof(profile
[0]),
674 "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
675 "%s\"%s", p
->resolution
->value
, p
->media_type
->value
,
676 density
, gamma
, profile
[0], profile
[1], profile
[2],
677 profile
[3], profile
[4], profile
[5], profile
[6], profile
[7],
684 // Add localizations for additional languages...
685 ppdcString
*locale
; // Locale name
686 ppdcCatalog
*locatalog
; // Message catalog for locale
689 // Write the list of languages...
690 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
692 for (locale
= (ppdcString
*)locales
->first();
694 locale
= (ppdcString
*)locales
->next())
696 // Skip (US) English...
697 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
700 // See if we have a po file for this language...
701 if (!src
->find_po(locale
->value
))
703 // No, see if we can use the base file?
704 locatalog
= new ppdcCatalog(locale
->value
);
706 if (locatalog
->messages
->count
== 0)
708 // No, skip this one...
709 _cupsLangPrintf(stderr
,
710 _("ppdc: No message catalog provided for locale "
711 "%s."), locale
->value
);
715 // Add the base file to the list...
716 src
->po_files
->add(locatalog
);
719 cupsFilePrintf(fp
, " %s", locale
->value
);
722 cupsFilePrintf(fp
, "\"%s", lf
);
725 for (cn
= (ppdcConstraint
*)constraints
->first();
727 cn
= (ppdcConstraint
*)constraints
->next())
729 // First constrain 1 against 2...
730 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
731 !strncmp(cn
->option2
->value
, "*Custom", 7))
732 cupsFilePuts(fp
, "*NonUIConstraints: ");
734 cupsFilePuts(fp
, "*UIConstraints: ");
736 if (cn
->option1
->value
[0] != '*')
737 cupsFilePutChar(fp
, '*');
739 cupsFilePuts(fp
, cn
->option1
->value
);
741 if (cn
->choice1
->value
)
742 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
744 cupsFilePutChar(fp
, ' ');
746 if (cn
->option2
->value
[0] != '*')
747 cupsFilePutChar(fp
, '*');
749 cupsFilePuts(fp
, cn
->option2
->value
);
751 if (cn
->choice2
->value
)
752 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
754 cupsFilePuts(fp
, lf
);
756 // Then constrain 2 against 1...
757 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
758 !strncmp(cn
->option2
->value
, "*Custom", 7))
759 cupsFilePuts(fp
, "*NonUIConstraints: ");
761 cupsFilePuts(fp
, "*UIConstraints: ");
763 if (cn
->option2
->value
[0] != '*')
764 cupsFilePutChar(fp
, '*');
766 cupsFilePuts(fp
, cn
->option2
->value
);
768 if (cn
->choice2
->value
)
769 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
771 cupsFilePutChar(fp
, ' ');
773 if (cn
->option1
->value
[0] != '*')
774 cupsFilePutChar(fp
, '*');
776 cupsFilePuts(fp
, cn
->option1
->value
);
778 if (cn
->choice1
->value
)
779 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
781 cupsFilePuts(fp
, lf
);
784 // PageSize option...
785 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
786 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
787 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
788 default_size
? default_size
->value
: "Letter", lf
);
790 for (m
= (ppdcMediaSize
*)sizes
->first();
792 m
= (ppdcMediaSize
*)sizes
->next())
793 if (m
->size_code
->value
)
795 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
796 m
->name
->value
, catalog
->find_message(m
->text
->value
),
797 m
->size_code
->value
, lf
);
799 if (strchr(m
->size_code
->value
, '\n') ||
800 strchr(m
->size_code
->value
, '\r'))
801 cupsFilePrintf(fp
, "*End%s", lf
);
805 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
806 "/ImagingBBox null>>setpagedevice\"%s",
807 m
->name
->value
, catalog
->find_message(m
->text
->value
),
808 m
->width
, m
->length
, lf
);
810 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
812 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
814 if (strchr(a
->value
->value
, '\n') ||
815 strchr(a
->value
->value
, '\r'))
816 cupsFilePrintf(fp
, "*End%s", lf
);
819 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
821 // PageRegion option...
822 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
823 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
824 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
825 default_size
? default_size
->value
: "Letter", lf
);
827 for (m
= (ppdcMediaSize
*)sizes
->first();
829 m
= (ppdcMediaSize
*)sizes
->next())
830 if (m
->region_code
->value
)
832 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
833 m
->name
->value
, catalog
->find_message(m
->text
->value
),
834 m
->region_code
->value
, lf
);
836 if (strchr(m
->region_code
->value
, '\n') ||
837 strchr(m
->region_code
->value
, '\r'))
838 cupsFilePrintf(fp
, "*End%s", lf
);
842 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
843 "/ImagingBBox null>>setpagedevice\"%s",
844 m
->name
->value
, catalog
->find_message(m
->text
->value
),
845 m
->width
, m
->length
, lf
);
847 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
849 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
851 if (strchr(a
->value
->value
, '\n') ||
852 strchr(a
->value
->value
, '\r'))
853 cupsFilePrintf(fp
, "*End%s", lf
);
856 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
858 // ImageableArea info...
859 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
860 default_size
? default_size
->value
: "Letter", lf
);
862 char left
[255], right
[255], bottom
[255], top
[255];
864 for (m
= (ppdcMediaSize
*)sizes
->first();
866 m
= (ppdcMediaSize
*)sizes
->next())
868 _cupsStrFormatd(left
, left
+ sizeof(left
), m
->left
, loc
);
869 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), m
->bottom
, loc
);
870 _cupsStrFormatd(right
, right
+ sizeof(right
), m
->width
- m
->right
, loc
);
871 _cupsStrFormatd(top
, top
+ sizeof(top
), m
->length
- m
->top
, loc
);
873 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
874 m
->name
->value
, catalog
->find_message(m
->text
->value
),
875 left
, bottom
, right
, top
, lf
);
878 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
880 cupsFilePrintf(fp
, "*?ImageableArea: \"%s\"%s", a
->value
->value
, lf
);
882 if (strchr(a
->value
->value
, '\n') ||
883 strchr(a
->value
->value
, '\r'))
884 cupsFilePrintf(fp
, "*End%s", lf
);
887 // PaperDimension info...
888 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
889 default_size
? default_size
->value
: "Letter", lf
);
891 char width
[255], length
[255];
893 for (m
= (ppdcMediaSize
*)sizes
->first();
895 m
= (ppdcMediaSize
*)sizes
->next())
897 _cupsStrFormatd(width
, width
+ sizeof(width
), m
->width
, loc
);
898 _cupsStrFormatd(length
, length
+ sizeof(length
), m
->length
, loc
);
900 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%s %s\"%s",
901 m
->name
->value
, catalog
->find_message(m
->text
->value
),
905 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
907 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
909 if (strchr(a
->value
->value
, '\n') ||
910 strchr(a
->value
->value
, '\r'))
911 cupsFilePrintf(fp
, "*End%s", lf
);
914 // Custom size support...
915 if (variable_paper_size
)
917 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
918 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
920 _cupsStrFormatd(left
, left
+ sizeof(left
), left_margin
, loc
);
921 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), bottom_margin
, loc
);
922 _cupsStrFormatd(right
, right
+ sizeof(right
), right_margin
, loc
);
923 _cupsStrFormatd(top
, top
+ sizeof(top
), top_margin
, loc
);
925 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%s\"%s", width
, lf
);
926 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%s\"%s", length
, lf
);
927 cupsFilePrintf(fp
, "*HWMargins: %s %s %s %s%s", left
, bottom
, right
, top
,
930 if (custom_size_code
&& custom_size_code
->value
)
932 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
933 custom_size_code
->value
, lf
);
935 if (strchr(custom_size_code
->value
, '\n') ||
936 strchr(custom_size_code
->value
, '\r'))
937 cupsFilePrintf(fp
, "*End%s", lf
);
941 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
942 "/ImagingBBox null>>setpagedevice\"%s", lf
);
944 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
945 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
951 _cupsStrFormatd(width0
, width0
+ sizeof(width0
), min_width
, loc
);
952 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
954 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %s %s%s",
958 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
959 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
965 _cupsStrFormatd(length0
, length0
+ sizeof(length0
), min_length
, loc
);
966 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
968 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %s %s%s",
969 length0
, length
, lf
);
972 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
973 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
974 a
->value
->value
, lf
);
976 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
978 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
979 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
980 a
->value
->value
, lf
);
982 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
984 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
985 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
986 a
->value
->value
, lf
);
988 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
991 // All other options...
992 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
994 if (!g
->options
->count
)
997 if (_cups_strcasecmp(g
->name
->value
, "General"))
998 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
999 catalog
->find_message(g
->text
->value
), lf
);
1001 for (o
= (ppdcOption
*)g
->options
->first();
1003 o
= (ppdcOption
*)g
->options
->next())
1005 if (!o
->choices
->count
)
1008 if (o
->section
== PPDC_SECTION_JCL
)
1010 if (!o
->text
->value
)
1011 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1012 catalog
->find_message(o
->name
->value
));
1014 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1015 catalog
->find_message(o
->text
->value
));
1017 else if (!o
->text
->value
)
1018 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1019 catalog
->find_message(o
->name
->value
));
1021 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1022 catalog
->find_message(o
->text
->value
));
1027 cupsFilePrintf(fp
, "Boolean%s", lf
);
1030 cupsFilePrintf(fp
, "PickOne%s", lf
);
1032 case PPDC_PICKMANY
:
1033 cupsFilePrintf(fp
, "PickMany%s", lf
);
1038 _cupsStrFormatd(order
, order
+ sizeof(order
), o
->order
, loc
);
1040 cupsFilePrintf(fp
, "*OrderDependency: %s ", order
);
1044 cupsFilePrintf(fp
, "AnySetup");
1046 case PPDC_SECTION_DOCUMENT
:
1047 cupsFilePrintf(fp
, "DocumentSetup");
1049 case PPDC_SECTION_EXIT
:
1050 cupsFilePrintf(fp
, "ExitServer");
1052 case PPDC_SECTION_JCL
:
1053 cupsFilePrintf(fp
, "JCLSetup");
1055 case PPDC_SECTION_PAGE
:
1056 cupsFilePrintf(fp
, "PageSetup");
1058 case PPDC_SECTION_PROLOG
:
1059 cupsFilePrintf(fp
, "Prolog");
1063 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
1067 // Use the programmer-supplied default...
1068 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
1069 o
->defchoice
->value
, lf
);
1073 // Make the first choice the default...
1074 c
= (ppdcChoice
*)o
->choices
->first();
1075 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
1079 for (c
= (ppdcChoice
*)o
->choices
->first();
1081 c
= (ppdcChoice
*)o
->choices
->next())
1083 // Write this choice...
1084 if (!c
->text
->value
)
1085 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1086 c
->name
->value
, catalog
->find_message(c
->name
->value
),
1087 c
->code
->value
, lf
);
1089 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1090 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1091 c
->code
->value
, lf
);
1093 // Multi-line commands need a *End line to terminate them.
1094 if (strchr(c
->code
->value
, '\n') ||
1095 strchr(c
->code
->value
, '\r'))
1096 cupsFilePrintf(fp
, "*End%s", lf
);
1099 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1101 if ((a
= find_attr(query
, NULL
)) != NULL
)
1103 cupsFilePrintf(fp
, "*%s: \"%s\"%s", query
, a
->value
->value
, lf
);
1105 if (strchr(a
->value
->value
, '\n') ||
1106 strchr(a
->value
->value
, '\r'))
1107 cupsFilePrintf(fp
, "*End%s", lf
);
1110 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1112 snprintf(custom
, sizeof(custom
), "Custom%s", o
->name
->value
);
1113 if ((a
= find_attr(custom
, "True")) != NULL
)
1115 // Output custom option information...
1116 cupsFilePrintf(fp
, "*%s True: \"%s\"%s", custom
, a
->value
->value
, lf
);
1117 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
1118 cupsFilePrintf(fp
, "*End%s", lf
);
1120 snprintf(custom
, sizeof(custom
), "ParamCustom%s", o
->name
->value
);
1121 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1123 if (strcmp(a
->name
->value
, custom
))
1126 if (!a
->selector
->value
|| !a
->selector
->value
[0])
1127 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
1128 else if (!a
->text
->value
|| !a
->text
->value
[0])
1129 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1130 catalog
->find_message(a
->selector
->value
));
1132 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1133 catalog
->find_message(a
->text
->value
));
1135 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
1140 if (_cups_strcasecmp(g
->name
->value
, "General"))
1141 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1146 // Add localizations for additional languages...
1147 ppdcString
*locale
; // Locale name
1148 ppdcCatalog
*locatalog
; // Message catalog for locale
1151 // Write the translation strings for each language...
1152 for (locale
= (ppdcString
*)locales
->first();
1154 locale
= (ppdcString
*)locales
->next())
1156 // Skip (US) English...
1157 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1160 // Skip missing languages...
1161 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1164 // Do the core stuff first...
1165 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1167 locatalog
->find_message(manufacturer
->value
), lf
);
1169 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1170 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1172 locatalog
->find_message(a
->value
->value
), lf
);
1173 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1174 strlen(manufacturer
->value
)))
1175 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1177 locatalog
->find_message(manufacturer
->value
),
1178 locatalog
->find_message(model_name
->value
), lf
);
1180 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1182 locatalog
->find_message(model_name
->value
), lf
);
1184 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1185 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1187 locatalog
->find_message(a
->value
->value
), lf
);
1188 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1189 strlen(manufacturer
->value
)))
1190 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1192 locatalog
->find_message(manufacturer
->value
),
1193 locatalog
->find_message(model_name
->value
), lf
);
1195 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1197 locatalog
->find_message(model_name
->value
), lf
);
1199 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1200 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1202 locatalog
->find_message(a
->value
->value
), lf
);
1203 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1204 strlen(manufacturer
->value
)))
1205 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1207 locatalog
->find_message(manufacturer
->value
),
1208 locatalog
->find_message(model_name
->value
),
1209 version
->value
, lf
);
1211 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1213 locatalog
->find_message(model_name
->value
),
1214 version
->value
, lf
);
1216 // Then the page sizes...
1217 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1218 locatalog
->find_message("Media Size"), lf
);
1220 for (m
= (ppdcMediaSize
*)sizes
->first();
1222 m
= (ppdcMediaSize
*)sizes
->next())
1224 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1225 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1229 // Next the groups and options...
1230 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1232 if (!g
->options
->count
)
1235 if (_cups_strcasecmp(g
->name
->value
, "General"))
1236 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1238 locatalog
->find_message(g
->text
->value
), lf
);
1240 for (o
= (ppdcOption
*)g
->options
->first();
1242 o
= (ppdcOption
*)g
->options
->next())
1244 if (!o
->choices
->count
)
1247 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1249 locatalog
->find_message(o
->text
->value
?
1251 o
->name
->value
), lf
);
1253 for (c
= (ppdcChoice
*)o
->choices
->first();
1255 c
= (ppdcChoice
*)o
->choices
->next())
1257 // Write this choice...
1258 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1259 o
->name
->value
, c
->name
->value
,
1260 locatalog
->find_message(c
->text
->value
?
1262 c
->name
->value
), lf
);
1267 // Finally the localizable attributes...
1268 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1270 if (!a
->localizable
&&
1271 (!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1272 strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1273 strcmp(a
->name
->value
, "APPrinterPreset") &&
1274 strcmp(a
->name
->value
, "cupsICCProfile") &&
1275 strcmp(a
->name
->value
, "cupsIPPReason") &&
1276 strcmp(a
->name
->value
, "cupsMarkerName") &&
1277 strncmp(a
->name
->value
, "Custom", 6) &&
1278 strncmp(a
->name
->value
, "ParamCustom", 11))
1281 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1282 a
->name
->value
, a
->selector
->value
,
1283 locatalog
->find_message(a
->text
&& a
->text
->value
?
1284 a
->text
->value
: a
->name
->value
),
1285 ((a
->localizable
&& a
->value
->value
[0]) ||
1286 !strcmp(a
->name
->value
, "cupsIPPReason")) ?
1287 locatalog
->find_message(a
->value
->value
) : "",
1293 if (default_font
&& default_font
->value
)
1294 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1296 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1298 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1299 if (!strcmp(fn
->name
->value
, "*"))
1301 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1303 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1304 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1305 bfn
->name
->value
, bfn
->encoding
->value
,
1306 bfn
->version
->value
, bfn
->charset
->value
,
1307 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1310 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1311 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1313 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1315 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1316 (int)((size_t)cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),