]>
git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-driver.cxx
4 // PPD file compiler definitions for the CUPS PPD Compiler.
6 // Copyright 2007-2014 by Apple Inc.
7 // Copyright 2002-2006 by Easy Software Products.
9 // These coded instructions, statements, and computer programs are the
10 // property of Apple Inc. and are protected by Federal copyright
11 // law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 // which should have been included with this file. If this file is
13 // file is missing or damaged, see the license at "http://www.cups.org/".
17 // Include necessary headers...
20 #include "ppdc-private.h"
24 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
27 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
30 ppdcGroup
*g
; // Current group
37 // Bump the use count of any strings we inherit...
39 d
->manufacturer
->retain();
43 d
->default_font
->retain();
45 d
->default_size
->retain();
46 if (d
->custom_size_code
)
47 d
->custom_size_code
->retain();
49 // Copy all of the data from the driver template...
50 copyright
= new ppdcArray(d
->copyright
);
51 manufacturer
= d
->manufacturer
;
57 model_number
= d
->model_number
;
58 manual_copies
= d
->manual_copies
;
59 color_device
= d
->color_device
;
60 throughput
= d
->throughput
;
61 attrs
= new ppdcArray(d
->attrs
);
62 constraints
= new ppdcArray(d
->constraints
);
63 filters
= new ppdcArray(d
->filters
);
64 fonts
= new ppdcArray(d
->fonts
);
65 profiles
= new ppdcArray(d
->profiles
);
66 sizes
= new ppdcArray(d
->sizes
);
67 default_font
= d
->default_font
;
68 default_size
= d
->default_size
;
69 variable_paper_size
= d
->variable_paper_size
;
70 custom_size_code
= d
->custom_size_code
;
71 left_margin
= d
->left_margin
;
72 bottom_margin
= d
->bottom_margin
;
73 right_margin
= d
->right_margin
;
74 top_margin
= d
->top_margin
;
75 max_width
= d
->max_width
;
76 max_length
= d
->max_length
;
77 min_width
= d
->min_width
;
78 min_length
= d
->min_length
;
80 // Then copy the groups manually, since we want separate copies
81 // of the groups and options...
82 groups
= new ppdcArray();
84 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
85 groups
->add(new ppdcGroup(g
));
89 // Zero all of the data in the driver...
90 copyright
= new ppdcArray();
96 type
= PPDC_DRIVER_CUSTOM
;
101 attrs
= new ppdcArray();
102 constraints
= new ppdcArray();
103 fonts
= new ppdcArray();
104 filters
= new ppdcArray();
105 groups
= new ppdcArray();
106 profiles
= new ppdcArray();
107 sizes
= new ppdcArray();
110 variable_paper_size
= 0;
111 custom_size_code
= 0;
125 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
128 ppdcDriver::~ppdcDriver()
132 copyright
->release();
135 manufacturer
->release();
137 model_name
->release();
139 file_name
->release();
141 pc_file_name
->release();
145 default_font
->release();
147 default_size
->release();
148 if (custom_size_code
)
149 custom_size_code
->release();
152 constraints
->release();
162 // 'ppdcDriver::find_attr()' - Find an attribute.
165 ppdcAttr
* // O - Attribute or NULL
166 ppdcDriver::find_attr(const char *k
, // I - Keyword string
167 const char *s
) // I - Spec string
169 ppdcAttr
*a
; // Current attribute
172 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
173 if (!strcmp(a
->name
->value
, k
) &&
174 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
175 (s
&& a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
183 // 'ppdcDriver::find_group()' - Find a group.
186 ppdcGroup
* // O - Matching group or NULL
187 ppdcDriver::find_group(const char *n
) // I - Group name
189 ppdcGroup
*g
; // Current group
192 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
193 if (!_cups_strcasecmp(n
, g
->name
->value
))
201 // 'ppdcDriver::find_option()' - Find an option.
204 ppdcOption
* // O - Matching option or NULL
205 ppdcDriver::find_option(const char *n
) // I - Option name
207 return (find_option_group(n
, (ppdcGroup
**)0));
212 // 'ppdcDriver::find_option_group()' - Find an option and its group.
215 ppdcOption
* // O - Matching option or NULL
216 ppdcDriver::find_option_group(
217 const char *n
, // I - Option name
218 ppdcGroup
**mg
) // O - Matching group or NULL
220 ppdcGroup
*g
; // Current group
221 ppdcOption
*o
; // Current option
224 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
225 for (o
= (ppdcOption
*)g
->options
->first(); o
; o
= (ppdcOption
*)g
->options
->next())
226 if (!_cups_strcasecmp(n
, o
->name
->value
))
235 *mg
= (ppdcGroup
*)0;
242 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
246 ppdcDriver::set_custom_size_code(
247 const char *c
) // I - CustomPageSize code
249 if (custom_size_code
)
250 custom_size_code
->release();
252 custom_size_code
= new ppdcString(c
);
257 // 'ppdcDriver::set_default_font()' - Set the default font name.
261 ppdcDriver::set_default_font(
262 ppdcFont
*f
) // I - Font
265 default_font
->release();
270 default_font
= f
->name
;
278 // 'ppdcDriver::set_default_size()' - Set the default size name.
282 ppdcDriver::set_default_size(
283 ppdcMediaSize
*m
) // I - Media size
286 default_size
->release();
291 default_size
= m
->name
;
299 // 'ppdcDriver::set_file_name()' - Set the full filename.
303 ppdcDriver::set_file_name(const char *f
)// I - Filename
306 file_name
->release();
308 file_name
= new ppdcString(f
);
313 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
317 ppdcDriver::set_manufacturer(
318 const char *m
) // I - Model name
321 manufacturer
->release();
323 manufacturer
= new ppdcString(m
);
328 // 'ppdcDriver::set_model_name()' - Set the model name.
332 ppdcDriver::set_model_name(
333 const char *m
) // I - Model name
336 model_name
->release();
338 model_name
= new ppdcString(m
);
343 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
347 ppdcDriver::set_pc_file_name(
348 const char *f
) // I - Filename
351 pc_file_name
->release();
353 pc_file_name
= new ppdcString(f
);
358 // 'ppdcDriver::set_version()' - Set the version string.
362 ppdcDriver::set_version(const char *v
) // I - Version
367 version
= new ppdcString(v
);
372 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
375 int // O - 0 on success, -1 on failure
376 ppdcDriver::write_ppd_file(
377 cups_file_t
*fp
, // I - PPD file
378 ppdcCatalog
*catalog
, // I - Message catalog
379 ppdcArray
*locales
, // I - Additional languages to add
380 ppdcSource
*src
, // I - Driver source
381 ppdcLineEnding le
) // I - Line endings to use
383 bool delete_cat
; // Delete the catalog when we are done?
384 char query
[42], // Query attribute
385 custom
[42]; // Custom attribute
386 ppdcString
*s
; // Copyright string
387 ppdcGroup
*g
; // Current group
388 ppdcOption
*o
; // Current option
389 ppdcChoice
*c
; // Current choice
390 ppdcMediaSize
*m
; // Current media size
391 ppdcProfile
*p
; // Current color profile
392 ppdcFilter
*f
; // Current filter
393 ppdcFont
*fn
, // Current font
394 *bfn
; // Current base font
395 ppdcConstraint
*cn
; // Current constraint
396 ppdcAttr
*a
; // Current attribute
397 const char *lf
; // Linefeed character to use
400 // If we don't have a message catalog, use an empty (English) one...
403 catalog
= new ppdcCatalog("en");
409 // Figure out the end-of-line string...
410 if (le
== PPDC_LFONLY
)
412 else if (le
== PPDC_CRONLY
)
417 // Write the standard header stuff...
418 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
419 cupsFilePrintf(fp
, "*%%%%%%%% PPD file for %s with CUPS.%s",
420 model_name
->value
, lf
);
422 "*%%%%%%%% Created by the CUPS PPD Compiler " CUPS_SVERSION
424 for (s
= (ppdcString
*)copyright
->first();
426 s
= (ppdcString
*)copyright
->next())
427 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
428 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
429 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
431 a
= find_attr("LanguageVersion", NULL
);
432 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
433 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
435 a
= find_attr("LanguageEncoding", NULL
);
436 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
437 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
439 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
441 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
442 if (!strcmp(a
->name
->value
, "Product"))
447 for (; a
; a
= (ppdcAttr
*)attrs
->next())
448 if (!strcmp(a
->name
->value
, "Product"))
449 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
452 cupsFilePrintf(fp
, "*Product: \"(%s)\"%s", model_name
->value
, lf
);
454 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
455 catalog
->find_message(manufacturer
->value
), lf
);
457 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
458 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
459 catalog
->find_message(a
->value
->value
), lf
);
460 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
461 strlen(manufacturer
->value
)))
462 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
463 catalog
->find_message(manufacturer
->value
),
464 catalog
->find_message(model_name
->value
), lf
);
466 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
467 catalog
->find_message(model_name
->value
), lf
);
469 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
470 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
471 catalog
->find_message(a
->value
->value
), lf
);
472 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
473 strlen(manufacturer
->value
)))
474 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
475 catalog
->find_message(manufacturer
->value
),
476 catalog
->find_message(model_name
->value
), lf
);
478 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
479 catalog
->find_message(model_name
->value
), lf
);
481 if ((a
= find_attr("NickName", NULL
)) != NULL
)
482 cupsFilePrintf(fp
, "*NickName: \"%s\"%s",
483 catalog
->find_message(a
->value
->value
), lf
);
484 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
485 strlen(manufacturer
->value
)))
486 cupsFilePrintf(fp
, "*NickName: \"%s %s, %s\"%s",
487 catalog
->find_message(manufacturer
->value
),
488 catalog
->find_message(model_name
->value
), version
->value
,
491 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
492 catalog
->find_message(model_name
->value
), version
->value
,
495 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
496 if (!strcmp(a
->name
->value
, "PSVersion"))
501 for (; a
; a
= (ppdcAttr
*)attrs
->next())
502 if (!strcmp(a
->name
->value
, "PSVersion"))
503 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
506 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 0\"%s", lf
);
508 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
509 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
511 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
513 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
515 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
516 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
518 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
519 color_device
? "RGB" : "Gray", lf
);
521 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
522 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
524 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
526 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
528 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
529 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
531 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
533 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
534 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
535 else if (type
!= PPDC_DRIVER_PS
)
536 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
538 struct lconv
*loc
= localeconv();
542 // Write driver-defined attributes...
543 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
544 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
546 if (!strcmp(a
->name
->value
, "Product") ||
547 !strcmp(a
->name
->value
, "PSVersion") ||
548 !strcmp(a
->name
->value
, "LanguageLevel") ||
549 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
550 !strcmp(a
->name
->value
, "FileSystem") ||
551 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
552 !strcmp(a
->name
->value
, "TTRasterizer") ||
553 !strcmp(a
->name
->value
, "LanguageVersion") ||
554 !strcmp(a
->name
->value
, "LanguageEncoding") ||
555 !strcmp(a
->name
->value
, "ModelName") ||
556 !strcmp(a
->name
->value
, "NickName") ||
557 !strcmp(a
->name
->value
, "ShortNickName") ||
558 !strcmp(a
->name
->value
, "cupsVersion"))
561 if (a
->name
->value
[0] == '?' &&
562 (find_option(a
->name
->value
+ 1) ||
563 !strcmp(a
->name
->value
, "?ImageableArea") ||
564 !strcmp(a
->name
->value
, "?PageRegion") ||
565 !strcmp(a
->name
->value
, "?PageSize") ||
566 !strcmp(a
->name
->value
, "?PaperDimension")))
569 if (!strncmp(a
->name
->value
, "Custom", 6) &&
570 find_option(a
->name
->value
+ 6))
573 if (!strncmp(a
->name
->value
, "ParamCustom", 11) &&
574 find_option(a
->name
->value
+ 11))
577 if (!a
->selector
->value
|| !a
->selector
->value
[0])
578 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
579 else if (!a
->text
->value
|| !a
->text
->value
[0])
580 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
582 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
585 if (strcmp(a
->value
->value
, "False") &&
586 strcmp(a
->value
->value
, "True") &&
587 strcmp(a
->name
->value
, "1284Modes") &&
588 strcmp(a
->name
->value
, "InkName") &&
589 strcmp(a
->name
->value
, "PageStackOrder") &&
590 strncmp(a
->name
->value
, "ParamCustom", 11) &&
591 strcmp(a
->name
->value
, "Protocols") &&
592 strcmp(a
->name
->value
, "ReferencePunch") &&
593 strncmp(a
->name
->value
, "Default", 7))
595 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
597 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
598 cupsFilePrintf(fp
, "*End%s", lf
);
601 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
605 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
607 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
608 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
610 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
611 CUPS_VERSION_MINOR
, lf
);
612 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
613 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
614 manual_copies
? "True" : "False", lf
);
618 for (f
= (ppdcFilter
*)filters
->first();
620 f
= (ppdcFilter
*)filters
->next())
621 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
622 f
->cost
, f
->program
->value
, lf
);
628 case PPDC_DRIVER_LABEL
:
629 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
630 "rastertolabel\"%s", lf
);
633 case PPDC_DRIVER_EPSON
:
634 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
635 "rastertoepson\"%s", lf
);
638 case PPDC_DRIVER_ESCP
:
639 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
640 "commandtoescpx\"%s", lf
);
641 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
642 "rastertoescpx\"%s", lf
);
645 case PPDC_DRIVER_HP
:
646 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
647 "rastertohp\"%s", lf
);
650 case PPDC_DRIVER_PCL
:
651 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
652 "commandtopclx\"%s", lf
);
653 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
654 "rastertopclx\"%s", lf
);
662 for (p
= (ppdcProfile
*)profiles
->first();
664 p
= (ppdcProfile
*)profiles
->next())
666 char density
[255], gamma
[255], profile
[9][255];
668 _cupsStrFormatd(density
, density
+ sizeof(density
), p
->density
, loc
);
669 _cupsStrFormatd(gamma
, gamma
+ sizeof(gamma
), p
->gamma
, loc
);
671 for (int i
= 0; i
< 9; i
++)
672 _cupsStrFormatd(profile
[i
], profile
[i
] + sizeof(profile
[0]),
676 "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
677 "%s\"%s", p
->resolution
->value
, p
->media_type
->value
,
678 density
, gamma
, profile
[0], profile
[1], profile
[2],
679 profile
[3], profile
[4], profile
[5], profile
[6], profile
[7],
686 // Add localizations for additional languages...
687 ppdcString
*locale
; // Locale name
688 ppdcCatalog
*locatalog
; // Message catalog for locale
691 // Write the list of languages...
692 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
694 for (locale
= (ppdcString
*)locales
->first();
696 locale
= (ppdcString
*)locales
->next())
698 // Skip (US) English...
699 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
702 // See if we have a po file for this language...
703 if (!src
->find_po(locale
->value
))
705 // No, see if we can use the base file?
706 locatalog
= new ppdcCatalog(locale
->value
);
708 if (locatalog
->messages
->count
== 0)
710 // No, skip this one...
711 _cupsLangPrintf(stderr
,
712 _("ppdc: No message catalog provided for locale "
713 "%s."), locale
->value
);
717 // Add the base file to the list...
718 src
->po_files
->add(locatalog
);
721 cupsFilePrintf(fp
, " %s", locale
->value
);
724 cupsFilePrintf(fp
, "\"%s", lf
);
727 for (cn
= (ppdcConstraint
*)constraints
->first();
729 cn
= (ppdcConstraint
*)constraints
->next())
731 // First constrain 1 against 2...
732 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
733 !strncmp(cn
->option2
->value
, "*Custom", 7))
734 cupsFilePuts(fp
, "*NonUIConstraints: ");
736 cupsFilePuts(fp
, "*UIConstraints: ");
738 if (cn
->option1
->value
[0] != '*')
739 cupsFilePutChar(fp
, '*');
741 cupsFilePuts(fp
, cn
->option1
->value
);
743 if (cn
->choice1
->value
)
744 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
746 cupsFilePutChar(fp
, ' ');
748 if (cn
->option2
->value
[0] != '*')
749 cupsFilePutChar(fp
, '*');
751 cupsFilePuts(fp
, cn
->option2
->value
);
753 if (cn
->choice2
->value
)
754 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
756 cupsFilePuts(fp
, lf
);
758 // Then constrain 2 against 1...
759 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
760 !strncmp(cn
->option2
->value
, "*Custom", 7))
761 cupsFilePuts(fp
, "*NonUIConstraints: ");
763 cupsFilePuts(fp
, "*UIConstraints: ");
765 if (cn
->option2
->value
[0] != '*')
766 cupsFilePutChar(fp
, '*');
768 cupsFilePuts(fp
, cn
->option2
->value
);
770 if (cn
->choice2
->value
)
771 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
773 cupsFilePutChar(fp
, ' ');
775 if (cn
->option1
->value
[0] != '*')
776 cupsFilePutChar(fp
, '*');
778 cupsFilePuts(fp
, cn
->option1
->value
);
780 if (cn
->choice1
->value
)
781 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
783 cupsFilePuts(fp
, lf
);
786 // PageSize option...
787 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
788 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
789 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
790 default_size
? default_size
->value
: "Letter", lf
);
792 for (m
= (ppdcMediaSize
*)sizes
->first();
794 m
= (ppdcMediaSize
*)sizes
->next())
795 if (m
->size_code
->value
)
797 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
798 m
->name
->value
, catalog
->find_message(m
->text
->value
),
799 m
->size_code
->value
, lf
);
801 if (strchr(m
->size_code
->value
, '\n') ||
802 strchr(m
->size_code
->value
, '\r'))
803 cupsFilePrintf(fp
, "*End%s", lf
);
807 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
808 "/ImagingBBox null>>setpagedevice\"%s",
809 m
->name
->value
, catalog
->find_message(m
->text
->value
),
810 m
->width
, m
->length
, lf
);
812 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
814 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
816 if (strchr(a
->value
->value
, '\n') ||
817 strchr(a
->value
->value
, '\r'))
818 cupsFilePrintf(fp
, "*End%s", lf
);
821 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
823 // PageRegion option...
824 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
825 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
826 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
827 default_size
? default_size
->value
: "Letter", lf
);
829 for (m
= (ppdcMediaSize
*)sizes
->first();
831 m
= (ppdcMediaSize
*)sizes
->next())
832 if (m
->region_code
->value
)
834 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
835 m
->name
->value
, catalog
->find_message(m
->text
->value
),
836 m
->region_code
->value
, lf
);
838 if (strchr(m
->region_code
->value
, '\n') ||
839 strchr(m
->region_code
->value
, '\r'))
840 cupsFilePrintf(fp
, "*End%s", lf
);
844 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
845 "/ImagingBBox null>>setpagedevice\"%s",
846 m
->name
->value
, catalog
->find_message(m
->text
->value
),
847 m
->width
, m
->length
, lf
);
849 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
851 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
853 if (strchr(a
->value
->value
, '\n') ||
854 strchr(a
->value
->value
, '\r'))
855 cupsFilePrintf(fp
, "*End%s", lf
);
858 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
860 // ImageableArea info...
861 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
862 default_size
? default_size
->value
: "Letter", lf
);
864 char left
[255], right
[255], bottom
[255], top
[255];
866 for (m
= (ppdcMediaSize
*)sizes
->first();
868 m
= (ppdcMediaSize
*)sizes
->next())
870 _cupsStrFormatd(left
, left
+ sizeof(left
), m
->left
, loc
);
871 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), m
->bottom
, loc
);
872 _cupsStrFormatd(right
, right
+ sizeof(right
), m
->width
- m
->right
, loc
);
873 _cupsStrFormatd(top
, top
+ sizeof(top
), m
->length
- m
->top
, loc
);
875 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
876 m
->name
->value
, catalog
->find_message(m
->text
->value
),
877 left
, bottom
, right
, top
, lf
);
880 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
882 cupsFilePrintf(fp
, "*?ImageableArea: \"%s\"%s", a
->value
->value
, lf
);
884 if (strchr(a
->value
->value
, '\n') ||
885 strchr(a
->value
->value
, '\r'))
886 cupsFilePrintf(fp
, "*End%s", lf
);
889 // PaperDimension info...
890 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
891 default_size
? default_size
->value
: "Letter", lf
);
893 char width
[255], length
[255];
895 for (m
= (ppdcMediaSize
*)sizes
->first();
897 m
= (ppdcMediaSize
*)sizes
->next())
899 _cupsStrFormatd(width
, width
+ sizeof(width
), m
->width
, loc
);
900 _cupsStrFormatd(length
, length
+ sizeof(length
), m
->length
, loc
);
902 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%s %s\"%s",
903 m
->name
->value
, catalog
->find_message(m
->text
->value
),
907 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
909 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
911 if (strchr(a
->value
->value
, '\n') ||
912 strchr(a
->value
->value
, '\r'))
913 cupsFilePrintf(fp
, "*End%s", lf
);
916 // Custom size support...
917 if (variable_paper_size
)
919 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
920 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
922 _cupsStrFormatd(left
, left
+ sizeof(left
), left_margin
, loc
);
923 _cupsStrFormatd(bottom
, bottom
+ sizeof(bottom
), bottom_margin
, loc
);
924 _cupsStrFormatd(right
, right
+ sizeof(right
), right_margin
, loc
);
925 _cupsStrFormatd(top
, top
+ sizeof(top
), top_margin
, loc
);
927 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%s\"%s", width
, lf
);
928 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%s\"%s", length
, lf
);
929 cupsFilePrintf(fp
, "*HWMargins: %s %s %s %s%s", left
, bottom
, right
, top
,
932 if (custom_size_code
&& custom_size_code
->value
)
934 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
935 custom_size_code
->value
, lf
);
937 if (strchr(custom_size_code
->value
, '\n') ||
938 strchr(custom_size_code
->value
, '\r'))
939 cupsFilePrintf(fp
, "*End%s", lf
);
943 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
944 "/ImagingBBox null>>setpagedevice\"%s", lf
);
946 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
947 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
953 _cupsStrFormatd(width0
, width0
+ sizeof(width0
), min_width
, loc
);
954 _cupsStrFormatd(width
, width
+ sizeof(width
), max_width
, loc
);
956 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %s %s%s",
960 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
961 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
967 _cupsStrFormatd(length0
, length0
+ sizeof(length0
), min_length
, loc
);
968 _cupsStrFormatd(length
, length
+ sizeof(length
), max_length
, loc
);
970 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %s %s%s",
971 length0
, length
, lf
);
974 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
975 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
976 a
->value
->value
, lf
);
978 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
980 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
981 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
982 a
->value
->value
, lf
);
984 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
986 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
987 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
988 a
->value
->value
, lf
);
990 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
993 // All other options...
994 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
996 if (!g
->options
->count
)
999 if (_cups_strcasecmp(g
->name
->value
, "General"))
1000 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
1001 catalog
->find_message(g
->text
->value
), lf
);
1003 for (o
= (ppdcOption
*)g
->options
->first();
1005 o
= (ppdcOption
*)g
->options
->next())
1007 if (!o
->choices
->count
)
1010 if (o
->section
== PPDC_SECTION_JCL
)
1012 if (!o
->text
->value
)
1013 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1014 catalog
->find_message(o
->name
->value
));
1016 cupsFilePrintf(fp
, "*JCLOpenUI *%s/%s: ", o
->name
->value
,
1017 catalog
->find_message(o
->text
->value
));
1019 else if (!o
->text
->value
)
1020 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1021 catalog
->find_message(o
->name
->value
));
1023 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
1024 catalog
->find_message(o
->text
->value
));
1029 cupsFilePrintf(fp
, "Boolean%s", lf
);
1032 cupsFilePrintf(fp
, "PickOne%s", lf
);
1034 case PPDC_PICKMANY
:
1035 cupsFilePrintf(fp
, "PickMany%s", lf
);
1040 _cupsStrFormatd(order
, order
+ sizeof(order
), o
->order
, loc
);
1042 cupsFilePrintf(fp
, "*OrderDependency: %s ", order
);
1046 cupsFilePrintf(fp
, "AnySetup");
1048 case PPDC_SECTION_DOCUMENT
:
1049 cupsFilePrintf(fp
, "DocumentSetup");
1051 case PPDC_SECTION_EXIT
:
1052 cupsFilePrintf(fp
, "ExitServer");
1054 case PPDC_SECTION_JCL
:
1055 cupsFilePrintf(fp
, "JCLSetup");
1057 case PPDC_SECTION_PAGE
:
1058 cupsFilePrintf(fp
, "PageSetup");
1060 case PPDC_SECTION_PROLOG
:
1061 cupsFilePrintf(fp
, "Prolog");
1065 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
1069 // Use the programmer-supplied default...
1070 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
1071 o
->defchoice
->value
, lf
);
1075 // Make the first choice the default...
1076 c
= (ppdcChoice
*)o
->choices
->first();
1077 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
1081 for (c
= (ppdcChoice
*)o
->choices
->first();
1083 c
= (ppdcChoice
*)o
->choices
->next())
1085 // Write this choice...
1086 if (!c
->text
->value
)
1087 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1088 c
->name
->value
, catalog
->find_message(c
->name
->value
),
1089 c
->code
->value
, lf
);
1091 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1092 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1093 c
->code
->value
, lf
);
1095 // Multi-line commands need a *End line to terminate them.
1096 if (strchr(c
->code
->value
, '\n') ||
1097 strchr(c
->code
->value
, '\r'))
1098 cupsFilePrintf(fp
, "*End%s", lf
);
1101 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1103 if ((a
= find_attr(query
, NULL
)) != NULL
)
1105 cupsFilePrintf(fp
, "*%s: \"%s\"%s", query
, a
->value
->value
, lf
);
1107 if (strchr(a
->value
->value
, '\n') ||
1108 strchr(a
->value
->value
, '\r'))
1109 cupsFilePrintf(fp
, "*End%s", lf
);
1112 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1114 snprintf(custom
, sizeof(custom
), "Custom%s", o
->name
->value
);
1115 if ((a
= find_attr(custom
, "True")) != NULL
)
1117 // Output custom option information...
1118 cupsFilePrintf(fp
, "*%s True: \"%s\"%s", custom
, a
->value
->value
, lf
);
1119 if (strchr(a
->value
->value
, '\n') || strchr(a
->value
->value
, '\r'))
1120 cupsFilePrintf(fp
, "*End%s", lf
);
1122 snprintf(custom
, sizeof(custom
), "ParamCustom%s", o
->name
->value
);
1123 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1125 if (strcmp(a
->name
->value
, custom
))
1128 if (!a
->selector
->value
|| !a
->selector
->value
[0])
1129 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
1130 else if (!a
->text
->value
|| !a
->text
->value
[0])
1131 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1132 catalog
->find_message(a
->selector
->value
));
1134 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
1135 catalog
->find_message(a
->text
->value
));
1137 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
1142 if (_cups_strcasecmp(g
->name
->value
, "General"))
1143 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1148 // Add localizations for additional languages...
1149 ppdcString
*locale
; // Locale name
1150 ppdcCatalog
*locatalog
; // Message catalog for locale
1153 // Write the translation strings for each language...
1154 for (locale
= (ppdcString
*)locales
->first();
1156 locale
= (ppdcString
*)locales
->next())
1158 // Skip (US) English...
1159 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1162 // Skip missing languages...
1163 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1166 // Do the core stuff first...
1167 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1169 locatalog
->find_message(manufacturer
->value
), lf
);
1171 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1172 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1174 locatalog
->find_message(a
->value
->value
), lf
);
1175 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1176 strlen(manufacturer
->value
)))
1177 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1179 locatalog
->find_message(manufacturer
->value
),
1180 locatalog
->find_message(model_name
->value
), lf
);
1182 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1184 locatalog
->find_message(model_name
->value
), lf
);
1186 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1187 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1189 locatalog
->find_message(a
->value
->value
), lf
);
1190 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1191 strlen(manufacturer
->value
)))
1192 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1194 locatalog
->find_message(manufacturer
->value
),
1195 locatalog
->find_message(model_name
->value
), lf
);
1197 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1199 locatalog
->find_message(model_name
->value
), lf
);
1201 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1202 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1204 locatalog
->find_message(a
->value
->value
), lf
);
1205 else if (_cups_strncasecmp(model_name
->value
, manufacturer
->value
,
1206 strlen(manufacturer
->value
)))
1207 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1209 locatalog
->find_message(manufacturer
->value
),
1210 locatalog
->find_message(model_name
->value
),
1211 version
->value
, lf
);
1213 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1215 locatalog
->find_message(model_name
->value
),
1216 version
->value
, lf
);
1218 // Then the page sizes...
1219 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1220 locatalog
->find_message("Media Size"), lf
);
1222 for (m
= (ppdcMediaSize
*)sizes
->first();
1224 m
= (ppdcMediaSize
*)sizes
->next())
1226 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1227 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1231 // Next the groups and options...
1232 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1234 if (!g
->options
->count
)
1237 if (_cups_strcasecmp(g
->name
->value
, "General"))
1238 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1240 locatalog
->find_message(g
->text
->value
), lf
);
1242 for (o
= (ppdcOption
*)g
->options
->first();
1244 o
= (ppdcOption
*)g
->options
->next())
1246 if (!o
->choices
->count
)
1249 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1251 locatalog
->find_message(o
->text
->value
?
1253 o
->name
->value
), lf
);
1255 for (c
= (ppdcChoice
*)o
->choices
->first();
1257 c
= (ppdcChoice
*)o
->choices
->next())
1259 // Write this choice...
1260 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1261 o
->name
->value
, c
->name
->value
,
1262 locatalog
->find_message(c
->text
->value
?
1264 c
->name
->value
), lf
);
1269 // Finally the localizable attributes...
1270 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1272 if (!a
->localizable
&&
1273 (!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1274 strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1275 strcmp(a
->name
->value
, "APPrinterPreset") &&
1276 strcmp(a
->name
->value
, "cupsICCProfile") &&
1277 strcmp(a
->name
->value
, "cupsIPPReason") &&
1278 strcmp(a
->name
->value
, "cupsMarkerName") &&
1279 strncmp(a
->name
->value
, "Custom", 6) &&
1280 strncmp(a
->name
->value
, "ParamCustom", 11))
1283 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1284 a
->name
->value
, a
->selector
->value
,
1285 locatalog
->find_message(a
->text
&& a
->text
->value
?
1286 a
->text
->value
: a
->name
->value
),
1287 ((a
->localizable
&& a
->value
->value
[0]) ||
1288 !strcmp(a
->name
->value
, "cupsIPPReason")) ?
1289 locatalog
->find_message(a
->value
->value
) : "",
1295 if (default_font
&& default_font
->value
)
1296 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1298 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1300 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1301 if (!strcmp(fn
->name
->value
, "*"))
1303 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1305 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1306 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1307 bfn
->name
->value
, bfn
->encoding
->value
,
1308 bfn
->version
->value
, bfn
->charset
->value
,
1309 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1312 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1313 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1315 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1317 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1318 (int)((size_t)cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),