1/* 2 * "$Id: genppd.c,v 1.186 2011/03/13 19:28:50 rlk Exp $" 3 * 4 * PPD file generation program for the CUPS drivers. 5 * 6 * Copyright 1993-2008 by Mike Sweet and Robert Krawitz. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the Free 10 * Software Foundation; either version 2 of the License, or (at your option) 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * 22 * Contents: 23 * 24 * main() - Process files on the command-line... 25 * cat_ppd() - Copy the named PPD to stdout. 26 * generate_ppd() - Generate a PPD file. 27 * getlangs() - Get a list of available translations. 28 * help() - Show detailed help. 29 * is_special_option() - Determine if an option should be grouped. 30 * list_ppds() - List the available drivers. 31 * print_group_close() - Close a UI group. 32 * print_group_open() - Open a new UI group. 33 * printlangs() - Print list of available translations. 34 * printmodels() - Print a list of available models. 35 * usage() - Show program usage. 36 * write_ppd() - Write a PPD file. 37 */ 38 39/* 40 * Include necessary headers... 41 */ 42 43#ifdef HAVE_CONFIG_H 44#include <config.h> 45#endif 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <dirent.h> 50#include <unistd.h> 51#include <fcntl.h> 52#include <sys/types.h> 53#include <sys/stat.h> 54#include <string.h> 55#include <ctype.h> 56#include <errno.h> 57#include <libgen.h> 58 59#ifdef CUPS_DRIVER_INTERFACE 60# ifdef HAVE_LIBZ 61# undef HAVE_LIBZ 62# endif /* HAVE_LIBZ */ 63#endif /* CUPS_DRIVER_INTERFACE */ 64 65static const char *cups_modeldir = CUPS_MODELDIR; 66 67#ifdef HAVE_LIBZ 68#include <zlib.h> 69static const char *gzext = ".gz"; 70#else 71static const char *gzext = ""; 72# define gzopen fopen 73# define gzclose fclose 74# define gzFile FILE * 75# define gzprintf fprintf 76# define gzputs(f,s) fputs((s),(f)) 77#endif 78 79#include <cups/cups.h> 80#include <cups/raster.h> 81 82#include "i18n.h" 83 84/* 85 * Some applications use the XxYdpi tags rather than the actual 86 * hardware resolutions to decide what resolution to print at. Some 87 * applications get very unhappy if the vertical resolution exceeds 88 * a certain amount. Some of those applications even get very unhappy if 89 * the PPD file even contains a resolution that exceeds that limit. 90 * And they're not even free source applications. 91 * Feh. 92 */ 93#define MAXIMUM_SAFE_PPD_Y_RESOLUTION (720) 94#define MAXIMUM_SAFE_PPD_X_RESOLUTION (1500) 95 96typedef enum 97{ 98 PPD_STANDARD = 0, 99 PPD_SIMPLIFIED = 1, 100 PPD_NO_COLOR_OPTS = 2 101} ppd_type_t; 102 103/* 104 * Note: 105 * 106 * The current release of ESP Ghostscript is fully Level 3 compliant, 107 * so we can report Level 3 support by default... 108 */ 109 110int cups_ppd_ps_level = CUPS_PPD_PS_LEVEL; 111int localize_numbers = 0; 112 113/* 114 * File handling stuff... 115 */ 116 117static const char *ppdext = ".ppd"; 118 119typedef struct /**** Media size values ****/ 120{ 121 const char *name, /* Media size name */ 122 *text; /* Media size text */ 123 int width, /* Media width */ 124 height, /* Media height */ 125 left, /* Media left margin */ 126 right, /* Media right margin */ 127 bottom, /* Media bottom margin */ 128 top; /* Media top margin */ 129} paper_t; 130 131const char *special_options[] = 132{ 133 "PageSize", 134 "MediaType", 135 "InputSlot", 136 "Resolution", 137 "OutputOrder", 138 "Quality", 139 "Duplex", 140 NULL 141}; 142 143/* 144 * TRANSLATORS: 145 * Please keep these translated names SHORT. The number of bytes in 146 * the parameter class name plus the number of bytes in the parameter 147 * name must not exceed 38 BYTES (not characters!) 148 */ 149 150const char *parameter_class_names[] = 151{ 152 _("Printer Features"), 153 _("Output Control") 154}; 155 156const char *parameter_level_names[] = 157{ 158 _("Common"), 159 _("Extra 1"), 160 _("Extra 2"), 161 _("Extra 3"), 162 _("Extra 4"), 163 _("Extra 5") 164}; 165 166 167/* 168 * Local functions... 169 */ 170 171#ifdef CUPS_DRIVER_INTERFACE 172static int cat_ppd(const char *uri); 173static int list_ppds(const char *argv0); 174#else /* !CUPS_DRIVER_INTERFACE */ 175static int generate_ppd(const char *prefix, int verbose, 176 const stp_printer_t *p, const char *language, 177 ppd_type_t ppd_type); 178static int generate_model_ppds(const char *prefix, int verbose, 179 const stp_printer_t *printer, 180 const char *language, int which_ppds); 181static void help(void); 182static void printlangs(char** langs); 183static void printmodels(int verbose); 184static void usage(void); 185#endif /* !CUPS_DRIVER_INTERFACE */ 186static char **getlangs(void); 187static int is_special_option(const char *name); 188static void print_group_close(gzFile fp, stp_parameter_class_t p_class, 189 stp_parameter_level_t p_level, 190 const char *language, 191 const stp_string_list_t *po); 192static void print_group_open(gzFile fp, stp_parameter_class_t p_class, 193 stp_parameter_level_t p_level, 194 const char *language, 195 const stp_string_list_t *po); 196static int write_ppd(gzFile fp, const stp_printer_t *p, 197 const char *language, const char *ppd_location, 198 ppd_type_t ppd_type, const char *filename); 199 200 201/* 202 * Global variables... 203 */ 204 205 206#ifdef CUPS_DRIVER_INTERFACE 207 208/* 209 * 'main()' - Process files on the command-line... 210 */ 211 212const char slang_c[] = "LANG=C"; 213const char slcall_c[] = "LC_ALL=C"; 214const char slcnumeric_c[] = "LC_NUMERIC=C"; 215char lang_c[sizeof(slang_c) + 1]; 216char lcall_c[sizeof(slcall_c) + 1]; 217char lcnumeric_c[sizeof(slcnumeric_c) + 1]; 218 219int /* O - Exit status */ 220main(int argc, /* I - Number of command-line arguments */ 221 char *argv[]) /* I - Command-line arguments */ 222{ 223 /* 224 * Force POSIX locale, since stp_init incorrectly calls setlocale... 225 */ 226 227 strcpy(lang_c, slang_c); 228 strcpy(lcall_c, slcall_c); 229 strcpy(lcnumeric_c, slcnumeric_c); 230 putenv(lang_c); 231 putenv(lcall_c); 232 putenv(lcnumeric_c); 233 234 /* 235 * Initialise libgutenprint 236 */ 237 238 stp_init(); 239 240 /* 241 * Process command-line... 242 */ 243 244 if (argc == 2 && !strcmp(argv[1], "list")) 245 return (list_ppds(argv[0])); 246 else if (argc == 3 && !strcmp(argv[1], "cat")) 247 return (cat_ppd(argv[2])); 248 else if (argc == 2 && !strcmp(argv[1], "org.gutenprint.multicat")) 249 { 250 char buf[1024]; 251 int status = 0; 252 while (status == 0 && fgets(buf, sizeof(buf) - 1, stdin)) 253 { 254 size_t len = strlen(buf); 255 if (len == 0) 256 continue; 257 if (buf[len - 1] == '\n') 258 buf[len - 1] = '\0'; 259 status = cat_ppd(buf); 260 fputs("*%*%EOFEOF\n", stdout); 261 (void) fflush(stdout); 262 } 263 return status; 264 } 265 else if (argc == 2 && !strcmp(argv[1], "VERSION")) 266 { 267 printf("%s\n", VERSION); 268 return (0); 269 } 270 else if (argc == 2 && !strcasecmp(argv[1], "org.gutenprint.extensions")) 271 { 272 printf("org.gutenprint.multicat"); 273 return (0); 274 } 275 else 276 { 277 fprintf(stderr, "Usage: %s list\n", argv[0]); 278 fprintf(stderr, " %s cat URI\n", argv[0]); 279 return (1); 280 } 281} 282 283 284/* 285 * 'cat_ppd()' - Copy the named PPD to stdout. 286 */ 287 288static int /* O - Exit status */ 289cat_ppd(const char *uri) /* I - Driver URI */ 290{ 291 char scheme[64], /* URI scheme */ 292 userpass[32], /* URI user/pass (unused) */ 293 hostname[32], /* URI hostname */ 294 resource[1024]; /* URI resource */ 295 int port; /* URI port (unused) */ 296 http_uri_status_t status; /* URI decode status */ 297 const stp_printer_t *p; /* Printer driver */ 298 const char *lang = NULL; 299 char *s; 300 char filename[1024], /* Filename */ 301 ppd_location[1024]; /* Installed location */ 302 const char *infix = ""; 303 ppd_type_t ppd_type = PPD_STANDARD; 304 305 if ((status = httpSeparateURI(HTTP_URI_CODING_ALL, uri, 306 scheme, sizeof(scheme), 307 userpass, sizeof(userpass), 308 hostname, sizeof(hostname), 309 &port, resource, sizeof(resource))) 310 < HTTP_URI_OK) 311 { 312 fprintf(stderr, "ERROR: Bad ppd-name \"%s\" (%d)!\n", uri, status); 313 return (1); 314 } 315 316 if (strcmp(scheme, "gutenprint." GUTENPRINT_RELEASE_VERSION) != 0) 317 { 318 fprintf(stderr, "ERROR: Gutenprint version mismatch!\n"); 319 return(1); 320 } 321 322 s = strchr(resource + 1, '/'); 323 if (s) 324 { 325 lang = s + 1; 326 *s = '\0'; 327 } 328 329 if ((p = stp_get_printer_by_driver(hostname)) == NULL) 330 { 331 fprintf(stderr, "ERROR: Unable to find driver \"%s\"!\n", hostname); 332 return (1); 333 } 334 335 if (strcmp(resource + 1, "simple") == 0) 336 { 337 infix = ".sim"; 338 ppd_type = PPD_SIMPLIFIED; 339 } 340 else if (strcmp(resource + 1, "nocolor") == 0) 341 { 342 infix = ".nc"; 343 ppd_type = PPD_NO_COLOR_OPTS; 344 } 345 346 /* 347 * This isn't really the right thing to do. We really shouldn't 348 * be embedding filenames in automatically generated PPD files, but 349 * if the user ever decides to go back from generated PPD files to 350 * static PPD files we'll need to have this for genppdupdate to work. 351 */ 352 snprintf(filename, sizeof(filename) - 1, "stp-%s.%s%s%s", 353 hostname, GUTENPRINT_RELEASE_VERSION, infix, ppdext); 354 snprintf(ppd_location, sizeof(ppd_location) - 1, "%s%s%s/ppd/%s%s", 355 cups_modeldir, 356 cups_modeldir[strlen(cups_modeldir) - 1] == '/' ? "" : "/", 357 lang ? lang : "C", 358 filename, gzext); 359 360 return (write_ppd(stdout, p, lang, ppd_location, ppd_type, filename)); 361} 362 363/* 364 * 'list_ppds()' - List the available drivers. 365 */ 366 367static int /* O - Exit status */ 368list_ppds(const char *argv0) /* I - Name of program */ 369{ 370 const char *scheme; /* URI scheme */ 371 int i; /* Looping var */ 372 const stp_printer_t *printer; /* Pointer to printer driver */ 373 374 if ((scheme = strrchr(argv0, '/')) != NULL) 375 scheme ++; 376 else 377 scheme = argv0; 378 379 for (i = 0; i < stp_printer_model_count(); i++) 380 if ((printer = stp_get_printer_by_index(i)) != NULL) 381 { 382 const char *device_id; 383 if (!strcmp(stp_printer_get_family(printer), "ps") || 384 !strcmp(stp_printer_get_family(printer), "raw")) 385 continue; 386 387 device_id = stp_printer_get_device_id(printer); 388 printf("\"%s://%s/expert\" " 389 "%s " 390 "\"%s\" " 391 "\"%s" CUPS_PPD_NICKNAME_STRING VERSION "\" " 392 "\"%s\"\n", 393 scheme, stp_printer_get_driver(printer), 394 "en", 395 stp_printer_get_manufacturer(printer), 396 stp_printer_get_long_name(printer), 397 device_id ? device_id : ""); 398 399#ifdef GENERATE_SIMPLIFIED_PPDS 400 printf("\"%s://%s/simple\" " 401 "%s " 402 "\"%s\" " 403 "\"%s" CUPS_PPD_NICKNAME_STRING VERSION " Simplified\" " 404 "\"%s\"\n", 405 scheme, stp_printer_get_driver(printer), 406 "en", 407 stp_printer_get_manufacturer(printer), 408 stp_printer_get_long_name(printer), 409 device_id ? device_id : ""); 410#endif 411 412#ifdef GENERATE_NOCOLOR_PPDS 413 printf("\"%s://%s/nocolor\" " 414 "%s " 415 "\"%s\" " 416 "\"%s" CUPS_PPD_NICKNAME_STRING VERSION " No color options\" " 417 "\"%s\"\n", 418 scheme, stp_printer_get_driver(printer), 419 "en", 420 stp_printer_get_manufacturer(printer), 421 stp_printer_get_long_name(printer), 422 device_id ? device_id : ""); 423#endif 424 } 425 426 return (0); 427} 428#endif /* CUPS_DRIVER_INTERFACE */ 429 430#ifndef CUPS_DRIVER_INTERFACE 431 432/* 433 * 'main()' - Process files on the command-line... 434 */ 435 436int /* O - Exit status */ 437main(int argc, /* I - Number of command-line arguments */ 438 char *argv[]) /* I - Command-line arguments */ 439{ 440 int i; /* Looping var */ 441 const char *prefix; /* Directory prefix for output */ 442 const char *language = NULL; /* Language */ 443 const stp_printer_t *printer; /* Pointer to printer driver */ 444 int verbose = 0; /* Verbose messages */ 445 char **langs = NULL; /* Available translations */ 446 char **models = NULL; /* Models to output, all if NULL */ 447 int opt_printlangs = 0; /* Print available translations */ 448 int opt_printmodels = 0;/* Print available models */ 449 int which_ppds = 2; /* Simplified PPD's = 1, full = 2, 450 no color opts = 4 */ 451 452 /* 453 * Parse command-line args... 454 */ 455 456 prefix = CUPS_MODELDIR; 457 458 for (;;) 459 { 460 if ((i = getopt(argc, argv, "23hvqc:p:l:LMVd:saNC")) == -1) 461 break; 462 463 switch (i) 464 { 465 case '2': 466 cups_ppd_ps_level = 2; 467 break; 468 case '3': 469 cups_ppd_ps_level = 3; 470 break; 471 case 'h': 472 help(); 473 exit(EXIT_SUCCESS); 474 break; 475 case 'v': 476 verbose = 1; 477 break; 478 case 'q': 479 verbose = 0; 480 break; 481 case 'c': 482 fputs("ERROR: -c option no longer supported!\n", stderr); 483 break; 484 case 'p': 485 prefix = optarg; 486# ifdef DEBUG 487 fprintf(stderr, "DEBUG: prefix: %s\n", prefix); 488# endif 489 break; 490 case 'l': 491 language = optarg; 492 break; 493 case 'L': 494 opt_printlangs = 1; 495 break; 496 case 'M': 497 opt_printmodels = 1; 498 break; 499 case 'd': 500 cups_modeldir = optarg; 501 break; 502 case 's': 503 which_ppds = 1; 504 break; 505 case 'a': 506 which_ppds = 3; 507 break; 508 case 'C': 509 which_ppds |= 4; 510 break; 511 case 'N': 512 localize_numbers = !localize_numbers; 513 break; 514 case 'V': 515 printf("cups-genppd version %s, " 516 "Copyright 1993-2008 by Michael R Sweet and Robert Krawitz.\n\n", 517 VERSION); 518 printf("Default CUPS PPD PostScript Level: %d\n", cups_ppd_ps_level); 519 printf("Default PPD location (prefix): %s\n", CUPS_MODELDIR); 520 printf("Default base locale directory: %s\n\n", PACKAGE_LOCALE_DIR); 521 puts("This program is free software; you can redistribute it and/or\n" 522 "modify it under the terms of the GNU General Public License,\n" 523 "version 2, as published by the Free Software Foundation.\n" 524 "\n" 525 "This program is distributed in the hope that it will be useful,\n" 526 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 527 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 528 "GNU General Public License for more details.\n"); 529 exit(EXIT_SUCCESS); 530 break; 531 default: 532 usage(); 533 exit(EXIT_FAILURE); 534 break; 535 } 536 } 537 if (optind < argc) { 538 int n, numargs; 539 numargs = argc-optind; 540 models = stp_malloc((numargs+1) * sizeof(char*)); 541 for (n=0; n<numargs; n++) 542 { 543 models[n] = argv[optind+n]; 544 } 545 models[numargs] = (char*)NULL; 546 547 n=0; 548 } 549 550/* 551 * Initialise libgutenprint 552 */ 553 554 stp_init(); 555 556 langs = getlangs(); 557 558 /* 559 * Print lists 560 */ 561 562 if (opt_printlangs) 563 { 564 printlangs(langs); 565 exit(EXIT_SUCCESS); 566 } 567 568 if (opt_printmodels) 569 { 570 printmodels(verbose); 571 exit(EXIT_SUCCESS); 572 } 573 574 /* 575 * Write PPD files... 576 */ 577 578 if (models) 579 { 580 int n; 581 for (n=0; models[n]; n++) 582 { 583 printer = stp_get_printer_by_driver(models[n]); 584 if (!printer) 585 printer = stp_get_printer_by_long_name(models[n]); 586 587 if (printer) 588 { 589 if (generate_model_ppds(prefix, verbose, printer, language, 590 which_ppds)) 591 return 1; 592 } 593 else 594 { 595 printf("Driver not found: %s\n", models[n]); 596 return (1); 597 } 598 } 599 stp_free(models); 600 } 601 else 602 { 603 for (i = 0; i < stp_printer_model_count(); i++) 604 { 605 printer = stp_get_printer_by_index(i); 606 607 if (printer) 608 { 609 if (generate_model_ppds(prefix, verbose, printer, language, 610 which_ppds)) 611 return 1; 612 } 613 } 614 } 615 if (!verbose) 616 fprintf(stderr, " done.\n"); 617 618 return (0); 619} 620 621static int 622generate_model_ppds(const char *prefix, int verbose, 623 const stp_printer_t *printer, const char *language, 624 int which_ppds) 625{ 626 if ((which_ppds & 1) && 627 generate_ppd(prefix, verbose, printer, language, PPD_SIMPLIFIED)) 628 return (1); 629 if ((which_ppds & 2) && 630 generate_ppd(prefix, verbose, printer, language, PPD_STANDARD)) 631 return (1); 632 if ((which_ppds & 4) && 633 generate_ppd(prefix, verbose, printer, language, PPD_NO_COLOR_OPTS)) 634 return (1); 635 return 0; 636} 637 638/* 639 * 'generate_ppd()' - Generate a PPD file. 640 */ 641 642static int /* O - Exit status */ 643generate_ppd( 644 const char *prefix, /* I - PPD directory prefix */ 645 int verbose, /* I - Verbosity level */ 646 const stp_printer_t *p, /* I - Driver */ 647 const char *language, /* I - Primary language */ 648 ppd_type_t ppd_type) /* I - full, simplified, no color */ 649{ 650 int status; /* Exit status */ 651 gzFile fp; /* File to write to */ 652 char filename[1024], /* Filename */ 653 ppd_location[1024]; /* Installed location */ 654 struct stat dir; /* Prefix dir status */ 655 const char *ppd_infix; 656 657 /* 658 * Skip the PostScript drivers... 659 */ 660 661 if (!strcmp(stp_printer_get_family(p), "ps") || 662 !strcmp(stp_printer_get_family(p), "raw")) 663 return (0); 664 665 /* 666 * Make sure the destination directory exists... 667 */ 668 669 if (stat(prefix, &dir) && !S_ISDIR(dir.st_mode)) 670 { 671 if (mkdir(prefix, 0777)) 672 { 673 printf("cups-genppd: Cannot create directory %s: %s\n", 674 prefix, strerror(errno)); 675 exit(EXIT_FAILURE); 676 } 677 } 678 679 /* 680 * The files will be named stp-<driver>.<major>.<minor>.ppd, for 681 * example: 682 * 683 * stp-escp2-ex.5.0.ppd 684 * 685 * or 686 * 687 * stp-escp2-ex.5.0.ppd.gz 688 */ 689 690 switch (ppd_type) 691 { 692 case PPD_SIMPLIFIED: 693 ppd_infix = ".sim"; 694 break; 695 case PPD_NO_COLOR_OPTS: 696 ppd_infix = ".nc"; 697 break; 698 default: 699 ppd_infix = ""; 700 } 701 702 snprintf(filename, sizeof(filename) - 1, "%s/stp-%s.%s%s%s%s", 703 prefix, stp_printer_get_driver(p), GUTENPRINT_RELEASE_VERSION, 704 ppd_infix, ppdext, gzext); 705 706 /* 707 * Open the PPD file... 708 */ 709 710 if ((fp = gzopen(filename, "wb")) == NULL) 711 { 712 fprintf(stderr, "cups-genppd: Unable to create file \"%s\" - %s.\n", 713 filename, strerror(errno)); 714 return (2); 715 } 716 717 if (verbose) 718 fprintf(stderr, "Writing %s...\n", filename); 719 else 720 fprintf(stderr, "."); 721 722 snprintf(ppd_location, sizeof(ppd_location), "%s%s%s/%s", 723 cups_modeldir, 724 cups_modeldir[strlen(cups_modeldir) - 1] == '/' ? "" : "/", 725 language ? language : "C", 726 basename(filename)); 727 728 snprintf(filename, sizeof(filename) - 1, "stp-%s.%s%s%s", 729 stp_printer_get_driver(p), GUTENPRINT_RELEASE_VERSION, 730 ppd_infix, ppdext); 731 732 status = write_ppd(fp, p, language, ppd_location, ppd_type, 733 basename(filename)); 734 735 gzclose(fp); 736 737 return (status); 738} 739 740/* 741 * 'help()' - Show detailed help. 742 */ 743 744void 745help(void) 746{ 747 puts("Generate Gutenprint PPD files for use with CUPS\n\n"); 748 usage(); 749 puts("\nExamples: LANG=de_DE cups-genppd -p ppd -c /usr/share/locale\n" 750 " cups-genppd -L -c /usr/share/locale\n" 751 " cups-genppd -M -v\n\n" 752 "Commands:\n" 753 " -h Show this help message.\n" 754 " -L List available translations (message catalogs).\n" 755 " -M List available printer models.\n" 756 " -V Show version information and defaults.\n" 757 " The default is to output PPDs.\n"); 758 puts("Options:\n" 759 " -l locale Output PPDs translated with messages for locale.\n" 760 " -p prefix Output PPDs in directory prefix.\n" 761 " -d prefix Embed directory prefix in PPD file.\n" 762 " -s Generate simplified PPD files.\n" 763 " -a Generate all (simplified and full) PPD files.\n" 764 " -q Quiet mode.\n" 765 " -v Verbose mode.\n" 766 "models:\n" 767 " A list of printer models, either the driver or quoted full name.\n"); 768} 769 770/* 771 * 'usage()' - Show program usage. 772 */ 773 774void 775usage(void) 776{ 777 puts("Usage: cups-genppd " 778 "[-l locale] [-p prefix] [-s | -a] [-q] [-v] models...\n" 779 " cups-genppd -L\n" 780 " cups-genppd -M [-v]\n" 781 " cups-genppd -h\n" 782 " cups-genppd -V\n"); 783} 784 785/* 786 * 'printlangs()' - Print list of available translations. 787 */ 788 789void 790printlangs(char **langs) /* I - Languages */ 791{ 792 if (langs) 793 { 794 int n = 0; 795 while (langs && langs[n]) 796 { 797 puts(langs[n]); 798 n++; 799 } 800 } 801 exit(EXIT_SUCCESS); 802} 803 804 805/* 806 * 'printmodels()' - Print a list of available models. 807 */ 808 809void 810printmodels(int verbose) /* I - Verbosity level */ 811{ 812 const stp_printer_t *p; 813 int i; 814 815 for (i = 0; i < stp_printer_model_count(); i++) 816 { 817 p = stp_get_printer_by_index(i); 818 if (p && 819 strcmp(stp_printer_get_family(p), "ps") != 0 && 820 strcmp(stp_printer_get_family(p), "raw") != 0) 821 { 822 if(verbose) 823 printf("%-20s%s\n", stp_printer_get_driver(p), 824 stp_printer_get_long_name(p)); 825 else 826 printf("%s\n", stp_printer_get_driver(p)); 827 } 828 } 829 exit(EXIT_SUCCESS); 830} 831 832#endif /* !CUPS_DRIVER_INTERFACE */ 833 834 835/* 836 * 'getlangs()' - Get a list of available translations. 837 */ 838 839char ** /* O - Array of languages */ 840getlangs(void) 841{ 842 int i; /* Looping var */ 843 char *ptr; /* Pointer into string */ 844 static char all_linguas[] = ALL_LINGUAS; 845 /* List of languages from configure.ac */ 846 static char **langs = NULL; /* Array of languages */ 847 848 849 if (!langs) 850 { 851 /* 852 * Create the langs array... 853 */ 854 855 for (i = 1, ptr = strchr(all_linguas, ' '); ptr; ptr = strchr(ptr + 1, ' ')) 856 i ++; 857 858 langs = calloc(i + 1, sizeof(char *)); 859 860 langs[0] = all_linguas; 861 for (i = 1, ptr = strchr(all_linguas, ' '); ptr; ptr = strchr(ptr + 1, ' ')) 862 { 863 *ptr = '\0'; 864 langs[i] = ptr + 1; 865 i ++; 866 } 867 } 868 869 return (langs); 870} 871 872 873/* 874 * 'is_special_option()' - Determine if an option should be grouped. 875 */ 876 877static int /* O - 1 if non-grouped, 0 otherwise */ 878is_special_option(const char *name) /* I - Option name */ 879{ 880 int i = 0; 881 while (special_options[i]) 882 { 883 if (strcmp(name, special_options[i]) == 0) 884 return 1; 885 i++; 886 } 887 return 0; 888} 889 890/* 891 * strlen returns the number of characters. PPD file limitations are 892 * defined in bytes. So we need something to count bytes, not merely 893 * characters. 894 */ 895 896static size_t 897bytelen(const char *buffer) 898{ 899 size_t answer = 0; 900 while (*buffer++ != '\0') 901 answer++; 902 return answer; 903} 904 905/* 906 * Use our localization routine to correctly do localization on all 907 * systems. The standard lookup routine has trouble creating multi-locale 908 * files on many systems, and on some systems there's not even a reliable 909 * way to use something other than the system locale. 910 */ 911#ifdef _ 912#undef _ 913#endif 914#define _(x) stp_i18n_lookup(po, x) 915 916#define PPD_MAX_SHORT_NICKNAME (31) 917 918static void 919print_ppd_header(gzFile fp, ppd_type_t ppd_type, int model, const char *driver, 920 const char *family, const char *long_name, 921 const char *manufacturer, const char *device_id, 922 const char *ppd_location, 923 const char *language, const stp_string_list_t *po, 924 char **all_langs) 925{ 926 char short_long_name[(PPD_MAX_SHORT_NICKNAME) + 1]; 927 /* 928 * Write a standard header... 929 */ 930 gzputs(fp, "*PPD-Adobe: \"4.3\"\n"); 931 gzputs(fp, "*% PPD file for CUPS/Gutenprint.\n"); 932 gzputs(fp, "*% Copyright 1993-2008 by Mike Sweet and Robert Krawitz.\n"); 933 gzputs(fp, "*% This program is free software; you can redistribute it and/or\n"); 934 gzputs(fp, "*% modify it under the terms of the GNU General Public License,\n"); 935 gzputs(fp, "*% version 2, as published by the Free Software Foundation.\n"); 936 gzputs(fp, "*%\n"); 937 gzputs(fp, "*% This program is distributed in the hope that it will be useful, but\n"); 938 gzputs(fp, "*% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n"); 939 gzputs(fp, "*% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n"); 940 gzputs(fp, "*% for more details.\n"); 941 gzputs(fp, "*%\n"); 942 gzputs(fp, "*% You should have received a copy of the GNU General Public License\n"); 943 gzputs(fp, "*% along with this program; if not, write to the Free Software\n"); 944 gzputs(fp, "*% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"); 945 gzputs(fp, "*%\n"); 946 gzputs(fp, "*FormatVersion: \"4.3\"\n"); 947 gzputs(fp, "*FileVersion: \"" VERSION "\"\n"); 948 /* Specify language of PPD translation */ 949 /* TRANSLATORS: Specify the language of the PPD translation. 950 * Use the English name of your language here, e.g. "Swedish" instead of 951 * "Svenska". */ 952 gzprintf(fp, "*LanguageVersion: %s\n", _("English")); 953 if (language) 954 gzputs(fp, "*LanguageEncoding: UTF-8\n"); 955 else 956 gzputs(fp, "*LanguageEncoding: ISOLatin1\n"); 957 /* 958 * Strictly speaking, the PCFileName attribute should be a 12 character 959 * max (12345678.ppd) filename, as a requirement of the old PPD spec. 960 * The following code generates a (hopefully unique) 8.3 filename from 961 * the driver name, and makes the filename all UPPERCASE as well... 962 */ 963 964 gzprintf(fp, "*PCFileName: \"STP%05d.PPD\"\n", 965 stp_get_printer_index_by_driver(driver) + 966 ((int) ppd_type * stp_printer_model_count())); 967 gzprintf(fp, "*Manufacturer: \"%s\"\n", manufacturer); 968 969 /* 970 * The Product attribute specifies the string returned by the PostScript 971 * interpreter. The last one will appear in the CUPS "product" field, 972 * while all instances are available as attributes. Rather than listing 973 * the PostScript interpreters we might encounter, we instead just list 974 * a single product line with the "long name" to be compatible with other 975 * CUPS-based drivers. (This is a change from Gutenprint 5.0 and earlier) 976 */ 977 978 gzprintf(fp, "*Product: \"(%s)\"\n", long_name); 979 980 /* 981 * The ModelName attribute now provides the long name rather than the 982 * short driver name... The rastertoprinter driver looks up both... 983 */ 984 985 gzprintf(fp, "*ModelName: \"%s\"\n", long_name); 986 strncpy(short_long_name, long_name, PPD_MAX_SHORT_NICKNAME); 987 short_long_name[PPD_MAX_SHORT_NICKNAME] = '\0'; 988 gzprintf(fp, "*ShortNickName: \"%s\"\n", short_long_name); 989 990 /* 991 * The Windows driver download stuff has problems with NickName fields 992 * with commas. Now use a dash instead... 993 */ 994 995 /* 996 * NOTE - code in rastertoprinter looks for this version string. 997 * If this is changed, the corresponding change must be made in 998 * rastertoprinter.c. Look for "ppd->nickname" 999 */ 1000 gzprintf(fp, "*NickName: \"%s%s%s%s\"\n", 1001 long_name, CUPS_PPD_NICKNAME_STRING, VERSION, 1002 (ppd_type == PPD_SIMPLIFIED ? " Simplified" : 1003 ppd_type == PPD_NO_COLOR_OPTS ? " No Color Options" : "")); 1004 if (cups_ppd_ps_level == 2) 1005 gzputs(fp, "*PSVersion: \"(2017.000) 550\"\n"); 1006 else 1007 gzputs(fp, "*PSVersion: \"(3010.000) 0\"\n"); 1008 gzprintf(fp, "*LanguageLevel: \"%d\"\n", cups_ppd_ps_level); 1009} 1010 1011static void 1012print_ppd_header_3(gzFile fp, ppd_type_t ppd_type, int model, const char *driver, 1013 const char *family, const char *long_name, 1014 const char *manufacturer, const char *device_id, 1015 const char *ppd_location, 1016 const char *language, const stp_string_list_t *po, 1017 char **all_langs) 1018{ 1019 int i; 1020 gzputs(fp, "*FileSystem: False\n"); 1021 gzputs(fp, "*LandscapeOrientation: Plus90\n"); 1022 gzputs(fp, "*TTRasterizer: Type42\n"); 1023 1024 gzputs(fp, "*cupsVersion: 1.2\n"); 1025 gzputs(fp, "*cupsManualCopies: True\n"); 1026 gzprintf(fp, "*cupsFilter: \"application/vnd.cups-raster 100 rastertogutenprint.%s\"\n", GUTENPRINT_RELEASE_VERSION); 1027 if (strcasecmp(manufacturer, "EPSON") == 0) 1028 gzputs(fp, "*cupsFilter: \"application/vnd.cups-command 33 commandtoepson\"\n"); 1029 if (device_id) 1030 gzprintf(fp, "*1284DeviceID: \"%s\"\n", device_id); 1031 if (!language) 1032 { 1033 /* 1034 * Generate globalized PPDs when POSIX language is requested... 1035 */ 1036 1037 const char *prefix = "*cupsLanguages: \""; 1038 1039 for (i = 0; all_langs[i]; i ++) 1040 { 1041 if (!strcmp(all_langs[i], "C") || !strcmp(all_langs[i], "en")) 1042 continue; 1043 1044 gzprintf(fp, "%s%s", prefix, all_langs[i]); 1045 prefix = " "; 1046 } 1047 1048 if (!strcmp(prefix, " ")) 1049 gzputs(fp, "\"\n"); 1050 } 1051} 1052 1053static void 1054print_ppd_header_2(gzFile fp, ppd_type_t ppd_type, int model, const char *driver, 1055 const char *family, const char *long_name, 1056 const char *manufacturer, const char *device_id, 1057 const char *ppd_location, 1058 const char *language, const stp_string_list_t *po, 1059 char **all_langs) 1060{ 1061 gzprintf(fp, "*StpDriverName: \"%s\"\n", driver); 1062 gzprintf(fp, "*StpDriverModelFamily: \"%d_%s\"\n", model, family); 1063 gzprintf(fp, "*StpPPDLocation: \"%s\"\n", ppd_location); 1064 gzprintf(fp, "*StpLocale: \"%s\"\n", language ? language : "C"); 1065} 1066 1067static void 1068print_page_sizes(gzFile fp, stp_vars_t *v, int simplified, 1069 const stp_string_list_t *po) 1070{ 1071 int variable_sizes = 0; 1072 stp_parameter_t desc; 1073 int num_opts; 1074 paper_t *the_papers; 1075 int i; 1076 int width, height, /* Page information */ 1077 bottom, left, 1078 top, right; 1079 int min_width, /* Min/max custom size */ 1080 min_height, 1081 max_width, 1082 max_height; 1083 const stp_param_string_t *opt; 1084 int cur_opt = 0; 1085 1086 stp_describe_parameter(v, "PageSize", &desc); 1087 num_opts = stp_string_list_count(desc.bounds.str); 1088 the_papers = stp_malloc(sizeof(paper_t) * num_opts); 1089 for (i = 0; i < num_opts; i++) 1090 { 1091 const stp_papersize_t *papersize; 1092 opt = stp_string_list_param(desc.bounds.str, i); 1093 papersize = stp_get_papersize_by_name(opt->name); 1094 1095 if (!papersize) 1096 { 1097 printf("Unable to lookup size %s!\n", opt->name); 1098 continue; 1099 } 1100 1101 if (strcmp(opt->name, "Custom") == 0) 1102 { 1103 variable_sizes = 1; 1104 continue; 1105 } 1106 if (simplified && num_opts >= 10 && 1107 (papersize->paper_unit == PAPERSIZE_ENGLISH_EXTENDED || 1108 papersize->paper_unit == PAPERSIZE_METRIC_EXTENDED)) 1109 continue; 1110 1111 width = papersize->width; 1112 height = papersize->height; 1113 1114 if (width <= 0 || height <= 0) 1115 continue; 1116 1117 stp_set_string_parameter(v, "PageSize", opt->name); 1118 1119 stp_get_media_size(v, &width, &height); 1120 stp_get_maximum_imageable_area(v, &left, &right, &bottom, &top); 1121 1122 if (left < 0) 1123 left = 0; 1124 if (right > width) 1125 right = width; 1126 if (bottom > height) 1127 bottom = height; 1128 if (top < 0) 1129 top = 0; 1130 1131 the_papers[cur_opt].name = opt->name; 1132 the_papers[cur_opt].text = stp_i18n_lookup(po, opt->text); 1133 the_papers[cur_opt].width = width; 1134 the_papers[cur_opt].height = height; 1135 the_papers[cur_opt].left = left; 1136 the_papers[cur_opt].right = right; 1137 the_papers[cur_opt].bottom = height - bottom; 1138 the_papers[cur_opt].top = height - top; 1139 1140 cur_opt++; 1141 stp_clear_string_parameter(v, "PageSize"); 1142 } 1143 1144 /* 1145 * The VariablePaperSize attribute is obsolete, however some popular 1146 * applications still look for it to provide custom page size support. 1147 */ 1148 1149 gzprintf(fp, "*VariablePaperSize: %s\n\n", variable_sizes ? "true" : "false"); 1150 1151 if (stp_parameter_has_category_value(v, &desc, "Color", "Yes")) 1152 gzputs(fp, "*ColorKeyWords: \"PageSize\"\n"); 1153 gzprintf(fp, "*OpenUI *PageSize/%s: PickOne\n", _("Media Size")); 1154 gzputs(fp, "*OPOptionHints PageSize: \"dropdown\"\n"); 1155 gzputs(fp, "*OrderDependency: 10 AnySetup *PageSize\n"); 1156 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1157 desc.name, desc.p_type, desc.is_mandatory, 1158 desc.p_class, desc.p_level, desc.channel, 0.0, 0.0, 0.0); 1159 gzprintf(fp, "*DefaultPageSize: %s\n", desc.deflt.str); 1160 gzprintf(fp, "*StpDefaultPageSize: %s\n", desc.deflt.str); 1161 for (i = 0; i < cur_opt; i ++) 1162 { 1163 gzprintf(fp, "*PageSize %s", the_papers[i].name); 1164 gzprintf(fp, "/%s:\t\"<</PageSize[%d %d]/ImagingBBox null>>setpagedevice\"\n", 1165 the_papers[i].text, the_papers[i].width, the_papers[i].height); 1166 } 1167 gzputs(fp, "*CloseUI: *PageSize\n\n"); 1168 1169 if (stp_parameter_has_category_value(v, &desc, "Color", "Yes")) 1170 gzputs(fp, "*ColorKeyWords: \"PageRegion\"\n"); 1171 gzprintf(fp, "*OpenUI *PageRegion/%s: PickOne\n", _("Media Size")); 1172 gzputs(fp, "*OPOptionHints PageRegion: \"dropdown\"\n"); 1173 gzputs(fp, "*OrderDependency: 10 AnySetup *PageRegion\n"); 1174 gzprintf(fp, "*DefaultPageRegion: %s\n", desc.deflt.str); 1175 gzprintf(fp, "*StpDefaultPageRegion: %s\n", desc.deflt.str); 1176 for (i = 0; i < cur_opt; i ++) 1177 { 1178 gzprintf(fp, "*PageRegion %s", the_papers[i].name); 1179 gzprintf(fp, "/%s:\t\"<</PageSize[%d %d]/ImagingBBox null>>setpagedevice\"\n", 1180 the_papers[i].text, the_papers[i].width, the_papers[i].height); 1181 } 1182 gzputs(fp, "*CloseUI: *PageRegion\n\n"); 1183 1184 gzprintf(fp, "*DefaultImageableArea: %s\n", desc.deflt.str); 1185 gzprintf(fp, "*StpDefaultImageableArea: %s\n", desc.deflt.str); 1186 for (i = 0; i < cur_opt; i ++) 1187 { 1188 gzprintf(fp, "*ImageableArea %s", the_papers[i].name); 1189 gzprintf(fp, "/%s:\t\"%d %d %d %d\"\n", the_papers[i].text, 1190 the_papers[i].left, the_papers[i].bottom, 1191 the_papers[i].right, the_papers[i].top); 1192 } 1193 gzputs(fp, "\n"); 1194 1195 gzprintf(fp, "*DefaultPaperDimension: %s\n", desc.deflt.str); 1196 gzprintf(fp, "*StpDefaultPaperDimension: %s\n", desc.deflt.str); 1197 1198 for (i = 0; i < cur_opt; i ++) 1199 { 1200 gzprintf(fp, "*PaperDimension %s", the_papers[i].name); 1201 gzprintf(fp, "/%s:\t\"%d %d\"\n", 1202 the_papers[i].text, the_papers[i].width, the_papers[i].height); 1203 } 1204 gzputs(fp, "\n"); 1205 1206 if (variable_sizes) 1207 { 1208 stp_get_size_limit(v, &max_width, &max_height, &min_width, &min_height); 1209 stp_set_string_parameter(v, "PageSize", "Custom"); 1210 stp_get_media_size(v, &width, &height); 1211 stp_get_maximum_imageable_area(v, &left, &right, &bottom, &top); 1212 if (left < 0) 1213 left = 0; 1214 if (top < 0) 1215 top = 0; 1216 if (bottom > height) 1217 bottom = height; 1218 if (right > width) 1219 width = right; 1220 1221 gzprintf(fp, "*MaxMediaWidth: \"%d\"\n", max_width); 1222 gzprintf(fp, "*MaxMediaHeight: \"%d\"\n", max_height); 1223 gzprintf(fp, "*HWMargins: %d %d %d %d\n", 1224 left, height - bottom, width - right, top); 1225 gzputs(fp, "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\"\n"); 1226 gzprintf(fp, "*ParamCustomPageSize Width: 1 points %d %d\n", 1227 min_width, max_width); 1228 gzprintf(fp, "*ParamCustomPageSize Height: 2 points %d %d\n", 1229 min_height, max_height); 1230 gzputs(fp, "*ParamCustomPageSize WidthOffset: 3 points 0 0\n"); 1231 gzputs(fp, "*ParamCustomPageSize HeightOffset: 4 points 0 0\n"); 1232 gzputs(fp, "*ParamCustomPageSize Orientation: 5 int 0 0\n\n"); 1233 stp_clear_string_parameter(v, "PageSize"); 1234 } 1235 1236 stp_parameter_description_destroy(&desc); 1237 if (the_papers) 1238 stp_free(the_papers); 1239} 1240 1241static void 1242print_color_setup(gzFile fp, int simplified, int printer_is_color, 1243 const stp_string_list_t *po) 1244{ 1245 gzputs(fp, "*ColorKeyWords: \"ColorModel\"\n"); 1246 gzprintf(fp, "*OpenUI *ColorModel/%s: PickOne\n", _("Color Model")); 1247 gzputs(fp, "*OPOptionHints ColorModel: \"radiobuttons\"\n"); 1248 gzputs(fp, "*OrderDependency: 10 AnySetup *ColorModel\n"); 1249 1250 if (printer_is_color) 1251 { 1252 gzputs(fp, "*DefaultColorModel: RGB\n"); 1253 gzputs(fp, "*StpDefaultColorModel: RGB\n"); 1254 } 1255 else 1256 { 1257 gzputs(fp, "*DefaultColorModel: Gray\n"); 1258 gzputs(fp, "*StpDefaultColorModel: Gray\n"); 1259 } 1260 1261 gzprintf(fp, "*ColorModel Gray/%s:\t\"<<" 1262 "/cupsColorSpace %d" 1263 "/cupsColorOrder %d" 1264 "%s" 1265 ">>setpagedevice\"\n", 1266 _("Grayscale"), CUPS_CSPACE_W, CUPS_ORDER_CHUNKED, 1267 simplified ? "/cupsBitsPerColor 8/cupsPreferredBitsPerColor 16" : ""); 1268 gzprintf(fp, "*ColorModel Black/%s:\t\"<<" 1269 "/cupsColorSpace %d" 1270 "/cupsColorOrder %d" 1271 "%s" 1272 ">>setpagedevice\"\n", 1273 _("Inverted Grayscale"), CUPS_CSPACE_K, CUPS_ORDER_CHUNKED, 1274 simplified ? "/cupsBitsPerColor 8/cupsPreferredBitsPerColor 16" : ""); 1275 1276 if (printer_is_color) 1277 { 1278 gzprintf(fp, "*ColorModel RGB/%s:\t\"<<" 1279 "/cupsColorSpace %d" 1280 "/cupsColorOrder %d" 1281 "%s" 1282 ">>setpagedevice\"\n", 1283 _("RGB Color"), CUPS_CSPACE_RGB, CUPS_ORDER_CHUNKED, 1284 simplified ? "/cupsBitsPerColor 8/cupsPreferredBitsPerColor 16" : ""); 1285 gzprintf(fp, "*ColorModel CMY/%s:\t\"<<" 1286 "/cupsColorSpace %d" 1287 "/cupsColorOrder %d" 1288 "%s" 1289 ">>setpagedevice\"\n", 1290 _("CMY Color"), CUPS_CSPACE_CMY, CUPS_ORDER_CHUNKED, 1291 simplified ? "/cupsBitsPerColor 8/cupsPreferredBitsPerColor 16" : ""); 1292 gzprintf(fp, "*ColorModel CMYK/%s:\t\"<<" 1293 "/cupsColorSpace %d" 1294 "/cupsColorOrder %d" 1295 "%s" 1296 ">>setpagedevice\"\n", 1297 _("CMYK"), CUPS_CSPACE_CMYK, CUPS_ORDER_CHUNKED, 1298 simplified ? "/cupsBitsPerColor 8/cupsPreferredBitsPerColor 16" : ""); 1299 gzprintf(fp, "*ColorModel KCMY/%s:\t\"<<" 1300 "/cupsColorSpace %d" 1301 "/cupsColorOrder %d" 1302 "%s" 1303 ">>setpagedevice\"\n", 1304 _("KCMY"), CUPS_CSPACE_KCMY, CUPS_ORDER_CHUNKED, 1305 simplified ? "/cupsBitsPerColor 8/cupsPreferredBitsPerColor 16" : ""); 1306 } 1307 1308 gzputs(fp, "*CloseUI: *ColorModel\n\n"); 1309 if (!simplified) 1310 { 1311 /* 1312 * 8 or 16 bit color (16 bit is slower) 1313 */ 1314 gzputs(fp, "*ColorKeyWords: \"StpColorPrecision\"\n"); 1315 gzprintf(fp, "*OpenUI *StpColorPrecision/%s: PickOne\n", _("Color Precision")); 1316 gzputs(fp, "*OPOptionHints StpColorPrecision: \"radiobuttons\"\n"); 1317 gzputs(fp, "*OrderDependency: 10 AnySetup *StpColorPrecision\n"); 1318 gzputs(fp, "*DefaultStpColorPrecision: Normal\n"); 1319 gzputs(fp, "*StpDefaultStpColorPrecision: Normal\n"); 1320 gzprintf(fp, "*StpColorPrecision Normal/%s:\t\"<<" 1321 "/cupsBitsPerColor 8>>setpagedevice\"\n", _("Normal")); 1322 gzprintf(fp, "*StpColorPrecision Best/%s:\t\"<<" 1323 "/cupsBitsPerColor 8" 1324 "/cupsPreferredBitsPerColor 16>>setpagedevice\"\n", _("Best")); 1325 gzputs(fp, "*CloseUI: *StpColorPrecision\n\n"); 1326 } 1327} 1328 1329static void 1330print_group( 1331 gzFile fp, /* I - File to write to */ 1332 const char *what, 1333 stp_parameter_class_t p_class, /* I - Option class */ 1334 stp_parameter_level_t p_level, /* I - Option level */ 1335 const char *language, /* I - Language */ 1336 const stp_string_list_t *po) /* I - Message catalog */ 1337{ 1338 char buf[64]; 1339 const char *class = stp_i18n_lookup(po, parameter_class_names[p_class]); 1340 const char *level = stp_i18n_lookup(po, parameter_level_names[p_level]); 1341 size_t bytes = bytelen(class) + bytelen(level); 1342 snprintf(buf, 40, "%s%s%s", class, bytes < 39 ? " " : "", level); 1343 gzprintf(fp, "*%sGroup: C%dL%d/%s\n", what, p_class, p_level, buf); 1344 if (language && !strcmp(language, "C") && !strcmp(what, "Open")) 1345 { 1346 char **all_langs = getlangs();/* All languages */ 1347 const char *lang; 1348 int langnum; 1349 1350 for (langnum = 0; all_langs[langnum]; langnum ++) 1351 { 1352 const stp_string_list_t *altpo; 1353 1354 lang = all_langs[langnum]; 1355 1356 if (!strcmp(lang, "C") || !strcmp(lang, "en")) 1357 continue; 1358 if ((altpo = stp_i18n_load(lang)) != NULL) 1359 { 1360 class = stp_i18n_lookup(altpo, parameter_class_names[p_class]); 1361 level = stp_i18n_lookup(altpo, parameter_level_names[p_level]); 1362 bytes = bytelen(class) + bytelen(level); 1363 snprintf(buf, 40, "%s%s%s", class, bytes < 39 ? " " : "", level); 1364 gzprintf(fp, "*%s.Translation C%dL%d/%s: \"\"\n", 1365 lang, p_class, p_level, buf); 1366 } 1367 } 1368 } 1369 gzputs(fp, "\n"); 1370} 1371 1372/* 1373 * 'print_group_close()' - Close a UI group. 1374 */ 1375 1376static void 1377print_group_close( 1378 gzFile fp, /* I - File to write to */ 1379 stp_parameter_class_t p_class, /* I - Option class */ 1380 stp_parameter_level_t p_level, /* I - Option level */ 1381 const char *language, /* I - language */ 1382 const stp_string_list_t *po) /* I - Message catalog */ 1383{ 1384 print_group(fp, "Close", p_class, p_level, NULL, NULL); 1385} 1386 1387 1388/* 1389 * 'print_group_open()' - Open a new UI group. 1390 */ 1391 1392static void 1393print_group_open( 1394 gzFile fp, /* I - File to write to */ 1395 stp_parameter_class_t p_class, /* I - Option class */ 1396 stp_parameter_level_t p_level, /* I - Option level */ 1397 const char *language, /* I - language */ 1398 const stp_string_list_t *po) /* I - Message catalog */ 1399{ 1400 print_group(fp, "Open", p_class, p_level, language ? language : "C", po); 1401} 1402 1403static void 1404print_one_option(gzFile fp, stp_vars_t *v, const stp_string_list_t *po, 1405 ppd_type_t ppd_type, const stp_parameter_t *lparam, 1406 const stp_parameter_t *desc) 1407{ 1408 int num_opts; 1409 int i; 1410 const stp_param_string_t *opt; 1411 int printed_default_value = 0; 1412 int simplified = ppd_type == PPD_SIMPLIFIED; 1413 char dimstr[255]; /* Dimension string */ 1414 int print_close_ui = 1; 1415 int is_color_opt = stp_parameter_has_category_value(v, desc, "Color", "Yes"); 1416 int skip_color = (ppd_type == PPD_NO_COLOR_OPTS && is_color_opt); 1417 if (is_color_opt) 1418 gzprintf(fp, "*ColorKeyWords: \"Stp%s\"\n", desc->name); 1419 gzprintf(fp, "*OpenUI *Stp%s/%s: PickOne\n", 1420 desc->name, stp_i18n_lookup(po, desc->text)); 1421 gzprintf(fp, "*OrderDependency: 10 AnySetup *Stp%s\n", desc->name); 1422 switch (desc->p_type) 1423 { 1424 case STP_PARAMETER_TYPE_STRING_LIST: 1425 num_opts = stp_string_list_count(desc->bounds.str); 1426 if (! skip_color) 1427 { 1428 if (num_opts > 3) 1429 gzprintf(fp, "*OPOptionHints Stp%s: \"dropdown\"\n", lparam->name); 1430 else 1431 gzprintf(fp, "*OPOptionHints Stp%s: \"radiobuttons\"\n", lparam->name); 1432 } 1433 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1434 desc->name, desc->p_type, desc->is_mandatory, desc->p_class, 1435 desc->p_level, desc->channel, 0.0, 0.0, 0.0); 1436 if (desc->is_mandatory) 1437 { 1438 gzprintf(fp, "*DefaultStp%s: %s\n", desc->name, desc->deflt.str); 1439 gzprintf(fp, "*StpDefaultStp%s: %s\n", desc->name, desc->deflt.str); 1440 } 1441 else 1442 { 1443 gzprintf(fp, "*DefaultStp%s: None\n", desc->name); 1444 gzprintf(fp, "*StpDefaultStp%s: None\n", desc->name); 1445 gzprintf(fp, "*Stp%s %s/%s: \"\"\n", desc->name, "None", _("None")); 1446 } 1447 for (i = 0; i < num_opts; i++) 1448 { 1449 opt = stp_string_list_param(desc->bounds.str, i); 1450 if (skip_color && strcmp(opt->name, desc->deflt.str) != 0) 1451 gzprintf(fp, "*?Stp%s %s/%s: \"\"\n", 1452 desc->name, opt->name, stp_i18n_lookup(po, opt->text)); 1453 else 1454 gzprintf(fp, "*Stp%s %s/%s: \"\"\n", 1455 desc->name, opt->name, stp_i18n_lookup(po, opt->text)); 1456 } 1457 break; 1458 case STP_PARAMETER_TYPE_BOOLEAN: 1459 gzprintf(fp, "*OPOptionHints Stp%s: \"checkbox\"\n", lparam->name); 1460 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1461 desc->name, desc->p_type, desc->is_mandatory, desc->p_class, 1462 desc->p_level, desc->channel, 0.0, 0.0, 1463 desc->deflt.boolean ? 1.0 : 0.0); 1464 if (desc->is_mandatory) 1465 { 1466 gzprintf(fp, "*DefaultStp%s: %s\n", desc->name, 1467 desc->deflt.boolean ? "True" : "False"); 1468 gzprintf(fp, "*StpDefaultStp%s: %s\n", desc->name, 1469 desc->deflt.boolean ? "True" : "False"); 1470 if (skip_color) 1471 gzprintf(fp, "*Stp%s %s/%s: \"\"\n", 1472 desc->name, desc->deflt.boolean ? "True" : "False", 1473 desc->deflt.boolean ? _("Yes") : _("No")); 1474 } 1475 else 1476 { 1477 gzprintf(fp, "*DefaultStp%s: None\n", desc->name); 1478 gzprintf(fp, "*StpDefaultStp%s: None\n", desc->name); 1479 gzprintf(fp, "*Stp%s %s/%s: \"\"\n", desc->name, "None", _("None")); 1480 } 1481 gzprintf(fp, "*%sStp%s %s/%s: \"\"\n", 1482 (skip_color ? "?" : ""), desc->name, "False", _("No")); 1483 gzprintf(fp, "*%sStp%s %s/%s: \"\"\n", 1484 (skip_color ? "?" : ""), desc->name, "True", _("Yes")); 1485 break; 1486 case STP_PARAMETER_TYPE_DOUBLE: 1487 gzprintf(fp, "*OPOptionHints Stp%s: \"slider input spinbox\"\n", 1488 lparam->name); 1489 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1490 desc->name, desc->p_type, desc->is_mandatory, desc->p_class, 1491 desc->p_level, desc->channel, desc->bounds.dbl.lower, 1492 desc->bounds.dbl.upper, desc->deflt.dbl); 1493 gzprintf(fp, "*DefaultStp%s: None\n", desc->name); 1494 gzprintf(fp, "*StpDefaultStp%s: None\n", desc->name); 1495 if (!skip_color) 1496 { 1497 for (i = desc->bounds.dbl.lower * 1000; 1498 i <= desc->bounds.dbl.upper * 1000 ; i += 100) 1499 { 1500 if (desc->deflt.dbl * 1000 == i && desc->is_mandatory) 1501 { 1502 gzprintf(fp, "*Stp%s None/%.3f: \"\"\n", 1503 desc->name, ((double) i) * .001); 1504 printed_default_value = 1; 1505 } 1506 else 1507 gzprintf(fp, "*Stp%s %d/%.3f: \"\"\n", 1508 desc->name, i, ((double) i) * .001); 1509 } 1510 } 1511 if (!desc->is_mandatory) 1512 gzprintf(fp, "*Stp%s None/%s: \"\"\n", desc->name, _("None")); 1513 else if (! printed_default_value) 1514 gzprintf(fp, "*Stp%s None/%.3f: \"\"\n", desc->name, desc->deflt.dbl); 1515 gzprintf(fp, "*CloseUI: *Stp%s\n\n", desc->name); 1516 1517 /* 1518 * Add custom option code and value parameter... 1519 */ 1520 1521 gzprintf(fp, "*CustomStp%s True: \"pop\"\n", desc->name); 1522 gzprintf(fp, "*ParamCustomStp%s Value/%s: 1 real %.3f %.3f\n\n", 1523 desc->name, _("Value"), desc->bounds.dbl.lower, 1524 desc->bounds.dbl.upper); 1525 if (!simplified && !skip_color) 1526 { 1527 if (is_color_opt) 1528 gzprintf(fp, "*ColorKeyWords: \"StpFine%s\"\n", desc->name); 1529 gzprintf(fp, "*OpenUI *StpFine%s/%s %s: PickOne\n", 1530 desc->name, stp_i18n_lookup(po, desc->text), 1531 _("Fine Adjustment")); 1532 gzprintf(fp, "*OPOptionHints StpFine%s: \"hide\"\n", lparam->name); 1533 gzprintf(fp, "*StpStpFine%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1534 desc->name, STP_PARAMETER_TYPE_INVALID, 0, 1535 0, 0, -1, 0.0, 0.0, 0.0); 1536 gzprintf(fp, "*DefaultStpFine%s: None\n", desc->name); 1537 gzprintf(fp, "*StpDefaultStpFine%s: None\n", desc->name); 1538 gzprintf(fp, "*StpFine%s None/0.000: \"\"\n", desc->name); 1539 for (i = 0; i < 100; i += 5) 1540 gzprintf(fp, "*StpFine%s %d/%.3f: \"\"\n", 1541 desc->name, i, ((double) i) * .001); 1542 gzprintf(fp, "*CloseUI: *StpFine%s\n\n", desc->name); 1543 } 1544 print_close_ui = 0; 1545 1546 break; 1547 case STP_PARAMETER_TYPE_DIMENSION: 1548 gzprintf(fp, "*OPOptionHints Stp%s: \"length slider input spinbox\"\n", 1549 lparam->name); 1550 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1551 desc->name, desc->p_type, desc->is_mandatory, 1552 desc->p_class, desc->p_level, desc->channel, 1553 (double) desc->bounds.dimension.lower, 1554 (double) desc->bounds.dimension.upper, 1555 (double) desc->deflt.dimension); 1556 if (desc->is_mandatory) 1557 { 1558 gzprintf(fp, "*DefaultStp%s: %d\n", 1559 desc->name, desc->deflt.dimension); 1560 gzprintf(fp, "*StpDefaultStp%s: %d\n", 1561 desc->name, desc->deflt.dimension); 1562 } 1563 else 1564 { 1565 gzprintf(fp, "*DefaultStp%s: None\n", desc->name); 1566 gzprintf(fp, "*StpDefaultStp%s: None\n", desc->name); 1567 gzprintf(fp, "*Stp%s %s/%s: \"\"\n", desc->name, "None", _("None")); 1568 } 1569 if (!skip_color) 1570 { 1571 for (i = desc->bounds.dimension.lower; 1572 i <= desc->bounds.dimension.upper; i++) 1573 { 1574 snprintf(dimstr, sizeof(dimstr), _("%.1f mm"), 1575 (double)i * 25.4 / 72.0); 1576 gzprintf(fp, "*Stp%s %d/%s: \"\"\n", desc->name, i, dimstr); 1577 } 1578 } 1579 1580 print_close_ui = 0; 1581 gzprintf(fp, "*CloseUI: *Stp%s\n\n", desc->name); 1582 1583 /* 1584 * Add custom option code and value parameter... 1585 */ 1586 1587 gzprintf(fp, "*CustomStp%s True: \"pop\"\n", desc->name); 1588 gzprintf(fp, "*ParamCustomStp%s Value/%s: 1 points %d %d\n\n", 1589 desc->name, _("Value"), desc->bounds.dimension.lower, 1590 desc->bounds.dimension.upper); 1591 1592 break; 1593 case STP_PARAMETER_TYPE_INT: 1594 gzprintf(fp, "*OPOptionHints Stp%s: \"input spinbox\"\n", lparam->name); 1595 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1596 desc->name, desc->p_type, desc->is_mandatory, desc->p_class, 1597 desc->p_level, desc->channel, 1598 (double) desc->bounds.integer.lower, 1599 (double) desc->bounds.integer.upper, 1600 (double) desc->deflt.integer); 1601 if (desc->is_mandatory) 1602 { 1603 gzprintf(fp, "*DefaultStp%s: %d\n", desc->name, desc->deflt.integer); 1604 gzprintf(fp, "*StpDefaultStp%s: %d\n", desc->name, desc->deflt.integer); 1605 if (skip_color) 1606 gzprintf(fp, "*Stp%s %d/%d: \"\"\n", desc->name, 1607 desc->deflt.integer, desc->deflt.integer); 1608 } 1609 else 1610 { 1611 gzprintf(fp, "*DefaultStp%s: None\n", desc->name); 1612 gzprintf(fp, "*StpDefaultStp%s: None\n", desc->name); 1613 gzprintf(fp, "*Stp%s %s/%s: \"\"\n", desc->name, "None", _("None")); 1614 } 1615 for (i = desc->bounds.integer.lower; i <= desc->bounds.integer.upper; i++) 1616 { 1617 gzprintf(fp, "*%sStp%s %d/%d: \"\"\n", 1618 (skip_color ? "?" : ""), desc->name, i, i); 1619 } 1620 1621 print_close_ui = 0; 1622 gzprintf(fp, "*CloseUI: *Stp%s\n\n", desc->name); 1623 1624 /* 1625 * Add custom option code and value parameter... 1626 */ 1627 1628 gzprintf(fp, "*CustomStp%s True: \"pop\"\n", desc->name); 1629 gzprintf(fp, "*ParamCustomStp%s Value/%s: 1 int %d %d\n\n", desc->name, 1630 _("Value"), desc->bounds.dimension.lower, 1631 desc->bounds.dimension.upper); 1632 1633 break; 1634 default: 1635 break; 1636 } 1637 if (print_close_ui) 1638 gzprintf(fp, "*CloseUI: *Stp%s\n\n", desc->name); 1639} 1640 1641static void 1642print_one_localization(gzFile fp, const stp_string_list_t *po, 1643 int simplified, const char *lang, 1644 const stp_parameter_t *lparam, 1645 const stp_parameter_t *desc) 1646{ 1647 int num_opts; 1648 int i; 1649 const stp_param_string_t *opt; 1650 char dimstr[255]; /* Dimension string */ 1651 1652 gzprintf(fp, "*%s.Translation Stp%s/%s: \"\"\n", lang, 1653 desc->name, stp_i18n_lookup(po, desc->text)); 1654 switch (desc->p_type) 1655 { 1656 case STP_PARAMETER_TYPE_STRING_LIST: 1657 if (!desc->is_mandatory) 1658 gzprintf(fp, "*%s.Stp%s %s/%s: \"\"\n", lang, desc->name, 1659 "None", _("None")); 1660 num_opts = stp_string_list_count(desc->bounds.str); 1661 for (i = 0; i < num_opts; i++) 1662 { 1663 opt = stp_string_list_param(desc->bounds.str, i); 1664 gzprintf(fp, "*%s.Stp%s %s/%s: \"\"\n", lang, 1665 desc->name, opt->name, stp_i18n_lookup(po, opt->text)); 1666 } 1667 break; 1668 1669 case STP_PARAMETER_TYPE_BOOLEAN: 1670 if (!desc->is_mandatory) 1671 gzprintf(fp, "*%s.Stp%s %s/%s: \"\"\n", lang, desc->name, 1672 "None", _("None")); 1673 gzprintf(fp, "*%s.Stp%s %s/%s: \"\"\n", lang, desc->name, "False", _("No")); 1674 gzprintf(fp, "*%s.Stp%s %s/%s: \"\"\n", lang, desc->name, "True", _("Yes")); 1675 break; 1676 1677 case STP_PARAMETER_TYPE_DOUBLE: 1678 if (localize_numbers) 1679 { 1680 for (i = desc->bounds.dbl.lower * 1000; 1681 i <= desc->bounds.dbl.upper * 1000; i += 100) 1682 { 1683 if (desc->deflt.dbl * 1000 == i && desc->is_mandatory) 1684 gzprintf(fp, "*%s.Stp%s None/%.3f: \"\"\n", lang, 1685 desc->name, ((double) i) * .001); 1686 else 1687 gzprintf(fp, "*%s.Stp%s %d/%.3f: \"\"\n", lang, 1688 desc->name, i, ((double) i) * .001); 1689 } 1690 } 1691 if (!desc->is_mandatory) 1692 gzprintf(fp, "*%s.Stp%s None/%s: \"\"\n", lang, desc->name, _("None")); 1693 gzprintf(fp, "*%s.ParamCustomStp%s Value/%s: \"\"\n", lang, 1694 desc->name, _("Value")); 1695 if (!simplified) 1696 { 1697 gzprintf(fp, "*%s.Translation StpFine%s/%s %s: \"\"\n", lang, 1698 desc->name, stp_i18n_lookup(po, desc->text), 1699 _("Fine Adjustment")); 1700 gzprintf(fp, "*%s.StpFine%s None/%.3f: \"\"\n", lang, 1701 desc->name, 0.0); 1702 if (localize_numbers) 1703 { 1704 for (i = 0; i < 100; i += 5) 1705 gzprintf(fp, "*%s.StpFine%s %d/%.3f: \"\"\n", lang, 1706 desc->name, i, ((double) i) * .001); 1707 } 1708 } 1709 break; 1710 1711 case STP_PARAMETER_TYPE_DIMENSION: 1712 if (!desc->is_mandatory) 1713 gzprintf(fp, "*%s.Stp%s %s/%s: \"\"\n", lang, desc->name, 1714 "None", _("None")); 1715 /* Unlike the other fields, dimensions are not strictly numbers */ 1716 for (i = desc->bounds.dimension.lower; 1717 i <= desc->bounds.dimension.upper; i++) 1718 { 1719 snprintf(dimstr, sizeof(dimstr), _("%.1f mm"), 1720 (double)i * 25.4 / 72.0); 1721 gzprintf(fp, "*%s.Stp%s %d/%s: \"\"\n", lang, 1722 desc->name, i, dimstr); 1723 } 1724 gzprintf(fp, "*%s.ParamCustomStp%s Value/%s: \"\"\n", lang, 1725 desc->name, _("Value")); 1726 break; 1727 1728 case STP_PARAMETER_TYPE_INT: 1729 if (!desc->is_mandatory) 1730 gzprintf(fp, "*%s.Stp%s %s/%s: \"\"\n", lang, desc->name, 1731 "None", _("None")); 1732 if (localize_numbers) 1733 { 1734 for (i = desc->bounds.integer.lower; 1735 i <= desc->bounds.integer.upper; i++) 1736 { 1737 gzprintf(fp, "*%s.Stp%s %d/%d: \"\"\n", lang, desc->name, i, i); 1738 } 1739 } 1740 gzprintf(fp, "*%s.ParamCustomStp%s Value/%s: \"\"\n", lang, 1741 desc->name, _("Value")); 1742 break; 1743 1744 default: 1745 break; 1746 } 1747} 1748 1749static void 1750print_standard_fonts(gzFile fp) 1751{ 1752 gzputs(fp, "\n*DefaultFont: Courier\n"); 1753 gzputs(fp, "*Font AvantGarde-Book: Standard \"(001.006S)\" Standard ROM\n"); 1754 gzputs(fp, "*Font AvantGarde-BookOblique: Standard \"(001.006S)\" Standard ROM\n"); 1755 gzputs(fp, "*Font AvantGarde-Demi: Standard \"(001.007S)\" Standard ROM\n"); 1756 gzputs(fp, "*Font AvantGarde-DemiOblique: Standard \"(001.007S)\" Standard ROM\n"); 1757 gzputs(fp, "*Font Bookman-Demi: Standard \"(001.004S)\" Standard ROM\n"); 1758 gzputs(fp, "*Font Bookman-DemiItalic: Standard \"(001.004S)\" Standard ROM\n"); 1759 gzputs(fp, "*Font Bookman-Light: Standard \"(001.004S)\" Standard ROM\n"); 1760 gzputs(fp, "*Font Bookman-LightItalic: Standard \"(001.004S)\" Standard ROM\n"); 1761 gzputs(fp, "*Font Courier: Standard \"(002.004S)\" Standard ROM\n"); 1762 gzputs(fp, "*Font Courier-Bold: Standard \"(002.004S)\" Standard ROM\n"); 1763 gzputs(fp, "*Font Courier-BoldOblique: Standard \"(002.004S)\" Standard ROM\n"); 1764 gzputs(fp, "*Font Courier-Oblique: Standard \"(002.004S)\" Standard ROM\n"); 1765 gzputs(fp, "*Font Helvetica: Standard \"(001.006S)\" Standard ROM\n"); 1766 gzputs(fp, "*Font Helvetica-Bold: Standard \"(001.007S)\" Standard ROM\n"); 1767 gzputs(fp, "*Font Helvetica-BoldOblique: Standard \"(001.007S)\" Standard ROM\n"); 1768 gzputs(fp, "*Font Helvetica-Narrow: Standard \"(001.006S)\" Standard ROM\n"); 1769 gzputs(fp, "*Font Helvetica-Narrow-Bold: Standard \"(001.007S)\" Standard ROM\n"); 1770 gzputs(fp, "*Font Helvetica-Narrow-BoldOblique: Standard \"(001.007S)\" Standard ROM\n"); 1771 gzputs(fp, "*Font Helvetica-Narrow-Oblique: Standard \"(001.006S)\" Standard ROM\n"); 1772 gzputs(fp, "*Font Helvetica-Oblique: Standard \"(001.006S)\" Standard ROM\n"); 1773 gzputs(fp, "*Font NewCenturySchlbk-Bold: Standard \"(001.009S)\" Standard ROM\n"); 1774 gzputs(fp, "*Font NewCenturySchlbk-BoldItalic: Standard \"(001.007S)\" Standard ROM\n"); 1775 gzputs(fp, "*Font NewCenturySchlbk-Italic: Standard \"(001.006S)\" Standard ROM\n"); 1776 gzputs(fp, "*Font NewCenturySchlbk-Roman: Standard \"(001.007S)\" Standard ROM\n"); 1777 gzputs(fp, "*Font Palatino-Bold: Standard \"(001.005S)\" Standard ROM\n"); 1778 gzputs(fp, "*Font Palatino-BoldItalic: Standard \"(001.005S)\" Standard ROM\n"); 1779 gzputs(fp, "*Font Palatino-Italic: Standard \"(001.005S)\" Standard ROM\n"); 1780 gzputs(fp, "*Font Palatino-Roman: Standard \"(001.005S)\" Standard ROM\n"); 1781 gzputs(fp, "*Font Symbol: Special \"(001.007S)\" Special ROM\n"); 1782 gzputs(fp, "*Font Times-Bold: Standard \"(001.007S)\" Standard ROM\n"); 1783 gzputs(fp, "*Font Times-BoldItalic: Standard \"(001.009S)\" Standard ROM\n"); 1784 gzputs(fp, "*Font Times-Italic: Standard \"(001.007S)\" Standard ROM\n"); 1785 gzputs(fp, "*Font Times-Roman: Standard \"(001.007S)\" Standard ROM\n"); 1786 gzputs(fp, "*Font ZapfChancery-MediumItalic: Standard \"(001.007S)\" Standard ROM\n"); 1787 gzputs(fp, "*Font ZapfDingbats: Special \"(001.004S)\" Standard ROM\n"); 1788} 1789 1790/* 1791 * 'write_ppd()' - Write a PPD file. 1792 */ 1793 1794static int /* O - Exit status */ 1795write_ppd( 1796 gzFile fp, /* I - File to write to */ 1797 const stp_printer_t *p, /* I - Printer driver */ 1798 const char *language, /* I - Primary language */ 1799 const char *ppd_location, /* I - Location of PPD file */ 1800 ppd_type_t ppd_type, /* I - 1 = simplified options */ 1801 const char *filename) /* I - input filename */ 1802{ 1803 int i, j, k, l; /* Looping vars */ 1804 int num_opts; /* Number of printer options */ 1805 int xdpi, ydpi; /* Resolution info */ 1806 stp_vars_t *v; /* Variable info */ 1807 const char *driver; /* Driver name */ 1808 const char *family; /* Printer family */ 1809 int model; /* Internal model ID */ 1810 const char *long_name; /* Driver long name */ 1811 const char *manufacturer; /* Manufacturer of printer */ 1812 const char *device_id; /* IEEE1284 device ID */ 1813 const stp_vars_t *printvars; /* Printer option names */ 1814 stp_parameter_t desc; 1815 stp_parameter_list_t param_list; 1816 const stp_param_string_t *opt; 1817 int has_quality_parameter = 0; 1818 int printer_is_color = 0; 1819 int simplified = ppd_type == PPD_SIMPLIFIED; 1820 int skip_color = ppd_type == PPD_NO_COLOR_OPTS; 1821 int maximum_level = simplified ? 1822 STP_PARAMETER_LEVEL_BASIC : STP_PARAMETER_LEVEL_ADVANCED4; 1823 char *default_resolution = NULL; /* Default resolution mapped name */ 1824 stp_string_list_t *resolutions = stp_string_list_create(); 1825 char **all_langs = getlangs();/* All languages */ 1826 const stp_string_list_t *po = stp_i18n_load(language); 1827 /* Message catalog */ 1828 1829 1830 /* 1831 * Initialize driver-specific variables... 1832 */ 1833 1834 driver = stp_printer_get_driver(p); 1835 family = stp_printer_get_family(p); 1836 model = stp_printer_get_model(p); 1837 long_name = stp_printer_get_long_name(p); 1838 manufacturer = stp_printer_get_manufacturer(p); 1839 device_id = stp_printer_get_device_id(p); 1840 printvars = stp_printer_get_defaults(p); 1841 1842 print_ppd_header(fp, ppd_type, model, driver, family, long_name, 1843 manufacturer, device_id, ppd_location, language, po, 1844 all_langs); 1845 1846 1847 /* Set Job Mode to "Job" as this enables the Duplex option */ 1848 v = stp_vars_create_copy(printvars); 1849 stp_set_string_parameter(v, "JobMode", "Job"); 1850 1851 /* Assume that color printers are inkjets and should have pages reversed */ 1852 stp_describe_parameter(v, "PrintingMode", &desc); 1853 if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) 1854 { 1855 if (stp_string_list_is_present(desc.bounds.str, "Color")) 1856 { 1857 printer_is_color = 1; 1858 gzputs(fp, "*ColorDevice: True\n"); 1859 } 1860 else 1861 { 1862 printer_is_color = 0; 1863 gzputs(fp, "*ColorDevice: False\n"); 1864 } 1865 if (strcmp(desc.deflt.str, "Color") == 0) 1866 gzputs(fp, "*DefaultColorSpace: RGB\n"); 1867 else 1868 gzputs(fp, "*DefaultColorSpace: Gray\n"); 1869 } 1870 stp_parameter_description_destroy(&desc); 1871 1872 print_ppd_header_3(fp, ppd_type, model, driver, family, long_name, 1873 manufacturer, device_id, ppd_location, language, po, 1874 all_langs); 1875 1876 /* Macintosh color management */ 1877 gzputs(fp, "*cupsICCProfile Gray../Grayscale: \"/System/Library/ColorSync/Profiles/sRGB Profile.icc\"\n"); 1878 gzputs(fp, "*cupsICCProfile RGB../Color: \"/System/Library/ColorSync/Profiles/sRGB Profile.icc\"\n"); 1879 gzputs(fp, "*cupsICCProfile CMYK../Color: \"/System/Library/ColorSync/Profiles/Generic CMYK Profile.icc\"\n"); 1880 gzputs(fp, "*APSupportsCustomColorMatching: true\n"); 1881 gzputs(fp, "*APDefaultCustomColorMatchingProfile: sRGB\n"); 1882 gzputs(fp, "*APCustomColorMatchingProfile: sRGB\n"); 1883 1884 gzputs(fp, "\n"); 1885 1886 print_ppd_header_2(fp, ppd_type, model, driver, family, long_name, 1887 manufacturer, device_id, ppd_location, language, po, 1888 all_langs); 1889 1890 /* 1891 * Get the page sizes from the driver... 1892 */ 1893 1894 if (printer_is_color) 1895 stp_set_string_parameter(v, "PrintingMode", "Color"); 1896 else 1897 stp_set_string_parameter(v, "PrintingMode", "BW"); 1898 stp_set_string_parameter(v, "ChannelBitDepth", "8"); 1899 print_page_sizes(fp, v, simplified, po); 1900 1901 /* 1902 * Do we support color? 1903 */ 1904 1905 print_color_setup(fp, simplified, printer_is_color, po); 1906 1907 /* 1908 * Media types... 1909 */ 1910 1911 stp_describe_parameter(v, "MediaType", &desc); 1912 num_opts = stp_string_list_count(desc.bounds.str); 1913 1914 if (num_opts > 0) 1915 { 1916 int is_color_opt = 1917 stp_parameter_has_category_value(v, &desc, "Color", "Yes"); 1918 int nocolor = skip_color && is_color_opt; 1919 if (is_color_opt) 1920 gzprintf(fp, "*ColorKeyWords: \"MediaType\"\n"); 1921 gzprintf(fp, "*OpenUI *MediaType/%s: PickOne\n", _("Media Type")); 1922 gzputs(fp, "*OPOptionHints MediaType: \"dropdown\"\n"); 1923 gzputs(fp, "*OrderDependency: 10 AnySetup *MediaType\n"); 1924 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1925 desc.name, desc.p_type, desc.is_mandatory, 1926 desc.p_class, desc.p_level, desc.channel, 0.0, 0.0, 0.0); 1927 gzprintf(fp, "*DefaultMediaType: %s\n", desc.deflt.str); 1928 gzprintf(fp, "*StpDefaultMediaType: %s\n", desc.deflt.str); 1929 1930 for (i = 0; i < num_opts; i ++) 1931 { 1932 opt = stp_string_list_param(desc.bounds.str, i); 1933 gzprintf(fp, "*%sMediaType %s/%s:\t\"<</MediaType(%s)>>setpagedevice\"\n", 1934 nocolor && strcmp(opt->name, desc.deflt.str) != 0 ? "?" : "", 1935 opt->name, stp_i18n_lookup(po, opt->text), opt->name); 1936 } 1937 1938 gzputs(fp, "*CloseUI: *MediaType\n\n"); 1939 } 1940 stp_parameter_description_destroy(&desc); 1941 1942 /* 1943 * Input slots... 1944 */ 1945 1946 stp_describe_parameter(v, "InputSlot", &desc); 1947 num_opts = stp_string_list_count(desc.bounds.str); 1948 1949 if (num_opts > 0) 1950 { 1951 int is_color_opt = 1952 stp_parameter_has_category_value(v, &desc, "Color", "Yes"); 1953 int nocolor = skip_color && is_color_opt; 1954 if (is_color_opt) 1955 gzprintf(fp, "*ColorKeyWords: \"InputSlot\"\n"); 1956 gzprintf(fp, "*OpenUI *InputSlot/%s: PickOne\n", _("Media Source")); 1957 gzputs(fp, "*OPOptionHints InputSlot: \"dropdown\"\n"); 1958 gzputs(fp, "*OrderDependency: 10 AnySetup *InputSlot\n"); 1959 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1960 desc.name, desc.p_type, desc.is_mandatory, 1961 desc.p_class, desc.p_level, desc.channel, 0.0, 0.0, 0.0); 1962 gzprintf(fp, "*DefaultInputSlot: %s\n", desc.deflt.str); 1963 gzprintf(fp, "*StpDefaultInputSlot: %s\n", desc.deflt.str); 1964 1965 for (i = 0; i < num_opts; i ++) 1966 { 1967 opt = stp_string_list_param(desc.bounds.str, i); 1968 gzprintf(fp, "*%sInputSlot %s/%s:\t\"<</MediaClass(%s)>>setpagedevice\"\n", 1969 nocolor && strcmp(opt->name, desc.deflt.str) != 0 ? "?" : "", 1970 opt->name, stp_i18n_lookup(po, opt->text), opt->name); 1971 } 1972 1973 gzputs(fp, "*CloseUI: *InputSlot\n\n"); 1974 } 1975 stp_parameter_description_destroy(&desc); 1976 1977 /* 1978 * Quality settings 1979 */ 1980 1981 stp_describe_parameter(v, "Quality", &desc); 1982 if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST && desc.is_active) 1983 { 1984 int is_color_opt = 1985 stp_parameter_has_category_value(v, &desc, "Color", "Yes"); 1986 int nocolor = skip_color && is_color_opt; 1987 if (is_color_opt) 1988 gzprintf(fp, "*ColorKeyWords: \"Quality\"\n"); 1989 stp_clear_string_parameter(v, "Resolution"); 1990 has_quality_parameter = 1; 1991 num_opts = stp_string_list_count(desc.bounds.str); 1992 gzprintf(fp, "*OpenUI *StpQuality/%s: PickOne\n", stp_i18n_lookup(po, desc.text)); 1993 if (num_opts > 3) 1994 gzputs(fp, "*OPOptionHints Quality: \"radiobuttons\"\n"); 1995 else 1996 gzputs(fp, "*OPOptionHints Quality: \"dropdown\"\n"); 1997 gzputs(fp, "*OrderDependency: 10 AnySetup *StpQuality\n"); 1998 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 1999 desc.name, desc.p_type, desc.is_mandatory, 2000 desc.p_type, desc.p_level, desc.channel, 0.0, 0.0, 0.0); 2001 gzprintf(fp, "*DefaultStpQuality: %s\n", desc.deflt.str); 2002 gzprintf(fp, "*StpDefaultStpQuality: %s\n", desc.deflt.str); 2003 for (i = 0; i < num_opts; i++) 2004 { 2005 opt = stp_string_list_param(desc.bounds.str, i); 2006 stp_set_string_parameter(v, "Quality", opt->name); 2007 stp_describe_resolution(v, &xdpi, &ydpi); 2008 if (xdpi == -1 || ydpi == -1) 2009 { 2010 stp_parameter_t res_desc; 2011 stp_clear_string_parameter(v, "Quality"); 2012 stp_describe_parameter(v, "Resolution", &res_desc); 2013 stp_set_string_parameter(v, "Resolution", res_desc.deflt.str); 2014 stp_describe_resolution(v, &xdpi, &ydpi); 2015 stp_clear_string_parameter(v, "Resolution"); 2016 stp_parameter_description_destroy(&res_desc); 2017 } 2018 gzprintf(fp, "*%sStpQuality %s/%s:\t\"<</HWResolution[%d %d]/cupsRowFeed %d>>setpagedevice\"\n", 2019 nocolor && strcmp(opt->name, desc.deflt.str) != 0 ? "?" : "", 2020 opt->name, stp_i18n_lookup(po, opt->text), xdpi, ydpi, i + 1); 2021 } 2022 gzputs(fp, "*CloseUI: *StpQuality\n\n"); 2023 } 2024 stp_parameter_description_destroy(&desc); 2025 stp_clear_string_parameter(v, "Quality"); 2026 2027 /* 2028 * Resolutions... 2029 */ 2030 2031 stp_describe_parameter(v, "Resolution", &desc); 2032 num_opts = stp_string_list_count(desc.bounds.str); 2033 2034 if (!simplified || desc.p_level == STP_PARAMETER_LEVEL_BASIC) 2035 { 2036 int is_color_opt = 2037 stp_parameter_has_category_value(v, &desc, "Color", "Yes"); 2038 int nocolor = skip_color && is_color_opt; 2039 stp_string_list_t *res_list = stp_string_list_create(); 2040 char res_name[64]; /* Plenty long enough for XXXxYYYdpi */ 2041 int resolution_ok; 2042 int tmp_xdpi, tmp_ydpi; 2043 2044 if (is_color_opt) 2045 gzprintf(fp, "*ColorKeyWords: \"Resolution\"\n"); 2046 gzprintf(fp, "*OpenUI *Resolution/%s: PickOne\n", _("Resolution")); 2047 if (num_opts > 3) 2048 gzputs(fp, "*OPOptionHints Resolution: \"resolution radiobuttons\"\n"); 2049 else 2050 gzputs(fp, "*OPOptionHints Resolution: \"resolution dropdown\"\n"); 2051 gzputs(fp, "*OrderDependency: 10 AnySetup *Resolution\n"); 2052 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 2053 desc.name, desc.p_type, desc.is_mandatory, 2054 desc.p_class, desc.p_level, desc.channel, 0.0, 0.0, 0.0); 2055 if (has_quality_parameter) 2056 { 2057 stp_parameter_t desc1; 2058 stp_clear_string_parameter(v, "Resolution"); 2059 stp_describe_parameter(v, "Quality", &desc1); 2060 stp_set_string_parameter(v, "Quality", desc1.deflt.str); 2061 stp_parameter_description_destroy(&desc1); 2062 stp_describe_resolution(v, &xdpi, &ydpi); 2063 stp_clear_string_parameter(v, "Quality"); 2064 tmp_xdpi = xdpi; 2065 while (tmp_xdpi > MAXIMUM_SAFE_PPD_X_RESOLUTION) 2066 tmp_xdpi /= 2; 2067 tmp_ydpi = ydpi; 2068 while (tmp_ydpi > MAXIMUM_SAFE_PPD_Y_RESOLUTION) 2069 tmp_ydpi /= 2; 2070 if (tmp_ydpi < tmp_xdpi) 2071 tmp_xdpi = tmp_ydpi; 2072 /* 2073 Make the default resolution look like an almost square resolution 2074 so that applications using it will be less likely to generate 2075 excess resolution. However, make the hardware resolution 2076 match the printer default. 2077 */ 2078 (void) snprintf(res_name, 63, "%dx%ddpi", tmp_xdpi + 1, tmp_xdpi); 2079 default_resolution = stp_strdup(res_name); 2080 stp_string_list_add_string(res_list, res_name, res_name); 2081 gzprintf(fp, "*DefaultResolution: %s\n", res_name); 2082 gzprintf(fp, "*StpDefaultResolution: %s\n", res_name); 2083 gzprintf(fp, "*Resolution %s/%s:\t\"<</HWResolution[%d %d]>>setpagedevice\"\n", 2084 res_name, _("Automatic"), xdpi, ydpi); 2085 gzprintf(fp, "*StpResolutionMap: %s %s\n", res_name, "None"); 2086 } 2087 else 2088 { 2089 stp_set_string_parameter(v, "Resolution", desc.deflt.str); 2090 stp_describe_resolution(v, &xdpi, &ydpi); 2091 2092 if (xdpi == ydpi) 2093 (void) snprintf(res_name, 63, "%ddpi", xdpi); 2094 else 2095 (void) snprintf(res_name, 63, "%dx%ddpi", xdpi, ydpi); 2096 gzprintf(fp, "*DefaultResolution: %s\n", res_name); 2097 gzprintf(fp, "*StpDefaultResolution: %s\n", res_name); 2098 /* 2099 * We need to add this to the resolution list here so that 2100 * some non-default resolution won't wind up with the 2101 * default resolution name 2102 */ 2103 stp_string_list_add_string(res_list, res_name, res_name); 2104 } 2105 2106 stp_clear_string_parameter(v, "Quality"); 2107 for (i = 0; i < num_opts; i ++) 2108 { 2109 /* 2110 * Strip resolution name to its essentials... 2111 */ 2112 opt = stp_string_list_param(desc.bounds.str, i); 2113 stp_set_string_parameter(v, "Resolution", opt->name); 2114 stp_describe_resolution(v, &xdpi, &ydpi); 2115 2116 /* This should only happen with a "None" resolution */ 2117 if (xdpi == -1 || ydpi == -1) 2118 continue; 2119 2120 resolution_ok = 0; 2121 tmp_xdpi = xdpi; 2122 while (tmp_xdpi > MAXIMUM_SAFE_PPD_X_RESOLUTION) 2123 tmp_xdpi /= 2; 2124 tmp_ydpi = ydpi; 2125 while (tmp_ydpi > MAXIMUM_SAFE_PPD_Y_RESOLUTION) 2126 tmp_ydpi /= 2; 2127 do 2128 { 2129 if (tmp_xdpi == tmp_ydpi) 2130 (void) snprintf(res_name, 63, "%ddpi", tmp_xdpi); 2131 else 2132 (void) snprintf(res_name, 63, "%dx%ddpi", tmp_xdpi, tmp_ydpi); 2133 if ((!has_quality_parameter && 2134 strcmp(opt->name, desc.deflt.str) == 0) || 2135 !stp_string_list_is_present(res_list, res_name)) 2136 { 2137 resolution_ok = 1; 2138 stp_string_list_add_string(res_list, res_name, opt->text); 2139 } 2140 else if (tmp_ydpi > tmp_xdpi && 2141 tmp_ydpi < MAXIMUM_SAFE_PPD_Y_RESOLUTION) 2142 /* Note that we're incrementing the *higher* resolution. 2143 This will generate less aliasing, and apps that convert 2144 down to a square resolution will do the right thing. */ 2145 tmp_ydpi++; 2146 else if (tmp_xdpi < MAXIMUM_SAFE_PPD_X_RESOLUTION) 2147 tmp_xdpi++; 2148 else 2149 tmp_xdpi /= 2; 2150 } while (!resolution_ok); 2151 stp_string_list_add_string(resolutions, res_name, opt->text); 2152 gzprintf(fp, "*%sResolution %s/%s:\t\"<</HWResolution[%d %d]/cupsCompression %d>>setpagedevice\"\n", 2153 nocolor && strcmp(opt->name, desc.deflt.str) != 0 ? "?" : "", 2154 res_name, stp_i18n_lookup(po, opt->text), xdpi, ydpi, i + 1); 2155 if (strcmp(res_name, opt->name) != 0) 2156 gzprintf(fp, "*StpResolutionMap: %s %s\n", res_name, opt->name); 2157 } 2158 2159 stp_string_list_destroy(res_list); 2160 gzputs(fp, "*CloseUI: *Resolution\n\n"); 2161 } 2162 2163 stp_parameter_description_destroy(&desc); 2164 2165 stp_describe_parameter(v, "OutputOrder", &desc); 2166 if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) 2167 { 2168 gzprintf(fp, "*OpenUI *OutputOrder/%s: PickOne\n", _("Output Order")); 2169 gzputs(fp, "*OPOptionHints OutputOrder: \"radiobuttons\"\n"); 2170 gzputs(fp, "*OrderDependency: 10 AnySetup *OutputOrder\n"); 2171 gzprintf(fp, "*DefaultOutputOrder: %s\n", desc.deflt.str); 2172 gzprintf(fp, "*StpDefaultOutputOrder: %s\n", desc.deflt.str); 2173 gzprintf(fp, "*OutputOrder Normal/%s: \"\"\n", _("Normal")); 2174 gzprintf(fp, "*OutputOrder Reverse/%s: \"\"\n", _("Reverse")); 2175 gzputs(fp, "*CloseUI: *OutputOrder\n\n"); 2176 } 2177 stp_parameter_description_destroy(&desc); 2178 2179 /* 2180 * Duplex 2181 * Note that the opt->name strings MUST match those in the printer driver(s) 2182 * else the PPD files will not be generated correctly 2183 */ 2184 2185 stp_describe_parameter(v, "Duplex", &desc); 2186 if (desc.is_active && desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) 2187 { 2188 num_opts = stp_string_list_count(desc.bounds.str); 2189 if (num_opts > 0) 2190 { 2191 int is_color_opt = 2192 stp_parameter_has_category_value(v, &desc, "Color", "Yes"); 2193 if (is_color_opt) 2194 gzprintf(fp, "*ColorKeyWords: \"InputSlot\"\n"); 2195 gzprintf(fp, "*OpenUI *Duplex/%s: PickOne\n", _("2-Sided Printing")); 2196 gzputs(fp, "*OPOptionHints Duplex: \"radiobuttons\"\n"); 2197 gzputs(fp, "*OrderDependency: 10 AnySetup *Duplex\n"); 2198 gzprintf(fp, "*StpStp%s: %d %d %d %d %d %.3f %.3f %.3f\n", 2199 desc.name, desc.p_type, desc.is_mandatory, 2200 desc.p_class, desc.p_level, desc.channel, 0.0, 0.0, 0.0); 2201 gzprintf(fp, "*DefaultDuplex: %s\n", desc.deflt.str); 2202 gzprintf(fp, "*StpDefaultDuplex: %s\n", desc.deflt.str); 2203 2204 for (i = 0; i < num_opts; i++) 2205 { 2206 opt = stp_string_list_param(desc.bounds.str, i); 2207 if (strcmp(opt->name, "None") == 0) 2208 gzprintf(fp, "*Duplex %s/%s: \"<</Duplex false>>setpagedevice\"\n", opt->name, stp_i18n_lookup(po, opt->text)); 2209 else if (strcmp(opt->name, "DuplexNoTumble") == 0) 2210 gzprintf(fp, "*Duplex %s/%s: \"<</Duplex true/Tumble false>>setpagedevice\"\n", opt->name, stp_i18n_lookup(po, opt->text)); 2211 else if (strcmp(opt->name, "DuplexTumble") == 0) 2212 gzprintf(fp, "*Duplex %s/%s: \"<</Duplex true/Tumble true>>setpagedevice\"\n", opt->name, stp_i18n_lookup(po, opt->text)); 2213 } 2214 gzputs(fp, "*CloseUI: *Duplex\n\n"); 2215 } 2216 } 2217 stp_parameter_description_destroy(&desc); 2218 2219 gzprintf(fp, "*OpenUI *StpiShrinkOutput/%s: PickOne\n", 2220 _("Shrink Page If Necessary to Fit Borders")); 2221 gzputs(fp, "*OPOptionHints StpiShrinkOutput: \"radiobuttons\"\n"); 2222 gzputs(fp, "*OrderDependency: 10 AnySetup *StpiShrinkOutput\n"); 2223 gzputs(fp, "*DefaultStpiShrinkOutput: Shrink\n"); 2224 gzputs(fp, "*StpDefaultStpiShrinkOutput: Shrink\n"); 2225 gzprintf(fp, "*StpiShrinkOutput %s/%s: \"\"\n", "Shrink", _("Shrink (print the whole page)")); 2226 gzprintf(fp, "*StpiShrinkOutput %s/%s: \"\"\n", "Crop", _("Crop (preserve dimensions)")); 2227 gzprintf(fp, "*StpiShrinkOutput %s/%s: \"\"\n", "Expand", _("Expand (use maximum page area)")); 2228 gzputs(fp, "*CloseUI: *StpiShrinkOutput\n\n"); 2229 2230 param_list = stp_get_parameter_list(v); 2231 2232 for (j = 0; j <= STP_PARAMETER_CLASS_OUTPUT; j++) 2233 { 2234 for (k = 0; k <= maximum_level; k++) 2235 { 2236 int printed_open_group = 0; 2237 size_t param_count = stp_parameter_list_count(param_list); 2238 for (l = 0; l < param_count; l++) 2239 { 2240 const stp_parameter_t *lparam = 2241 stp_parameter_list_param(param_list, l); 2242 if (lparam->p_class != j || lparam->p_level != k || 2243 is_special_option(lparam->name) || lparam->read_only || 2244 (lparam->p_type != STP_PARAMETER_TYPE_STRING_LIST && 2245 lparam->p_type != STP_PARAMETER_TYPE_BOOLEAN && 2246 lparam->p_type != STP_PARAMETER_TYPE_DIMENSION && 2247 lparam->p_type != STP_PARAMETER_TYPE_INT && 2248 lparam->p_type != STP_PARAMETER_TYPE_DOUBLE)) 2249 continue; 2250 stp_describe_parameter(v, lparam->name, &desc); 2251 if (desc.is_active) 2252 { 2253 if (!printed_open_group) 2254 { 2255 print_group_open(fp, j, k, language, po); 2256 printed_open_group = 1; 2257 } 2258 print_one_option(fp, v, po, ppd_type, lparam, &desc); 2259 } 2260 stp_parameter_description_destroy(&desc); 2261 } 2262 if (printed_open_group) 2263 print_group_close(fp, j, k, language, po); 2264 } 2265 } 2266 stp_parameter_list_destroy(param_list); 2267 stp_describe_parameter(v, "ImageType", &desc); 2268 if (desc.is_active && desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) 2269 { 2270 num_opts = stp_string_list_count(desc.bounds.str); 2271 if (num_opts > 0) 2272 { 2273 for (i = 0; i < num_opts; i++) 2274 { 2275 opt = stp_string_list_param(desc.bounds.str, i); 2276 if (strcmp(opt->name, "None") != 0) 2277 gzprintf(fp, "*APPrinterPreset %s/%s: \"*StpImageType %s\"\n", 2278 opt->name, stp_i18n_lookup(po, opt->text), opt->name); 2279 } 2280 gzputs(fp, "\n"); 2281 } 2282 } 2283 stp_parameter_description_destroy(&desc); 2284 2285 if (!language) 2286 { 2287 /* 2288 * Generate globalized PPDs when POSIX language is requested... 2289 */ 2290 2291 const char *lang; 2292 const stp_string_list_t *savepo = po; 2293 int langnum; 2294 2295 for (langnum = 0; all_langs[langnum]; langnum ++) 2296 { 2297 lang = all_langs[langnum]; 2298 2299 if (!strcmp(lang, "C") || !strcmp(lang, "en")) 2300 continue; 2301 2302 if ((po = stp_i18n_load(lang)) == NULL) 2303 continue; 2304 2305 /* 2306 * Get the page sizes from the driver... 2307 */ 2308 2309 if (printer_is_color) 2310 stp_set_string_parameter(v, "PrintingMode", "Color"); 2311 else 2312 stp_set_string_parameter(v, "PrintingMode", "BW"); 2313 stp_set_string_parameter(v, "ChannelBitDepth", "8"); 2314 stp_describe_parameter(v, "PageSize", &desc); 2315 num_opts = stp_string_list_count(desc.bounds.str); 2316 2317 gzprintf(fp, "*%s.Translation PageSize/%s: \"\"\n", lang, _("Media Size")); 2318 gzprintf(fp, "*%s.Translation PageRegion/%s: \"\"\n", lang, _("Media Size")); 2319 2320 for (i = 0; i < num_opts; i++) 2321 { 2322 const stp_papersize_t *papersize; 2323 opt = stp_string_list_param(desc.bounds.str, i); 2324 papersize = stp_get_papersize_by_name(opt->name); 2325 2326 if (!papersize) 2327 continue; 2328 2329 /* 2330 if (strcmp(opt->name, "Custom") == 0) 2331 continue; 2332 */ 2333 2334 if (simplified && num_opts >= 10 && 2335 (papersize->paper_unit == PAPERSIZE_ENGLISH_EXTENDED || 2336 papersize->paper_unit == PAPERSIZE_METRIC_EXTENDED)) 2337 continue; 2338 2339 if ((papersize->width <= 0 || papersize->height <= 0) && 2340 strcmp(opt->name, "Custom") != 0) 2341 continue; 2342 2343 gzprintf(fp, "*%s.PageSize %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2344 gzprintf(fp, "*%s.PageRegion %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2345 } 2346 2347 stp_parameter_description_destroy(&desc); 2348 2349 /* 2350 * Do we support color? 2351 */ 2352 2353 gzprintf(fp, "*%s.Translation ColorModel/%s: \"\"\n", lang, _("Color Model")); 2354 gzprintf(fp, "*%s.ColorModel Gray/%s: \"\"\n", lang, _("Grayscale")); 2355 gzprintf(fp, "*%s.ColorModel Black/%s: \"\"\n", lang, _("Inverted Grayscale")); 2356 2357 if (printer_is_color) 2358 { 2359 gzprintf(fp, "*%s.ColorModel RGB/%s: \"\"\n", lang, _("RGB Color")); 2360 gzprintf(fp, "*%s.ColorModel CMY/%s: \"\"\n", lang, _("CMY Color")); 2361 gzprintf(fp, "*%s.ColorModel CMYK/%s: \"\"\n", lang, _("CMYK")); 2362 gzprintf(fp, "*%s.ColorModel KCMY/%s: \"\"\n", lang, _("KCMY")); 2363 } 2364 2365 if (!simplified) 2366 { 2367 /* 2368 * 8 or 16 bit color (16 bit is slower) 2369 */ 2370 gzprintf(fp, "*%s.Translation StpColorPrecision/%s: \"\"\n", lang, _("Color Precision")); 2371 gzprintf(fp, "*%s.StpColorPrecision Normal/%s: \"\"\n", lang, _("Normal")); 2372 gzprintf(fp, "*%s.StpColorPrecision Best/%s: \"\"\n", lang, _("Best")); 2373 } 2374 2375 /* 2376 * Media types... 2377 */ 2378 2379 stp_describe_parameter(v, "MediaType", &desc); 2380 num_opts = stp_string_list_count(desc.bounds.str); 2381 2382 if (num_opts > 0) 2383 { 2384 gzprintf(fp, "*%s.Translation MediaType/%s: \"\"\n", lang, _("Media Type")); 2385 2386 for (i = 0; i < num_opts; i ++) 2387 { 2388 opt = stp_string_list_param(desc.bounds.str, i); 2389 gzprintf(fp, "*%s.MediaType %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2390 } 2391 } 2392 stp_parameter_description_destroy(&desc); 2393 2394 /* 2395 * Input slots... 2396 */ 2397 2398 stp_describe_parameter(v, "InputSlot", &desc); 2399 num_opts = stp_string_list_count(desc.bounds.str); 2400 2401 if (num_opts > 0) 2402 { 2403 gzprintf(fp, "*%s.Translation InputSlot/%s: \"\"\n", lang, _("Media Source")); 2404 2405 for (i = 0; i < num_opts; i ++) 2406 { 2407 opt = stp_string_list_param(desc.bounds.str, i); 2408 gzprintf(fp, "*%s.InputSlot %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2409 } 2410 } 2411 stp_parameter_description_destroy(&desc); 2412 2413 /* 2414 * Quality settings 2415 */ 2416 2417 stp_describe_parameter(v, "Quality", &desc); 2418 if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST && desc.is_active) 2419 { 2420 gzprintf(fp, "*%s.Translation StpQuality/%s: \"\"\n", lang, stp_i18n_lookup(po, desc.text)); 2421 num_opts = stp_string_list_count(desc.bounds.str); 2422 for (i = 0; i < num_opts; i++) 2423 { 2424 opt = stp_string_list_param(desc.bounds.str, i); 2425 gzprintf(fp, "*%s.StpQuality %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2426 } 2427 } 2428 stp_parameter_description_destroy(&desc); 2429 2430 /* 2431 * Resolution 2432 */ 2433 2434 stp_describe_parameter(v, "Resolution", &desc); 2435 num_opts = stp_string_list_count(resolutions); 2436 2437 if (!simplified || desc.p_level == STP_PARAMETER_LEVEL_BASIC) 2438 { 2439 gzprintf(fp, "*%s.Translation Resolution/%s: \"\"\n", lang, _("Resolution")); 2440 if (has_quality_parameter) 2441 gzprintf(fp, "*%s.Resolution %s/%s: \"\"\n", lang, 2442 default_resolution, _("Automatic")); 2443 2444 for (i = 0; i < num_opts; i ++) 2445 { 2446 opt = stp_string_list_param(resolutions, i); 2447 gzprintf(fp, "*%s.Resolution %s/%s: \"\"\n", lang, 2448 opt->name, stp_i18n_lookup(po, opt->text)); 2449 } 2450 } 2451 2452 stp_parameter_description_destroy(&desc); 2453 2454 /* 2455 * OutputOrder 2456 */ 2457 2458 stp_describe_parameter(v, "OutputOrder", &desc); 2459 if (desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) 2460 { 2461 gzprintf(fp, "*%s.Translation OutputOrder/%s: \"\"\n", lang, _("Output Order")); 2462 gzprintf(fp, "*%s.OutputOrder Normal/%s: \"\"\n", lang, _("Normal")); 2463 gzprintf(fp, "*%s.OutputOrder Reverse/%s: \"\"\n", lang, _("Reverse")); 2464 } 2465 stp_parameter_description_destroy(&desc); 2466 2467 /* 2468 * Duplex 2469 * Note that the opt->name strings MUST match those in the printer driver(s) 2470 * else the PPD files will not be generated correctly 2471 */ 2472 2473 stp_describe_parameter(v, "Duplex", &desc); 2474 if (desc.is_active && desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) 2475 { 2476 num_opts = stp_string_list_count(desc.bounds.str); 2477 if (num_opts > 0) 2478 { 2479 gzprintf(fp, "*%s.Translation Duplex/%s: \"\"\n", lang, _("2-Sided Printing")); 2480 2481 for (i = 0; i < num_opts; i++) 2482 { 2483 opt = stp_string_list_param(desc.bounds.str, i); 2484 if (strcmp(opt->name, "None") == 0) 2485 gzprintf(fp, "*%s.Duplex %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2486 else if (strcmp(opt->name, "DuplexNoTumble") == 0) 2487 gzprintf(fp, "*%s.Duplex %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2488 else if (strcmp(opt->name, "DuplexTumble") == 0) 2489 gzprintf(fp, "*%s.Duplex %s/%s: \"\"\n", lang, opt->name, stp_i18n_lookup(po, opt->text)); 2490 } 2491 } 2492 } 2493 stp_parameter_description_destroy(&desc); 2494 2495 gzprintf(fp, "*%s.Translation StpiShrinkOutput/%s: \"\"\n", lang, 2496 _("Shrink Page If Necessary to Fit Borders")); 2497 gzprintf(fp, "*%s.StpiShrinkOutput %s/%s: \"\"\n", lang, "Shrink", _("Shrink (print the whole page)")); 2498 gzprintf(fp, "*%s.StpiShrinkOutput %s/%s: \"\"\n", lang, "Crop", _("Crop (preserve dimensions)")); 2499 gzprintf(fp, "*%s.StpiShrinkOutput %s/%s: \"\"\n", lang, "Expand", _("Expand (use maximum page area)")); 2500 2501 param_list = stp_get_parameter_list(v); 2502 2503 for (j = 0; j <= STP_PARAMETER_CLASS_OUTPUT; j++) 2504 { 2505 for (k = 0; k <= maximum_level; k++) 2506 { 2507 size_t param_count = stp_parameter_list_count(param_list); 2508 for (l = 0; l < param_count; l++) 2509 { 2510 const stp_parameter_t *lparam = 2511 stp_parameter_list_param(param_list, l); 2512 if (lparam->p_class != j || lparam->p_level != k || 2513 is_special_option(lparam->name) || lparam->read_only || 2514 (lparam->p_type != STP_PARAMETER_TYPE_STRING_LIST && 2515 lparam->p_type != STP_PARAMETER_TYPE_BOOLEAN && 2516 lparam->p_type != STP_PARAMETER_TYPE_DIMENSION && 2517 lparam->p_type != STP_PARAMETER_TYPE_INT && 2518 lparam->p_type != STP_PARAMETER_TYPE_DOUBLE)) 2519 continue; 2520 stp_describe_parameter(v, lparam->name, &desc); 2521 if (desc.is_active) 2522 print_one_localization(fp, po, simplified, lang, 2523 lparam, &desc); 2524 stp_parameter_description_destroy(&desc); 2525 } 2526 } 2527 } 2528 stp_parameter_list_destroy(param_list); 2529 stp_describe_parameter(v, "ImageType", &desc); 2530 if (desc.is_active && desc.p_type == STP_PARAMETER_TYPE_STRING_LIST) 2531 { 2532 num_opts = stp_string_list_count(desc.bounds.str); 2533 if (num_opts > 0) 2534 { 2535 for (i = 0; i < num_opts; i++) 2536 { 2537 opt = stp_string_list_param(desc.bounds.str, i); 2538 if (strcmp(opt->name, "None") != 0) 2539 gzprintf(fp, "*%s.APPrinterPreset %s/%s: \"*StpImageType %s\"\n", 2540 lang, opt->name, opt->text, opt->name); 2541 } 2542 } 2543 } 2544 stp_parameter_description_destroy(&desc); 2545 } 2546 po = savepo; 2547 } 2548 if (has_quality_parameter) 2549 stp_free(default_resolution); 2550 stp_string_list_destroy(resolutions); 2551 2552 /* 2553 * Fonts... 2554 */ 2555 2556 print_standard_fonts(fp); 2557 gzprintf(fp, "\n*%% End of %s\n", filename); 2558 2559 stp_vars_destroy(v); 2560 2561 return (0); 2562} 2563 2564 2565/* 2566 * End of "$Id: genppd.c,v 1.186 2011/03/13 19:28:50 rlk Exp $". 2567 */ 2568