]> git.ipfire.org Git - thirdparty/cups.git/blame - ppdc/ppdc-driver.cxx
License change: Apache License, Version 2.0.
[thirdparty/cups.git] / ppdc / ppdc-driver.cxx
CommitLineData
ac884b6a 1//
7e86f2f6 2// PPD file compiler definitions for the CUPS PPD Compiler.
ac884b6a 3//
7e86f2f6
MS
4// Copyright 2007-2014 by Apple Inc.
5// Copyright 2002-2006 by Easy Software Products.
ac884b6a 6//
e3101897 7// Licensed under Apache License v2.0. See the file "LICENSE" for more information.
ac884b6a
MS
8//
9
10//
11// Include necessary headers...
12//
13
38e73f87 14#include "ppdc-private.h"
ac884b6a
MS
15
16
17//
18// 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
19//
20
21ppdcDriver::ppdcDriver(ppdcDriver *d) // I - Printer driver template
94da7e34 22 : ppdcShared()
ac884b6a
MS
23{
24 ppdcGroup *g; // Current group
25
26
94da7e34
MS
27 PPDC_NEW;
28
ac884b6a
MS
29 if (d)
30 {
31 // Bump the use count of any strings we inherit...
32 if (d->manufacturer)
e4572d57 33 d->manufacturer->retain();
ac884b6a 34 if (d->version)
e4572d57 35 d->version->retain();
ac884b6a 36 if (d->default_font)
e4572d57 37 d->default_font->retain();
ac884b6a 38 if (d->default_size)
e4572d57 39 d->default_size->retain();
ac884b6a 40 if (d->custom_size_code)
e4572d57 41 d->custom_size_code->retain();
ac884b6a
MS
42
43 // Copy all of the data from the driver template...
44 copyright = new ppdcArray(d->copyright);
45 manufacturer = d->manufacturer;
46 model_name = 0;
bdd6c45b 47 file_name = 0;
ac884b6a
MS
48 pc_file_name = 0;
49 type = d->type;
50 version = d->version;
51 model_number = d->model_number;
52 manual_copies = d->manual_copies;
53 color_device = d->color_device;
54 throughput = d->throughput;
55 attrs = new ppdcArray(d->attrs);
56 constraints = new ppdcArray(d->constraints);
57 filters = new ppdcArray(d->filters);
58 fonts = new ppdcArray(d->fonts);
59 profiles = new ppdcArray(d->profiles);
60 sizes = new ppdcArray(d->sizes);
61 default_font = d->default_font;
62 default_size = d->default_size;
63 variable_paper_size = d->variable_paper_size;
64 custom_size_code = d->custom_size_code;
65 left_margin = d->left_margin;
66 bottom_margin = d->bottom_margin;
67 right_margin = d->right_margin;
68 top_margin = d->top_margin;
69 max_width = d->max_width;
70 max_length = d->max_length;
71 min_width = d->min_width;
72 min_length = d->min_length;
73
74 // Then copy the groups manually, since we want separate copies
75 // of the groups and options...
76 groups = new ppdcArray();
77
78 for (g = (ppdcGroup *)d->groups->first(); g; g = (ppdcGroup *)d->groups->next())
79 groups->add(new ppdcGroup(g));
80 }
81 else
82 {
83 // Zero all of the data in the driver...
84 copyright = new ppdcArray();
85 manufacturer = 0;
86 model_name = 0;
bdd6c45b 87 file_name = 0;
ac884b6a
MS
88 pc_file_name = 0;
89 version = 0;
90 type = PPDC_DRIVER_CUSTOM;
91 model_number = 0;
92 manual_copies = 0;
93 color_device = 0;
94 throughput = 1;
95 attrs = new ppdcArray();
96 constraints = new ppdcArray();
97 fonts = new ppdcArray();
98 filters = new ppdcArray();
99 groups = new ppdcArray();
100 profiles = new ppdcArray();
101 sizes = new ppdcArray();
102 default_font = 0;
103 default_size = 0;
104 variable_paper_size = 0;
105 custom_size_code = 0;
106 left_margin = 0;
107 bottom_margin = 0;
108 right_margin = 0;
109 top_margin = 0;
110 max_width = 0;
111 max_length = 0;
112 min_width = 0;
113 min_length = 0;
114 }
115}
116
117
118//
119// 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
120//
121
122ppdcDriver::~ppdcDriver()
123{
94da7e34
MS
124 PPDC_DELETE;
125
e4572d57 126 copyright->release();
ac884b6a
MS
127
128 if (manufacturer)
129 manufacturer->release();
130 if (model_name)
131 model_name->release();
bdd6c45b
MS
132 if (file_name)
133 file_name->release();
ac884b6a
MS
134 if (pc_file_name)
135 pc_file_name->release();
136 if (version)
137 version->release();
138 if (default_font)
139 default_font->release();
140 if (default_size)
141 default_size->release();
142 if (custom_size_code)
143 custom_size_code->release();
144
e4572d57
MS
145 attrs->release();
146 constraints->release();
147 filters->release();
148 fonts->release();
149 groups->release();
150 profiles->release();
151 sizes->release();
ac884b6a
MS
152}
153
154
155//
156// 'ppdcDriver::find_attr()' - Find an attribute.
157//
158
159ppdcAttr * // O - Attribute or NULL
160ppdcDriver::find_attr(const char *k, // I - Keyword string
161 const char *s) // I - Spec string
162{
163 ppdcAttr *a; // Current attribute
164
165
166 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
167 if (!strcmp(a->name->value, k) &&
168 ((!s && (!a->selector->value || !a->selector->value[0])) ||
f11a948a 169 (s && a->selector->value && !strcmp(a->selector->value, s))))
ac884b6a
MS
170 return (a);
171
172 return (NULL);
173}
174
175
176//
177// 'ppdcDriver::find_group()' - Find a group.
178//
179
180ppdcGroup * // O - Matching group or NULL
181ppdcDriver::find_group(const char *n) // I - Group name
182{
183 ppdcGroup *g; // Current group
184
185
186 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
88f9aafc 187 if (!_cups_strcasecmp(n, g->name->value))
ac884b6a
MS
188 return (g);
189
190 return (0);
191}
192
193
194//
195// 'ppdcDriver::find_option()' - Find an option.
196//
197
198ppdcOption * // O - Matching option or NULL
199ppdcDriver::find_option(const char *n) // I - Option name
97c9a8d7
MS
200{
201 return (find_option_group(n, (ppdcGroup **)0));
202}
203
204
205//
206// 'ppdcDriver::find_option_group()' - Find an option and its group.
207//
208
209ppdcOption * // O - Matching option or NULL
210ppdcDriver::find_option_group(
211 const char *n, // I - Option name
212 ppdcGroup **mg) // O - Matching group or NULL
ac884b6a
MS
213{
214 ppdcGroup *g; // Current group
215 ppdcOption *o; // Current option
216
217
218 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
219 for (o = (ppdcOption *)g->options->first(); o; o = (ppdcOption *)g->options->next())
88f9aafc 220 if (!_cups_strcasecmp(n, o->name->value))
97c9a8d7
MS
221 {
222 if (mg)
223 *mg = g;
224
ac884b6a 225 return (o);
97c9a8d7
MS
226 }
227
228 if (mg)
229 *mg = (ppdcGroup *)0;
ac884b6a
MS
230
231 return (0);
232}
233
234
235//
236// 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
237//
238
239void
bdd6c45b
MS
240ppdcDriver::set_custom_size_code(
241 const char *c) // I - CustomPageSize code
ac884b6a
MS
242{
243 if (custom_size_code)
244 custom_size_code->release();
245
246 custom_size_code = new ppdcString(c);
247}
248
249
250//
251// 'ppdcDriver::set_default_font()' - Set the default font name.
252//
253
254void
bdd6c45b
MS
255ppdcDriver::set_default_font(
256 ppdcFont *f) // I - Font
ac884b6a
MS
257{
258 if (default_font)
259 default_font->release();
260
261 if (f)
262 {
e4572d57 263 f->name->retain();
ac884b6a
MS
264 default_font = f->name;
265 }
266 else
267 default_font = 0;
268}
269
270
271//
272// 'ppdcDriver::set_default_size()' - Set the default size name.
273//
274
275void
bdd6c45b
MS
276ppdcDriver::set_default_size(
277 ppdcMediaSize *m) // I - Media size
ac884b6a
MS
278{
279 if (default_size)
280 default_size->release();
281
282 if (m)
283 {
e4572d57 284 m->name->retain();
ac884b6a
MS
285 default_size = m->name;
286 }
287 else
288 default_size = 0;
289}
290
291
bdd6c45b
MS
292//
293// 'ppdcDriver::set_file_name()' - Set the full filename.
294//
295
296void
297ppdcDriver::set_file_name(const char *f)// I - Filename
298{
299 if (file_name)
300 file_name->release();
301
302 file_name = new ppdcString(f);
303}
304
305
ac884b6a
MS
306//
307// 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
308//
309
310void
bdd6c45b
MS
311ppdcDriver::set_manufacturer(
312 const char *m) // I - Model name
ac884b6a
MS
313{
314 if (manufacturer)
315 manufacturer->release();
316
317 manufacturer = new ppdcString(m);
318}
319
320
321//
322// 'ppdcDriver::set_model_name()' - Set the model name.
323//
324
325void
bdd6c45b
MS
326ppdcDriver::set_model_name(
327 const char *m) // I - Model name
ac884b6a
MS
328{
329 if (model_name)
330 model_name->release();
331
332 model_name = new ppdcString(m);
333}
334
335
336//
337// 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
338//
339
340void
bdd6c45b
MS
341ppdcDriver::set_pc_file_name(
342 const char *f) // I - Filename
ac884b6a
MS
343{
344 if (pc_file_name)
345 pc_file_name->release();
346
347 pc_file_name = new ppdcString(f);
348}
349
350
351//
352// 'ppdcDriver::set_version()' - Set the version string.
353//
354
355void
356ppdcDriver::set_version(const char *v) // I - Version
357{
358 if (version)
359 version->release();
360
361 version = new ppdcString(v);
362}
363
364
365//
366// 'ppdcDriver::write_ppd_file()' - Write a PPD file...
367//
368
369int // O - 0 on success, -1 on failure
370ppdcDriver::write_ppd_file(
371 cups_file_t *fp, // I - PPD file
372 ppdcCatalog *catalog, // I - Message catalog
373 ppdcArray *locales, // I - Additional languages to add
374 ppdcSource *src, // I - Driver source
375 ppdcLineEnding le) // I - Line endings to use
376{
377 bool delete_cat; // Delete the catalog when we are done?
f11a948a
MS
378 char query[42], // Query attribute
379 custom[42]; // Custom attribute
ac884b6a
MS
380 ppdcString *s; // Copyright string
381 ppdcGroup *g; // Current group
382 ppdcOption *o; // Current option
383 ppdcChoice *c; // Current choice
384 ppdcMediaSize *m; // Current media size
385 ppdcProfile *p; // Current color profile
386 ppdcFilter *f; // Current filter
387 ppdcFont *fn, // Current font
388 *bfn; // Current base font
389 ppdcConstraint *cn; // Current constraint
390 ppdcAttr *a; // Current attribute
391 const char *lf; // Linefeed character to use
392
393
394 // If we don't have a message catalog, use an empty (English) one...
395 if (!catalog)
396 {
e34d3482 397 catalog = new ppdcCatalog(NULL);
ac884b6a
MS
398 delete_cat = true;
399 }
400 else
401 delete_cat = false;
402
403 // Figure out the end-of-line string...
404 if (le == PPDC_LFONLY)
405 lf = "\n";
406 else if (le == PPDC_CRONLY)
407 lf = "\r";
408 else
409 lf = "\r\n";
410
411 // Write the standard header stuff...
412 cupsFilePrintf(fp, "*PPD-Adobe: \"4.3\"%s", lf);
f11a948a
MS
413 cupsFilePrintf(fp, "*%%%%%%%% PPD file for %s with CUPS.%s",
414 model_name->value, lf);
ac884b6a 415 cupsFilePrintf(fp,
f11a948a
MS
416 "*%%%%%%%% Created by the CUPS PPD Compiler " CUPS_SVERSION
417 ".%s", lf);
ac884b6a
MS
418 for (s = (ppdcString *)copyright->first();
419 s;
420 s = (ppdcString *)copyright->next())
421 cupsFilePrintf(fp, "*%% %s%s", catalog->find_message(s->value), lf);
422 cupsFilePrintf(fp, "*FormatVersion: \"4.3\"%s", lf);
423 cupsFilePrintf(fp, "*FileVersion: \"%s\"%s", version->value, lf);
424
425 a = find_attr("LanguageVersion", NULL);
426 cupsFilePrintf(fp, "*LanguageVersion: %s%s",
427 catalog->find_message(a ? a->value->value : "English"), lf);
428
429 a = find_attr("LanguageEncoding", NULL);
430 cupsFilePrintf(fp, "*LanguageEncoding: %s%s",
431 catalog->find_message(a ? a->value->value : "ISOLatin1"), lf);
432
433 cupsFilePrintf(fp, "*PCFileName: \"%s\"%s", pc_file_name->value, lf);
434
435 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
436 if (!strcmp(a->name->value, "Product"))
437 break;
438
439 if (a)
440 {
441 for (; a; a = (ppdcAttr *)attrs->next())
442 if (!strcmp(a->name->value, "Product"))
443 cupsFilePrintf(fp, "*Product: \"%s\"%s", a->value->value, lf);
444 }
445 else
bdd6c45b 446 cupsFilePrintf(fp, "*Product: \"(%s)\"%s", model_name->value, lf);
ac884b6a
MS
447
448 cupsFilePrintf(fp, "*Manufacturer: \"%s\"%s",
449 catalog->find_message(manufacturer->value), lf);
450
451 if ((a = find_attr("ModelName", NULL)) != NULL)
452 cupsFilePrintf(fp, "*ModelName: \"%s\"%s",
453 catalog->find_message(a->value->value), lf);
88f9aafc 454 else if (_cups_strncasecmp(model_name->value, manufacturer->value,
ac884b6a
MS
455 strlen(manufacturer->value)))
456 cupsFilePrintf(fp, "*ModelName: \"%s %s\"%s",
457 catalog->find_message(manufacturer->value),
458 catalog->find_message(model_name->value), lf);
459 else
460 cupsFilePrintf(fp, "*ModelName: \"%s\"%s",
461 catalog->find_message(model_name->value), lf);
462
463 if ((a = find_attr("ShortNickName", NULL)) != NULL)
464 cupsFilePrintf(fp, "*ShortNickName: \"%s\"%s",
465 catalog->find_message(a->value->value), lf);
88f9aafc 466 else if (_cups_strncasecmp(model_name->value, manufacturer->value,
ac884b6a
MS
467 strlen(manufacturer->value)))
468 cupsFilePrintf(fp, "*ShortNickName: \"%s %s\"%s",
469 catalog->find_message(manufacturer->value),
470 catalog->find_message(model_name->value), lf);
471 else
472 cupsFilePrintf(fp, "*ShortNickName: \"%s\"%s",
473 catalog->find_message(model_name->value), lf);
474
475 if ((a = find_attr("NickName", NULL)) != NULL)
476 cupsFilePrintf(fp, "*NickName: \"%s\"%s",
477 catalog->find_message(a->value->value), lf);
88f9aafc 478 else if (_cups_strncasecmp(model_name->value, manufacturer->value,
ac884b6a
MS
479 strlen(manufacturer->value)))
480 cupsFilePrintf(fp, "*NickName: \"%s %s, %s\"%s",
481 catalog->find_message(manufacturer->value),
482 catalog->find_message(model_name->value), version->value,
483 lf);
484 else
485 cupsFilePrintf(fp, "*NickName: \"%s, %s\"%s",
486 catalog->find_message(model_name->value), version->value,
487 lf);
488
489 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
490 if (!strcmp(a->name->value, "PSVersion"))
491 break;
492
493 if (a)
494 {
495 for (; a; a = (ppdcAttr *)attrs->next())
496 if (!strcmp(a->name->value, "PSVersion"))
497 cupsFilePrintf(fp, "*PSVersion: \"%s\"%s", a->value->value, lf);
498 }
499 else
bdd6c45b 500 cupsFilePrintf(fp, "*PSVersion: \"(3010.000) 0\"%s", lf);
ac884b6a
MS
501
502 if ((a = find_attr("LanguageLevel", NULL)) != NULL)
503 cupsFilePrintf(fp, "*LanguageLevel: \"%s\"%s", a->value->value, lf);
504 else
505 cupsFilePrintf(fp, "*LanguageLevel: \"3\"%s", lf);
506
507 cupsFilePrintf(fp, "*ColorDevice: %s%s", color_device ? "True" : "False", lf);
508
509 if ((a = find_attr("DefaultColorSpace", NULL)) != NULL)
510 cupsFilePrintf(fp, "*DefaultColorSpace: %s%s", a->value->value, lf);
511 else
512 cupsFilePrintf(fp, "*DefaultColorSpace: %s%s",
513 color_device ? "RGB" : "Gray", lf);
514
515 if ((a = find_attr("FileSystem", NULL)) != NULL)
516 cupsFilePrintf(fp, "*FileSystem: %s%s", a->value->value, lf);
517 else
518 cupsFilePrintf(fp, "*FileSystem: False%s", lf);
519
520 cupsFilePrintf(fp, "*Throughput: \"%d\"%s", throughput, lf);
521
522 if ((a = find_attr("LandscapeOrientation", NULL)) != NULL)
523 cupsFilePrintf(fp, "*LandscapeOrientation: %s%s", a->value->value, lf);
524 else
525 cupsFilePrintf(fp, "*LandscapeOrientation: Plus90%s", lf);
526
527 if ((a = find_attr("TTRasterizer", NULL)) != NULL)
528 cupsFilePrintf(fp, "*TTRasterizer: %s%s", a->value->value, lf);
529 else if (type != PPDC_DRIVER_PS)
530 cupsFilePrintf(fp, "*TTRasterizer: Type42%s", lf);
531
7a0cbd5e
MS
532 struct lconv *loc = localeconv();
533
ac884b6a
MS
534 if (attrs->count)
535 {
536 // Write driver-defined attributes...
537 cupsFilePrintf(fp, "*%% Driver-defined attributes...%s", lf);
538 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
539 {
540 if (!strcmp(a->name->value, "Product") ||
541 !strcmp(a->name->value, "PSVersion") ||
542 !strcmp(a->name->value, "LanguageLevel") ||
543 !strcmp(a->name->value, "DefaultColorSpace") ||
544 !strcmp(a->name->value, "FileSystem") ||
545 !strcmp(a->name->value, "LandscapeOrientation") ||
546 !strcmp(a->name->value, "TTRasterizer") ||
547 !strcmp(a->name->value, "LanguageVersion") ||
548 !strcmp(a->name->value, "LanguageEncoding") ||
549 !strcmp(a->name->value, "ModelName") ||
550 !strcmp(a->name->value, "NickName") ||
551 !strcmp(a->name->value, "ShortNickName") ||
4509bb49 552 !strcmp(a->name->value, "cupsVersion"))
ac884b6a
MS
553 continue;
554
4509bb49
MS
555 if (a->name->value[0] == '?' &&
556 (find_option(a->name->value + 1) ||
557 !strcmp(a->name->value, "?ImageableArea") ||
558 !strcmp(a->name->value, "?PageRegion") ||
559 !strcmp(a->name->value, "?PageSize") ||
560 !strcmp(a->name->value, "?PaperDimension")))
561 continue;
562
f11a948a
MS
563 if (!strncmp(a->name->value, "Custom", 6) &&
564 find_option(a->name->value + 6))
565 continue;
566
567 if (!strncmp(a->name->value, "ParamCustom", 11) &&
568 find_option(a->name->value + 11))
569 continue;
570
ac884b6a
MS
571 if (!a->selector->value || !a->selector->value[0])
572 cupsFilePrintf(fp, "*%s", a->name->value);
573 else if (!a->text->value || !a->text->value[0])
574 cupsFilePrintf(fp, "*%s %s", a->name->value, a->selector->value);
575 else
576 cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
577 a->text->value);
578
579 if (strcmp(a->value->value, "False") &&
580 strcmp(a->value->value, "True") &&
581 strcmp(a->name->value, "1284Modes") &&
582 strcmp(a->name->value, "InkName") &&
583 strcmp(a->name->value, "PageStackOrder") &&
584 strncmp(a->name->value, "ParamCustom", 11) &&
585 strcmp(a->name->value, "Protocols") &&
586 strcmp(a->name->value, "ReferencePunch") &&
587 strncmp(a->name->value, "Default", 7))
588 {
589 cupsFilePrintf(fp, ": \"%s\"%s", a->value->value, lf);
590
f11a948a 591 if (strchr(a->value->value, '\n') || strchr(a->value->value, '\r'))
ac884b6a
MS
592 cupsFilePrintf(fp, "*End%s", lf);
593 }
594 else
595 cupsFilePrintf(fp, ": %s%s", a->value->value, lf);
596 }
597 }
598
599 if (type != PPDC_DRIVER_PS || filters->count)
600 {
601 if ((a = find_attr("cupsVersion", NULL)) != NULL)
602 cupsFilePrintf(fp, "*cupsVersion: %s%s", a->value->value, lf);
603 else
604 cupsFilePrintf(fp, "*cupsVersion: %d.%d%s", CUPS_VERSION_MAJOR,
605 CUPS_VERSION_MINOR, lf);
606 cupsFilePrintf(fp, "*cupsModelNumber: %d%s", model_number, lf);
607 cupsFilePrintf(fp, "*cupsManualCopies: %s%s",
608 manual_copies ? "True" : "False", lf);
609
610 if (filters->count)
611 {
612 for (f = (ppdcFilter *)filters->first();
613 f;
614 f = (ppdcFilter *)filters->next())
615 cupsFilePrintf(fp, "*cupsFilter: \"%s %d %s\"%s", f->mime_type->value,
616 f->cost, f->program->value, lf);
617 }
618 else
619 {
620 switch (type)
621 {
622 case PPDC_DRIVER_LABEL :
623 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
624 "rastertolabel\"%s", lf);
625 break;
626
627 case PPDC_DRIVER_EPSON :
628 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
629 "rastertoepson\"%s", lf);
630 break;
631
632 case PPDC_DRIVER_ESCP :
633 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-command 50 "
634 "commandtoescpx\"%s", lf);
635 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
636 "rastertoescpx\"%s", lf);
637 break;
638
639 case PPDC_DRIVER_HP :
640 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
641 "rastertohp\"%s", lf);
642 break;
643
644 case PPDC_DRIVER_PCL :
645 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-command 50 "
646 "commandtopclx\"%s", lf);
647 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
648 "rastertopclx\"%s", lf);
649 break;
650
651 default :
652 break;
653 }
654 }
655
656 for (p = (ppdcProfile *)profiles->first();
657 p;
658 p = (ppdcProfile *)profiles->next())
7a0cbd5e
MS
659 {
660 char density[255], gamma[255], profile[9][255];
661
662 _cupsStrFormatd(density, density + sizeof(density), p->density, loc);
663 _cupsStrFormatd(gamma, gamma + sizeof(gamma), p->gamma, loc);
664
665 for (int i = 0; i < 9; i ++)
666 _cupsStrFormatd(profile[i], profile[i] + sizeof(profile[0]),
667 p->profile[i], loc);
ef55b745 668
ac884b6a 669 cupsFilePrintf(fp,
7a0cbd5e
MS
670 "*cupsColorProfile %s/%s: \"%s %s %s %s %s %s %s %s %s %s "
671 "%s\"%s", p->resolution->value, p->media_type->value,
672 density, gamma, profile[0], profile[1], profile[2],
673 profile[3], profile[4], profile[5], profile[6], profile[7],
674 profile[8], lf);
675 }
ac884b6a
MS
676 }
677
678 if (locales)
679 {
680 // Add localizations for additional languages...
681 ppdcString *locale; // Locale name
682 ppdcCatalog *locatalog; // Message catalog for locale
683
684
685 // Write the list of languages...
686 cupsFilePrintf(fp, "*cupsLanguages: \"en");
687
688 for (locale = (ppdcString *)locales->first();
689 locale;
690 locale = (ppdcString *)locales->next())
691 {
692 // Skip (US) English...
693 if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
694 continue;
695
696 // See if we have a po file for this language...
697 if (!src->find_po(locale->value))
698 {
699 // No, see if we can use the base file?
700 locatalog = new ppdcCatalog(locale->value);
701
702 if (locatalog->messages->count == 0)
703 {
704 // No, skip this one...
61cf44e2
MS
705 _cupsLangPrintf(stderr,
706 _("ppdc: No message catalog provided for locale "
0837b7e8 707 "%s."), locale->value);
ac884b6a
MS
708 continue;
709 }
710
711 // Add the base file to the list...
712 src->po_files->add(locatalog);
713 }
714
715 cupsFilePrintf(fp, " %s", locale->value);
716 }
717
718 cupsFilePrintf(fp, "\"%s", lf);
719 }
720
721 for (cn = (ppdcConstraint *)constraints->first();
722 cn;
723 cn = (ppdcConstraint *)constraints->next())
724 {
725 // First constrain 1 against 2...
726 if (!strncmp(cn->option1->value, "*Custom", 7) ||
727 !strncmp(cn->option2->value, "*Custom", 7))
61cf44e2 728 cupsFilePuts(fp, "*NonUIConstraints: ");
ac884b6a 729 else
61cf44e2 730 cupsFilePuts(fp, "*UIConstraints: ");
ac884b6a
MS
731
732 if (cn->option1->value[0] != '*')
733 cupsFilePutChar(fp, '*');
734
61cf44e2 735 cupsFilePuts(fp, cn->option1->value);
ac884b6a
MS
736
737 if (cn->choice1->value)
738 cupsFilePrintf(fp, " %s", cn->choice1->value);
739
740 cupsFilePutChar(fp, ' ');
741
742 if (cn->option2->value[0] != '*')
743 cupsFilePutChar(fp, '*');
744
61cf44e2 745 cupsFilePuts(fp, cn->option2->value);
ac884b6a
MS
746
747 if (cn->choice2->value)
748 cupsFilePrintf(fp, " %s", cn->choice2->value);
749
61cf44e2 750 cupsFilePuts(fp, lf);
ac884b6a
MS
751
752 // Then constrain 2 against 1...
753 if (!strncmp(cn->option1->value, "*Custom", 7) ||
754 !strncmp(cn->option2->value, "*Custom", 7))
61cf44e2 755 cupsFilePuts(fp, "*NonUIConstraints: ");
ac884b6a 756 else
61cf44e2 757 cupsFilePuts(fp, "*UIConstraints: ");
ac884b6a
MS
758
759 if (cn->option2->value[0] != '*')
760 cupsFilePutChar(fp, '*');
761
61cf44e2 762 cupsFilePuts(fp, cn->option2->value);
ac884b6a
MS
763
764 if (cn->choice2->value)
765 cupsFilePrintf(fp, " %s", cn->choice2->value);
766
767 cupsFilePutChar(fp, ' ');
768
769 if (cn->option1->value[0] != '*')
770 cupsFilePutChar(fp, '*');
771
61cf44e2 772 cupsFilePuts(fp, cn->option1->value);
ac884b6a
MS
773
774 if (cn->choice1->value)
775 cupsFilePrintf(fp, " %s", cn->choice1->value);
776
777 cupsFilePuts(fp, lf);
778 }
779
780 // PageSize option...
781 cupsFilePrintf(fp, "*OpenUI *PageSize/Media Size: PickOne%s", lf);
782 cupsFilePrintf(fp, "*OrderDependency: 10 AnySetup *PageSize%s", lf);
783 cupsFilePrintf(fp, "*DefaultPageSize: %s%s",
784 default_size ? default_size->value : "Letter", lf);
785
786 for (m = (ppdcMediaSize *)sizes->first();
787 m;
788 m = (ppdcMediaSize *)sizes->next())
789 if (m->size_code->value)
790 {
791 cupsFilePrintf(fp, "*PageSize %s/%s: \"%s\"%s",
792 m->name->value, catalog->find_message(m->text->value),
793 m->size_code->value, lf);
794
795 if (strchr(m->size_code->value, '\n') ||
796 strchr(m->size_code->value, '\r'))
797 cupsFilePrintf(fp, "*End%s", lf);
798 }
799 else
800 cupsFilePrintf(fp,
801 "*PageSize %s/%s: \"<</PageSize[%.0f %.0f]"
802 "/ImagingBBox null>>setpagedevice\"%s",
803 m->name->value, catalog->find_message(m->text->value),
804 m->width, m->length, lf);
805
806 if ((a = find_attr("?PageSize", NULL)) != NULL)
807 {
808 cupsFilePrintf(fp, "*?PageSize: \"%s\"%s", a->value->value, lf);
809
810 if (strchr(a->value->value, '\n') ||
811 strchr(a->value->value, '\r'))
812 cupsFilePrintf(fp, "*End%s", lf);
813 }
814
815 cupsFilePrintf(fp, "*CloseUI: *PageSize%s", lf);
816
817 // PageRegion option...
818 cupsFilePrintf(fp, "*OpenUI *PageRegion/Media Size: PickOne%s", lf);
819 cupsFilePrintf(fp, "*OrderDependency: 10 AnySetup *PageRegion%s", lf);
820 cupsFilePrintf(fp, "*DefaultPageRegion: %s%s",
821 default_size ? default_size->value : "Letter", lf);
822
823 for (m = (ppdcMediaSize *)sizes->first();
824 m;
825 m = (ppdcMediaSize *)sizes->next())
826 if (m->region_code->value)
827 {
828 cupsFilePrintf(fp, "*PageRegion %s/%s: \"%s\"%s",
829 m->name->value, catalog->find_message(m->text->value),
830 m->region_code->value, lf);
831
832 if (strchr(m->region_code->value, '\n') ||
833 strchr(m->region_code->value, '\r'))
834 cupsFilePrintf(fp, "*End%s", lf);
835 }
836 else
837 cupsFilePrintf(fp,
838 "*PageRegion %s/%s: \"<</PageSize[%.0f %.0f]"
839 "/ImagingBBox null>>setpagedevice\"%s",
840 m->name->value, catalog->find_message(m->text->value),
841 m->width, m->length, lf);
842
843 if ((a = find_attr("?PageRegion", NULL)) != NULL)
844 {
845 cupsFilePrintf(fp, "*?PageRegion: \"%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 cupsFilePrintf(fp, "*CloseUI: *PageRegion%s", lf);
853
854 // ImageableArea info...
855 cupsFilePrintf(fp, "*DefaultImageableArea: %s%s",
856 default_size ? default_size->value : "Letter", lf);
857
7a0cbd5e
MS
858 char left[255], right[255], bottom[255], top[255];
859
ac884b6a
MS
860 for (m = (ppdcMediaSize *)sizes->first();
861 m;
862 m = (ppdcMediaSize *)sizes->next())
7a0cbd5e
MS
863 {
864 _cupsStrFormatd(left, left + sizeof(left), m->left, loc);
865 _cupsStrFormatd(bottom, bottom + sizeof(bottom), m->bottom, loc);
866 _cupsStrFormatd(right, right + sizeof(right), m->width - m->right, loc);
867 _cupsStrFormatd(top, top + sizeof(top), m->length - m->top, loc);
868
869 cupsFilePrintf(fp, "*ImageableArea %s/%s: \"%s %s %s %s\"%s",
ac884b6a 870 m->name->value, catalog->find_message(m->text->value),
7a0cbd5e
MS
871 left, bottom, right, top, lf);
872 }
ac884b6a
MS
873
874 if ((a = find_attr("?ImageableArea", NULL)) != NULL)
875 {
876 cupsFilePrintf(fp, "*?ImageableArea: \"%s\"%s", a->value->value, lf);
877
878 if (strchr(a->value->value, '\n') ||
879 strchr(a->value->value, '\r'))
880 cupsFilePrintf(fp, "*End%s", lf);
881 }
882
883 // PaperDimension info...
884 cupsFilePrintf(fp, "*DefaultPaperDimension: %s%s",
885 default_size ? default_size->value : "Letter", lf);
886
7a0cbd5e
MS
887 char width[255], length[255];
888
ac884b6a
MS
889 for (m = (ppdcMediaSize *)sizes->first();
890 m;
891 m = (ppdcMediaSize *)sizes->next())
7a0cbd5e
MS
892 {
893 _cupsStrFormatd(width, width + sizeof(width), m->width, loc);
894 _cupsStrFormatd(length, length + sizeof(length), m->length, loc);
895
896 cupsFilePrintf(fp, "*PaperDimension %s/%s: \"%s %s\"%s",
ac884b6a 897 m->name->value, catalog->find_message(m->text->value),
7a0cbd5e
MS
898 width, length, lf);
899 }
ac884b6a
MS
900
901 if ((a = find_attr("?PaperDimension", NULL)) != NULL)
902 {
903 cupsFilePrintf(fp, "*?PaperDimension: \"%s\"%s", a->value->value, lf);
904
905 if (strchr(a->value->value, '\n') ||
906 strchr(a->value->value, '\r'))
907 cupsFilePrintf(fp, "*End%s", lf);
908 }
909
910 // Custom size support...
911 if (variable_paper_size)
912 {
7a0cbd5e
MS
913 _cupsStrFormatd(width, width + sizeof(width), max_width, loc);
914 _cupsStrFormatd(length, length + sizeof(length), max_length, loc);
915
916 _cupsStrFormatd(left, left + sizeof(left), left_margin, loc);
917 _cupsStrFormatd(bottom, bottom + sizeof(bottom), bottom_margin, loc);
918 _cupsStrFormatd(right, right + sizeof(right), right_margin, loc);
919 _cupsStrFormatd(top, top + sizeof(top), top_margin, loc);
920
921 cupsFilePrintf(fp, "*MaxMediaWidth: \"%s\"%s", width, lf);
922 cupsFilePrintf(fp, "*MaxMediaHeight: \"%s\"%s", length, lf);
923 cupsFilePrintf(fp, "*HWMargins: %s %s %s %s%s", left, bottom, right, top,
924 lf);
ac884b6a
MS
925
926 if (custom_size_code && custom_size_code->value)
927 {
928 cupsFilePrintf(fp, "*CustomPageSize True: \"%s\"%s",
929 custom_size_code->value, lf);
930
931 if (strchr(custom_size_code->value, '\n') ||
932 strchr(custom_size_code->value, '\r'))
933 cupsFilePrintf(fp, "*End%s", lf);
934 }
935 else
936 cupsFilePrintf(fp,
937 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
938 "/ImagingBBox null>>setpagedevice\"%s", lf);
939
940 if ((a = find_attr("ParamCustomPageSize", "Width")) != NULL)
941 cupsFilePrintf(fp, "*ParamCustomPageSize Width: %s%s", a->value->value,
942 lf);
943 else
7a0cbd5e
MS
944 {
945 char width0[255];
946
947 _cupsStrFormatd(width0, width0 + sizeof(width0), min_width, loc);
948 _cupsStrFormatd(width, width + sizeof(width), max_width, loc);
949
950 cupsFilePrintf(fp, "*ParamCustomPageSize Width: 1 points %s %s%s",
951 width0, width, lf);
952 }
ac884b6a
MS
953
954 if ((a = find_attr("ParamCustomPageSize", "Height")) != NULL)
955 cupsFilePrintf(fp, "*ParamCustomPageSize Height: %s%s", a->value->value,
956 lf);
957 else
7a0cbd5e
MS
958 {
959 char length0[255];
960
961 _cupsStrFormatd(length0, length0 + sizeof(length0), min_length, loc);
962 _cupsStrFormatd(length, length + sizeof(length), max_length, loc);
963
964 cupsFilePrintf(fp, "*ParamCustomPageSize Height: 2 points %s %s%s",
965 length0, length, lf);
966 }
ac884b6a
MS
967
968 if ((a = find_attr("ParamCustomPageSize", "WidthOffset")) != NULL)
969 cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: %s%s",
970 a->value->value, lf);
971 else
972 cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf);
973
974 if ((a = find_attr("ParamCustomPageSize", "HeightOffset")) != NULL)
975 cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: %s%s",
976 a->value->value, lf);
977 else
978 cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf);
979
980 if ((a = find_attr("ParamCustomPageSize", "Orientation")) != NULL)
981 cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: %s%s",
982 a->value->value, lf);
983 else
984 cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf);
985 }
986
ac884b6a
MS
987 // All other options...
988 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
989 {
990 if (!g->options->count)
991 continue;
992
88f9aafc 993 if (_cups_strcasecmp(g->name->value, "General"))
ac884b6a
MS
994 cupsFilePrintf(fp, "*OpenGroup: %s/%s%s", g->name->value,
995 catalog->find_message(g->text->value), lf);
996
997 for (o = (ppdcOption *)g->options->first();
998 o;
999 o = (ppdcOption *)g->options->next())
1000 {
1001 if (!o->choices->count)
1002 continue;
1003
3dd9c340
MS
1004 if (o->section == PPDC_SECTION_JCL)
1005 {
1006 if (!o->text->value)
1007 cupsFilePrintf(fp, "*JCLOpenUI *%s/%s: ", o->name->value,
1008 catalog->find_message(o->name->value));
1009 else
1010 cupsFilePrintf(fp, "*JCLOpenUI *%s/%s: ", o->name->value,
1011 catalog->find_message(o->text->value));
1012 }
1013 else if (!o->text->value)
d1c13e16 1014 cupsFilePrintf(fp, "*OpenUI *%s/%s: ", o->name->value,
d2354e63 1015 catalog->find_message(o->name->value));
ac884b6a
MS
1016 else
1017 cupsFilePrintf(fp, "*OpenUI *%s/%s: ", o->name->value,
1018 catalog->find_message(o->text->value));
1019
1020 switch (o->type)
1021 {
1022 case PPDC_BOOLEAN :
1023 cupsFilePrintf(fp, "Boolean%s", lf);
1024 break;
1025 default :
1026 cupsFilePrintf(fp, "PickOne%s", lf);
1027 break;
1028 case PPDC_PICKMANY :
1029 cupsFilePrintf(fp, "PickMany%s", lf);
1030 break;
1031 }
1032
7a0cbd5e
MS
1033 char order[255];
1034 _cupsStrFormatd(order, order + sizeof(order), o->order, loc);
1035
1036 cupsFilePrintf(fp, "*OrderDependency: %s ", order);
ac884b6a
MS
1037 switch (o->section)
1038 {
1039 default :
1040 cupsFilePrintf(fp, "AnySetup");
1041 break;
1042 case PPDC_SECTION_DOCUMENT :
1043 cupsFilePrintf(fp, "DocumentSetup");
1044 break;
1045 case PPDC_SECTION_EXIT :
1046 cupsFilePrintf(fp, "ExitServer");
1047 break;
1048 case PPDC_SECTION_JCL :
1049 cupsFilePrintf(fp, "JCLSetup");
1050 break;
1051 case PPDC_SECTION_PAGE :
1052 cupsFilePrintf(fp, "PageSetup");
1053 break;
1054 case PPDC_SECTION_PROLOG :
1055 cupsFilePrintf(fp, "Prolog");
1056 break;
1057 }
1058
1059 cupsFilePrintf(fp, " *%s%s", o->name->value, lf);
1060
1061 if (o->defchoice)
1062 {
1063 // Use the programmer-supplied default...
1064 cupsFilePrintf(fp, "*Default%s: %s%s", o->name->value,
1065 o->defchoice->value, lf);
1066 }
1067 else
1068 {
1069 // Make the first choice the default...
1070 c = (ppdcChoice *)o->choices->first();
1071 cupsFilePrintf(fp, "*Default%s: %s%s", o->name->value, c->name->value,
1072 lf);
1073 }
1074
1075 for (c = (ppdcChoice *)o->choices->first();
1076 c;
1077 c = (ppdcChoice *)o->choices->next())
1078 {
1079 // Write this choice...
ef55b745
MS
1080 if (!c->text->value)
1081 cupsFilePrintf(fp, "*%s %s/%s: \"%s\"%s", o->name->value,
1082 c->name->value, catalog->find_message(c->name->value),
ac884b6a
MS
1083 c->code->value, lf);
1084 else
1085 cupsFilePrintf(fp, "*%s %s/%s: \"%s\"%s", o->name->value,
1086 c->name->value, catalog->find_message(c->text->value),
1087 c->code->value, lf);
1088
1089 // Multi-line commands need a *End line to terminate them.
1090 if (strchr(c->code->value, '\n') ||
1091 strchr(c->code->value, '\r'))
1092 cupsFilePrintf(fp, "*End%s", lf);
1093 }
1094
1095 snprintf(query, sizeof(query), "?%s", o->name->value);
1096
1097 if ((a = find_attr(query, NULL)) != NULL)
1098 {
f11a948a 1099 cupsFilePrintf(fp, "*%s: \"%s\"%s", query, a->value->value, lf);
ac884b6a
MS
1100
1101 if (strchr(a->value->value, '\n') ||
1102 strchr(a->value->value, '\r'))
1103 cupsFilePrintf(fp, "*End%s", lf);
1104 }
1105
1106 cupsFilePrintf(fp, "*CloseUI: *%s%s", o->name->value, lf);
f11a948a
MS
1107
1108 snprintf(custom, sizeof(custom), "Custom%s", o->name->value);
1109 if ((a = find_attr(custom, "True")) != NULL)
1110 {
1111 // Output custom option information...
1112 cupsFilePrintf(fp, "*%s True: \"%s\"%s", custom, a->value->value, lf);
1113 if (strchr(a->value->value, '\n') || strchr(a->value->value, '\r'))
1114 cupsFilePrintf(fp, "*End%s", lf);
1115
1116 snprintf(custom, sizeof(custom), "ParamCustom%s", o->name->value);
1117 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
1118 {
1119 if (strcmp(a->name->value, custom))
1120 continue;
1121
1122 if (!a->selector->value || !a->selector->value[0])
1123 cupsFilePrintf(fp, "*%s", a->name->value);
1124 else if (!a->text->value || !a->text->value[0])
ef55b745
MS
1125 cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
1126 catalog->find_message(a->selector->value));
f11a948a
MS
1127 else
1128 cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
ef55b745 1129 catalog->find_message(a->text->value));
f11a948a
MS
1130
1131 cupsFilePrintf(fp, ": %s%s", a->value->value, lf);
1132 }
1133 }
ac884b6a
MS
1134 }
1135
88f9aafc 1136 if (_cups_strcasecmp(g->name->value, "General"))
ac884b6a
MS
1137 cupsFilePrintf(fp, "*CloseGroup: %s%s", g->name->value, lf);
1138 }
1139
1140 if (locales)
1141 {
1142 // Add localizations for additional languages...
1143 ppdcString *locale; // Locale name
1144 ppdcCatalog *locatalog; // Message catalog for locale
1145
1146
1147 // Write the translation strings for each language...
1148 for (locale = (ppdcString *)locales->first();
1149 locale;
1150 locale = (ppdcString *)locales->next())
1151 {
1152 // Skip (US) English...
1153 if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
1154 continue;
1155
1156 // Skip missing languages...
1157 if ((locatalog = src->find_po(locale->value)) == NULL)
1158 continue;
1159
1160 // Do the core stuff first...
1161 cupsFilePrintf(fp, "*%s.Translation Manufacturer/%s: \"\"%s",
1162 locale->value,
1163 locatalog->find_message(manufacturer->value), lf);
1164
1165 if ((a = find_attr("ModelName", NULL)) != NULL)
1166 cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
1167 locale->value,
1168 locatalog->find_message(a->value->value), lf);
88f9aafc 1169 else if (_cups_strncasecmp(model_name->value, manufacturer->value,
ac884b6a
MS
1170 strlen(manufacturer->value)))
1171 cupsFilePrintf(fp, "*%s.Translation ModelName/%s %s: \"\"%s",
1172 locale->value,
1173 locatalog->find_message(manufacturer->value),
1174 locatalog->find_message(model_name->value), lf);
1175 else
1176 cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
1177 locale->value,
1178 locatalog->find_message(model_name->value), lf);
1179
1180 if ((a = find_attr("ShortNickName", NULL)) != NULL)
1181 cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
1182 locale->value,
1183 locatalog->find_message(a->value->value), lf);
88f9aafc 1184 else if (_cups_strncasecmp(model_name->value, manufacturer->value,
ac884b6a
MS
1185 strlen(manufacturer->value)))
1186 cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s %s: \"\"%s",
1187 locale->value,
1188 locatalog->find_message(manufacturer->value),
1189 locatalog->find_message(model_name->value), lf);
1190 else
1191 cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
1192 locale->value,
1193 locatalog->find_message(model_name->value), lf);
1194
1195 if ((a = find_attr("NickName", NULL)) != NULL)
1196 cupsFilePrintf(fp, "*%s.Translation NickName/%s: \"\"%s",
1197 locale->value,
1198 locatalog->find_message(a->value->value), lf);
88f9aafc 1199 else if (_cups_strncasecmp(model_name->value, manufacturer->value,
ac884b6a
MS
1200 strlen(manufacturer->value)))
1201 cupsFilePrintf(fp, "*%s.Translation NickName/%s %s, %s: \"\"%s",
1202 locale->value,
1203 locatalog->find_message(manufacturer->value),
1204 locatalog->find_message(model_name->value),
1205 version->value, lf);
1206 else
1207 cupsFilePrintf(fp, "*%s.Translation NickName/%s, %s: \"\"%s",
1208 locale->value,
1209 locatalog->find_message(model_name->value),
1210 version->value, lf);
1211
1212 // Then the page sizes...
1213 cupsFilePrintf(fp, "*%s.Translation PageSize/%s: \"\"%s", locale->value,
1214 locatalog->find_message("Media Size"), lf);
1215
1216 for (m = (ppdcMediaSize *)sizes->first();
1217 m;
1218 m = (ppdcMediaSize *)sizes->next())
1219 {
1220 cupsFilePrintf(fp, "*%s.PageSize %s/%s: \"\"%s", locale->value,
1221 m->name->value, locatalog->find_message(m->text->value),
1222 lf);
1223 }
1224
1225 // Next the groups and options...
1226 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
1227 {
1228 if (!g->options->count)
1229 continue;
1230
88f9aafc 1231 if (_cups_strcasecmp(g->name->value, "General"))
ac884b6a
MS
1232 cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
1233 g->name->value,
1234 locatalog->find_message(g->text->value), lf);
1235
1236 for (o = (ppdcOption *)g->options->first();
1237 o;
1238 o = (ppdcOption *)g->options->next())
1239 {
1240 if (!o->choices->count)
1241 continue;
1242
1243 cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
1244 o->name->value,
1245 locatalog->find_message(o->text->value ?
1246 o->text->value :
1247 o->name->value), lf);
1248
1249 for (c = (ppdcChoice *)o->choices->first();
1250 c;
1251 c = (ppdcChoice *)o->choices->next())
1252 {
1253 // Write this choice...
1254 cupsFilePrintf(fp, "*%s.%s %s/%s: \"\"%s", locale->value,
1255 o->name->value, c->name->value,
1256 locatalog->find_message(c->text->value ?
1257 c->text->value :
1258 c->name->value), lf);
1259 }
1260 }
1261 }
1262
1263 // Finally the localizable attributes...
1264 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
1265 {
bdd6c45b 1266 if (!a->localizable &&
ef55b745 1267 (!a->text || !a->text->value || !a->text->value[0]) &&
bdd6c45b 1268 strcmp(a->name->value, "APCustomColorMatchingName") &&
ac884b6a
MS
1269 strcmp(a->name->value, "APPrinterPreset") &&
1270 strcmp(a->name->value, "cupsICCProfile") &&
1271 strcmp(a->name->value, "cupsIPPReason") &&
bdd6c45b 1272 strcmp(a->name->value, "cupsMarkerName") &&
ac884b6a
MS
1273 strncmp(a->name->value, "Custom", 6) &&
1274 strncmp(a->name->value, "ParamCustom", 11))
ef55b745 1275 continue;
ac884b6a
MS
1276
1277 cupsFilePrintf(fp, "*%s.%s %s/%s: \"%s\"%s", locale->value,
1278 a->name->value, a->selector->value,
1279 locatalog->find_message(a->text && a->text->value ?
1280 a->text->value : a->name->value),
bdd6c45b
MS
1281 ((a->localizable && a->value->value[0]) ||
1282 !strcmp(a->name->value, "cupsIPPReason")) ?
ac884b6a
MS
1283 locatalog->find_message(a->value->value) : "",
1284 lf);
1285 }
1286 }
1287 }
1288
1289 if (default_font && default_font->value)
1290 cupsFilePrintf(fp, "*DefaultFont: %s%s", default_font->value, lf);
1291 else
1292 cupsFilePrintf(fp, "*DefaultFont: Courier%s", lf);
1293
1294 for (fn = (ppdcFont *)fonts->first(); fn; fn = (ppdcFont *)fonts->next())
1295 if (!strcmp(fn->name->value, "*"))
1296 {
1297 for (bfn = (ppdcFont *)src->base_fonts->first();
1298 bfn;
1299 bfn = (ppdcFont *)src->base_fonts->next())
1300 cupsFilePrintf(fp, "*Font %s: %s \"%s\" %s %s%s",
1301 bfn->name->value, bfn->encoding->value,
1302 bfn->version->value, bfn->charset->value,
1303 bfn->status == PPDC_FONT_ROM ? "ROM" : "Disk", lf);
1304 }
1305 else
1306 cupsFilePrintf(fp, "*Font %s: %s \"%s\" %s %s%s",
1307 fn->name->value, fn->encoding->value, fn->version->value,
1308 fn->charset->value,
1309 fn->status == PPDC_FONT_ROM ? "ROM" : "Disk", lf);
1310
1311 cupsFilePrintf(fp, "*%% End of %s, %05d bytes.%s", pc_file_name->value,
7e86f2f6 1312 (int)((size_t)cupsFileTell(fp) + 25 + strlen(pc_file_name->value)),
ac884b6a
MS
1313 lf);
1314
1315 if (delete_cat)
e4572d57 1316 catalog->release();
ac884b6a
MS
1317
1318 return (0);
1319}