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