]>
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 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_manufacturer() - Set the manufacturer name.
24 // ppdcDriver::set_model_name() - Set the model name.
25 // ppdcDriver::set_pc_file_name() - Set the PC filename.
26 // ppdcDriver::set_version() - Set the version string.
27 // ppdcDriver::write_ppd_file() - Write a PPD file...
31 // Include necessary headers...
35 #include <cups/cups.h>
39 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
42 ppdcDriver::ppdcDriver(ppdcDriver
*d
) // I - Printer driver template
44 ppdcGroup
*g
; // Current group
49 // Bump the use count of any strings we inherit...
51 d
->manufacturer
->get();
55 d
->default_font
->get();
57 d
->default_size
->get();
58 if (d
->custom_size_code
)
59 d
->custom_size_code
->get();
61 // Copy all of the data from the driver template...
62 copyright
= new ppdcArray(d
->copyright
);
63 manufacturer
= d
->manufacturer
;
68 model_number
= d
->model_number
;
69 manual_copies
= d
->manual_copies
;
70 color_device
= d
->color_device
;
71 throughput
= d
->throughput
;
72 attrs
= new ppdcArray(d
->attrs
);
73 constraints
= new ppdcArray(d
->constraints
);
74 filters
= new ppdcArray(d
->filters
);
75 fonts
= new ppdcArray(d
->fonts
);
76 profiles
= new ppdcArray(d
->profiles
);
77 sizes
= new ppdcArray(d
->sizes
);
78 default_font
= d
->default_font
;
79 default_size
= d
->default_size
;
80 variable_paper_size
= d
->variable_paper_size
;
81 custom_size_code
= d
->custom_size_code
;
82 left_margin
= d
->left_margin
;
83 bottom_margin
= d
->bottom_margin
;
84 right_margin
= d
->right_margin
;
85 top_margin
= d
->top_margin
;
86 max_width
= d
->max_width
;
87 max_length
= d
->max_length
;
88 min_width
= d
->min_width
;
89 min_length
= d
->min_length
;
91 // Then copy the groups manually, since we want separate copies
92 // of the groups and options...
93 groups
= new ppdcArray();
95 for (g
= (ppdcGroup
*)d
->groups
->first(); g
; g
= (ppdcGroup
*)d
->groups
->next())
96 groups
->add(new ppdcGroup(g
));
100 // Zero all of the data in the driver...
101 copyright
= new ppdcArray();
106 type
= PPDC_DRIVER_CUSTOM
;
111 attrs
= new ppdcArray();
112 constraints
= new ppdcArray();
113 fonts
= new ppdcArray();
114 filters
= new ppdcArray();
115 groups
= new ppdcArray();
116 profiles
= new ppdcArray();
117 sizes
= new ppdcArray();
120 variable_paper_size
= 0;
121 custom_size_code
= 0;
135 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
138 ppdcDriver::~ppdcDriver()
143 manufacturer
->release();
145 model_name
->release();
147 pc_file_name
->release();
151 default_font
->release();
153 default_size
->release();
154 if (custom_size_code
)
155 custom_size_code
->release();
168 // 'ppdcDriver::find_attr()' - Find an attribute.
171 ppdcAttr
* // O - Attribute or NULL
172 ppdcDriver::find_attr(const char *k
, // I - Keyword string
173 const char *s
) // I - Spec string
175 ppdcAttr
*a
; // Current attribute
178 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
179 if (!strcmp(a
->name
->value
, k
) &&
180 ((!s
&& (!a
->selector
->value
|| !a
->selector
->value
[0])) ||
181 (!s
&& !a
->selector
->value
&& !strcmp(a
->selector
->value
, s
))))
189 // 'ppdcDriver::find_group()' - Find a group.
192 ppdcGroup
* // O - Matching group or NULL
193 ppdcDriver::find_group(const char *n
) // I - Group name
195 ppdcGroup
*g
; // Current group
198 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
199 if (!strcasecmp(n
, g
->name
->value
))
207 // 'ppdcDriver::find_option()' - Find an option.
210 ppdcOption
* // O - Matching option or NULL
211 ppdcDriver::find_option(const char *n
) // I - Option name
213 ppdcGroup
*g
; // Current group
214 ppdcOption
*o
; // Current option
217 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
218 for (o
= (ppdcOption
*)g
->options
->first(); o
; o
= (ppdcOption
*)g
->options
->next())
219 if (!strcasecmp(n
, o
->name
->value
))
227 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
231 ppdcDriver::set_custom_size_code(const char *c
)
232 // I - CustomPageSize code
234 if (custom_size_code
)
235 custom_size_code
->release();
237 custom_size_code
= new ppdcString(c
);
242 // 'ppdcDriver::set_default_font()' - Set the default font name.
246 ppdcDriver::set_default_font(ppdcFont
*f
)
250 default_font
->release();
255 default_font
= f
->name
;
263 // 'ppdcDriver::set_default_size()' - Set the default size name.
267 ppdcDriver::set_default_size(ppdcMediaSize
*m
)
271 default_size
->release();
276 default_size
= m
->name
;
284 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
288 ppdcDriver::set_manufacturer(const char *m
)
292 manufacturer
->release();
294 manufacturer
= new ppdcString(m
);
299 // 'ppdcDriver::set_model_name()' - Set the model name.
303 ppdcDriver::set_model_name(const char *m
)
307 model_name
->release();
309 model_name
= new ppdcString(m
);
314 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
318 ppdcDriver::set_pc_file_name(const char *f
)
322 pc_file_name
->release();
324 pc_file_name
= new ppdcString(f
);
329 // 'ppdcDriver::set_version()' - Set the version string.
333 ppdcDriver::set_version(const char *v
) // I - Version
338 version
= new ppdcString(v
);
343 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
346 int // O - 0 on success, -1 on failure
347 ppdcDriver::write_ppd_file(
348 cups_file_t
*fp
, // I - PPD file
349 ppdcCatalog
*catalog
, // I - Message catalog
350 ppdcArray
*locales
, // I - Additional languages to add
351 ppdcSource
*src
, // I - Driver source
352 ppdcLineEnding le
) // I - Line endings to use
354 bool delete_cat
; // Delete the catalog when we are done?
355 char query
[42]; // Query attribute
356 ppdcString
*s
; // Copyright string
357 ppdcGroup
*g
; // Current group
358 ppdcOption
*o
; // Current option
359 ppdcChoice
*c
; // Current choice
360 ppdcMediaSize
*m
; // Current media size
361 ppdcProfile
*p
; // Current color profile
362 ppdcFilter
*f
; // Current filter
363 ppdcFont
*fn
, // Current font
364 *bfn
; // Current base font
365 ppdcConstraint
*cn
; // Current constraint
366 ppdcAttr
*a
; // Current attribute
367 const char *lf
; // Linefeed character to use
370 // If we don't have a message catalog, use an empty (English) one...
373 catalog
= new ppdcCatalog("en");
379 // Figure out the end-of-line string...
380 if (le
== PPDC_LFONLY
)
382 else if (le
== PPDC_CRONLY
)
387 // Write the standard header stuff...
388 cupsFilePrintf(fp
, "*PPD-Adobe: \"4.3\"%s", lf
);
389 cupsFilePrintf(fp
, "*%% PPD file for %s with CUPS.%s", model_name
->value
, lf
);
391 "*%% Created by the CUPS PPD Compiler " CUPS_SVERSION
".%s",
393 for (s
= (ppdcString
*)copyright
->first();
395 s
= (ppdcString
*)copyright
->next())
396 cupsFilePrintf(fp
, "*%% %s%s", catalog
->find_message(s
->value
), lf
);
397 cupsFilePrintf(fp
, "*FormatVersion: \"4.3\"%s", lf
);
398 cupsFilePrintf(fp
, "*FileVersion: \"%s\"%s", version
->value
, lf
);
400 a
= find_attr("LanguageVersion", NULL
);
401 cupsFilePrintf(fp
, "*LanguageVersion: %s%s",
402 catalog
->find_message(a
? a
->value
->value
: "English"), lf
);
404 a
= find_attr("LanguageEncoding", NULL
);
405 cupsFilePrintf(fp
, "*LanguageEncoding: %s%s",
406 catalog
->find_message(a
? a
->value
->value
: "ISOLatin1"), lf
);
408 cupsFilePrintf(fp
, "*PCFileName: \"%s\"%s", pc_file_name
->value
, lf
);
410 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
411 if (!strcmp(a
->name
->value
, "Product"))
416 for (; a
; a
= (ppdcAttr
*)attrs
->next())
417 if (!strcmp(a
->name
->value
, "Product"))
418 cupsFilePrintf(fp
, "*Product: \"%s\"%s", a
->value
->value
, lf
);
422 cupsFilePrintf(fp
, "*Product: \"(ESP Ghostscript)\"%s", lf
);
423 cupsFilePrintf(fp
, "*Product: \"(GPL Ghostscript)\"%s", lf
);
424 cupsFilePrintf(fp
, "*Product: \"(GNU Ghostscript)\"%s", lf
);
427 cupsFilePrintf(fp
, "*Manufacturer: \"%s\"%s",
428 catalog
->find_message(manufacturer
->value
), lf
);
430 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
431 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
432 catalog
->find_message(a
->value
->value
), lf
);
433 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
434 strlen(manufacturer
->value
)))
435 cupsFilePrintf(fp
, "*ModelName: \"%s %s\"%s",
436 catalog
->find_message(manufacturer
->value
),
437 catalog
->find_message(model_name
->value
), lf
);
439 cupsFilePrintf(fp
, "*ModelName: \"%s\"%s",
440 catalog
->find_message(model_name
->value
), lf
);
442 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
443 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
444 catalog
->find_message(a
->value
->value
), lf
);
445 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
446 strlen(manufacturer
->value
)))
447 cupsFilePrintf(fp
, "*ShortNickName: \"%s %s\"%s",
448 catalog
->find_message(manufacturer
->value
),
449 catalog
->find_message(model_name
->value
), lf
);
451 cupsFilePrintf(fp
, "*ShortNickName: \"%s\"%s",
452 catalog
->find_message(model_name
->value
), lf
);
454 if ((a
= find_attr("NickName", NULL
)) != NULL
)
455 cupsFilePrintf(fp
, "*NickName: \"%s\"%s",
456 catalog
->find_message(a
->value
->value
), lf
);
457 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
458 strlen(manufacturer
->value
)))
459 cupsFilePrintf(fp
, "*NickName: \"%s %s, %s\"%s",
460 catalog
->find_message(manufacturer
->value
),
461 catalog
->find_message(model_name
->value
), version
->value
,
464 cupsFilePrintf(fp
, "*NickName: \"%s, %s\"%s",
465 catalog
->find_message(model_name
->value
), version
->value
,
468 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
469 if (!strcmp(a
->name
->value
, "PSVersion"))
474 for (; a
; a
= (ppdcAttr
*)attrs
->next())
475 if (!strcmp(a
->name
->value
, "PSVersion"))
476 cupsFilePrintf(fp
, "*PSVersion: \"%s\"%s", a
->value
->value
, lf
);
480 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 705\"%s", lf
);
481 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 707\"%s", lf
);
482 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 815\"%s", lf
);
483 cupsFilePrintf(fp
, "*PSVersion: \"(3010.000) 853\"%s", lf
);
486 if ((a
= find_attr("LanguageLevel", NULL
)) != NULL
)
487 cupsFilePrintf(fp
, "*LanguageLevel: \"%s\"%s", a
->value
->value
, lf
);
489 cupsFilePrintf(fp
, "*LanguageLevel: \"3\"%s", lf
);
491 cupsFilePrintf(fp
, "*ColorDevice: %s%s", color_device
? "True" : "False", lf
);
493 if ((a
= find_attr("DefaultColorSpace", NULL
)) != NULL
)
494 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s", a
->value
->value
, lf
);
496 cupsFilePrintf(fp
, "*DefaultColorSpace: %s%s",
497 color_device
? "RGB" : "Gray", lf
);
499 if ((a
= find_attr("FileSystem", NULL
)) != NULL
)
500 cupsFilePrintf(fp
, "*FileSystem: %s%s", a
->value
->value
, lf
);
502 cupsFilePrintf(fp
, "*FileSystem: False%s", lf
);
504 cupsFilePrintf(fp
, "*Throughput: \"%d\"%s", throughput
, lf
);
506 if ((a
= find_attr("LandscapeOrientation", NULL
)) != NULL
)
507 cupsFilePrintf(fp
, "*LandscapeOrientation: %s%s", a
->value
->value
, lf
);
509 cupsFilePrintf(fp
, "*LandscapeOrientation: Plus90%s", lf
);
511 if ((a
= find_attr("TTRasterizer", NULL
)) != NULL
)
512 cupsFilePrintf(fp
, "*TTRasterizer: %s%s", a
->value
->value
, lf
);
513 else if (type
!= PPDC_DRIVER_PS
)
514 cupsFilePrintf(fp
, "*TTRasterizer: Type42%s", lf
);
518 // Write driver-defined attributes...
519 cupsFilePrintf(fp
, "*%% Driver-defined attributes...%s", lf
);
520 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
522 if (!strcmp(a
->name
->value
, "Product") ||
523 !strcmp(a
->name
->value
, "PSVersion") ||
524 !strcmp(a
->name
->value
, "LanguageLevel") ||
525 !strcmp(a
->name
->value
, "DefaultColorSpace") ||
526 !strcmp(a
->name
->value
, "FileSystem") ||
527 !strcmp(a
->name
->value
, "LandscapeOrientation") ||
528 !strcmp(a
->name
->value
, "TTRasterizer") ||
529 !strcmp(a
->name
->value
, "LanguageVersion") ||
530 !strcmp(a
->name
->value
, "LanguageEncoding") ||
531 !strcmp(a
->name
->value
, "ModelName") ||
532 !strcmp(a
->name
->value
, "NickName") ||
533 !strcmp(a
->name
->value
, "ShortNickName") ||
534 !strcmp(a
->name
->value
, "cupsVersion") ||
535 a
->name
->value
[0] == '?')
538 if (!a
->selector
->value
|| !a
->selector
->value
[0])
539 cupsFilePrintf(fp
, "*%s", a
->name
->value
);
540 else if (!a
->text
->value
|| !a
->text
->value
[0])
541 cupsFilePrintf(fp
, "*%s %s", a
->name
->value
, a
->selector
->value
);
543 cupsFilePrintf(fp
, "*%s %s/%s", a
->name
->value
, a
->selector
->value
,
546 if (strcmp(a
->value
->value
, "False") &&
547 strcmp(a
->value
->value
, "True") &&
548 strcmp(a
->name
->value
, "1284Modes") &&
549 strcmp(a
->name
->value
, "InkName") &&
550 strcmp(a
->name
->value
, "PageStackOrder") &&
551 strncmp(a
->name
->value
, "ParamCustom", 11) &&
552 strcmp(a
->name
->value
, "Protocols") &&
553 strcmp(a
->name
->value
, "ReferencePunch") &&
554 strncmp(a
->name
->value
, "Default", 7))
556 cupsFilePrintf(fp
, ": \"%s\"%s", a
->value
->value
, lf
);
558 if (strchr(a
->value
->value
, '\n'))
559 cupsFilePrintf(fp
, "*End%s", lf
);
562 cupsFilePrintf(fp
, ": %s%s", a
->value
->value
, lf
);
566 if (type
!= PPDC_DRIVER_PS
|| filters
->count
)
568 if ((a
= find_attr("cupsVersion", NULL
)) != NULL
)
569 cupsFilePrintf(fp
, "*cupsVersion: %s%s", a
->value
->value
, lf
);
571 cupsFilePrintf(fp
, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR
,
572 CUPS_VERSION_MINOR
, lf
);
573 cupsFilePrintf(fp
, "*cupsModelNumber: %d%s", model_number
, lf
);
574 cupsFilePrintf(fp
, "*cupsManualCopies: %s%s",
575 manual_copies
? "True" : "False", lf
);
579 for (f
= (ppdcFilter
*)filters
->first();
581 f
= (ppdcFilter
*)filters
->next())
582 cupsFilePrintf(fp
, "*cupsFilter: \"%s %d %s\"%s", f
->mime_type
->value
,
583 f
->cost
, f
->program
->value
, lf
);
589 case PPDC_DRIVER_LABEL
:
590 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
591 "rastertolabel\"%s", lf
);
594 case PPDC_DRIVER_EPSON
:
595 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
596 "rastertoepson\"%s", lf
);
599 case PPDC_DRIVER_ESCP
:
600 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
601 "commandtoescpx\"%s", lf
);
602 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
603 "rastertoescpx\"%s", lf
);
606 case PPDC_DRIVER_HP
:
607 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
608 "rastertohp\"%s", lf
);
611 case PPDC_DRIVER_PCL
:
612 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-command 50 "
613 "commandtopclx\"%s", lf
);
614 cupsFilePrintf(fp
, "*cupsFilter: \"application/vnd.cups-raster 50 "
615 "rastertopclx\"%s", lf
);
623 for (p
= (ppdcProfile
*)profiles
->first();
625 p
= (ppdcProfile
*)profiles
->next())
627 "*cupsColorProfile %s/%s: \"%.3f %.3f %.3f %.3f %.3f %.3f "
628 "%.3f %.3f %.3f %.3f %.3f\"%s",
629 p
->resolution
->value
, p
->media_type
->value
,
630 p
->density
, p
->gamma
,
631 p
->profile
[0], p
->profile
[1],
632 p
->profile
[2], p
->profile
[3],
633 p
->profile
[4], p
->profile
[5],
634 p
->profile
[6], p
->profile
[7],
640 // Add localizations for additional languages...
641 ppdcString
*locale
; // Locale name
642 ppdcCatalog
*locatalog
; // Message catalog for locale
645 // Write the list of languages...
646 cupsFilePrintf(fp
, "*cupsLanguages: \"en");
648 for (locale
= (ppdcString
*)locales
->first();
650 locale
= (ppdcString
*)locales
->next())
652 // Skip (US) English...
653 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
656 // See if we have a po file for this language...
657 if (!src
->find_po(locale
->value
))
659 // No, see if we can use the base file?
660 locatalog
= new ppdcCatalog(locale
->value
);
662 if (locatalog
->messages
->count
== 0)
664 // No, skip this one...
665 fprintf(stderr
, "ppdc: No message catalog provided for locale %s!\n",
670 // Add the base file to the list...
671 src
->po_files
->add(locatalog
);
674 cupsFilePrintf(fp
, " %s", locale
->value
);
677 cupsFilePrintf(fp
, "\"%s", lf
);
680 for (cn
= (ppdcConstraint
*)constraints
->first();
682 cn
= (ppdcConstraint
*)constraints
->next())
684 // First constrain 1 against 2...
685 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
686 !strncmp(cn
->option2
->value
, "*Custom", 7))
687 cupsFilePrintf(fp
, "*NonUIConstraints: ");
689 cupsFilePrintf(fp
, "*UIConstraints: ");
691 if (cn
->option1
->value
[0] != '*')
692 cupsFilePutChar(fp
, '*');
694 cupsFilePrintf(fp
, cn
->option1
->value
);
696 if (cn
->choice1
->value
)
697 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
699 cupsFilePutChar(fp
, ' ');
701 if (cn
->option2
->value
[0] != '*')
702 cupsFilePutChar(fp
, '*');
704 cupsFilePrintf(fp
, cn
->option2
->value
);
706 if (cn
->choice2
->value
)
707 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
709 cupsFilePrintf(fp
, "%s", lf
);
711 // Then constrain 2 against 1...
712 if (!strncmp(cn
->option1
->value
, "*Custom", 7) ||
713 !strncmp(cn
->option2
->value
, "*Custom", 7))
714 cupsFilePrintf(fp
, "*NonUIConstraints: ");
716 cupsFilePrintf(fp
, "*UIConstraints: ");
718 if (cn
->option2
->value
[0] != '*')
719 cupsFilePutChar(fp
, '*');
721 cupsFilePrintf(fp
, cn
->option2
->value
);
723 if (cn
->choice2
->value
)
724 cupsFilePrintf(fp
, " %s", cn
->choice2
->value
);
726 cupsFilePutChar(fp
, ' ');
728 if (cn
->option1
->value
[0] != '*')
729 cupsFilePutChar(fp
, '*');
731 cupsFilePrintf(fp
, cn
->option1
->value
);
733 if (cn
->choice1
->value
)
734 cupsFilePrintf(fp
, " %s", cn
->choice1
->value
);
736 cupsFilePuts(fp
, lf
);
739 // PageSize option...
740 cupsFilePrintf(fp
, "*OpenUI *PageSize/Media Size: PickOne%s", lf
);
741 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageSize%s", lf
);
742 cupsFilePrintf(fp
, "*DefaultPageSize: %s%s",
743 default_size
? default_size
->value
: "Letter", lf
);
745 for (m
= (ppdcMediaSize
*)sizes
->first();
747 m
= (ppdcMediaSize
*)sizes
->next())
748 if (m
->size_code
->value
)
750 cupsFilePrintf(fp
, "*PageSize %s/%s: \"%s\"%s",
751 m
->name
->value
, catalog
->find_message(m
->text
->value
),
752 m
->size_code
->value
, lf
);
754 if (strchr(m
->size_code
->value
, '\n') ||
755 strchr(m
->size_code
->value
, '\r'))
756 cupsFilePrintf(fp
, "*End%s", lf
);
760 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
761 "/ImagingBBox null>>setpagedevice\"%s",
762 m
->name
->value
, catalog
->find_message(m
->text
->value
),
763 m
->width
, m
->length
, lf
);
765 if ((a
= find_attr("?PageSize", NULL
)) != NULL
)
767 cupsFilePrintf(fp
, "*?PageSize: \"%s\"%s", a
->value
->value
, lf
);
769 if (strchr(a
->value
->value
, '\n') ||
770 strchr(a
->value
->value
, '\r'))
771 cupsFilePrintf(fp
, "*End%s", lf
);
774 cupsFilePrintf(fp
, "*CloseUI: *PageSize%s", lf
);
776 // PageRegion option...
777 cupsFilePrintf(fp
, "*OpenUI *PageRegion/Media Size: PickOne%s", lf
);
778 cupsFilePrintf(fp
, "*OrderDependency: 10 AnySetup *PageRegion%s", lf
);
779 cupsFilePrintf(fp
, "*DefaultPageRegion: %s%s",
780 default_size
? default_size
->value
: "Letter", lf
);
782 for (m
= (ppdcMediaSize
*)sizes
->first();
784 m
= (ppdcMediaSize
*)sizes
->next())
785 if (m
->region_code
->value
)
787 cupsFilePrintf(fp
, "*PageRegion %s/%s: \"%s\"%s",
788 m
->name
->value
, catalog
->find_message(m
->text
->value
),
789 m
->region_code
->value
, lf
);
791 if (strchr(m
->region_code
->value
, '\n') ||
792 strchr(m
->region_code
->value
, '\r'))
793 cupsFilePrintf(fp
, "*End%s", lf
);
797 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
798 "/ImagingBBox null>>setpagedevice\"%s",
799 m
->name
->value
, catalog
->find_message(m
->text
->value
),
800 m
->width
, m
->length
, lf
);
802 if ((a
= find_attr("?PageRegion", NULL
)) != NULL
)
804 cupsFilePrintf(fp
, "*?PageRegion: \"%s\"%s", a
->value
->value
, lf
);
806 if (strchr(a
->value
->value
, '\n') ||
807 strchr(a
->value
->value
, '\r'))
808 cupsFilePrintf(fp
, "*End%s", lf
);
811 cupsFilePrintf(fp
, "*CloseUI: *PageRegion%s", lf
);
813 // ImageableArea info...
814 cupsFilePrintf(fp
, "*DefaultImageableArea: %s%s",
815 default_size
? default_size
->value
: "Letter", lf
);
817 for (m
= (ppdcMediaSize
*)sizes
->first();
819 m
= (ppdcMediaSize
*)sizes
->next())
820 cupsFilePrintf(fp
, "*ImageableArea %s/%s: \"%.2f %.2f %.2f %.2f\"%s",
821 m
->name
->value
, catalog
->find_message(m
->text
->value
),
822 m
->left
, m
->bottom
, m
->width
- m
->right
, m
->length
- m
->top
,
825 if ((a
= find_attr("?ImageableArea", NULL
)) != NULL
)
827 cupsFilePrintf(fp
, "*?ImageableArea: \"%s\"%s", a
->value
->value
, lf
);
829 if (strchr(a
->value
->value
, '\n') ||
830 strchr(a
->value
->value
, '\r'))
831 cupsFilePrintf(fp
, "*End%s", lf
);
834 // PaperDimension info...
835 cupsFilePrintf(fp
, "*DefaultPaperDimension: %s%s",
836 default_size
? default_size
->value
: "Letter", lf
);
838 for (m
= (ppdcMediaSize
*)sizes
->first();
840 m
= (ppdcMediaSize
*)sizes
->next())
841 cupsFilePrintf(fp
, "*PaperDimension %s/%s: \"%.2f %.2f\"%s",
842 m
->name
->value
, catalog
->find_message(m
->text
->value
),
843 m
->width
, m
->length
, lf
);
845 if ((a
= find_attr("?PaperDimension", NULL
)) != NULL
)
847 cupsFilePrintf(fp
, "*?PaperDimension: \"%s\"%s", a
->value
->value
, lf
);
849 if (strchr(a
->value
->value
, '\n') ||
850 strchr(a
->value
->value
, '\r'))
851 cupsFilePrintf(fp
, "*End%s", lf
);
854 // Custom size support...
855 if (variable_paper_size
)
857 cupsFilePrintf(fp
, "*MaxMediaWidth: \"%.2f\"%s", max_width
, lf
);
858 cupsFilePrintf(fp
, "*MaxMediaHeight: \"%.2f\"%s", max_length
, lf
);
859 cupsFilePrintf(fp
, "*HWMargins: %.2f %.2f %.2f %.2f\n",
860 left_margin
, bottom_margin
, right_margin
, top_margin
);
862 if (custom_size_code
&& custom_size_code
->value
)
864 cupsFilePrintf(fp
, "*CustomPageSize True: \"%s\"%s",
865 custom_size_code
->value
, lf
);
867 if (strchr(custom_size_code
->value
, '\n') ||
868 strchr(custom_size_code
->value
, '\r'))
869 cupsFilePrintf(fp
, "*End%s", lf
);
873 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
874 "/ImagingBBox null>>setpagedevice\"%s", lf
);
876 if ((a
= find_attr("ParamCustomPageSize", "Width")) != NULL
)
877 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: %s%s", a
->value
->value
,
880 cupsFilePrintf(fp
, "*ParamCustomPageSize Width: 1 points %.2f %.2f%s",
881 min_width
, max_width
, lf
);
883 if ((a
= find_attr("ParamCustomPageSize", "Height")) != NULL
)
884 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: %s%s", a
->value
->value
,
887 cupsFilePrintf(fp
, "*ParamCustomPageSize Height: 2 points %.2f %.2f%s",
888 min_length
, max_length
, lf
);
890 if ((a
= find_attr("ParamCustomPageSize", "WidthOffset")) != NULL
)
891 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: %s%s",
892 a
->value
->value
, lf
);
894 cupsFilePrintf(fp
, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf
);
896 if ((a
= find_attr("ParamCustomPageSize", "HeightOffset")) != NULL
)
897 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: %s%s",
898 a
->value
->value
, lf
);
900 cupsFilePrintf(fp
, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf
);
902 if ((a
= find_attr("ParamCustomPageSize", "Orientation")) != NULL
)
903 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: %s%s",
904 a
->value
->value
, lf
);
906 cupsFilePrintf(fp
, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf
);
909 if (type
!= PPDC_DRIVER_PS
&& !find_attr("RequiresPageRegion", NULL
))
910 cupsFilePrintf(fp
, "*RequiresPageRegion All: True%s", lf
);
912 // All other options...
913 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
915 if (!g
->options
->count
)
918 if (strcasecmp(g
->name
->value
, "General"))
919 cupsFilePrintf(fp
, "*OpenGroup: %s/%s%s", g
->name
->value
,
920 catalog
->find_message(g
->text
->value
), lf
);
922 for (o
= (ppdcOption
*)g
->options
->first();
924 o
= (ppdcOption
*)g
->options
->next())
926 if (!o
->choices
->count
)
929 if (!o
->text
->value
|| !strcmp(o
->name
->value
, o
->text
->value
))
930 cupsFilePrintf(fp
, "*OpenUI *%s: ", o
->name
->value
);
932 cupsFilePrintf(fp
, "*OpenUI *%s/%s: ", o
->name
->value
,
933 catalog
->find_message(o
->text
->value
));
938 cupsFilePrintf(fp
, "Boolean%s", lf
);
941 cupsFilePrintf(fp
, "PickOne%s", lf
);
944 cupsFilePrintf(fp
, "PickMany%s", lf
);
948 cupsFilePrintf(fp
, "*OrderDependency: %.1f ", o
->order
);
952 cupsFilePrintf(fp
, "AnySetup");
954 case PPDC_SECTION_DOCUMENT
:
955 cupsFilePrintf(fp
, "DocumentSetup");
957 case PPDC_SECTION_EXIT
:
958 cupsFilePrintf(fp
, "ExitServer");
960 case PPDC_SECTION_JCL
:
961 cupsFilePrintf(fp
, "JCLSetup");
963 case PPDC_SECTION_PAGE
:
964 cupsFilePrintf(fp
, "PageSetup");
966 case PPDC_SECTION_PROLOG
:
967 cupsFilePrintf(fp
, "Prolog");
971 cupsFilePrintf(fp
, " *%s%s", o
->name
->value
, lf
);
975 // Use the programmer-supplied default...
976 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
,
977 o
->defchoice
->value
, lf
);
981 // Make the first choice the default...
982 c
= (ppdcChoice
*)o
->choices
->first();
983 cupsFilePrintf(fp
, "*Default%s: %s%s", o
->name
->value
, c
->name
->value
,
987 for (c
= (ppdcChoice
*)o
->choices
->first();
989 c
= (ppdcChoice
*)o
->choices
->next())
991 // Write this choice...
992 if (!c
->text
->value
|| !strcmp(c
->name
->value
, c
->text
->value
))
993 cupsFilePrintf(fp
, "*%s %s: \"%s\"%s", o
->name
->value
, c
->name
->value
,
996 cupsFilePrintf(fp
, "*%s %s/%s: \"%s\"%s", o
->name
->value
,
997 c
->name
->value
, catalog
->find_message(c
->text
->value
),
1000 // Multi-line commands need a *End line to terminate them.
1001 if (strchr(c
->code
->value
, '\n') ||
1002 strchr(c
->code
->value
, '\r'))
1003 cupsFilePrintf(fp
, "*End%s", lf
);
1006 snprintf(query
, sizeof(query
), "?%s", o
->name
->value
);
1008 if ((a
= find_attr(query
, NULL
)) != NULL
)
1010 cupsFilePrintf(fp
, "*%s: \"%s\"\n", query
, a
->value
->value
);
1012 if (strchr(a
->value
->value
, '\n') ||
1013 strchr(a
->value
->value
, '\r'))
1014 cupsFilePrintf(fp
, "*End%s", lf
);
1017 cupsFilePrintf(fp
, "*CloseUI: *%s%s", o
->name
->value
, lf
);
1020 if (strcasecmp(g
->name
->value
, "General"))
1021 cupsFilePrintf(fp
, "*CloseGroup: %s%s", g
->name
->value
, lf
);
1026 // Add localizations for additional languages...
1027 ppdcString
*locale
; // Locale name
1028 ppdcCatalog
*locatalog
; // Message catalog for locale
1031 // Write the translation strings for each language...
1032 for (locale
= (ppdcString
*)locales
->first();
1034 locale
= (ppdcString
*)locales
->next())
1036 // Skip (US) English...
1037 if (!strcmp(locale
->value
, "en") || !strcmp(locale
->value
, "en_US"))
1040 // Skip missing languages...
1041 if ((locatalog
= src
->find_po(locale
->value
)) == NULL
)
1044 // Do the core stuff first...
1045 cupsFilePrintf(fp
, "*%s.Translation Manufacturer/%s: \"\"%s",
1047 locatalog
->find_message(manufacturer
->value
), lf
);
1049 if ((a
= find_attr("ModelName", NULL
)) != NULL
)
1050 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1052 locatalog
->find_message(a
->value
->value
), lf
);
1053 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1054 strlen(manufacturer
->value
)))
1055 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s %s: \"\"%s",
1057 locatalog
->find_message(manufacturer
->value
),
1058 locatalog
->find_message(model_name
->value
), lf
);
1060 cupsFilePrintf(fp
, "*%s.Translation ModelName/%s: \"\"%s",
1062 locatalog
->find_message(model_name
->value
), lf
);
1064 if ((a
= find_attr("ShortNickName", NULL
)) != NULL
)
1065 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1067 locatalog
->find_message(a
->value
->value
), lf
);
1068 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1069 strlen(manufacturer
->value
)))
1070 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1072 locatalog
->find_message(manufacturer
->value
),
1073 locatalog
->find_message(model_name
->value
), lf
);
1075 cupsFilePrintf(fp
, "*%s.Translation ShortNickName/%s: \"\"%s",
1077 locatalog
->find_message(model_name
->value
), lf
);
1079 if ((a
= find_attr("NickName", NULL
)) != NULL
)
1080 cupsFilePrintf(fp
, "*%s.Translation NickName/%s: \"\"%s",
1082 locatalog
->find_message(a
->value
->value
), lf
);
1083 else if (strncasecmp(model_name
->value
, manufacturer
->value
,
1084 strlen(manufacturer
->value
)))
1085 cupsFilePrintf(fp
, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1087 locatalog
->find_message(manufacturer
->value
),
1088 locatalog
->find_message(model_name
->value
),
1089 version
->value
, lf
);
1091 cupsFilePrintf(fp
, "*%s.Translation NickName/%s, %s: \"\"%s",
1093 locatalog
->find_message(model_name
->value
),
1094 version
->value
, lf
);
1096 // Then the page sizes...
1097 cupsFilePrintf(fp
, "*%s.Translation PageSize/%s: \"\"%s", locale
->value
,
1098 locatalog
->find_message("Media Size"), lf
);
1100 for (m
= (ppdcMediaSize
*)sizes
->first();
1102 m
= (ppdcMediaSize
*)sizes
->next())
1104 cupsFilePrintf(fp
, "*%s.PageSize %s/%s: \"\"%s", locale
->value
,
1105 m
->name
->value
, locatalog
->find_message(m
->text
->value
),
1109 // Next the groups and options...
1110 for (g
= (ppdcGroup
*)groups
->first(); g
; g
= (ppdcGroup
*)groups
->next())
1112 if (!g
->options
->count
)
1115 if (strcasecmp(g
->name
->value
, "General"))
1116 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1118 locatalog
->find_message(g
->text
->value
), lf
);
1120 for (o
= (ppdcOption
*)g
->options
->first();
1122 o
= (ppdcOption
*)g
->options
->next())
1124 if (!o
->choices
->count
)
1127 cupsFilePrintf(fp
, "*%s.Translation %s/%s: \"\"%s", locale
->value
,
1129 locatalog
->find_message(o
->text
->value
?
1131 o
->name
->value
), lf
);
1133 for (c
= (ppdcChoice
*)o
->choices
->first();
1135 c
= (ppdcChoice
*)o
->choices
->next())
1137 // Write this choice...
1138 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"\"%s", locale
->value
,
1139 o
->name
->value
, c
->name
->value
,
1140 locatalog
->find_message(c
->text
->value
?
1142 c
->name
->value
), lf
);
1147 // Finally the localizable attributes...
1148 for (a
= (ppdcAttr
*)attrs
->first(); a
; a
= (ppdcAttr
*)attrs
->next())
1150 if ((!a
->text
|| !a
->text
->value
|| !a
->text
->value
[0]) &&
1151 strncmp(a
->name
->value
, "Custom", 6) &&
1152 strncmp(a
->name
->value
, "ParamCustom", 11))
1155 if (strcmp(a
->name
->value
, "APCustomColorMatchingName") &&
1156 strcmp(a
->name
->value
, "APPrinterPreset") &&
1157 strcmp(a
->name
->value
, "cupsICCProfile") &&
1158 strcmp(a
->name
->value
, "cupsIPPReason") &&
1159 strncmp(a
->name
->value
, "Custom", 6) &&
1160 strncmp(a
->name
->value
, "ParamCustom", 11))
1163 cupsFilePrintf(fp
, "*%s.%s %s/%s: \"%s\"%s", locale
->value
,
1164 a
->name
->value
, a
->selector
->value
,
1165 locatalog
->find_message(a
->text
&& a
->text
->value
?
1166 a
->text
->value
: a
->name
->value
),
1167 !strcmp(a
->name
->value
, "cupsIPPReason") ?
1168 locatalog
->find_message(a
->value
->value
) : "",
1174 if (default_font
&& default_font
->value
)
1175 cupsFilePrintf(fp
, "*DefaultFont: %s%s", default_font
->value
, lf
);
1177 cupsFilePrintf(fp
, "*DefaultFont: Courier%s", lf
);
1179 for (fn
= (ppdcFont
*)fonts
->first(); fn
; fn
= (ppdcFont
*)fonts
->next())
1180 if (!strcmp(fn
->name
->value
, "*"))
1182 for (bfn
= (ppdcFont
*)src
->base_fonts
->first();
1184 bfn
= (ppdcFont
*)src
->base_fonts
->next())
1185 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1186 bfn
->name
->value
, bfn
->encoding
->value
,
1187 bfn
->version
->value
, bfn
->charset
->value
,
1188 bfn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1191 cupsFilePrintf(fp
, "*Font %s: %s \"%s\" %s %s%s",
1192 fn
->name
->value
, fn
->encoding
->value
, fn
->version
->value
,
1194 fn
->status
== PPDC_FONT_ROM
? "ROM" : "Disk", lf
);
1196 cupsFilePrintf(fp
, "*%% End of %s, %05d bytes.%s", pc_file_name
->value
,
1197 (int)(cupsFileTell(fp
) + 25 + strlen(pc_file_name
->value
)),