]> git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-driver.cxx
Merge CUPS 1.4svn-r7319.
[thirdparty/cups.git] / ppdc / ppdc-driver.cxx
1 //
2 // "$Id$"
3 //
4 // PPD file compiler definitions for the CUPS PPD Compiler.
5 //
6 // Copyright 2007 by Apple Inc.
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.
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...
28 //
29
30 //
31 // Include necessary headers...
32 //
33
34 #include "ppdc.h"
35 #include <cups/cups.h>
36
37
38 //
39 // 'ppdcDriver::ppdcDriver()' - Create a new printer driver.
40 //
41
42 ppdcDriver::ppdcDriver(ppdcDriver *d) // I - Printer driver template
43 {
44 ppdcGroup *g; // Current group
45
46
47 if (d)
48 {
49 // Bump the use count of any strings we inherit...
50 if (d->manufacturer)
51 d->manufacturer->get();
52 if (d->version)
53 d->version->get();
54 if (d->default_font)
55 d->default_font->get();
56 if (d->default_size)
57 d->default_size->get();
58 if (d->custom_size_code)
59 d->custom_size_code->get();
60
61 // Copy all of the data from the driver template...
62 copyright = new ppdcArray(d->copyright);
63 manufacturer = d->manufacturer;
64 model_name = 0;
65 pc_file_name = 0;
66 type = d->type;
67 version = d->version;
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;
90
91 // Then copy the groups manually, since we want separate copies
92 // of the groups and options...
93 groups = new ppdcArray();
94
95 for (g = (ppdcGroup *)d->groups->first(); g; g = (ppdcGroup *)d->groups->next())
96 groups->add(new ppdcGroup(g));
97 }
98 else
99 {
100 // Zero all of the data in the driver...
101 copyright = new ppdcArray();
102 manufacturer = 0;
103 model_name = 0;
104 pc_file_name = 0;
105 version = 0;
106 type = PPDC_DRIVER_CUSTOM;
107 model_number = 0;
108 manual_copies = 0;
109 color_device = 0;
110 throughput = 1;
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();
118 default_font = 0;
119 default_size = 0;
120 variable_paper_size = 0;
121 custom_size_code = 0;
122 left_margin = 0;
123 bottom_margin = 0;
124 right_margin = 0;
125 top_margin = 0;
126 max_width = 0;
127 max_length = 0;
128 min_width = 0;
129 min_length = 0;
130 }
131 }
132
133
134 //
135 // 'ppdcDriver::~ppdcDriver()' - Destroy a printer driver.
136 //
137
138 ppdcDriver::~ppdcDriver()
139 {
140 delete copyright;
141
142 if (manufacturer)
143 manufacturer->release();
144 if (model_name)
145 model_name->release();
146 if (pc_file_name)
147 pc_file_name->release();
148 if (version)
149 version->release();
150 if (default_font)
151 default_font->release();
152 if (default_size)
153 default_size->release();
154 if (custom_size_code)
155 custom_size_code->release();
156
157 delete attrs;
158 delete constraints;
159 delete filters;
160 delete fonts;
161 delete groups;
162 delete profiles;
163 delete sizes;
164 }
165
166
167 //
168 // 'ppdcDriver::find_attr()' - Find an attribute.
169 //
170
171 ppdcAttr * // O - Attribute or NULL
172 ppdcDriver::find_attr(const char *k, // I - Keyword string
173 const char *s) // I - Spec string
174 {
175 ppdcAttr *a; // Current attribute
176
177
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))))
182 return (a);
183
184 return (NULL);
185 }
186
187
188 //
189 // 'ppdcDriver::find_group()' - Find a group.
190 //
191
192 ppdcGroup * // O - Matching group or NULL
193 ppdcDriver::find_group(const char *n) // I - Group name
194 {
195 ppdcGroup *g; // Current group
196
197
198 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
199 if (!strcasecmp(n, g->name->value))
200 return (g);
201
202 return (0);
203 }
204
205
206 //
207 // 'ppdcDriver::find_option()' - Find an option.
208 //
209
210 ppdcOption * // O - Matching option or NULL
211 ppdcDriver::find_option(const char *n) // I - Option name
212 {
213 ppdcGroup *g; // Current group
214 ppdcOption *o; // Current option
215
216
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))
220 return (o);
221
222 return (0);
223 }
224
225
226 //
227 // 'ppdcDriver::set_custom_size_code()' - Set the custom page size code.
228 //
229
230 void
231 ppdcDriver::set_custom_size_code(const char *c)
232 // I - CustomPageSize code
233 {
234 if (custom_size_code)
235 custom_size_code->release();
236
237 custom_size_code = new ppdcString(c);
238 }
239
240
241 //
242 // 'ppdcDriver::set_default_font()' - Set the default font name.
243 //
244
245 void
246 ppdcDriver::set_default_font(ppdcFont *f)
247 // I - Font
248 {
249 if (default_font)
250 default_font->release();
251
252 if (f)
253 {
254 f->name->get();
255 default_font = f->name;
256 }
257 else
258 default_font = 0;
259 }
260
261
262 //
263 // 'ppdcDriver::set_default_size()' - Set the default size name.
264 //
265
266 void
267 ppdcDriver::set_default_size(ppdcMediaSize *m)
268 // I - Media size
269 {
270 if (default_size)
271 default_size->release();
272
273 if (m)
274 {
275 m->name->get();
276 default_size = m->name;
277 }
278 else
279 default_size = 0;
280 }
281
282
283 //
284 // 'ppdcDriver::set_manufacturer()' - Set the manufacturer name.
285 //
286
287 void
288 ppdcDriver::set_manufacturer(const char *m)
289 // I - Model name
290 {
291 if (manufacturer)
292 manufacturer->release();
293
294 manufacturer = new ppdcString(m);
295 }
296
297
298 //
299 // 'ppdcDriver::set_model_name()' - Set the model name.
300 //
301
302 void
303 ppdcDriver::set_model_name(const char *m)
304 // I - Model name
305 {
306 if (model_name)
307 model_name->release();
308
309 model_name = new ppdcString(m);
310 }
311
312
313 //
314 // 'ppdcDriver::set_pc_file_name()' - Set the PC filename.
315 //
316
317 void
318 ppdcDriver::set_pc_file_name(const char *f)
319 // I - Filename
320 {
321 if (pc_file_name)
322 pc_file_name->release();
323
324 pc_file_name = new ppdcString(f);
325 }
326
327
328 //
329 // 'ppdcDriver::set_version()' - Set the version string.
330 //
331
332 void
333 ppdcDriver::set_version(const char *v) // I - Version
334 {
335 if (version)
336 version->release();
337
338 version = new ppdcString(v);
339 }
340
341
342 //
343 // 'ppdcDriver::write_ppd_file()' - Write a PPD file...
344 //
345
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
353 {
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
368
369
370 // If we don't have a message catalog, use an empty (English) one...
371 if (!catalog)
372 {
373 catalog = new ppdcCatalog("en");
374 delete_cat = true;
375 }
376 else
377 delete_cat = false;
378
379 // Figure out the end-of-line string...
380 if (le == PPDC_LFONLY)
381 lf = "\n";
382 else if (le == PPDC_CRONLY)
383 lf = "\r";
384 else
385 lf = "\r\n";
386
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);
390 cupsFilePrintf(fp,
391 "*%% Created by the CUPS PPD Compiler " CUPS_SVERSION ".%s",
392 lf);
393 for (s = (ppdcString *)copyright->first();
394 s;
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);
399
400 a = find_attr("LanguageVersion", NULL);
401 cupsFilePrintf(fp, "*LanguageVersion: %s%s",
402 catalog->find_message(a ? a->value->value : "English"), lf);
403
404 a = find_attr("LanguageEncoding", NULL);
405 cupsFilePrintf(fp, "*LanguageEncoding: %s%s",
406 catalog->find_message(a ? a->value->value : "ISOLatin1"), lf);
407
408 cupsFilePrintf(fp, "*PCFileName: \"%s\"%s", pc_file_name->value, lf);
409
410 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
411 if (!strcmp(a->name->value, "Product"))
412 break;
413
414 if (a)
415 {
416 for (; a; a = (ppdcAttr *)attrs->next())
417 if (!strcmp(a->name->value, "Product"))
418 cupsFilePrintf(fp, "*Product: \"%s\"%s", a->value->value, lf);
419 }
420 else
421 {
422 cupsFilePrintf(fp, "*Product: \"(ESP Ghostscript)\"%s", lf);
423 cupsFilePrintf(fp, "*Product: \"(GPL Ghostscript)\"%s", lf);
424 cupsFilePrintf(fp, "*Product: \"(GNU Ghostscript)\"%s", lf);
425 }
426
427 cupsFilePrintf(fp, "*Manufacturer: \"%s\"%s",
428 catalog->find_message(manufacturer->value), lf);
429
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);
438 else
439 cupsFilePrintf(fp, "*ModelName: \"%s\"%s",
440 catalog->find_message(model_name->value), lf);
441
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);
450 else
451 cupsFilePrintf(fp, "*ShortNickName: \"%s\"%s",
452 catalog->find_message(model_name->value), lf);
453
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,
462 lf);
463 else
464 cupsFilePrintf(fp, "*NickName: \"%s, %s\"%s",
465 catalog->find_message(model_name->value), version->value,
466 lf);
467
468 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
469 if (!strcmp(a->name->value, "PSVersion"))
470 break;
471
472 if (a)
473 {
474 for (; a; a = (ppdcAttr *)attrs->next())
475 if (!strcmp(a->name->value, "PSVersion"))
476 cupsFilePrintf(fp, "*PSVersion: \"%s\"%s", a->value->value, lf);
477 }
478 else
479 {
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);
484 }
485
486 if ((a = find_attr("LanguageLevel", NULL)) != NULL)
487 cupsFilePrintf(fp, "*LanguageLevel: \"%s\"%s", a->value->value, lf);
488 else
489 cupsFilePrintf(fp, "*LanguageLevel: \"3\"%s", lf);
490
491 cupsFilePrintf(fp, "*ColorDevice: %s%s", color_device ? "True" : "False", lf);
492
493 if ((a = find_attr("DefaultColorSpace", NULL)) != NULL)
494 cupsFilePrintf(fp, "*DefaultColorSpace: %s%s", a->value->value, lf);
495 else
496 cupsFilePrintf(fp, "*DefaultColorSpace: %s%s",
497 color_device ? "RGB" : "Gray", lf);
498
499 if ((a = find_attr("FileSystem", NULL)) != NULL)
500 cupsFilePrintf(fp, "*FileSystem: %s%s", a->value->value, lf);
501 else
502 cupsFilePrintf(fp, "*FileSystem: False%s", lf);
503
504 cupsFilePrintf(fp, "*Throughput: \"%d\"%s", throughput, lf);
505
506 if ((a = find_attr("LandscapeOrientation", NULL)) != NULL)
507 cupsFilePrintf(fp, "*LandscapeOrientation: %s%s", a->value->value, lf);
508 else
509 cupsFilePrintf(fp, "*LandscapeOrientation: Plus90%s", lf);
510
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);
515
516 if (attrs->count)
517 {
518 // Write driver-defined attributes...
519 cupsFilePrintf(fp, "*%% Driver-defined attributes...%s", lf);
520 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
521 {
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] == '?')
536 continue;
537
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);
542 else
543 cupsFilePrintf(fp, "*%s %s/%s", a->name->value, a->selector->value,
544 a->text->value);
545
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))
555 {
556 cupsFilePrintf(fp, ": \"%s\"%s", a->value->value, lf);
557
558 if (strchr(a->value->value, '\n'))
559 cupsFilePrintf(fp, "*End%s", lf);
560 }
561 else
562 cupsFilePrintf(fp, ": %s%s", a->value->value, lf);
563 }
564 }
565
566 if (type != PPDC_DRIVER_PS || filters->count)
567 {
568 if ((a = find_attr("cupsVersion", NULL)) != NULL)
569 cupsFilePrintf(fp, "*cupsVersion: %s%s", a->value->value, lf);
570 else
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);
576
577 if (filters->count)
578 {
579 for (f = (ppdcFilter *)filters->first();
580 f;
581 f = (ppdcFilter *)filters->next())
582 cupsFilePrintf(fp, "*cupsFilter: \"%s %d %s\"%s", f->mime_type->value,
583 f->cost, f->program->value, lf);
584 }
585 else
586 {
587 switch (type)
588 {
589 case PPDC_DRIVER_LABEL :
590 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
591 "rastertolabel\"%s", lf);
592 break;
593
594 case PPDC_DRIVER_EPSON :
595 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
596 "rastertoepson\"%s", lf);
597 break;
598
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);
604 break;
605
606 case PPDC_DRIVER_HP :
607 cupsFilePrintf(fp, "*cupsFilter: \"application/vnd.cups-raster 50 "
608 "rastertohp\"%s", lf);
609 break;
610
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);
616 break;
617
618 default :
619 break;
620 }
621 }
622
623 for (p = (ppdcProfile *)profiles->first();
624 p;
625 p = (ppdcProfile *)profiles->next())
626 cupsFilePrintf(fp,
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],
635 p->profile[8], lf);
636 }
637
638 if (locales)
639 {
640 // Add localizations for additional languages...
641 ppdcString *locale; // Locale name
642 ppdcCatalog *locatalog; // Message catalog for locale
643
644
645 // Write the list of languages...
646 cupsFilePrintf(fp, "*cupsLanguages: \"en");
647
648 for (locale = (ppdcString *)locales->first();
649 locale;
650 locale = (ppdcString *)locales->next())
651 {
652 // Skip (US) English...
653 if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
654 continue;
655
656 // See if we have a po file for this language...
657 if (!src->find_po(locale->value))
658 {
659 // No, see if we can use the base file?
660 locatalog = new ppdcCatalog(locale->value);
661
662 if (locatalog->messages->count == 0)
663 {
664 // No, skip this one...
665 fprintf(stderr, "ppdc: No message catalog provided for locale %s!\n",
666 locale->value);
667 continue;
668 }
669
670 // Add the base file to the list...
671 src->po_files->add(locatalog);
672 }
673
674 cupsFilePrintf(fp, " %s", locale->value);
675 }
676
677 cupsFilePrintf(fp, "\"%s", lf);
678 }
679
680 for (cn = (ppdcConstraint *)constraints->first();
681 cn;
682 cn = (ppdcConstraint *)constraints->next())
683 {
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: ");
688 else
689 cupsFilePrintf(fp, "*UIConstraints: ");
690
691 if (cn->option1->value[0] != '*')
692 cupsFilePutChar(fp, '*');
693
694 cupsFilePrintf(fp, cn->option1->value);
695
696 if (cn->choice1->value)
697 cupsFilePrintf(fp, " %s", cn->choice1->value);
698
699 cupsFilePutChar(fp, ' ');
700
701 if (cn->option2->value[0] != '*')
702 cupsFilePutChar(fp, '*');
703
704 cupsFilePrintf(fp, cn->option2->value);
705
706 if (cn->choice2->value)
707 cupsFilePrintf(fp, " %s", cn->choice2->value);
708
709 cupsFilePrintf(fp, "%s", lf);
710
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: ");
715 else
716 cupsFilePrintf(fp, "*UIConstraints: ");
717
718 if (cn->option2->value[0] != '*')
719 cupsFilePutChar(fp, '*');
720
721 cupsFilePrintf(fp, cn->option2->value);
722
723 if (cn->choice2->value)
724 cupsFilePrintf(fp, " %s", cn->choice2->value);
725
726 cupsFilePutChar(fp, ' ');
727
728 if (cn->option1->value[0] != '*')
729 cupsFilePutChar(fp, '*');
730
731 cupsFilePrintf(fp, cn->option1->value);
732
733 if (cn->choice1->value)
734 cupsFilePrintf(fp, " %s", cn->choice1->value);
735
736 cupsFilePuts(fp, lf);
737 }
738
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);
744
745 for (m = (ppdcMediaSize *)sizes->first();
746 m;
747 m = (ppdcMediaSize *)sizes->next())
748 if (m->size_code->value)
749 {
750 cupsFilePrintf(fp, "*PageSize %s/%s: \"%s\"%s",
751 m->name->value, catalog->find_message(m->text->value),
752 m->size_code->value, lf);
753
754 if (strchr(m->size_code->value, '\n') ||
755 strchr(m->size_code->value, '\r'))
756 cupsFilePrintf(fp, "*End%s", lf);
757 }
758 else
759 cupsFilePrintf(fp,
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);
764
765 if ((a = find_attr("?PageSize", NULL)) != NULL)
766 {
767 cupsFilePrintf(fp, "*?PageSize: \"%s\"%s", a->value->value, lf);
768
769 if (strchr(a->value->value, '\n') ||
770 strchr(a->value->value, '\r'))
771 cupsFilePrintf(fp, "*End%s", lf);
772 }
773
774 cupsFilePrintf(fp, "*CloseUI: *PageSize%s", lf);
775
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);
781
782 for (m = (ppdcMediaSize *)sizes->first();
783 m;
784 m = (ppdcMediaSize *)sizes->next())
785 if (m->region_code->value)
786 {
787 cupsFilePrintf(fp, "*PageRegion %s/%s: \"%s\"%s",
788 m->name->value, catalog->find_message(m->text->value),
789 m->region_code->value, lf);
790
791 if (strchr(m->region_code->value, '\n') ||
792 strchr(m->region_code->value, '\r'))
793 cupsFilePrintf(fp, "*End%s", lf);
794 }
795 else
796 cupsFilePrintf(fp,
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);
801
802 if ((a = find_attr("?PageRegion", NULL)) != NULL)
803 {
804 cupsFilePrintf(fp, "*?PageRegion: \"%s\"%s", a->value->value, lf);
805
806 if (strchr(a->value->value, '\n') ||
807 strchr(a->value->value, '\r'))
808 cupsFilePrintf(fp, "*End%s", lf);
809 }
810
811 cupsFilePrintf(fp, "*CloseUI: *PageRegion%s", lf);
812
813 // ImageableArea info...
814 cupsFilePrintf(fp, "*DefaultImageableArea: %s%s",
815 default_size ? default_size->value : "Letter", lf);
816
817 for (m = (ppdcMediaSize *)sizes->first();
818 m;
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,
823 lf);
824
825 if ((a = find_attr("?ImageableArea", NULL)) != NULL)
826 {
827 cupsFilePrintf(fp, "*?ImageableArea: \"%s\"%s", a->value->value, lf);
828
829 if (strchr(a->value->value, '\n') ||
830 strchr(a->value->value, '\r'))
831 cupsFilePrintf(fp, "*End%s", lf);
832 }
833
834 // PaperDimension info...
835 cupsFilePrintf(fp, "*DefaultPaperDimension: %s%s",
836 default_size ? default_size->value : "Letter", lf);
837
838 for (m = (ppdcMediaSize *)sizes->first();
839 m;
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);
844
845 if ((a = find_attr("?PaperDimension", NULL)) != NULL)
846 {
847 cupsFilePrintf(fp, "*?PaperDimension: \"%s\"%s", a->value->value, lf);
848
849 if (strchr(a->value->value, '\n') ||
850 strchr(a->value->value, '\r'))
851 cupsFilePrintf(fp, "*End%s", lf);
852 }
853
854 // Custom size support...
855 if (variable_paper_size)
856 {
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);
861
862 if (custom_size_code && custom_size_code->value)
863 {
864 cupsFilePrintf(fp, "*CustomPageSize True: \"%s\"%s",
865 custom_size_code->value, lf);
866
867 if (strchr(custom_size_code->value, '\n') ||
868 strchr(custom_size_code->value, '\r'))
869 cupsFilePrintf(fp, "*End%s", lf);
870 }
871 else
872 cupsFilePrintf(fp,
873 "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]"
874 "/ImagingBBox null>>setpagedevice\"%s", lf);
875
876 if ((a = find_attr("ParamCustomPageSize", "Width")) != NULL)
877 cupsFilePrintf(fp, "*ParamCustomPageSize Width: %s%s", a->value->value,
878 lf);
879 else
880 cupsFilePrintf(fp, "*ParamCustomPageSize Width: 1 points %.2f %.2f%s",
881 min_width, max_width, lf);
882
883 if ((a = find_attr("ParamCustomPageSize", "Height")) != NULL)
884 cupsFilePrintf(fp, "*ParamCustomPageSize Height: %s%s", a->value->value,
885 lf);
886 else
887 cupsFilePrintf(fp, "*ParamCustomPageSize Height: 2 points %.2f %.2f%s",
888 min_length, max_length, lf);
889
890 if ((a = find_attr("ParamCustomPageSize", "WidthOffset")) != NULL)
891 cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: %s%s",
892 a->value->value, lf);
893 else
894 cupsFilePrintf(fp, "*ParamCustomPageSize WidthOffset: 3 points 0 0%s", lf);
895
896 if ((a = find_attr("ParamCustomPageSize", "HeightOffset")) != NULL)
897 cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: %s%s",
898 a->value->value, lf);
899 else
900 cupsFilePrintf(fp, "*ParamCustomPageSize HeightOffset: 4 points 0 0%s", lf);
901
902 if ((a = find_attr("ParamCustomPageSize", "Orientation")) != NULL)
903 cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: %s%s",
904 a->value->value, lf);
905 else
906 cupsFilePrintf(fp, "*ParamCustomPageSize Orientation: 5 int 0 0%s", lf);
907 }
908
909 if (type != PPDC_DRIVER_PS && !find_attr("RequiresPageRegion", NULL))
910 cupsFilePrintf(fp, "*RequiresPageRegion All: True%s", lf);
911
912 // All other options...
913 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
914 {
915 if (!g->options->count)
916 continue;
917
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);
921
922 for (o = (ppdcOption *)g->options->first();
923 o;
924 o = (ppdcOption *)g->options->next())
925 {
926 if (!o->choices->count)
927 continue;
928
929 if (!o->text->value || !strcmp(o->name->value, o->text->value))
930 cupsFilePrintf(fp, "*OpenUI *%s: ", o->name->value);
931 else
932 cupsFilePrintf(fp, "*OpenUI *%s/%s: ", o->name->value,
933 catalog->find_message(o->text->value));
934
935 switch (o->type)
936 {
937 case PPDC_BOOLEAN :
938 cupsFilePrintf(fp, "Boolean%s", lf);
939 break;
940 default :
941 cupsFilePrintf(fp, "PickOne%s", lf);
942 break;
943 case PPDC_PICKMANY :
944 cupsFilePrintf(fp, "PickMany%s", lf);
945 break;
946 }
947
948 cupsFilePrintf(fp, "*OrderDependency: %.1f ", o->order);
949 switch (o->section)
950 {
951 default :
952 cupsFilePrintf(fp, "AnySetup");
953 break;
954 case PPDC_SECTION_DOCUMENT :
955 cupsFilePrintf(fp, "DocumentSetup");
956 break;
957 case PPDC_SECTION_EXIT :
958 cupsFilePrintf(fp, "ExitServer");
959 break;
960 case PPDC_SECTION_JCL :
961 cupsFilePrintf(fp, "JCLSetup");
962 break;
963 case PPDC_SECTION_PAGE :
964 cupsFilePrintf(fp, "PageSetup");
965 break;
966 case PPDC_SECTION_PROLOG :
967 cupsFilePrintf(fp, "Prolog");
968 break;
969 }
970
971 cupsFilePrintf(fp, " *%s%s", o->name->value, lf);
972
973 if (o->defchoice)
974 {
975 // Use the programmer-supplied default...
976 cupsFilePrintf(fp, "*Default%s: %s%s", o->name->value,
977 o->defchoice->value, lf);
978 }
979 else
980 {
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,
984 lf);
985 }
986
987 for (c = (ppdcChoice *)o->choices->first();
988 c;
989 c = (ppdcChoice *)o->choices->next())
990 {
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,
994 c->code->value, lf);
995 else
996 cupsFilePrintf(fp, "*%s %s/%s: \"%s\"%s", o->name->value,
997 c->name->value, catalog->find_message(c->text->value),
998 c->code->value, lf);
999
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);
1004 }
1005
1006 snprintf(query, sizeof(query), "?%s", o->name->value);
1007
1008 if ((a = find_attr(query, NULL)) != NULL)
1009 {
1010 cupsFilePrintf(fp, "*%s: \"%s\"\n", query, a->value->value);
1011
1012 if (strchr(a->value->value, '\n') ||
1013 strchr(a->value->value, '\r'))
1014 cupsFilePrintf(fp, "*End%s", lf);
1015 }
1016
1017 cupsFilePrintf(fp, "*CloseUI: *%s%s", o->name->value, lf);
1018 }
1019
1020 if (strcasecmp(g->name->value, "General"))
1021 cupsFilePrintf(fp, "*CloseGroup: %s%s", g->name->value, lf);
1022 }
1023
1024 if (locales)
1025 {
1026 // Add localizations for additional languages...
1027 ppdcString *locale; // Locale name
1028 ppdcCatalog *locatalog; // Message catalog for locale
1029
1030
1031 // Write the translation strings for each language...
1032 for (locale = (ppdcString *)locales->first();
1033 locale;
1034 locale = (ppdcString *)locales->next())
1035 {
1036 // Skip (US) English...
1037 if (!strcmp(locale->value, "en") || !strcmp(locale->value, "en_US"))
1038 continue;
1039
1040 // Skip missing languages...
1041 if ((locatalog = src->find_po(locale->value)) == NULL)
1042 continue;
1043
1044 // Do the core stuff first...
1045 cupsFilePrintf(fp, "*%s.Translation Manufacturer/%s: \"\"%s",
1046 locale->value,
1047 locatalog->find_message(manufacturer->value), lf);
1048
1049 if ((a = find_attr("ModelName", NULL)) != NULL)
1050 cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
1051 locale->value,
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",
1056 locale->value,
1057 locatalog->find_message(manufacturer->value),
1058 locatalog->find_message(model_name->value), lf);
1059 else
1060 cupsFilePrintf(fp, "*%s.Translation ModelName/%s: \"\"%s",
1061 locale->value,
1062 locatalog->find_message(model_name->value), lf);
1063
1064 if ((a = find_attr("ShortNickName", NULL)) != NULL)
1065 cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
1066 locale->value,
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",
1071 locale->value,
1072 locatalog->find_message(manufacturer->value),
1073 locatalog->find_message(model_name->value), lf);
1074 else
1075 cupsFilePrintf(fp, "*%s.Translation ShortNickName/%s: \"\"%s",
1076 locale->value,
1077 locatalog->find_message(model_name->value), lf);
1078
1079 if ((a = find_attr("NickName", NULL)) != NULL)
1080 cupsFilePrintf(fp, "*%s.Translation NickName/%s: \"\"%s",
1081 locale->value,
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",
1086 locale->value,
1087 locatalog->find_message(manufacturer->value),
1088 locatalog->find_message(model_name->value),
1089 version->value, lf);
1090 else
1091 cupsFilePrintf(fp, "*%s.Translation NickName/%s, %s: \"\"%s",
1092 locale->value,
1093 locatalog->find_message(model_name->value),
1094 version->value, lf);
1095
1096 // Then the page sizes...
1097 cupsFilePrintf(fp, "*%s.Translation PageSize/%s: \"\"%s", locale->value,
1098 locatalog->find_message("Media Size"), lf);
1099
1100 for (m = (ppdcMediaSize *)sizes->first();
1101 m;
1102 m = (ppdcMediaSize *)sizes->next())
1103 {
1104 cupsFilePrintf(fp, "*%s.PageSize %s/%s: \"\"%s", locale->value,
1105 m->name->value, locatalog->find_message(m->text->value),
1106 lf);
1107 }
1108
1109 // Next the groups and options...
1110 for (g = (ppdcGroup *)groups->first(); g; g = (ppdcGroup *)groups->next())
1111 {
1112 if (!g->options->count)
1113 continue;
1114
1115 if (strcasecmp(g->name->value, "General"))
1116 cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
1117 g->name->value,
1118 locatalog->find_message(g->text->value), lf);
1119
1120 for (o = (ppdcOption *)g->options->first();
1121 o;
1122 o = (ppdcOption *)g->options->next())
1123 {
1124 if (!o->choices->count)
1125 continue;
1126
1127 cupsFilePrintf(fp, "*%s.Translation %s/%s: \"\"%s", locale->value,
1128 o->name->value,
1129 locatalog->find_message(o->text->value ?
1130 o->text->value :
1131 o->name->value), lf);
1132
1133 for (c = (ppdcChoice *)o->choices->first();
1134 c;
1135 c = (ppdcChoice *)o->choices->next())
1136 {
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 ?
1141 c->text->value :
1142 c->name->value), lf);
1143 }
1144 }
1145 }
1146
1147 // Finally the localizable attributes...
1148 for (a = (ppdcAttr *)attrs->first(); a; a = (ppdcAttr *)attrs->next())
1149 {
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))
1153 continue;
1154
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))
1161 continue;
1162
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) : "",
1169 lf);
1170 }
1171 }
1172 }
1173
1174 if (default_font && default_font->value)
1175 cupsFilePrintf(fp, "*DefaultFont: %s%s", default_font->value, lf);
1176 else
1177 cupsFilePrintf(fp, "*DefaultFont: Courier%s", lf);
1178
1179 for (fn = (ppdcFont *)fonts->first(); fn; fn = (ppdcFont *)fonts->next())
1180 if (!strcmp(fn->name->value, "*"))
1181 {
1182 for (bfn = (ppdcFont *)src->base_fonts->first();
1183 bfn;
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);
1189 }
1190 else
1191 cupsFilePrintf(fp, "*Font %s: %s \"%s\" %s %s%s",
1192 fn->name->value, fn->encoding->value, fn->version->value,
1193 fn->charset->value,
1194 fn->status == PPDC_FONT_ROM ? "ROM" : "Disk", lf);
1195
1196 cupsFilePrintf(fp, "*%% End of %s, %05d bytes.%s", pc_file_name->value,
1197 (int)(cupsFileTell(fp) + 25 + strlen(pc_file_name->value)),
1198 lf);
1199
1200 if (delete_cat)
1201 delete catalog;
1202
1203 return (0);
1204 }
1205
1206
1207 //
1208 // End of "$Id$".
1209 //