1// 2// "$Id: ppdc-driver.cxx 11560 2014-02-06 20:10:19Z msweet $" 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 27ppdcDriver::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 128ppdcDriver::~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 165ppdcAttr * // O - Attribute or NULL 166ppdcDriver::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 186ppdcGroup * // O - Matching group or NULL 187ppdcDriver::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 204ppdcOption * // O - Matching option or NULL 205ppdcDriver::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 215ppdcOption * // O - Matching option or NULL 216ppdcDriver::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 245void 246ppdcDriver::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 260void 261ppdcDriver::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 281void 282ppdcDriver::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 302void 303ppdcDriver::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 316void 317ppdcDriver::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 331void 332ppdcDriver::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 346void 347ppdcDriver::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 361void 362ppdcDriver::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 375int // O - 0 on success, -1 on failure 376ppdcDriver::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: ppdc-driver.cxx 11560 2014-02-06 20:10:19Z msweet $". 1330// 1331