]> git.ipfire.org Git - thirdparty/cups.git/blame - ppdc/ppdc-driver.cxx
Merge changes from CUPS 1.4svn-r8454.
[thirdparty/cups.git] / ppdc / ppdc-driver.cxx
CommitLineData
ac884b6a
MS
1//
2// "$Id$"
3//
4// PPD file compiler definitions for the CUPS PPD Compiler.
5//
d2354e63 6// Copyright 2007-2009 by Apple Inc.
ac884b6a
MS
7// Copyright 2002-2006 by Easy Software Products.
8//
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/".
14//
15// Contents:
16//
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.
bdd6c45b 23// ppdcDriver::set_file_name() - Set the full filename.
ac884b6a
MS
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...
29//
30
31//
32// Include necessary headers...
33//
34
35#include "ppdc.h"
61cf44e2 36#include <cups/globals.h>
ac884b6a
MS
37
38
39//
40// 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
41//
42
43ppdcDriver::ppdcDriver(ppdcDriver *d) // I - Printer driver template
44{
45 ppdcGroup *g; // Current group
46
47
48 if (d)
49 {
50 // Bump the use count of any strings we inherit...
51 if (d->manufacturer)
e4572d57 52 d->manufacturer->retain();
ac884b6a 53 if (d->version)
e4572d57 54 d->version->retain();
ac884b6a 55 if (d->default_font)
e4572d57 56 d->default_font->retain();
ac884b6a 57 if (d->default_size)
e4572d57 58 d->default_size->retain();
ac884b6a 59 if (d->custom_size_code)
e4572d57 60 d->custom_size_code->retain();
ac884b6a
MS
61
62 // Copy all of the data from the driver template...
63 copyright = new ppdcArray(d->copyright);
64 manufacturer = d->manufacturer;
65 model_name = 0;
bdd6c45b 66 file_name = 0;
ac884b6a
MS
67 pc_file_name = 0;
68 type = d->type;
69 version = d->version;
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;
92
93 // Then copy the groups manually, since we want separate copies
94 // of the groups and options...
95 groups = new ppdcArray();
96
97 for (g = (ppdcGroup *)d->groups->first(); g; g = (ppdcGroup *)d->groups->next())
98 groups->add(new ppdcGroup(g));
99 }
100 else
101 {
102 // Zero all of the data in the driver...
103 copyright = new ppdcArray();
104 manufacturer = 0;
105 model_name = 0;
bdd6c45b 106 file_name = 0;
ac884b6a
MS
107 pc_file_name = 0;
108 version = 0;
109 type = PPDC_DRIVER_CUSTOM;
110 model_number = 0;
111 manual_copies = 0;
112 color_device = 0;
113 throughput = 1;
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();
121 default_font = 0;
122 default_size = 0;
123 variable_paper_size = 0;
124 custom_size_code = 0;
125 left_margin = 0;
126 bottom_margin = 0;
127 right_margin = 0;
128 top_margin = 0;
129 max_width = 0;
130 max_length = 0;
131 min_width = 0;
132 min_length = 0;
133 }
134}
135
136
137//
138// 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
139//
140
141ppdcDriver::~ppdcDriver()
142{
e4572d57 143 copyright->release();
ac884b6a
MS
144
145 if (manufacturer)
146 manufacturer->release();
147 if (model_name)
148 model_name->release();
bdd6c45b
MS
149 if (file_name)
150 file_name->release();
ac884b6a
MS
151 if (pc_file_name)
152 pc_file_name->release();
153 if (version)
154 version->release();
155 if (default_font)
156 default_font->release();
157 if (default_size)
158 default_size->release();
159 if (custom_size_code)
160 custom_size_code->release();
161
e4572d57
MS
162 attrs->release();
163 constraints->release();
164 filters->release();
165 fonts->release();
166 groups->release();
167 profiles->release();
168 sizes->release();
ac884b6a
MS
169}
170
171
172//
173// 'ppdcDriver::find_attr()' - Find an attribute.
174//
175
176ppdcAttr * // O - Attribute or NULL
177ppdcDriver::find_attr(const char *k, // I - Keyword string
178 const char *s) // I - Spec string
179{
180 ppdcAttr *a; // Current attribute
181
182
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))))
187 return (a);
188
189 return (NULL);
190}
191
192
193//
194// 'ppdcDriver::find_group()' - Find a group.
195//
196
197ppdcGroup * // O - Matching group or NULL
198ppdcDriver::find_group(const char *n) // I - Group name
199{
200 ppdcGroup *g; // Current group
201
202
203 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
204 if (!strcasecmp(n, g->name->value))
205 return (g);
206
207 return (0);
208}
209
210
211//
212// 'ppdcDriver::find_option()' - Find an option.
213//
214
215ppdcOption * // O - Matching option or NULL
216ppdcDriver::find_option(const char *n) // I - Option name
217{
218 ppdcGroup *g; // Current group
219 ppdcOption *o; // Current option
220
221
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))
225 return (o);
226
227 return (0);
228}
229
230
231//
232// 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
233//
234
235void
bdd6c45b
MS
236ppdcDriver::set_custom_size_code(
237 const char *c) // I - CustomPageSize code
ac884b6a
MS
238{
239 if (custom_size_code)
240 custom_size_code->release();
241
242 custom_size_code = new ppdcString(c);
243}
244
245
246//
247// 'ppdcDriver::set_default_font()' - Set the default font name.
248//
249
250void
bdd6c45b
MS
251ppdcDriver::set_default_font(
252 ppdcFont *f) // I - Font
ac884b6a
MS
253{
254 if (default_font)
255 default_font->release();
256
257 if (f)
258 {
e4572d57 259 f->name->retain();
ac884b6a
MS
260 default_font = f->name;
261 }
262 else
263 default_font = 0;
264}
265
266
267//
268// 'ppdcDriver::set_default_size()' - Set the default size name.
269//
270
271void
bdd6c45b
MS
272ppdcDriver::set_default_size(
273 ppdcMediaSize *m) // I - Media size
ac884b6a
MS
274{
275 if (default_size)
276 default_size->release();
277
278 if (m)
279 {
e4572d57 280 m->name->retain();
ac884b6a
MS
281 default_size = m->name;
282 }
283 else
284 default_size = 0;
285}
286
287
bdd6c45b
MS
288//
289// 'ppdcDriver::set_file_name()' - Set the full filename.
290//
291
292void
293ppdcDriver::set_file_name(const char *f)// I - Filename
294{
295 if (file_name)
296 file_name->release();
297
298 file_name = new ppdcString(f);
299}
300
301
ac884b6a
MS
302//
303// 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
304//
305
306void
bdd6c45b
MS
307ppdcDriver::set_manufacturer(
308 const char *m) // I - Model name
ac884b6a
MS
309{
310 if (manufacturer)
311 manufacturer->release();
312
313 manufacturer = new ppdcString(m);
314}
315
316
317//
318// 'ppdcDriver::set_model_name()' - Set the model name.
319//
320
321void
bdd6c45b
MS
322ppdcDriver::set_model_name(
323 const char *m) // I - Model name
ac884b6a
MS
324{
325 if (model_name)
326 model_name->release();
327
328 model_name = new ppdcString(m);
329}
330
331
332//
333// 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
334//
335
336void
bdd6c45b
MS
337ppdcDriver::set_pc_file_name(
338 const char *f) // I - Filename
ac884b6a
MS
339{
340 if (pc_file_name)
341 pc_file_name->release();
342
343 pc_file_name = new ppdcString(f);
344}
345
346
347//
348// 'ppdcDriver::set_version()' - Set the version string.
349//
350
351void
352ppdcDriver::set_version(const char *v) // I - Version
353{
354 if (version)
355 version->release();
356
357 version = new ppdcString(v);
358}
359
360
361//
362// 'ppdcDriver::write_ppd_file()' - Write a PPD file...
363//
364
365int // O - 0 on success, -1 on failure
366ppdcDriver::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
372{
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
387
388
389 // If we don't have a message catalog, use an empty (English) one...
390 if (!catalog)
391 {
392 catalog = new ppdcCatalog("en");
393 delete_cat = true;
394 }
395 else
396 delete_cat = false;
397
398 // Figure out the end-of-line string...
399 if (le == PPDC_LFONLY)
400 lf = "\n";
401 else if (le == PPDC_CRONLY)
402 lf = "\r";
403 else
404 lf = "\r\n";
405
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);
409 cupsFilePrintf(fp,
410 "*%% Created by the CUPS PPD Compiler " CUPS_SVERSION ".%s",
411 lf);
412 for (s = (ppdcString *)copyright->first();
413 s;
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);
418
419 a = find_attr("LanguageVersion", NULL);
420 cupsFilePrintf(fp, "*LanguageVersion: %s%s",
421 catalog->find_message(a ? a->value->value : "English"), lf);
422
423 a = find_attr("LanguageEncoding", NULL);
424 cupsFilePrintf(fp, "*LanguageEncoding: %s%s",
425 catalog->find_message(a ? a->value->value : "ISOLatin1"), lf);
426
427 cupsFilePrintf(fp, "*PCFileName: \"%s\"%s", pc_file_name->value, lf);
428
429 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
430 if (!strcmp(a->name->value, "Product"))
431 break;
432
433 if (a)
434 {
435 for (; a; a = (ppdcAttr *)attrs->next())
436 if (!strcmp(a->name->value, "Product"))
437 cupsFilePrintf(fp, "*Product: \"%s\"%s", a->value->value, lf);
438 }
439 else
bdd6c45b 440 cupsFilePrintf(fp, "*Product: \"(%s)\"%s", model_name->value, lf);
ac884b6a
MS
441
442 cupsFilePrintf(fp, "*Manufacturer: \"%s\"%s",
443 catalog->find_message(manufacturer->value), lf);
444
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);
453 else
454 cupsFilePrintf(fp, "*ModelName: \"%s\"%s",
455 catalog->find_message(model_name->value), lf);
456
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);
465 else
466 cupsFilePrintf(fp, "*ShortNickName: \"%s\"%s",
467 catalog->find_message(model_name->value), lf);
468
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,
477 lf);
478 else
479 cupsFilePrintf(fp, "*NickName: \"%s, %s\"%s",
480 catalog->find_message(model_name->value), version->value,
481 lf);
482
483 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
484 if (!strcmp(a->name->value, "PSVersion"))
485 break;
486
487 if (a)
488 {
489 for (; a; a = (ppdcAttr *)attrs->next())
490 if (!strcmp(a->name->value, "PSVersion"))
491 cupsFilePrintf(fp, "*PSVersion: \"%s\"%s", a->value->value, lf);
492 }
493 else
bdd6c45b 494 cupsFilePrintf(fp, "*PSVersion: \"(3010.000) 0\"%s", lf);
ac884b6a
MS
495
496 if ((a = find_attr("LanguageLevel", NULL)) != NULL)
497 cupsFilePrintf(fp, "*LanguageLevel: \"%s\"%s", a->value->value, lf);
498 else
499 cupsFilePrintf(fp, "*LanguageLevel: \"3\"%s", lf);
500
501 cupsFilePrintf(fp, "*ColorDevice: %s%s", color_device ? "True" : "False", lf);
502
503 if ((a = find_attr("DefaultColorSpace", NULL)) != NULL)
504 cupsFilePrintf(fp, "*DefaultColorSpace: %s%s", a->value->value, lf);
505 else
506 cupsFilePrintf(fp, "*DefaultColorSpace: %s%s",
507 color_device ? "RGB" : "Gray", lf);
508
509 if ((a = find_attr("FileSystem", NULL)) != NULL)
510 cupsFilePrintf(fp, "*FileSystem: %s%s", a->value->value, lf);
511 else
512 cupsFilePrintf(fp, "*FileSystem: False%s", lf);
513
514 cupsFilePrintf(fp, "*Throughput: \"%d\"%s", throughput, lf);
515
516 if ((a = find_attr("LandscapeOrientation", NULL)) != NULL)
517 cupsFilePrintf(fp, "*LandscapeOrientation: %s%s", a->value->value, lf);
518 else
519 cupsFilePrintf(fp, "*LandscapeOrientation: Plus90%s", lf);
520
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);
525
526 if (attrs->count)
527 {
528 // Write driver-defined attributes...
529 cupsFilePrintf(fp, "*%% Driver-defined attributes...%s", lf);
530 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
531 {
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") ||
4509bb49 544 !strcmp(a->name->value, "cupsVersion"))
ac884b6a
MS
545 continue;
546
4509bb49
MS
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")))
553 continue;
554
ac884b6a
MS
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);
559 else
560 cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
561 a->text->value);
562
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))
572 {
573 cupsFilePrintf(fp, ": \"%s\"%s", a->value->value, lf);
574
575 if (strchr(a->value->value, '\n'))
576 cupsFilePrintf(fp, "*End%s", lf);
577 }
578 else
579 cupsFilePrintf(fp, ": %s%s", a->value->value, lf);
580 }
581 }
582
583 if (type != PPDC_DRIVER_PS || filters->count)
584 {
585 if ((a = find_attr("cupsVersion", NULL)) != NULL)
586 cupsFilePrintf(fp, "*cupsVersion: %s%s", a->value->value, lf);
587 else
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);
593
594 if (filters->count)
595 {
596 for (f = (ppdcFilter *)filters->first();
597 f;
598 f = (ppdcFilter *)filters->next())
599 cupsFilePrintf(fp, "*cupsFilter: \"%s %d %s\"%s", f->mime_type->value,
600 f->cost, f->program->value, lf);
601 }
602 else
603 {
604 switch (type)
605 {
606 case PPDC_DRIVER_LABEL :
607 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
608 "rastertolabel\"%s", lf);
609 break;
610
611 case PPDC_DRIVER_EPSON :
612 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
613 "rastertoepson\"%s", lf);
614 break;
615
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);
621 break;
622
623 case PPDC_DRIVER_HP :
624 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
625 "rastertohp\"%s", lf);
626 break;
627
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);
633 break;
634
635 default :
636 break;
637 }
638 }
639
640 for (p = (ppdcProfile *)profiles->first();
641 p;
642 p = (ppdcProfile *)profiles->next())
643 cupsFilePrintf(fp,
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],
652 p->profile[8], lf);
653 }
654
655 if (locales)
656 {
657 // Add localizations for additional languages...
658 ppdcString *locale; // Locale name
659 ppdcCatalog *locatalog; // Message catalog for locale
660
661
662 // Write the list of languages...
663 cupsFilePrintf(fp, "*cupsLanguages: \"en");
664
665 for (locale = (ppdcString *)locales->first();
666 locale;
667 locale = (ppdcString *)locales->next())
668 {
669 // Skip (US) English...
670 if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
671 continue;
672
673 // See if we have a po file for this language...
674 if (!src->find_po(locale->value))
675 {
676 // No, see if we can use the base file?
677 locatalog = new ppdcCatalog(locale->value);
678
679 if (locatalog->messages->count == 0)
680 {
681 // No, skip this one...
61cf44e2
MS
682 _cupsLangPrintf(stderr,
683 _("ppdc: No message catalog provided for locale "
684 "%s!\n"), locale->value);
ac884b6a
MS
685 continue;
686 }
687
688 // Add the base file to the list...
689 src->po_files->add(locatalog);
690 }
691
692 cupsFilePrintf(fp, " %s", locale->value);
693 }
694
695 cupsFilePrintf(fp, "\"%s", lf);
696 }
697
698 for (cn = (ppdcConstraint *)constraints->first();
699 cn;
700 cn = (ppdcConstraint *)constraints->next())
701 {
702 // First constrain 1 against 2...
703 if (!strncmp(cn->option1->value, "*Custom", 7) ||
704 !strncmp(cn->option2->value, "*Custom", 7))
61cf44e2 705 cupsFilePuts(fp, "*NonUIConstraints: ");
ac884b6a 706 else
61cf44e2 707 cupsFilePuts(fp, "*UIConstraints: ");
ac884b6a
MS
708
709 if (cn->option1->value[0] != '*')
710 cupsFilePutChar(fp, '*');
711
61cf44e2 712 cupsFilePuts(fp, cn->option1->value);
ac884b6a
MS
713
714 if (cn->choice1->value)
715 cupsFilePrintf(fp, " %s", cn->choice1->value);
716
717 cupsFilePutChar(fp, ' ');
718
719 if (cn->option2->value[0] != '*')
720 cupsFilePutChar(fp, '*');
721
61cf44e2 722 cupsFilePuts(fp, cn->option2->value);
ac884b6a
MS
723
724 if (cn->choice2->value)
725 cupsFilePrintf(fp, " %s", cn->choice2->value);
726
61cf44e2 727 cupsFilePuts(fp, lf);
ac884b6a
MS
728
729 // Then constrain 2 against 1...
730 if (!strncmp(cn->option1->value, "*Custom", 7) ||
731 !strncmp(cn->option2->value, "*Custom", 7))
61cf44e2 732 cupsFilePuts(fp, "*NonUIConstraints: ");
ac884b6a 733 else
61cf44e2 734 cupsFilePuts(fp, "*UIConstraints: ");
ac884b6a
MS
735
736 if (cn->option2->value[0] != '*')
737 cupsFilePutChar(fp, '*');
738
61cf44e2 739 cupsFilePuts(fp, cn->option2->value);
ac884b6a
MS
740
741 if (cn->choice2->value)
742 cupsFilePrintf(fp, " %s", cn->choice2->value);
743
744 cupsFilePutChar(fp, ' ');
745
746 if (cn->option1->value[0] != '*')
747 cupsFilePutChar(fp, '*');
748
61cf44e2 749 cupsFilePuts(fp, cn->option1->value);
ac884b6a
MS
750
751 if (cn->choice1->value)
752 cupsFilePrintf(fp, " %s", cn->choice1->value);
753
754 cupsFilePuts(fp, lf);
755 }
756
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);
762
763 for (m = (ppdcMediaSize *)sizes->first();
764 m;
765 m = (ppdcMediaSize *)sizes->next())
766 if (m->size_code->value)
767 {
768 cupsFilePrintf(fp, "*PageSize %s/%s: \"%s\"%s",
769 m->name->value, catalog->find_message(m->text->value),
770 m->size_code->value, lf);
771
772 if (strchr(m->size_code->value, '\n') ||
773 strchr(m->size_code->value, '\r'))
774 cupsFilePrintf(fp, "*End%s", lf);
775 }
776 else
777 cupsFilePrintf(fp,
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);
782
783 if ((a = find_attr("?PageSize", NULL)) != NULL)
784 {
785 cupsFilePrintf(fp, "*?PageSize: \"%s\"%s", a->value->value, lf);
786
787 if (strchr(a->value->value, '\n') ||
788 strchr(a->value->value, '\r'))
789 cupsFilePrintf(fp, "*End%s", lf);
790 }
791
792 cupsFilePrintf(fp, "*CloseUI: *PageSize%s", lf);
793
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);
799
800 for (m = (ppdcMediaSize *)sizes->first();
801 m;
802 m = (ppdcMediaSize *)sizes->next())
803 if (m->region_code->value)
804 {
805 cupsFilePrintf(fp, "*PageRegion %s/%s: \"%s\"%s",
806 m->name->value, catalog->find_message(m->text->value),
807 m->region_code->value, lf);
808
809 if (strchr(m->region_code->value, '\n') ||
810 strchr(m->region_code->value, '\r'))
811 cupsFilePrintf(fp, "*End%s", lf);
812 }
813 else
814 cupsFilePrintf(fp,
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);
819
820 if ((a = find_attr("?PageRegion", NULL)) != NULL)
821 {
822 cupsFilePrintf(fp, "*?PageRegion: \"%s\"%s", a->value->value, lf);
823
824 if (strchr(a->value->value, '\n') ||
825 strchr(a->value->value, '\r'))
826 cupsFilePrintf(fp, "*End%s", lf);
827 }
828
829 cupsFilePrintf(fp, "*CloseUI: *PageRegion%s", lf);
830
831 // ImageableArea info...
832 cupsFilePrintf(fp, "*DefaultImageableArea: %s%s",
833 default_size ? default_size->value : "Letter", lf);
834
835 for (m = (ppdcMediaSize *)sizes->first();
836 m;
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,
841 lf);
842
843 if ((a = find_attr("?ImageableArea", NULL)) != NULL)
844 {
845 cupsFilePrintf(fp, "*?ImageableArea: \"%s\"%s", a->value->value, lf);
846
847 if (strchr(a->value->value, '\n') ||
848 strchr(a->value->value, '\r'))
849 cupsFilePrintf(fp, "*End%s", lf);
850 }
851
852 // PaperDimension info...
853 cupsFilePrintf(fp, "*DefaultPaperDimension: %s%s",
854 default_size ? default_size->value : "Letter", lf);
855
856 for (m = (ppdcMediaSize *)sizes->first();
857 m;
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);
862
863 if ((a = find_attr("?PaperDimension", NULL)) != NULL)
864 {
865 cupsFilePrintf(fp, "*?PaperDimension: \"%s\"%s", a->value->value, lf);
866
867 if (strchr(a->value->value, '\n') ||
868 strchr(a->value->value, '\r'))
869 cupsFilePrintf(fp, "*End%s", lf);
870 }
871
872 // Custom size support...
873 if (variable_paper_size)
874 {
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);
879
880 if (custom_size_code && custom_size_code->value)
881 {
882 cupsFilePrintf(fp, "*CustomPageSize True: \"%s\"%s",
883 custom_size_code->value, lf);
884
885 if (strchr(custom_size_code->value, '\n') ||
886 strchr(custom_size_code->value, '\r'))
887 cupsFilePrintf(fp, "*End%s", lf);
888 }
889 else
890 cupsFilePrintf(fp,
891 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
892 "/ImagingBBox null>>setpagedevice\"%s", lf);
893
894 if ((a = find_attr("ParamCustomPageSize", "Width")) != NULL)
895 cupsFilePrintf(fp, "*ParamCustomPageSize Width: %s%s", a->value->value,
896 lf);
897 else
898 cupsFilePrintf(fp, "*ParamCustomPageSize Width: 1 points %.2f %.2f%s",
899 min_width, max_width, lf);
900
901 if ((a = find_attr("ParamCustomPageSize", "Height")) != NULL)
902 cupsFilePrintf(fp, "*ParamCustomPageSize Height: %s%s", a->value->value,
903 lf);
904 else
905 cupsFilePrintf(fp, "*ParamCustomPageSize Height: 2 points %.2f %.2f%s",
906 min_length, max_length, lf);
907
908 if ((a = find_attr("ParamCustomPageSize", "WidthOffset")) != NULL)
909 cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: %s%s",
910 a->value->value, lf);
911 else
912 cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf);
913
914 if ((a = find_attr("ParamCustomPageSize", "HeightOffset")) != NULL)
915 cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: %s%s",
916 a->value->value, lf);
917 else
918 cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf);
919
920 if ((a = find_attr("ParamCustomPageSize", "Orientation")) != NULL)
921 cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: %s%s",
922 a->value->value, lf);
923 else
924 cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf);
925 }
926
927 if (type != PPDC_DRIVER_PS && !find_attr("RequiresPageRegion", NULL))
928 cupsFilePrintf(fp, "*RequiresPageRegion All: True%s", lf);
929
930 // All other options...
931 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
932 {
933 if (!g->options->count)
934 continue;
935
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);
939
940 for (o = (ppdcOption *)g->options->first();
941 o;
942 o = (ppdcOption *)g->options->next())
943 {
944 if (!o->choices->count)
945 continue;
946
947 if (!o->text->value || !strcmp(o->name->value, o->text->value))
d1c13e16 948 cupsFilePrintf(fp, "*OpenUI *%s/%s: ", o->name->value,
d2354e63 949 catalog->find_message(o->name->value));
ac884b6a
MS
950 else
951 cupsFilePrintf(fp, "*OpenUI *%s/%s: ", o->name->value,
952 catalog->find_message(o->text->value));
953
954 switch (o->type)
955 {
956 case PPDC_BOOLEAN :
957 cupsFilePrintf(fp, "Boolean%s", lf);
958 break;
959 default :
960 cupsFilePrintf(fp, "PickOne%s", lf);
961 break;
962 case PPDC_PICKMANY :
963 cupsFilePrintf(fp, "PickMany%s", lf);
964 break;
965 }
966
967 cupsFilePrintf(fp, "*OrderDependency: %.1f ", o->order);
968 switch (o->section)
969 {
970 default :
971 cupsFilePrintf(fp, "AnySetup");
972 break;
973 case PPDC_SECTION_DOCUMENT :
974 cupsFilePrintf(fp, "DocumentSetup");
975 break;
976 case PPDC_SECTION_EXIT :
977 cupsFilePrintf(fp, "ExitServer");
978 break;
979 case PPDC_SECTION_JCL :
980 cupsFilePrintf(fp, "JCLSetup");
981 break;
982 case PPDC_SECTION_PAGE :
983 cupsFilePrintf(fp, "PageSetup");
984 break;
985 case PPDC_SECTION_PROLOG :
986 cupsFilePrintf(fp, "Prolog");
987 break;
988 }
989
990 cupsFilePrintf(fp, " *%s%s", o->name->value, lf);
991
992 if (o->defchoice)
993 {
994 // Use the programmer-supplied default...
995 cupsFilePrintf(fp, "*Default%s: %s%s", o->name->value,
996 o->defchoice->value, lf);
997 }
998 else
999 {
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,
1003 lf);
1004 }
1005
1006 for (c = (ppdcChoice *)o->choices->first();
1007 c;
1008 c = (ppdcChoice *)o->choices->next())
1009 {
1010 // Write this choice...
1011 if (!c->text->value || !strcmp(c->name->value, c->text->value))
d2354e63
MS
1012 cupsFilePrintf(fp, "*%s %s: \"%s\"%s", o->name->value,
1013 catalog->find_message(c->name->value),
ac884b6a
MS
1014 c->code->value, lf);
1015 else
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);
1019
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);
1024 }
1025
1026 snprintf(query, sizeof(query), "?%s", o->name->value);
1027
1028 if ((a = find_attr(query, NULL)) != NULL)
1029 {
1030 cupsFilePrintf(fp, "*%s: \"%s\"\n", query, a->value->value);
1031
1032 if (strchr(a->value->value, '\n') ||
1033 strchr(a->value->value, '\r'))
1034 cupsFilePrintf(fp, "*End%s", lf);
1035 }
1036
1037 cupsFilePrintf(fp, "*CloseUI: *%s%s", o->name->value, lf);
1038 }
1039
1040 if (strcasecmp(g->name->value, "General"))
1041 cupsFilePrintf(fp, "*CloseGroup: %s%s", g->name->value, lf);
1042 }
1043
1044 if (locales)
1045 {
1046 // Add localizations for additional languages...
1047 ppdcString *locale; // Locale name
1048 ppdcCatalog *locatalog; // Message catalog for locale
1049
1050
1051 // Write the translation strings for each language...
1052 for (locale = (ppdcString *)locales->first();
1053 locale;
1054 locale = (ppdcString *)locales->next())
1055 {
1056 // Skip (US) English...
1057 if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
1058 continue;
1059
1060 // Skip missing languages...
1061 if ((locatalog = src->find_po(locale->value)) == NULL)
1062 continue;
1063
1064 // Do the core stuff first...
1065 cupsFilePrintf(fp, "*%s.Translation Manufacturer/%s: \"\"%s",
1066 locale->value,
1067 locatalog->find_message(manufacturer->value), lf);
1068
1069 if ((a = find_attr("ModelName", NULL)) != NULL)
1070 cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
1071 locale->value,
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",
1076 locale->value,
1077 locatalog->find_message(manufacturer->value),
1078 locatalog->find_message(model_name->value), lf);
1079 else
1080 cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
1081 locale->value,
1082 locatalog->find_message(model_name->value), lf);
1083
1084 if ((a = find_attr("ShortNickName", NULL)) != NULL)
1085 cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
1086 locale->value,
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",
1091 locale->value,
1092 locatalog->find_message(manufacturer->value),
1093 locatalog->find_message(model_name->value), lf);
1094 else
1095 cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
1096 locale->value,
1097 locatalog->find_message(model_name->value), lf);
1098
1099 if ((a = find_attr("NickName", NULL)) != NULL)
1100 cupsFilePrintf(fp, "*%s.Translation NickName/%s: \"\"%s",
1101 locale->value,
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",
1106 locale->value,
1107 locatalog->find_message(manufacturer->value),
1108 locatalog->find_message(model_name->value),
1109 version->value, lf);
1110 else
1111 cupsFilePrintf(fp, "*%s.Translation NickName/%s, %s: \"\"%s",
1112 locale->value,
1113 locatalog->find_message(model_name->value),
1114 version->value, lf);
1115
1116 // Then the page sizes...
1117 cupsFilePrintf(fp, "*%s.Translation PageSize/%s: \"\"%s", locale->value,
1118 locatalog->find_message("Media Size"), lf);
1119
1120 for (m = (ppdcMediaSize *)sizes->first();
1121 m;
1122 m = (ppdcMediaSize *)sizes->next())
1123 {
1124 cupsFilePrintf(fp, "*%s.PageSize %s/%s: \"\"%s", locale->value,
1125 m->name->value, locatalog->find_message(m->text->value),
1126 lf);
1127 }
1128
1129 // Next the groups and options...
1130 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
1131 {
1132 if (!g->options->count)
1133 continue;
1134
1135 if (strcasecmp(g->name->value, "General"))
1136 cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
1137 g->name->value,
1138 locatalog->find_message(g->text->value), lf);
1139
1140 for (o = (ppdcOption *)g->options->first();
1141 o;
1142 o = (ppdcOption *)g->options->next())
1143 {
1144 if (!o->choices->count)
1145 continue;
1146
1147 cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
1148 o->name->value,
1149 locatalog->find_message(o->text->value ?
1150 o->text->value :
1151 o->name->value), lf);
1152
1153 for (c = (ppdcChoice *)o->choices->first();
1154 c;
1155 c = (ppdcChoice *)o->choices->next())
1156 {
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 ?
1161 c->text->value :
1162 c->name->value), lf);
1163 }
1164 }
1165 }
1166
1167 // Finally the localizable attributes...
1168 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
1169 {
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))
1173 continue;
1174
bdd6c45b
MS
1175 if (!a->localizable &&
1176 strcmp(a->name->value, "APCustomColorMatchingName") &&
ac884b6a
MS
1177 strcmp(a->name->value, "APPrinterPreset") &&
1178 strcmp(a->name->value, "cupsICCProfile") &&
1179 strcmp(a->name->value, "cupsIPPReason") &&
bdd6c45b 1180 strcmp(a->name->value, "cupsMarkerName") &&
ac884b6a
MS
1181 strncmp(a->name->value, "Custom", 6) &&
1182 strncmp(a->name->value, "ParamCustom", 11))
1183 continue;
1184
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),
bdd6c45b
MS
1189 ((a->localizable && a->value->value[0]) ||
1190 !strcmp(a->name->value, "cupsIPPReason")) ?
ac884b6a
MS
1191 locatalog->find_message(a->value->value) : "",
1192 lf);
1193 }
1194 }
1195 }
1196
1197 if (default_font && default_font->value)
1198 cupsFilePrintf(fp, "*DefaultFont: %s%s", default_font->value, lf);
1199 else
1200 cupsFilePrintf(fp, "*DefaultFont: Courier%s", lf);
1201
1202 for (fn = (ppdcFont *)fonts->first(); fn; fn = (ppdcFont *)fonts->next())
1203 if (!strcmp(fn->name->value, "*"))
1204 {
1205 for (bfn = (ppdcFont *)src->base_fonts->first();
1206 bfn;
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);
1212 }
1213 else
1214 cupsFilePrintf(fp, "*Font %s: %s \"%s\" %s %s%s",
1215 fn->name->value, fn->encoding->value, fn->version->value,
1216 fn->charset->value,
1217 fn->status == PPDC_FONT_ROM ? "ROM" : "Disk", lf);
1218
1219 cupsFilePrintf(fp, "*%% End of %s, %05d bytes.%s", pc_file_name->value,
1220 (int)(cupsFileTell(fp) + 25 + strlen(pc_file_name->value)),
1221 lf);
1222
1223 if (delete_cat)
e4572d57 1224 catalog->release();
ac884b6a
MS
1225
1226 return (0);
1227}
1228
1229
1230//
1231// End of "$Id$".
1232//