]>
git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-driver.cxx
4 // PPD file compiler definitions for the CUPS PPD Compiler.
6 // Copyright 2007-2009 by Apple Inc.
7 // Copyright 2002-2006 by Easy Software Products.
9 // These coded instructions, statements, and computer programs are the
10 // property of Apple Inc. and are protected by Federal copyright
11 // law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 // which should have been included with this file. If this file is
13 // file is missing or damaged, see the license at "http://www.cups.org/".
17 // ppdcDriver::ppdcDriver() - Create a new printer driver.
18 // ppdcDriver::~ppdcDriver() - Destroy a printer driver.
19 // ppdcDriver::find_attr() - Find an attribute.
20 // ppdcDriver::find_group() - Find a group.
21 // ppdcDriver::find_option() - Find an option.
22 // ppdcDriver::set_default_size() - Set the default size name.
23 // ppdcDriver::set_file_name() - Set the full filename.
24 // ppdcDriver::set_manufacturer() - Set the manufacturer name.
25 // ppdcDriver::set_model_name() - Set the model name.
26 // ppdcDriver::set_pc_file_name() - Set the PC filename.
27 // ppdcDriver::set_version() - Set the version string.
28 // ppdcDriver::write_ppd_file() - Write a PPD file...
32 // Include necessary headers...
36 #include <cups/globals.h>
40 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
43 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
45 ppdcGroup
*g
; // Current group
50 // Bump the use count of any strings we inherit...
52 d
->manufacturer
->retain();
56 d
->default_font
->retain();
58 d
->default_size
->retain();
59 if (d
->custom_size_code
)
60 d
->custom_size_code
->retain();
62 // Copy all of the data from the driver template...
63 copyright
= new ppdcArray(d
->copyright
);
64 manufacturer
= d
->manufacturer
;
70 model_number
= d
->model_number
;
71 manual_copies
= d
->manual_copies
;
72 color_device
= d
->color_device
;
73 throughput
= d
->throughput
;
74 attrs
= new ppdcArray(d
->attrs
);
75 constraints
= new ppdcArray(d
->constraints
);
76 filters
= new ppdcArray(d
->filters
);
77 fonts
= new ppdcArray(d
->fonts
);
78 profiles
= new ppdcArray(d
->profiles
);
79 sizes
= new ppdcArray(d
->sizes
);
80 default_font
= d
->default_font
;
81 default_size
= d
->default_size
;
82 variable_paper_size
= d
->variable_paper_size
;
83 custom_size_code
= d
->custom_size_code
;
84 left_margin
= d
->left_margin
;
85 bottom_margin
= d
->bottom_margin
;
86 right_margin
= d
->right_margin
;
87 top_margin
= d
->top_margin
;
88 max_width
= d
->max_width
;
89 max_length
= d
->max_length
;
90 min_width
= d
->min_width
;
91 min_length
= d
->min_length
;
93 // Then copy the groups manually, since we want separate copies
94 // of the groups and options...
95 groups
= new ppdcArray();
97 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
98 groups
->add(new ppdcGroup(g
));
102 // Zero all of the data in the driver...
103 copyright
= new ppdcArray();
109 type
= PPDC_DRIVER_CUSTOM
;
114 attrs
= new ppdcArray();
115 constraints
= new ppdcArray();
116 fonts
= new ppdcArray();
117 filters
= new ppdcArray();
118 groups
= new ppdcArray();
119 profiles
= new ppdcArray();
120 sizes
= new ppdcArray();
123 variable_paper_size
= 0;
124 custom_size_code
= 0;
138 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
141 ppdcDriver::~ppdcDriver()
143 copyright
->release();
146 manufacturer
->release();
148 model_name
->release();
150 file_name
->release();
152 pc_file_name
->release();
156 default_font
->release();
158 default_size
->release();
159 if (custom_size_code
)
160 custom_size_code
->release();
163 constraints
->release();
173 // 'ppdcDriver::find_attr()' - Find an attribute.
176 ppdcAttr
* // O - Attribute or NULL
177 ppdcDriver::find_attr(const char *k
, // I - Keyword string
178 const char *s
) // I - Spec string
180 ppdcAttr
*a
; // Current attribute
183 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
184 if (!strcmp(a
->name
->value
, k
) &&
185 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
186 (!s
&& !a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
194 // 'ppdcDriver::find_group()' - Find a group.
197 ppdcGroup
* // O - Matching group or NULL
198 ppdcDriver::find_group(const char *n
) // I - Group name
200 ppdcGroup
*g
; // Current group
203 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
204 if (!strcasecmp(n
, g
->name
->value
))
212 // 'ppdcDriver::find_option()' - Find an option.
215 ppdcOption
* // O - Matching option or NULL
216 ppdcDriver::find_option(const char *n
) // I - Option name
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 (!strcasecmp(n
, o
->name
->value
))
232 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
236 ppdcDriver::set_custom_size_code(
237 const char *c
) // I - CustomPageSize code
239 if (custom_size_code
)
240 custom_size_code
->release();
242 custom_size_code
= new ppdcString(c
);
247 // 'ppdcDriver::set_default_font()' - Set the default font name.
251 ppdcDriver::set_default_font(
252 ppdcFont
*f
) // I - Font
255 default_font
->release();
260 default_font
= f
->name
;
268 // 'ppdcDriver::set_default_size()' - Set the default size name.
272 ppdcDriver::set_default_size(
273 ppdcMediaSize
*m
) // I - Media size
276 default_size
->release();
281 default_size
= m
->name
;
289 // 'ppdcDriver::set_file_name()' - Set the full filename.
293 ppdcDriver::set_file_name(const char *f
)// I - Filename
296 file_name
->release();
298 file_name
= new ppdcString(f
);
303 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
307 ppdcDriver::set_manufacturer(
308 const char *m
) // I - Model name
311 manufacturer
->release();
313 manufacturer
= new ppdcString(m
);
318 // 'ppdcDriver::set_model_name()' - Set the model name.
322 ppdcDriver::set_model_name(
323 const char *m
) // I - Model name
326 model_name
->release();
328 model_name
= new ppdcString(m
);
333 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
337 ppdcDriver::set_pc_file_name(
338 const char *f
) // I - Filename
341 pc_file_name
->release();
343 pc_file_name
= new ppdcString(f
);
348 // 'ppdcDriver::set_version()' - Set the version string.
352 ppdcDriver::set_version(const char *v
) // I - Version
357 version
= new ppdcString(v
);
362 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
365 int // O - 0 on success, -1 on failure
366 ppdcDriver::write_ppd_file(
367 cups_file_t
*fp
, // I - PPD file
368 ppdcCatalog
*catalog
, // I - Message catalog
369 ppdcArray
*locales
, // I - Additional languages to add
370 ppdcSource
*src
, // I - Driver source
371 ppdcLineEnding le
) // I - Line endings to use
373 bool delete_cat
; // Delete the catalog when we are done?
374 char query
[42]; // Query attribute
375 ppdcString
*s
; // Copyright string
376 ppdcGroup
*g
; // Current group
377 ppdcOption
*o
; // Current option
378 ppdcChoice
*c
; // Current choice
379 ppdcMediaSize
*m
; // Current media size
380 ppdcProfile
*p
; // Current color profile
381 ppdcFilter
*f
; // Current filter
382 ppdcFont
*fn
, // Current font
383 *bfn
; // Current base font
384 ppdcConstraint
*cn
; // Current constraint
385 ppdcAttr
*a
; // Current attribute
386 const char *lf
; // Linefeed character to use
389 // If we don't have a message catalog, use an empty (English) one...
392 catalog
= new ppdcCatalog("en");
398 // Figure out the end-of-line string...
399 if (le
== PPDC_LFONLY
)
401 else if (le
== PPDC_CRONLY
)
406 // Write the standard header stuff...
407 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
408 cupsFilePrintf(fp
, "*%% PPD file for %s with CUPS.%s", model_name
->value
, lf
);
410 "*%% Created by the CUPS PPD Compiler " CUPS_SVERSION
".%s",
412 for (s
= (ppdcString
*)copyright
->first();
414 s
= (ppdcString
*)copyright
->next())
415 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
416 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
417 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
419 a
= find_attr("LanguageVersion", NULL
);
420 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
421 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
423 a
= find_attr("LanguageEncoding", NULL
);
424 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
425 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
427 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
429 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
430 if (!strcmp(a
->name
->value
, "Product"))
435 for (; a
; a
= (ppdcAttr
*)attrs
->next())
436 if (!strcmp(a
->name
->value
, "Product"))
437 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
440 cupsFilePrintf(fp
, "*Product: \"(%s)\"%s", model_name
->value
, lf
);
442 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
443 catalog
->find_message(manufacturer
->value
), lf
);
445 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
446 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
447 catalog
->find_message(a
->value
->value
), lf
);
448 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
449 strlen(manufacturer
->value
)))
450 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
451 catalog
->find_message(manufacturer
->value
),
452 catalog
->find_message(model_name
->value
), lf
);
454 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
455 catalog
->find_message(model_name
->value
), lf
);
457 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
458 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
459 catalog
->find_message(a
->value
->value
), lf
);
460 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
461 strlen(manufacturer
->value
)))
462 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
463 catalog
->find_message(manufacturer
->value
),
464 catalog
->find_message(model_name
->value
), lf
);
466 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
467 catalog
->find_message(model_name
->value
), lf
);
469 if ((a
= find_attr("NickName", NULL
)) != NULL
)
470 cupsFilePrintf(fp
, "*NickName: \"%s\"%s",
471 catalog
->find_message(a
->value
->value
), lf
);
472 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
473 strlen(manufacturer
->value
)))
474 cupsFilePrintf(fp
, "*NickName: \"%s %s, %s\"%s",
475 catalog
->find_message(manufacturer
->value
),
476 catalog
->find_message(model_name
->value
), version
->value
,
479 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
480 catalog
->find_message(model_name
->value
), version
->value
,
483 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
484 if (!strcmp(a
->name
->value
, "PSVersion"))
489 for (; a
; a
= (ppdcAttr
*)attrs
->next())
490 if (!strcmp(a
->name
->value
, "PSVersion"))
491 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
494 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 0\"%s", lf
);
496 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
497 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
499 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
501 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
503 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
504 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
506 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
507 color_device
? "RGB" : "Gray", lf
);
509 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
510 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
512 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
514 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
516 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
517 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
519 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
521 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
522 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
523 else if (type
!= PPDC_DRIVER_PS
)
524 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
528 // Write driver-defined attributes...
529 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
530 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
532 if (!strcmp(a
->name
->value
, "Product") ||
533 !strcmp(a
->name
->value
, "PSVersion") ||
534 !strcmp(a
->name
->value
, "LanguageLevel") ||
535 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
536 !strcmp(a
->name
->value
, "FileSystem") ||
537 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
538 !strcmp(a
->name
->value
, "TTRasterizer") ||
539 !strcmp(a
->name
->value
, "LanguageVersion") ||
540 !strcmp(a
->name
->value
, "LanguageEncoding") ||
541 !strcmp(a
->name
->value
, "ModelName") ||
542 !strcmp(a
->name
->value
, "NickName") ||
543 !strcmp(a
->name
->value
, "ShortNickName") ||
544 !strcmp(a
->name
->value
, "cupsVersion"))
547 if (a
->name
->value
[0] == '?' &&
548 (find_option(a
->name
->value
+ 1) ||
549 !strcmp(a
->name
->value
, "?ImageableArea") ||
550 !strcmp(a
->name
->value
, "?PageRegion") ||
551 !strcmp(a
->name
->value
, "?PageSize") ||
552 !strcmp(a
->name
->value
, "?PaperDimension")))
555 if (!a
->selector
->value
|| !a
->selector
->value
[0])
556 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
557 else if (!a
->text
->value
|| !a
->text
->value
[0])
558 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
560 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
563 if (strcmp(a
->value
->value
, "False") &&
564 strcmp(a
->value
->value
, "True") &&
565 strcmp(a
->name
->value
, "1284Modes") &&
566 strcmp(a
->name
->value
, "InkName") &&
567 strcmp(a
->name
->value
, "PageStackOrder") &&
568 strncmp(a
->name
->value
, "ParamCustom", 11) &&
569 strcmp(a
->name
->value
, "Protocols") &&
570 strcmp(a
->name
->value
, "ReferencePunch") &&
571 strncmp(a
->name
->value
, "Default", 7))
573 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
575 if (strchr(a
->value
->value
, '\n'))
576 cupsFilePrintf(fp
, "*End%s", lf
);
579 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
583 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
585 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
586 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
588 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
589 CUPS_VERSION_MINOR
, lf
);
590 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
591 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
592 manual_copies
? "True" : "False", lf
);
596 for (f
= (ppdcFilter
*)filters
->first();
598 f
= (ppdcFilter
*)filters
->next())
599 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
600 f
->cost
, f
->program
->value
, lf
);
606 case PPDC_DRIVER_LABEL
:
607 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
608 "rastertolabel\"%s", lf
);
611 case PPDC_DRIVER_EPSON
:
612 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
613 "rastertoepson\"%s", lf
);
616 case PPDC_DRIVER_ESCP
:
617 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
618 "commandtoescpx\"%s", lf
);
619 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
620 "rastertoescpx\"%s", lf
);
623 case PPDC_DRIVER_HP
:
624 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
625 "rastertohp\"%s", lf
);
628 case PPDC_DRIVER_PCL
:
629 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
630 "commandtopclx\"%s", lf
);
631 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
632 "rastertopclx\"%s", lf
);
640 for (p
= (ppdcProfile
*)profiles
->first();
642 p
= (ppdcProfile
*)profiles
->next())
644 "*cupsColorProfile %s/%s: \"%.3f %.3f %.3f %.3f %.3f %.3f "
645 "%.3f %.3f %.3f %.3f %.3f\"%s",
646 p
->resolution
->value
, p
->media_type
->value
,
647 p
->density
, p
->gamma
,
648 p
->profile
[0], p
->profile
[1],
649 p
->profile
[2], p
->profile
[3],
650 p
->profile
[4], p
->profile
[5],
651 p
->profile
[6], p
->profile
[7],
657 // Add localizations for additional languages...
658 ppdcString
*locale
; // Locale name
659 ppdcCatalog
*locatalog
; // Message catalog for locale
662 // Write the list of languages...
663 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
665 for (locale
= (ppdcString
*)locales
->first();
667 locale
= (ppdcString
*)locales
->next())
669 // Skip (US) English...
670 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
673 // See if we have a po file for this language...
674 if (!src
->find_po(locale
->value
))
676 // No, see if we can use the base file?
677 locatalog
= new ppdcCatalog(locale
->value
);
679 if (locatalog
->messages
->count
== 0)
681 // No, skip this one...
682 _cupsLangPrintf(stderr
,
683 _("ppdc: No message catalog provided for locale "
684 "%s!\n"), locale
->value
);
688 // Add the base file to the list...
689 src
->po_files
->add(locatalog
);
692 cupsFilePrintf(fp
, " %s", locale
->value
);
695 cupsFilePrintf(fp
, "\"%s", lf
);
698 for (cn
= (ppdcConstraint
*)constraints
->first();
700 cn
= (ppdcConstraint
*)constraints
->next())
702 // First constrain 1 against 2...
703 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
704 !strncmp(cn
->option2
->value
, "*Custom", 7))
705 cupsFilePuts(fp
, "*NonUIConstraints: ");
707 cupsFilePuts(fp
, "*UIConstraints: ");
709 if (cn
->option1
->value
[0] != '*')
710 cupsFilePutChar(fp
, '*');
712 cupsFilePuts(fp
, cn
->option1
->value
);
714 if (cn
->choice1
->value
)
715 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
717 cupsFilePutChar(fp
, ' ');
719 if (cn
->option2
->value
[0] != '*')
720 cupsFilePutChar(fp
, '*');
722 cupsFilePuts(fp
, cn
->option2
->value
);
724 if (cn
->choice2
->value
)
725 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
727 cupsFilePuts(fp
, lf
);
729 // Then constrain 2 against 1...
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
->option2
->value
[0] != '*')
737 cupsFilePutChar(fp
, '*');
739 cupsFilePuts(fp
, cn
->option2
->value
);
741 if (cn
->choice2
->value
)
742 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
744 cupsFilePutChar(fp
, ' ');
746 if (cn
->option1
->value
[0] != '*')
747 cupsFilePutChar(fp
, '*');
749 cupsFilePuts(fp
, cn
->option1
->value
);
751 if (cn
->choice1
->value
)
752 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
754 cupsFilePuts(fp
, lf
);
757 // PageSize option...
758 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
759 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
760 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
761 default_size
? default_size
->value
: "Letter", lf
);
763 for (m
= (ppdcMediaSize
*)sizes
->first();
765 m
= (ppdcMediaSize
*)sizes
->next())
766 if (m
->size_code
->value
)
768 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
769 m
->name
->value
, catalog
->find_message(m
->text
->value
),
770 m
->size_code
->value
, lf
);
772 if (strchr(m
->size_code
->value
, '\n') ||
773 strchr(m
->size_code
->value
, '\r'))
774 cupsFilePrintf(fp
, "*End%s", lf
);
778 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
779 "/ImagingBBox null>>setpagedevice\"%s",
780 m
->name
->value
, catalog
->find_message(m
->text
->value
),
781 m
->width
, m
->length
, lf
);
783 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
785 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
787 if (strchr(a
->value
->value
, '\n') ||
788 strchr(a
->value
->value
, '\r'))
789 cupsFilePrintf(fp
, "*End%s", lf
);
792 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
794 // PageRegion option...
795 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
796 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
797 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
798 default_size
? default_size
->value
: "Letter", lf
);
800 for (m
= (ppdcMediaSize
*)sizes
->first();
802 m
= (ppdcMediaSize
*)sizes
->next())
803 if (m
->region_code
->value
)
805 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
806 m
->name
->value
, catalog
->find_message(m
->text
->value
),
807 m
->region_code
->value
, lf
);
809 if (strchr(m
->region_code
->value
, '\n') ||
810 strchr(m
->region_code
->value
, '\r'))
811 cupsFilePrintf(fp
, "*End%s", lf
);
815 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
816 "/ImagingBBox null>>setpagedevice\"%s",
817 m
->name
->value
, catalog
->find_message(m
->text
->value
),
818 m
->width
, m
->length
, lf
);
820 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
822 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
824 if (strchr(a
->value
->value
, '\n') ||
825 strchr(a
->value
->value
, '\r'))
826 cupsFilePrintf(fp
, "*End%s", lf
);
829 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
831 // ImageableArea info...
832 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
833 default_size
? default_size
->value
: "Letter", lf
);
835 for (m
= (ppdcMediaSize
*)sizes
->first();
837 m
= (ppdcMediaSize
*)sizes
->next())
838 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%.2f %.2f %.2f %.2f\"%s",
839 m
->name
->value
, catalog
->find_message(m
->text
->value
),
840 m
->left
, m
->bottom
, m
->width
- m
->right
, m
->length
- m
->top
,
843 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
845 cupsFilePrintf(fp
, "*?ImageableArea: \"%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 // PaperDimension info...
853 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
854 default_size
? default_size
->value
: "Letter", lf
);
856 for (m
= (ppdcMediaSize
*)sizes
->first();
858 m
= (ppdcMediaSize
*)sizes
->next())
859 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%.2f %.2f\"%s",
860 m
->name
->value
, catalog
->find_message(m
->text
->value
),
861 m
->width
, m
->length
, lf
);
863 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
865 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
867 if (strchr(a
->value
->value
, '\n') ||
868 strchr(a
->value
->value
, '\r'))
869 cupsFilePrintf(fp
, "*End%s", lf
);
872 // Custom size support...
873 if (variable_paper_size
)
875 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%.2f\"%s", max_width
, lf
);
876 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%.2f\"%s", max_length
, lf
);
877 cupsFilePrintf(fp
, "*HWMargins: %.2f %.2f %.2f %.2f\n",
878 left_margin
, bottom_margin
, right_margin
, top_margin
);
880 if (custom_size_code
&& custom_size_code
->value
)
882 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
883 custom_size_code
->value
, lf
);
885 if (strchr(custom_size_code
->value
, '\n') ||
886 strchr(custom_size_code
->value
, '\r'))
887 cupsFilePrintf(fp
, "*End%s", lf
);
891 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
892 "/ImagingBBox null>>setpagedevice\"%s", lf
);
894 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
895 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
898 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %.2f %.2f%s",
899 min_width
, max_width
, lf
);
901 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
902 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
905 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %.2f %.2f%s",
906 min_length
, max_length
, lf
);
908 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
909 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
910 a
->value
->value
, lf
);
912 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
914 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
915 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
916 a
->value
->value
, lf
);
918 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
920 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
921 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
922 a
->value
->value
, lf
);
924 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
927 if (type
!= PPDC_DRIVER_PS
&& !find_attr("RequiresPageRegion", NULL
))
928 cupsFilePrintf(fp
, "*RequiresPageRegion All: True%s", lf
);
930 // All other options...
931 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
933 if (!g
->options
->count
)
936 if (strcasecmp(g
->name
->value
, "General"))
937 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
938 catalog
->find_message(g
->text
->value
), lf
);
940 for (o
= (ppdcOption
*)g
->options
->first();
942 o
= (ppdcOption
*)g
->options
->next())
944 if (!o
->choices
->count
)
947 if (!o
->text
->value
|| !strcmp(o
->name
->value
, o
->text
->value
))
948 cupsFilePrintf(fp
, "*OpenUI *%s: ", o
->name
->value
,
949 catalog
->find_message(o
->name
->value
));
951 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
952 catalog
->find_message(o
->text
->value
));
957 cupsFilePrintf(fp
, "Boolean%s", lf
);
960 cupsFilePrintf(fp
, "PickOne%s", lf
);
963 cupsFilePrintf(fp
, "PickMany%s", lf
);
967 cupsFilePrintf(fp
, "*OrderDependency: %.1f ", o
->order
);
971 cupsFilePrintf(fp
, "AnySetup");
973 case PPDC_SECTION_DOCUMENT
:
974 cupsFilePrintf(fp
, "DocumentSetup");
976 case PPDC_SECTION_EXIT
:
977 cupsFilePrintf(fp
, "ExitServer");
979 case PPDC_SECTION_JCL
:
980 cupsFilePrintf(fp
, "JCLSetup");
982 case PPDC_SECTION_PAGE
:
983 cupsFilePrintf(fp
, "PageSetup");
985 case PPDC_SECTION_PROLOG
:
986 cupsFilePrintf(fp
, "Prolog");
990 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
994 // Use the programmer-supplied default...
995 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
996 o
->defchoice
->value
, lf
);
1000 // Make the first choice the default...
1001 c
= (ppdcChoice
*)o
->choices
->first();
1002 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
1006 for (c
= (ppdcChoice
*)o
->choices
->first();
1008 c
= (ppdcChoice
*)o
->choices
->next())
1010 // Write this choice...
1011 if (!c
->text
->value
|| !strcmp(c
->name
->value
, c
->text
->value
))
1012 cupsFilePrintf(fp
, "*%s %s: \"%s\"%s", o
->name
->value
,
1013 catalog
->find_message(c
->name
->value
),
1014 c
->code
->value
, lf
);
1016 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
1017 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1018 c
->code
->value
, lf
);
1020 // Multi-line commands need a *End line to terminate them.
1021 if (strchr(c
->code
->value
, '\n') ||
1022 strchr(c
->code
->value
, '\r'))
1023 cupsFilePrintf(fp
, "*End%s", lf
);
1026 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1028 if ((a
= find_attr(query
, NULL
)) != NULL
)
1030 cupsFilePrintf(fp
, "*%s: \"%s\"\n", query
, a
->value
->value
);
1032 if (strchr(a
->value
->value
, '\n') ||
1033 strchr(a
->value
->value
, '\r'))
1034 cupsFilePrintf(fp
, "*End%s", lf
);
1037 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1040 if (strcasecmp(g
->name
->value
, "General"))
1041 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1046 // Add localizations for additional languages...
1047 ppdcString
*locale
; // Locale name
1048 ppdcCatalog
*locatalog
; // Message catalog for locale
1051 // Write the translation strings for each language...
1052 for (locale
= (ppdcString
*)locales
->first();
1054 locale
= (ppdcString
*)locales
->next())
1056 // Skip (US) English...
1057 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1060 // Skip missing languages...
1061 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1064 // Do the core stuff first...
1065 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1067 locatalog
->find_message(manufacturer
->value
), lf
);
1069 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1070 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1072 locatalog
->find_message(a
->value
->value
), lf
);
1073 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1074 strlen(manufacturer
->value
)))
1075 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1077 locatalog
->find_message(manufacturer
->value
),
1078 locatalog
->find_message(model_name
->value
), lf
);
1080 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1082 locatalog
->find_message(model_name
->value
), lf
);
1084 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1085 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1087 locatalog
->find_message(a
->value
->value
), lf
);
1088 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1089 strlen(manufacturer
->value
)))
1090 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1092 locatalog
->find_message(manufacturer
->value
),
1093 locatalog
->find_message(model_name
->value
), lf
);
1095 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1097 locatalog
->find_message(model_name
->value
), lf
);
1099 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1100 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1102 locatalog
->find_message(a
->value
->value
), lf
);
1103 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1104 strlen(manufacturer
->value
)))
1105 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1107 locatalog
->find_message(manufacturer
->value
),
1108 locatalog
->find_message(model_name
->value
),
1109 version
->value
, lf
);
1111 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1113 locatalog
->find_message(model_name
->value
),
1114 version
->value
, lf
);
1116 // Then the page sizes...
1117 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1118 locatalog
->find_message("Media Size"), lf
);
1120 for (m
= (ppdcMediaSize
*)sizes
->first();
1122 m
= (ppdcMediaSize
*)sizes
->next())
1124 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1125 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1129 // Next the groups and options...
1130 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1132 if (!g
->options
->count
)
1135 if (strcasecmp(g
->name
->value
, "General"))
1136 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1138 locatalog
->find_message(g
->text
->value
), lf
);
1140 for (o
= (ppdcOption
*)g
->options
->first();
1142 o
= (ppdcOption
*)g
->options
->next())
1144 if (!o
->choices
->count
)
1147 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1149 locatalog
->find_message(o
->text
->value
?
1151 o
->name
->value
), lf
);
1153 for (c
= (ppdcChoice
*)o
->choices
->first();
1155 c
= (ppdcChoice
*)o
->choices
->next())
1157 // Write this choice...
1158 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1159 o
->name
->value
, c
->name
->value
,
1160 locatalog
->find_message(c
->text
->value
?
1162 c
->name
->value
), lf
);
1167 // Finally the localizable attributes...
1168 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1170 if ((!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1171 strncmp(a
->name
->value
, "Custom", 6) &&
1172 strncmp(a
->name
->value
, "ParamCustom", 11))
1175 if (!a
->localizable
&&
1176 strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1177 strcmp(a
->name
->value
, "APPrinterPreset") &&
1178 strcmp(a
->name
->value
, "cupsICCProfile") &&
1179 strcmp(a
->name
->value
, "cupsIPPReason") &&
1180 strcmp(a
->name
->value
, "cupsMarkerName") &&
1181 strncmp(a
->name
->value
, "Custom", 6) &&
1182 strncmp(a
->name
->value
, "ParamCustom", 11))
1185 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1186 a
->name
->value
, a
->selector
->value
,
1187 locatalog
->find_message(a
->text
&& a
->text
->value
?
1188 a
->text
->value
: a
->name
->value
),
1189 ((a
->localizable
&& a
->value
->value
[0]) ||
1190 !strcmp(a
->name
->value
, "cupsIPPReason")) ?
1191 locatalog
->find_message(a
->value
->value
) : "",
1197 if (default_font
&& default_font
->value
)
1198 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1200 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1202 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1203 if (!strcmp(fn
->name
->value
, "*"))
1205 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1207 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1208 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1209 bfn
->name
->value
, bfn
->encoding
->value
,
1210 bfn
->version
->value
, bfn
->charset
->value
,
1211 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1214 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1215 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1217 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1219 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1220 (int)(cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),