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