]>
git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc-source.cxx
4 // Source class for the CUPS PPD Compiler.
6 // Copyright 2007-2009 by Apple Inc.
7 // Copyright 2002-2007 by Easy Software Products.
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/".
17 // ppdcSource::ppdcSource() - Load a driver source file.
18 // ppdcSource::~ppdcSource() - Free a driver source file.
19 // ppdcSource::add_include() - Add an include directory.
20 // ppdcSource::find_driver() - Find a driver.
21 // ppdcSource::find_include() - Find an include file.
22 // ppdcSource::find_po() - Find a message catalog for the given
24 // ppdcSource::find_size() - Find a media size.
25 // ppdcSource::find_variable() - Find a variable.
26 // ppdcSource::get_attr() - Get an attribute.
27 // ppdcSource::get_boolean() - Get a boolean value.
28 // ppdcSource::get_choice() - Get a choice.
29 // ppdcSource::get_color_model() - Get an old-style color model option.
30 // ppdcSource::get_color_order() - Get an old-style color order value.
31 // ppdcSource::get_color_profile() - Get a color profile definition.
32 // ppdcSource::get_color_space() - Get an old-style colorspace value.
33 // ppdcSource::get_constraint() - Get a constraint.
34 // ppdcSource::get_custom_size() - Get a custom media size definition from
36 // ppdcSource::get_duplex() - Get a duplex option.
37 // ppdcSource::get_filter() - Get a filter.
38 // ppdcSource::get_float() - Get a single floating-point number.
39 // ppdcSource::get_font() - Get a font definition.
40 // ppdcSource::get_generic() - Get a generic old-style option.
41 // ppdcSource::get_group() - Get an option group.
42 // ppdcSource::get_installable() - Get an installable option.
43 // ppdcSource::get_integer() - Get an integer value from a file.
44 // ppdcSource::get_measurement() - Get a measurement value.
45 // ppdcSource::get_option() - Get an option definition.
46 // ppdcSource::get_po() - Get a message catalog.
47 // ppdcSource::get_resolution() - Get an old-style resolution option.
48 // ppdcSource::get_simple_profile() - Get a simple color profile definition.
49 // ppdcSource::get_size() - Get a media size definition from a file.
50 // ppdcSource::get_token() - Get a token from a file.
51 // ppdcSource::get_variable() - Get a variable definition.
52 // ppdcSource::quotef() - Write a formatted, quoted string...
53 // ppdcSource::read_file() - Read a driver source file.
54 // ppdcSource::scan_file() - Scan a driver source file.
55 // ppdcSource::set_variable() - Set a variable.
56 // ppdcSource::write_file() - Write the current source data to a file.
60 // Include necessary headers...
63 #include "ppdc-private.h"
64 #include <cups/globals.h>
68 #include <cups/raster.h>
69 #include "data/epson.h"
70 #include "data/escp.h"
72 #include "data/label.h"
75 # include <sys/utsname.h>
83 ppdcArray
*ppdcSource::includes
= 0;
84 const char *ppdcSource::driver_types
[] =
97 // 'ppdcSource::ppdcSource()' - Load a driver source file.
100 ppdcSource::ppdcSource(const char *f
, // I - File to read
101 cups_file_t
*ffp
)// I - File pointer to use
106 filename
= new ppdcString(f
);
107 base_fonts
= new ppdcArray();
108 drivers
= new ppdcArray();
109 po_files
= new ppdcArray();
110 sizes
= new ppdcArray();
111 vars
= new ppdcArray();
112 cond_state
= PPDC_COND_NORMAL
;
113 cond_current
= cond_stack
;
114 cond_stack
[0] = PPDC_COND_NORMAL
;
116 // Add standard #define variables...
117 #define MAKE_STRING(x) #x
119 vars
->add(new ppdcVariable("CUPS_VERSION", MAKE_STRING(CUPS_VERSION
)));
120 vars
->add(new ppdcVariable("CUPS_VERSION_MAJOR", MAKE_STRING(CUPS_VERSION_MAJOR
)));
121 vars
->add(new ppdcVariable("CUPS_VERSION_MINOR", MAKE_STRING(CUPS_VERSION_MINOR
)));
122 vars
->add(new ppdcVariable("CUPS_VERSION_PATCH", MAKE_STRING(CUPS_VERSION_PATCH
)));
125 vars
->add(new ppdcVariable("PLATFORM_NAME", "Windows"));
126 vars
->add(new ppdcVariable("PLATFORM_ARCH", "X86"));
129 struct utsname name
; // uname information
133 vars
->add(new ppdcVariable("PLATFORM_NAME", name
.sysname
));
134 vars
->add(new ppdcVariable("PLATFORM_ARCH", name
.machine
));
138 vars
->add(new ppdcVariable("PLATFORM_NAME", "unknown"));
139 vars
->add(new ppdcVariable("PLATFORM_ARCH", "unknown"));
149 // 'ppdcSource::~ppdcSource()' - Free a driver source file.
152 ppdcSource::~ppdcSource()
157 base_fonts
->release();
166 // 'ppdcSource::add_include()' - Add an include directory.
170 ppdcSource::add_include(const char *d
) // I - Include directory
176 includes
= new ppdcArray();
178 includes
->add(new ppdcString(d
));
183 // 'ppdcSource::find_driver()' - Find a driver.
186 ppdcDriver
* // O - Driver
187 ppdcSource::find_driver(const char *f
) // I - Driver file name
189 ppdcDriver
*d
; // Current driver
192 for (d
= (ppdcDriver
*)drivers
->first(); d
; d
= (ppdcDriver
*)drivers
->next())
193 if (!strcasecmp(f
, d
->pc_file_name
->value
))
201 // 'ppdcSource::find_include()' - Find an include file.
204 char * // O - Found path or NULL
205 ppdcSource::find_include(
206 const char *f
, // I - Include filename
207 const char *base
, // I - Current directory
208 char *n
, // I - Path buffer
209 int nlen
) // I - Path buffer length
211 ppdcString
*dir
; // Include directory
212 char temp
[1024], // Temporary path
213 *ptr
; // Pointer to end of path
216 // Range check input...
217 if (!f
|| !*f
|| !n
|| nlen
< 2)
220 // Check the first character to see if we have <name> or "name"...
223 // Remove the surrounding <> from the name...
224 strlcpy(temp
, f
+ 1, sizeof(temp
));
225 ptr
= temp
+ strlen(temp
) - 1;
229 _cupsLangPrintf(stderr
,
230 _("ppdc: Invalid #include/#po filename \"%s\"!\n"), n
);
239 // Check for the local file relative to the current directory...
240 if (base
&& *base
&& f
[0] != '/')
241 snprintf(n
, nlen
, "%s/%s", base
, f
);
249 // Absolute path that doesn't exist...
254 // Search the include directories, if any...
257 for (dir
= (ppdcString
*)includes
->first(); dir
; dir
= (ppdcString
*)includes
->next())
259 snprintf(n
, nlen
, "%s/%s", dir
->value
, f
);
265 // Search the standard include directories...
266 _cups_globals_t
*cg
= _cupsGlobals(); // Global data
268 snprintf(n
, nlen
, "%s/ppdc/%s", cg
->cups_datadir
, f
);
272 snprintf(n
, nlen
, "%s/po/%s", cg
->cups_datadir
, f
);
281 // 'ppdcSource::find_po()' - Find a message catalog for the given locale...
284 ppdcCatalog
* // O - Message catalog or NULL
285 ppdcSource::find_po(const char *l
) // I - Locale name
287 ppdcCatalog
*cat
; // Current message catalog
290 for (cat
= (ppdcCatalog
*)po_files
->first();
292 cat
= (ppdcCatalog
*)po_files
->next())
293 if (!strcasecmp(l
, cat
->locale
->value
))
301 // 'ppdcSource::find_size()' - Find a media size.
304 ppdcMediaSize
* // O - Size
305 ppdcSource::find_size(const char *s
) // I - Size name
307 ppdcMediaSize
*m
; // Current media size
310 for (m
= (ppdcMediaSize
*)sizes
->first(); m
; m
= (ppdcMediaSize
*)sizes
->next())
311 if (!strcasecmp(s
, m
->name
->value
))
319 // 'ppdcSource::find_variable()' - Find a variable.
322 ppdcVariable
* // O - Variable
323 ppdcSource::find_variable(const char *n
)// I - Variable name
325 ppdcVariable
*v
; // Current variable
328 for (v
= (ppdcVariable
*)vars
->first(); v
; v
= (ppdcVariable
*)vars
->next())
329 if (!strcasecmp(n
, v
->name
->value
))
337 // 'ppdcSource::get_attr()' - Get an attribute.
340 ppdcAttr
* // O - Attribute
341 ppdcSource::get_attr(ppdcFile
*fp
, // I - File to read
342 bool loc
) // I - Localize this attribute?
344 char name
[1024], // Name string
345 selector
[1024], // Selector string
346 *text
, // Text string
347 value
[1024]; // Value string
350 // Get the attribute parameters:
352 // Attribute name selector value
353 if (!get_token(fp
, name
, sizeof(name
)))
355 _cupsLangPrintf(stderr
,
356 _("ppdc: Expected name after %s on line %d of %s!\n"),
357 loc
? "LocAttribute" : "Attribute", fp
->line
, fp
->filename
);
361 if (!get_token(fp
, selector
, sizeof(selector
)))
363 _cupsLangPrintf(stderr
,
364 _("ppdc: Expected selector after %s on line %d of %s!\n"),
365 loc
? "LocAttribute" : "Attribute", fp
->line
, fp
->filename
);
369 if ((text
= strchr(selector
, '/')) != NULL
)
372 if (!get_token(fp
, value
, sizeof(value
)))
374 _cupsLangPrintf(stderr
,
375 _("ppdc: Expected value after %s on line %d of %s!\n"),
376 loc
? "LocAttribute" : "Attribute", fp
->line
, fp
->filename
);
380 return (new ppdcAttr(name
, selector
, text
, value
, loc
));
385 // 'ppdcSource::get_boolean()' - Get a boolean value.
388 int // O - Boolean value
389 ppdcSource::get_boolean(ppdcFile
*fp
) // I - File to read
391 char buffer
[256]; // String buffer
394 if (!get_token(fp
, buffer
, sizeof(buffer
)))
396 _cupsLangPrintf(stderr
,
397 _("ppdc: Expected boolean value on line %d of %s.\n"),
398 fp
->line
, fp
->filename
);
402 if (!strcasecmp(buffer
, "on") ||
403 !strcasecmp(buffer
, "yes") ||
404 !strcasecmp(buffer
, "true"))
406 else if (!strcasecmp(buffer
, "off") ||
407 !strcasecmp(buffer
, "no") ||
408 !strcasecmp(buffer
, "false"))
412 _cupsLangPrintf(stderr
,
413 _("ppdc: Bad boolean value (%s) on line %d of %s.\n"),
414 buffer
, fp
->line
, fp
->filename
);
421 // 'ppdcSource::get_choice()' - Get a choice.
424 ppdcChoice
* // O - Choice data
425 ppdcSource::get_choice(ppdcFile
*fp
) // I - File to read
427 char name
[1024], // Name
432 // Read a choice from the file:
434 // Choice name/text code
435 if (!get_token(fp
, name
, sizeof(name
)))
437 _cupsLangPrintf(stderr
,
438 _("ppdc: Expected choice name/text on line %d of %s.\n"),
439 fp
->line
, fp
->filename
);
443 if ((text
= strchr(name
, '/')) != NULL
)
448 if (!get_token(fp
, code
, sizeof(code
)))
450 _cupsLangPrintf(stderr
, _("ppdc: Expected choice code on line %d of %s.\n"),
451 fp
->line
, fp
->filename
);
455 // Return the new choice
456 return (new ppdcChoice(name
, text
, code
));
461 // 'ppdcSource::get_color_model()' - Get an old-style color model option.
464 ppdcChoice
* // O - Choice data
465 ppdcSource::get_color_model(ppdcFile
*fp
)
468 char name
[1024], // Option name
469 *text
, // Text option
470 temp
[256]; // Temporary string
471 int color_space
, // Colorspace
472 color_order
, // Color order
473 compression
; // Compression mode
476 // Get the ColorModel parameters:
478 // ColorModel name/text colorspace colororder compression
479 if (!get_token(fp
, name
, sizeof(name
)))
481 _cupsLangPrintf(stderr
,
482 _("ppdc: Expected name/text combination for ColorModel on "
483 "line %d of %s!\n"), fp
->line
, fp
->filename
);
487 if ((text
= strchr(name
, '/')) != NULL
)
492 if (!get_token(fp
, temp
, sizeof(temp
)))
494 _cupsLangPrintf(stderr
,
495 _("ppdc: Expected colorspace for ColorModel on line %d of "
496 "%s!\n"), fp
->line
, fp
->filename
);
500 if ((color_space
= get_color_space(temp
)) < 0)
501 color_space
= get_integer(temp
);
503 if (!get_token(fp
, temp
, sizeof(temp
)))
505 _cupsLangPrintf(stderr
,
506 _("ppdc: Expected color order for ColorModel on line %d of "
507 "%s!\n"), fp
->line
, fp
->filename
);
511 if ((color_order
= get_color_order(temp
)) < 0)
512 color_order
= get_integer(temp
);
514 if (!get_token(fp
, temp
, sizeof(temp
)))
516 _cupsLangPrintf(stderr
,
517 _("ppdc: Expected compression for ColorModel on line %d of "
518 "%s!\n"), fp
->line
, fp
->filename
);
522 compression
= get_integer(temp
);
524 snprintf(temp
, sizeof(temp
),
525 "<</cupsColorSpace %d/cupsColorOrder %d/cupsCompression %d>>"
527 color_space
, color_order
, compression
);
529 return (new ppdcChoice(name
, text
, temp
));
534 // 'ppdcSource::get_color_order()' - Get an old-style color order value.
537 int // O - Color order value
538 ppdcSource::get_color_order(
539 const char *co
) // I - Color order string
541 if (!strcasecmp(co
, "chunked") ||
542 !strcasecmp(co
, "chunky"))
543 return (CUPS_ORDER_CHUNKED
);
544 else if (!strcasecmp(co
, "banded"))
545 return (CUPS_ORDER_BANDED
);
546 else if (!strcasecmp(co
, "planar"))
547 return (CUPS_ORDER_PLANAR
);
554 // 'ppdcSource::get_color_profile()' - Get a color profile definition.
557 ppdcProfile
* // O - Color profile
558 ppdcSource::get_color_profile(
559 ppdcFile
*fp
) // I - File to read
561 char resolution
[1024], // Resolution/media type
562 *media_type
; // Media type
563 int i
; // Looping var
564 float g
, // Gamma value
566 m
[9]; // Transform matrix
569 // Get the ColorProfile parameters:
571 // ColorProfile resolution/mediatype gamma density m00 m01 m02 ... m22
572 if (!get_token(fp
, resolution
, sizeof(resolution
)))
574 _cupsLangPrintf(stderr
,
575 _("ppdc: Expected resolution/mediatype following "
576 "ColorProfile on line %d of %s!\n"),
577 fp
->line
, fp
->filename
);
581 if ((media_type
= strchr(resolution
, '/')) != NULL
)
582 *media_type
++ = '\0';
584 media_type
= resolution
;
588 for (i
= 0; i
< 9; i
++)
589 m
[i
] = get_float(fp
);
591 return (new ppdcProfile(resolution
, media_type
, g
, d
, m
));
596 // 'ppdcSource::get_color_space()' - Get an old-style colorspace value.
599 int // O - Colorspace value
600 ppdcSource::get_color_space(
601 const char *cs
) // I - Colorspace string
603 if (!strcasecmp(cs
, "w"))
604 return (CUPS_CSPACE_W
);
605 else if (!strcasecmp(cs
, "rgb"))
606 return (CUPS_CSPACE_RGB
);
607 else if (!strcasecmp(cs
, "rgba"))
608 return (CUPS_CSPACE_RGBA
);
609 else if (!strcasecmp(cs
, "k"))
610 return (CUPS_CSPACE_K
);
611 else if (!strcasecmp(cs
, "cmy"))
612 return (CUPS_CSPACE_CMY
);
613 else if (!strcasecmp(cs
, "ymc"))
614 return (CUPS_CSPACE_YMC
);
615 else if (!strcasecmp(cs
, "cmyk"))
616 return (CUPS_CSPACE_CMYK
);
617 else if (!strcasecmp(cs
, "ymck"))
618 return (CUPS_CSPACE_YMCK
);
619 else if (!strcasecmp(cs
, "kcmy"))
620 return (CUPS_CSPACE_KCMY
);
621 else if (!strcasecmp(cs
, "kcmycm"))
622 return (CUPS_CSPACE_KCMYcm
);
623 else if (!strcasecmp(cs
, "gmck"))
624 return (CUPS_CSPACE_GMCK
);
625 else if (!strcasecmp(cs
, "gmcs"))
626 return (CUPS_CSPACE_GMCS
);
627 else if (!strcasecmp(cs
, "white"))
628 return (CUPS_CSPACE_WHITE
);
629 else if (!strcasecmp(cs
, "gold"))
630 return (CUPS_CSPACE_GOLD
);
631 else if (!strcasecmp(cs
, "silver"))
632 return (CUPS_CSPACE_SILVER
);
633 else if (!strcasecmp(cs
, "CIEXYZ"))
634 return (CUPS_CSPACE_CIEXYZ
);
635 else if (!strcasecmp(cs
, "CIELab"))
636 return (CUPS_CSPACE_CIELab
);
637 else if (!strcasecmp(cs
, "RGBW"))
638 return (CUPS_CSPACE_RGBW
);
639 else if (!strcasecmp(cs
, "ICC1"))
640 return (CUPS_CSPACE_ICC1
);
641 else if (!strcasecmp(cs
, "ICC2"))
642 return (CUPS_CSPACE_ICC2
);
643 else if (!strcasecmp(cs
, "ICC3"))
644 return (CUPS_CSPACE_ICC3
);
645 else if (!strcasecmp(cs
, "ICC4"))
646 return (CUPS_CSPACE_ICC4
);
647 else if (!strcasecmp(cs
, "ICC5"))
648 return (CUPS_CSPACE_ICC5
);
649 else if (!strcasecmp(cs
, "ICC6"))
650 return (CUPS_CSPACE_ICC6
);
651 else if (!strcasecmp(cs
, "ICC7"))
652 return (CUPS_CSPACE_ICC7
);
653 else if (!strcasecmp(cs
, "ICC8"))
654 return (CUPS_CSPACE_ICC8
);
655 else if (!strcasecmp(cs
, "ICC9"))
656 return (CUPS_CSPACE_ICC9
);
657 else if (!strcasecmp(cs
, "ICCA"))
658 return (CUPS_CSPACE_ICCA
);
659 else if (!strcasecmp(cs
, "ICCB"))
660 return (CUPS_CSPACE_ICCB
);
661 else if (!strcasecmp(cs
, "ICCC"))
662 return (CUPS_CSPACE_ICCC
);
663 else if (!strcasecmp(cs
, "ICCD"))
664 return (CUPS_CSPACE_ICCD
);
665 else if (!strcasecmp(cs
, "ICCE"))
666 return (CUPS_CSPACE_ICCE
);
667 else if (!strcasecmp(cs
, "ICCF"))
668 return (CUPS_CSPACE_ICCF
);
675 // 'ppdcSource::get_constraint()' - Get a constraint.
678 ppdcConstraint
* // O - Constraint
679 ppdcSource::get_constraint(ppdcFile
*fp
)// I - File to read
681 char temp
[1024], // One string to rule them all
682 *ptr
, // Pointer into string
683 *option1
, // Constraint option 1
684 *choice1
, // Constraint choice 1
685 *option2
, // Constraint option 2
686 *choice2
; // Constraint choice 2
689 // Read the UIConstaints parameter in one of the following forms:
691 // UIConstraints "*Option1 *Option2"
692 // UIConstraints "*Option1 Choice1 *Option2"
693 // UIConstraints "*Option1 *Option2 Choice2"
694 // UIConstraints "*Option1 Choice1 *Option2 Choice2"
695 if (!get_token(fp
, temp
, sizeof(temp
)))
697 _cupsLangPrintf(stderr
,
698 _("ppdc: Expected constraints string for UIConstraints on "
699 "line %d of %s!\n"), fp
->line
, fp
->filename
);
703 for (ptr
= temp
; isspace(*ptr
); ptr
++);
707 _cupsLangPrintf(stderr
,
708 _("ppdc: Option constraint must *name on line %d of %s!\n"),
709 fp
->line
, fp
->filename
);
715 for (; *ptr
&& !isspace(*ptr
); ptr
++);
716 for (; isspace(*ptr
); *ptr
++ = '\0');
722 for (; *ptr
&& !isspace(*ptr
); ptr
++);
723 for (; isspace(*ptr
); *ptr
++ = '\0');
730 _cupsLangPrintf(stderr
,
731 _("ppdc: Expected two option names on line %d of %s!\n"),
732 fp
->line
, fp
->filename
);
738 for (; *ptr
&& !isspace(*ptr
); ptr
++);
739 for (; isspace(*ptr
); *ptr
++ = '\0');
746 return (new ppdcConstraint(option1
, choice1
, option2
, choice2
));
751 // 'ppdcSource::get_custom_size()' - Get a custom media size definition from a file.
754 ppdcMediaSize
* // O - Media size
755 ppdcSource::get_custom_size(ppdcFile
*fp
)
758 char name
[1024], // Name
760 size_code
[10240], // PageSize code
761 region_code
[10240]; // PageRegion
762 float width
, // Width
765 bottom
, // Bottom margin
766 right
, // Right margin
770 // Get the name, text, width, length, margins, and code:
772 // CustomMedia name/text width length left bottom right top size-code region-code
773 if (!get_token(fp
, name
, sizeof(name
)))
776 if ((text
= strchr(name
, '/')) != NULL
)
781 if ((width
= get_measurement(fp
)) < 0.0f
)
784 if ((length
= get_measurement(fp
)) < 0.0f
)
787 if ((left
= get_measurement(fp
)) < 0.0f
)
790 if ((bottom
= get_measurement(fp
)) < 0.0f
)
793 if ((right
= get_measurement(fp
)) < 0.0f
)
796 if ((top
= get_measurement(fp
)) < 0.0f
)
799 if (!get_token(fp
, size_code
, sizeof(size_code
)))
802 if (!get_token(fp
, region_code
, sizeof(region_code
)))
805 // Return the new media size...
806 return (new ppdcMediaSize(name
, text
, width
, length
, left
, bottom
,
807 right
, top
, size_code
, region_code
));
812 // 'ppdcSource::get_duplex()' - Get a duplex option.
816 ppdcSource::get_duplex(ppdcFile
*fp
, // I - File to read from
817 ppdcDriver
*d
) // I - Current driver
819 char temp
[256]; // Duplex keyword
820 ppdcAttr
*attr
; // cupsFlipDuplex attribute
821 ppdcGroup
*g
; // Current group
822 ppdcOption
*o
; // Duplex option
825 // Duplex {boolean|none|normal|flip}
826 if (!get_token(fp
, temp
, sizeof(temp
)))
828 _cupsLangPrintf(stderr
,
829 _("ppdc: Expected duplex type after Duplex on line %d of "
830 "%s!\n"), fp
->line
, fp
->filename
);
837 if (!strcasecmp(temp
, "none") || !strcasecmp(temp
, "false") ||
838 !strcasecmp(temp
, "no") || !strcasecmp(temp
, "off"))
840 g
= d
->find_group("General");
841 if ((o
= g
->find_option("Duplex")) != NULL
)
842 g
->options
->remove(o
);
844 for (attr
= (ppdcAttr
*)d
->attrs
->first();
846 attr
= (ppdcAttr
*)d
->attrs
->next())
847 if (!strcmp(attr
->name
->value
, "cupsFlipDuplex"))
849 d
->attrs
->remove(attr
);
853 else if (!strcasecmp(temp
, "normal") || !strcasecmp(temp
, "true") ||
854 !strcasecmp(temp
, "yes") || !strcasecmp(temp
, "on") ||
855 !strcasecmp(temp
, "flip") || !strcasecmp(temp
, "rotated") ||
856 !strcasecmp(temp
, "manualtumble"))
858 g
= d
->find_group("General");
859 o
= g
->find_option("Duplex");
863 o
= new ppdcOption(PPDC_PICKONE
, "Duplex", "2-Sided Printing",
864 !strcasecmp(temp
, "flip") ? PPDC_SECTION_PAGE
:
865 PPDC_SECTION_ANY
, 10.0f
);
866 o
->add_choice(new ppdcChoice("None", "Off (1-Sided)",
867 "<</Duplex false>>setpagedevice"));
868 o
->add_choice(new ppdcChoice("DuplexNoTumble", "Long-Edge (Portrait)",
869 "<</Duplex true/Tumble false>>setpagedevice"));
870 o
->add_choice(new ppdcChoice("DuplexTumble", "Short-Edge (Landscape)",
871 "<</Duplex true/Tumble true>>setpagedevice"));
876 for (attr
= (ppdcAttr
*)d
->attrs
->first();
878 attr
= (ppdcAttr
*)d
->attrs
->next())
879 if (!strcmp(attr
->name
->value
, "cupsFlipDuplex"))
881 if (strcasecmp(temp
, "flip"))
882 d
->attrs
->remove(attr
);
886 if (!strcasecmp(temp
, "flip") && !attr
)
887 d
->add_attr(new ppdcAttr("cupsFlipDuplex", NULL
, NULL
, "true"));
889 for (attr
= (ppdcAttr
*)d
->attrs
->first();
891 attr
= (ppdcAttr
*)d
->attrs
->next())
892 if (!strcmp(attr
->name
->value
, "cupsBackSide"))
894 d
->attrs
->remove(attr
);
898 if (!strcasecmp(temp
, "flip"))
899 d
->add_attr(new ppdcAttr("cupsBackSide", NULL
, NULL
, "Flipped"));
900 else if (!strcasecmp(temp
, "rotated"))
901 d
->add_attr(new ppdcAttr("cupsBackSide", NULL
, NULL
, "Rotated"));
902 else if (!strcasecmp(temp
, "manualtumble"))
903 d
->add_attr(new ppdcAttr("cupsBackSide", NULL
, NULL
, "ManualTumble"));
905 d
->add_attr(new ppdcAttr("cupsBackSide", NULL
, NULL
, "Normal"));
908 _cupsLangPrintf(stderr
,
909 _("ppdc: Unknown duplex type \"%s\" on line %d of %s!\n"),
910 temp
, fp
->line
, fp
->filename
);
915 // 'ppdcSource::get_filter()' - Get a filter.
918 ppdcFilter
* // O - Filter
919 ppdcSource::get_filter(ppdcFile
*fp
) // I - File to read
921 char type
[1024], // MIME type
922 program
[1024], // Filter program
923 *ptr
; // Pointer into MIME type
924 int cost
; // Relative cost
927 // Read filter parameters in one of the following formats:
929 // Filter "type cost program"
930 // Filter type cost program
932 if (!get_token(fp
, type
, sizeof(type
)))
934 _cupsLangPrintf(stderr
,
935 _("ppdc: Expected a filter definition on line %d of %s!\n"),
936 fp
->line
, fp
->filename
);
940 if ((ptr
= strchr(type
, ' ')) != NULL
)
942 // Old-style filter definition in one string...
944 cost
= strtol(ptr
, &ptr
, 10);
946 while (isspace(*ptr
))
949 strcpy(program
, ptr
);
953 cost
= get_integer(fp
);
955 if (!get_token(fp
, program
, sizeof(program
)))
957 _cupsLangPrintf(stderr
,
958 _("ppdc: Expected a program name on line %d of %s!\n"),
959 fp
->line
, fp
->filename
);
966 _cupsLangPrintf(stderr
,
967 _("ppdc: Invalid empty MIME type for filter on line %d of "
968 "%s!\n"), fp
->line
, fp
->filename
);
972 if (cost
< 0 || cost
> 200)
974 _cupsLangPrintf(stderr
,
975 _("ppdc: Invalid cost for filter on line %d of %s!\n"),
976 fp
->line
, fp
->filename
);
982 _cupsLangPrintf(stderr
,
983 _("ppdc: Invalid empty program name for filter on line %d "
984 "of %s!\n"), fp
->line
, fp
->filename
);
988 return (new ppdcFilter(type
, program
, cost
));
993 // 'ppdcSource::get_float()' - Get a single floating-point number.
997 ppdcSource::get_float(ppdcFile
*fp
) // I - File to read
999 char temp
[256], // String buffer
1000 *ptr
; // Pointer into buffer
1001 float val
; // Floating point value
1004 // Get the number from the file and range-check...
1005 if (!get_token(fp
, temp
, sizeof(temp
)))
1007 _cupsLangPrintf(stderr
, _("ppdc: Expected real number on line %d of %s!\n"),
1008 fp
->line
, fp
->filename
);
1012 val
= (float)strtod(temp
, &ptr
);
1016 _cupsLangPrintf(stderr
,
1017 _("ppdc: Unknown trailing characters in real number \"%s\" "
1018 "on line %d of %s!\n"), temp
, fp
->line
, fp
->filename
);
1027 // 'ppdcSource::get_font()' - Get a font definition.
1030 ppdcFont
* // O - Font data
1031 ppdcSource::get_font(ppdcFile
*fp
) // I - File to read
1033 char name
[256], // Font name
1034 encoding
[256], // Font encoding
1035 version
[256], // Font version
1036 charset
[256], // Font charset
1037 temp
[256]; // Font status string
1038 ppdcFontStatus status
; // Font status enumeration
1041 // Read font parameters as follows:
1044 // Font name encoding version charset status
1045 // %font name encoding version charset status
1047 // "Name" is the PostScript font name.
1049 // "Encoding" is the default encoding of the font: Standard, ISOLatin1,
1050 // Special, Expert, ExpertSubset, etc.
1052 // "Version" is the version number string.
1054 // "Charset" specifies the characters that are included in the font:
1055 // Standard, Special, Expert, Adobe-Identity, etc.
1057 // "Status" is the keyword ROM or Disk.
1058 if (!get_token(fp
, name
, sizeof(name
)))
1060 _cupsLangPrintf(stderr
,
1061 _("ppdc: Expected name after Font on line %d of %s!\n"),
1062 fp
->line
, fp
->filename
);
1066 if (!strcmp(name
, "*"))
1068 // Include all base fonts...
1072 status
= PPDC_FONT_ROM
;
1076 // Load a full font definition...
1077 if (!get_token(fp
, encoding
, sizeof(encoding
)))
1079 _cupsLangPrintf(stderr
,
1080 _("ppdc: Expected encoding after Font on line %d of "
1081 "%s!\n"), fp
->line
, fp
->filename
);
1085 if (!get_token(fp
, version
, sizeof(version
)))
1087 _cupsLangPrintf(stderr
,
1088 _("ppdc: Expected version after Font on line %d of "
1089 "%s!\n"), fp
->line
, fp
->filename
);
1093 if (!get_token(fp
, charset
, sizeof(charset
)))
1095 _cupsLangPrintf(stderr
,
1096 _("ppdc: Expected charset after Font on line %d of "
1097 "%s!\n"), fp
->line
, fp
->filename
);
1101 if (!get_token(fp
, temp
, sizeof(temp
)))
1103 _cupsLangPrintf(stderr
,
1104 _("ppdc: Expected status after Font on line %d of %s!\n"),
1105 fp
->line
, fp
->filename
);
1109 if (!strcasecmp(temp
, "ROM"))
1110 status
= PPDC_FONT_ROM
;
1111 else if (!strcasecmp(temp
, "Disk"))
1112 status
= PPDC_FONT_DISK
;
1115 _cupsLangPrintf(stderr
,
1116 _("ppdc: Bad status keyword %s on line %d of %s!\n"),
1117 temp
, fp
->line
, fp
->filename
);
1122 // printf("Font %s %s %s %s %s\n", name, encoding, version, charset, temp);
1124 return (new ppdcFont(name
, encoding
, version
, charset
, status
));
1129 // 'ppdcSource::get_generic()' - Get a generic old-style option.
1132 ppdcChoice
* // O - Choice data
1133 ppdcSource::get_generic(ppdcFile
*fp
, // I - File to read
1134 const char *keyword
,
1137 // I - Text attribute
1139 // I - Numeric attribute
1141 char name
[1024], // Name
1143 command
[256]; // Command string
1144 int val
; // Numeric value
1147 // Read one of the following parameters:
1150 // Foo integer name/text
1152 val
= get_integer(fp
);
1156 if (!get_token(fp
, name
, sizeof(name
)))
1158 _cupsLangPrintf(stderr
,
1159 _("ppdc: Expected name/text after %s on line %d of %s!\n"),
1160 keyword
, fp
->line
, fp
->filename
);
1164 if ((text
= strchr(name
, '/')) != NULL
)
1172 snprintf(command
, sizeof(command
),
1173 "<</%s(%s)/%s %d>>setpagedevice",
1174 tattr
, name
, nattr
, val
);
1176 snprintf(command
, sizeof(command
),
1177 "<</%s %d>>setpagedevice",
1181 snprintf(command
, sizeof(command
),
1182 "<</%s(%s)>>setpagedevice",
1185 return (new ppdcChoice(name
, text
, command
));
1190 // 'ppdcSource::get_group()' - Get an option group.
1193 ppdcGroup
* // O - Group
1194 ppdcSource::get_group(ppdcFile
*fp
, // I - File to read
1195 ppdcDriver
*d
) // I - Printer driver
1197 char name
[1024], // UI name
1199 ppdcGroup
*g
; // Group
1202 // Read the Group parameters:
1205 if (!get_token(fp
, name
, sizeof(name
)))
1207 _cupsLangPrintf(stderr
,
1208 _("ppdc: Expected group name/text on line %d of %s!\n"),
1209 fp
->line
, fp
->filename
);
1213 if ((text
= strchr(name
, '/')) != NULL
)
1218 // See if the group already exists...
1219 if ((g
= d
->find_group(name
)) == NULL
)
1221 // Nope, add a new one...
1222 g
= new ppdcGroup(name
, text
);
1230 // 'ppdcSource::get_installable()' - Get an installable option.
1233 ppdcOption
* // O - Option
1234 ppdcSource::get_installable(ppdcFile
*fp
)
1237 char name
[1024], // Name for installable option
1238 *text
; // Text for installable option
1239 ppdcOption
*o
; // Option
1242 // Read the parameter for an installable option:
1244 // Installable name/text
1245 if (!get_token(fp
, name
, sizeof(name
)))
1247 _cupsLangPrintf(stderr
,
1248 _("ppdc: Expected name/text after Installable on line %d "
1249 "of %s!\n"), fp
->line
, fp
->filename
);
1253 if ((text
= strchr(name
, '/')) != NULL
)
1258 // Create the option...
1259 o
= new ppdcOption(PPDC_BOOLEAN
, name
, text
, PPDC_SECTION_ANY
, 10.0f
);
1261 // Add the false and true choices...
1262 o
->add_choice(new ppdcChoice("False", "Not Installed", ""));
1263 o
->add_choice(new ppdcChoice("True", "Installed", ""));
1270 // 'ppdcSource::get_integer()' - Get an integer value from a string.
1273 #define PPDC_XX -1 // Bad
1274 #define PPDC_EQ 0 // ==
1275 #define PPDC_NE 1 // !=
1276 #define PPDC_LT 2 // <
1277 #define PPDC_LE 3 // <=
1278 #define PPDC_GT 4 // >
1279 #define PPDC_GE 5 // >=
1281 int // O - Integer value
1282 ppdcSource::get_integer(const char *v
) // I - Value string
1285 long temp
, // Temporary value
1286 temp2
; // Second temporary value
1287 char *newv
, // New value string pointer
1288 ch
; // Temporary character
1289 ppdcVariable
*var
; // #define variable
1290 int compop
; // Comparison operator
1293 // Parse the value string...
1297 if (isdigit(*v
& 255) || *v
== '-' || *v
== '+')
1299 // Return a simple integer value
1300 val
= strtol(v
, (char **)&v
, 0);
1301 if (*v
|| val
== LONG_MIN
)
1308 // Evaluate and expression in any of the following formats:
1310 // (number number ... number) Bitwise OR of all numbers
1311 // (NAME == value) 1 if equal, 0 otherwise
1312 // (NAME != value) 1 if not equal, 0 otherwise
1313 // (NAME < value) 1 if less than, 0 otherwise
1314 // (NAME <= value) 1 if less than or equal, 0 otherwise
1315 // (NAME > value) 1 if greater than, 0 otherwise
1316 // (NAME >= value) 1 if greater than or equal, 0 otherwise
1321 while (*v
&& *v
!= ')')
1323 // Skip leading whitespace...
1324 while (*v
&& isspace(*v
& 255));
1327 if (!*v
|| *v
== ')')
1330 if (isdigit(*v
& 255) || *v
== '-' || *v
== '+')
1332 // Bitwise OR a number...
1333 temp
= strtol(v
, &newv
, 0);
1335 if (!*newv
|| newv
== v
|| !(isspace(*newv
) || *newv
== ')') ||
1341 // NAME logicop value
1342 for (newv
= (char *)v
+ 1;
1343 *newv
&& (isalnum(*newv
& 255) || *newv
== '_');
1349 if ((var
= find_variable(v
)) != NULL
)
1351 if (!var
->value
|| !var
->value
->value
|| !var
->value
->value
[0])
1353 else if (isdigit(var
->value
->value
[0] & 255) ||
1354 var
->value
->value
[0] == '-' ||
1355 var
->value
->value
[0] == '+')
1356 temp
= strtol(var
->value
->value
, NULL
, 0);
1364 while (isspace(*newv
& 255))
1367 if (strncmp(newv
, "==", 2))
1372 else if (strncmp(newv
, "!=", 2))
1377 else if (strncmp(newv
, "<=", 2))
1382 else if (*newv
== '<')
1387 else if (strncmp(newv
, ">=", 2))
1392 else if (*newv
== '>')
1400 if (compop
!= PPDC_XX
)
1402 while (isspace(*newv
& 255))
1405 if (*newv
== ')' || !*newv
)
1408 if (isdigit(*v
& 255) || *v
== '-' || *v
== '+')
1410 // Get the second number...
1411 temp2
= strtol(newv
, &newv
, 0);
1412 if (!*newv
|| newv
== v
|| !(isspace(*newv
) || *newv
== ')') ||
1418 // Lookup the second name...
1419 for (v
= newv
, newv
++;
1420 *newv
&& (isalnum(*newv
& 255) || *newv
== '_');
1426 if ((var
= find_variable(v
)) != NULL
)
1428 if (!var
->value
|| !var
->value
->value
|| !var
->value
->value
[0])
1430 else if (isdigit(var
->value
->value
[0] & 255) ||
1431 var
->value
->value
[0] == '-' ||
1432 var
->value
->value
[0] == '+')
1433 temp2
= strtol(var
->value
->value
, NULL
, 0);
1443 // Do the comparison...
1447 temp
= temp
== temp2
;
1450 temp
= temp
!= temp2
;
1453 temp
= temp
< temp2
;
1456 temp
= temp
<= temp2
;
1459 temp
= temp
> temp2
;
1462 temp
= temp
>= temp2
;
1472 if (*v
== ')' && !v
[1])
1477 else if ((var
= find_variable(v
)) != NULL
)
1479 // NAME by itself returns 1 if the #define variable is not blank and
1481 return (var
->value
->value
&& var
->value
->value
[0] &&
1482 strcmp(var
->value
->value
, "0"));
1486 // Anything else is an error...
1493 // 'ppdcSource::get_integer()' - Get an integer value from a file.
1496 int // O - Integer value
1497 ppdcSource::get_integer(ppdcFile
*fp
) // I - File to read
1499 char temp
[1024]; // String buffer
1502 if (!get_token(fp
, temp
, sizeof(temp
)))
1504 _cupsLangPrintf(stderr
, _("ppdc: Expected integer on line %d of %s!\n"),
1505 fp
->line
, fp
->filename
);
1509 return (get_integer(temp
));
1514 // 'ppdcSource::get_measurement()' - Get a measurement value.
1517 float // O - Measurement value in points
1518 ppdcSource::get_measurement(ppdcFile
*fp
)
1521 char buffer
[256], // Number buffer
1522 *ptr
; // Pointer into buffer
1523 float val
; // Measurement value
1526 // Grab a token from the file...
1527 if (!get_token(fp
, buffer
, sizeof(buffer
)))
1530 // Get the floating point value of "s" and skip all digits and decimal points.
1531 val
= (float)strtod(buffer
, &ptr
);
1533 // Check for a trailing unit specifier...
1534 if (!strcasecmp(ptr
, "mm"))
1535 val
*= 72.0f
/ 25.4f
;
1536 else if (!strcasecmp(ptr
, "cm"))
1537 val
*= 72.0f
/ 2.54f
;
1538 else if (!strcasecmp(ptr
, "m"))
1539 val
*= 72.0f
/ 0.0254f
;
1540 else if (!strcasecmp(ptr
, "in"))
1542 else if (!strcasecmp(ptr
, "ft"))
1543 val
*= 72.0f
* 12.0f
;
1544 else if (strcasecmp(ptr
, "pt") && *ptr
)
1552 // 'ppdcSource::get_option()' - Get an option definition.
1555 ppdcOption
* // O - Option
1556 ppdcSource::get_option(ppdcFile
*fp
, // I - File to read
1557 ppdcDriver
*d
, // I - Printer driver
1558 ppdcGroup
*g
) // I - Current group
1560 char name
[1024], // UI name
1562 type
[256]; // UI type string
1563 ppdcOptType ot
; // Option type value
1564 ppdcOptSection section
; // Option section
1565 float order
; // Option order
1566 ppdcOption
*o
; // Option
1567 ppdcGroup
*mg
; // Matching group, if any
1570 // Read the Option parameters:
1572 // Option name/text type section order
1573 if (!get_token(fp
, name
, sizeof(name
)))
1575 _cupsLangPrintf(stderr
,
1576 _("ppdc: Expected option name/text on line %d of %s!\n"),
1577 fp
->line
, fp
->filename
);
1581 if ((text
= strchr(name
, '/')) != NULL
)
1586 if (!get_token(fp
, type
, sizeof(type
)))
1588 _cupsLangPrintf(stderr
, _("ppdc: Expected option type on line %d of %s!\n"),
1589 fp
->line
, fp
->filename
);
1593 if (!strcasecmp(type
, "boolean"))
1595 else if (!strcasecmp(type
, "pickone"))
1597 else if (!strcasecmp(type
, "pickmany"))
1601 _cupsLangPrintf(stderr
,
1602 _("ppdc: Invalid option type \"%s\" on line %d of %s!\n"),
1603 type
, fp
->line
, fp
->filename
);
1607 if (!get_token(fp
, type
, sizeof(type
)))
1609 _cupsLangPrintf(stderr
,
1610 _("ppdc: Expected option section on line %d of %s!\n"),
1611 fp
->line
, fp
->filename
);
1615 if (!strcasecmp(type
, "AnySetup"))
1616 section
= PPDC_SECTION_ANY
;
1617 else if (!strcasecmp(type
, "DocumentSetup"))
1618 section
= PPDC_SECTION_DOCUMENT
;
1619 else if (!strcasecmp(type
, "ExitServer"))
1620 section
= PPDC_SECTION_EXIT
;
1621 else if (!strcasecmp(type
, "JCLSetup"))
1622 section
= PPDC_SECTION_JCL
;
1623 else if (!strcasecmp(type
, "PageSetup"))
1624 section
= PPDC_SECTION_PAGE
;
1625 else if (!strcasecmp(type
, "Prolog"))
1626 section
= PPDC_SECTION_PROLOG
;
1629 _cupsLangPrintf(stderr
,
1630 _("ppdc: Invalid option section \"%s\" on line %d of "
1631 "%s!\n"), type
, fp
->line
, fp
->filename
);
1635 order
= get_float(fp
);
1637 // See if the option already exists...
1638 if ((o
= d
->find_option_group(name
, &mg
)) == NULL
)
1640 // Nope, add a new one...
1641 o
= new ppdcOption(ot
, name
, text
, section
, order
);
1643 else if (o
->type
!= ot
)
1645 _cupsLangPrintf(stderr
,
1646 _("ppdc: Option %s redefined with a different type on line "
1647 "%d of %s!\n"), name
, fp
->line
, fp
->filename
);
1652 _cupsLangPrintf(stderr
,
1653 _("ppdc: Option %s defined in two different groups on line "
1654 "%d of %s!\n"), name
, fp
->line
, fp
->filename
);
1663 // 'ppdcSource::get_po()' - Get a message catalog.
1666 ppdcCatalog
* // O - Message catalog
1667 ppdcSource::get_po(ppdcFile
*fp
) // I - File to read
1669 char locale
[32], // Locale name
1670 poname
[1024], // Message catalog filename
1671 basedir
[1024], // Base directory
1672 *baseptr
, // Pointer into directory
1673 pofilename
[1024]; // Full filename of message catalog
1674 ppdcCatalog
*cat
; // Message catalog
1677 // Read the #po parameters:
1679 // #po locale "filename.po"
1680 if (!get_token(fp
, locale
, sizeof(locale
)))
1682 _cupsLangPrintf(stderr
,
1683 _("ppdc: Expected locale after #po on line %d of %s!\n"),
1684 fp
->line
, fp
->filename
);
1688 if (!get_token(fp
, poname
, sizeof(poname
)))
1690 _cupsLangPrintf(stderr
,
1691 _("ppdc: Expected filename after #po %s on line %d of "
1692 "%s!\n"), locale
, fp
->line
, fp
->filename
);
1696 // See if the locale is already loaded...
1697 if (find_po(locale
))
1699 _cupsLangPrintf(stderr
,
1700 _("ppdc: Duplicate #po for locale %s on line %d of %s!\n"),
1701 locale
, fp
->line
, fp
->filename
);
1705 // Figure out the current directory...
1706 strlcpy(basedir
, fp
->filename
, sizeof(basedir
));
1708 if ((baseptr
= strrchr(basedir
, '/')) != NULL
)
1711 strcpy(basedir
, ".");
1713 // Find the po file...
1714 pofilename
[0] = '\0';
1717 find_include(poname
, basedir
, pofilename
, sizeof(pofilename
)))
1719 // Found it, so load it...
1720 cat
= new ppdcCatalog(locale
, pofilename
);
1722 // Reset the filename to the name supplied by the user...
1723 cat
->filename
->release();
1724 cat
->filename
= new ppdcString(poname
);
1726 // Return the catalog...
1731 _cupsLangPrintf(stderr
,
1732 _("ppdc: Unable to find #po file %s on line %d of %s!\n"),
1733 poname
, fp
->line
, fp
->filename
);
1740 // 'ppdcSource::get_resolution()' - Get an old-style resolution option.
1743 ppdcChoice
* // O - Choice data
1744 ppdcSource::get_resolution(ppdcFile
*fp
)// I - File to read
1746 char name
[1024], // Name
1748 temp
[256], // Temporary string
1749 command
[256], // Command string
1750 *commptr
; // Pointer into command
1751 int xdpi
, ydpi
, // X + Y resolution
1752 color_order
, // Color order
1753 color_space
, // Colorspace
1754 compression
, // Compression mode
1755 depth
, // Bits per color
1756 row_count
, // Row count
1757 row_feed
, // Row feed
1758 row_step
; // Row step/interval
1761 // Read the resolution parameters:
1763 // Resolution colorspace bits row-count row-feed row-step name/text
1764 if (!get_token(fp
, temp
, sizeof(temp
)))
1766 _cupsLangPrintf(stderr
,
1767 _("ppdc: Expected override field after Resolution on line "
1768 "%d of %s!\n"), fp
->line
, fp
->filename
);
1772 color_order
= get_color_order(temp
);
1773 color_space
= get_color_space(temp
);
1774 compression
= get_integer(temp
);
1776 depth
= get_integer(fp
);
1777 row_count
= get_integer(fp
);
1778 row_feed
= get_integer(fp
);
1779 row_step
= get_integer(fp
);
1781 if (!get_token(fp
, name
, sizeof(name
)))
1783 _cupsLangPrintf(stderr
,
1784 _("ppdc: Expected name/text after Resolution on line %d of "
1785 "%s!\n"), fp
->line
, fp
->filename
);
1789 if ((text
= strchr(name
, '/')) != NULL
)
1794 switch (sscanf(name
, "%dx%d", &xdpi
, &ydpi
))
1797 _cupsLangPrintf(stderr
,
1798 _("ppdc: Bad resolution name \"%s\" on line %d of "
1799 "%s!\n"), name
, fp
->line
, fp
->filename
);
1806 // Create the necessary PS commands...
1807 snprintf(command
, sizeof(command
),
1808 "<</HWResolution[%d %d]/cupsBitsPerColor %d/cupsRowCount %d"
1809 "/cupsRowFeed %d/cupsRowStep %d",
1810 xdpi
, ydpi
, depth
, row_count
, row_feed
, row_step
);
1811 commptr
= command
+ strlen(command
);
1813 if (color_order
>= 0)
1815 snprintf(commptr
, sizeof(command
) - (commptr
- command
),
1816 "/cupsColorOrder %d", color_order
);
1817 commptr
+= strlen(commptr
);
1820 if (color_space
>= 0)
1822 snprintf(commptr
, sizeof(command
) - (commptr
- command
),
1823 "/cupsColorSpace %d", color_space
);
1824 commptr
+= strlen(commptr
);
1827 if (compression
>= 0)
1829 snprintf(commptr
, sizeof(command
) - (commptr
- command
),
1830 "/cupsCompression %d", compression
);
1831 commptr
+= strlen(commptr
);
1834 snprintf(commptr
, sizeof(command
) - (commptr
- command
), ">>setpagedevice");
1836 // Return the new choice...
1837 return (new ppdcChoice(name
, text
, command
));
1842 // 'ppdcSource::get_simple_profile()' - Get a simple color profile definition.
1845 ppdcProfile
* // O - Color profile
1846 ppdcSource::get_simple_profile(ppdcFile
*fp
)
1849 char resolution
[1024], // Resolution/media type
1850 *media_type
; // Media type
1851 float m
[9]; // Transform matrix
1852 float kd
, rd
, g
; // Densities and gamma
1853 float red
, green
, blue
; // RGB adjustments
1854 float yellow
; // Yellow density
1855 float color
; // Color density values
1858 // Get the SimpleColorProfile parameters:
1860 // SimpleColorProfile resolution/mediatype black-density yellow-density
1861 // red-density gamma red-adjust green-adjust blue-adjust
1862 if (!get_token(fp
, resolution
, sizeof(resolution
)))
1864 _cupsLangPrintf(stderr
,
1865 _("ppdc: Expected resolution/mediatype following "
1866 "SimpleColorProfile on line %d of %s!\n"),
1867 fp
->line
, fp
->filename
);
1871 if ((media_type
= strchr(resolution
, '/')) != NULL
)
1872 *media_type
++ = '\0';
1874 media_type
= resolution
;
1876 // Collect the profile parameters...
1878 yellow
= get_float(fp
);
1881 red
= get_float(fp
);
1882 green
= get_float(fp
);
1883 blue
= get_float(fp
);
1885 // Build the color profile...
1886 color
= 0.5f
* rd
/ kd
- kd
;
1888 m
[1] = color
+ blue
; // C + M (blue)
1889 m
[2] = color
- green
; // C + Y (green)
1890 m
[3] = color
- blue
; // M + C (blue)
1892 m
[5] = color
+ red
; // M + Y (red)
1893 m
[6] = yellow
* (color
+ green
); // Y + C (green)
1894 m
[7] = yellow
* (color
- red
); // Y + M (red)
1902 else if (m
[3] > 0.0f
)
1913 else if (m
[6] > 0.0f
)
1924 else if (m
[7] > 0.0f
)
1930 // Return the new profile...
1931 return (new ppdcProfile(resolution
, media_type
, g
, kd
, m
));
1936 // 'ppdcSource::get_size()' - Get a media size definition from a file.
1939 ppdcMediaSize
* // O - Media size
1940 ppdcSource::get_size(ppdcFile
*fp
) // I - File to read
1942 char name
[1024], // Name
1944 float width
, // Width
1948 // Get the name, text, width, and length:
1950 // #media name/text width length
1951 if (!get_token(fp
, name
, sizeof(name
)))
1954 if ((text
= strchr(name
, '/')) != NULL
)
1959 if ((width
= get_measurement(fp
)) < 0.0f
)
1962 if ((length
= get_measurement(fp
)) < 0.0f
)
1965 // Return the new media size...
1966 return (new ppdcMediaSize(name
, text
, width
, length
, 0.0f
, 0.0f
, 0.0f
, 0.0f
));
1971 // 'ppdcSource::get_token()' - Get a token from a file.
1974 char * // O - Token string or NULL
1975 ppdcSource::get_token(ppdcFile
*fp
, // I - File to read
1976 char *buffer
, // I - Buffer
1977 int buflen
) // I - Length of buffer
1979 char *bufptr
, // Pointer into string buffer
1980 *bufend
; // End of string buffer
1981 int ch
, // Character from file
1982 nextch
, // Next char in file
1983 quote
, // Quote character used...
1984 empty
, // Empty input?
1985 startline
; // Start line for quote
1986 char name
[256], // Name string
1987 *nameptr
; // Name pointer
1988 ppdcVariable
*var
; // Variable pointer
1991 // Mark the beginning and end of the buffer...
1993 bufend
= buffer
+ buflen
- 1;
1995 // Loop intil we've read a token...
2000 while ((ch
= fp
->get()) != EOF
)
2002 if (isspace(ch
) && !quote
)
2011 // Variable substitution
2014 for (nameptr
= name
; (ch
= fp
->peek()) != EOF
;)
2016 if (!isalnum(ch
) && ch
!= '_')
2018 else if (nameptr
< (name
+ sizeof(name
) - 1))
2019 *nameptr
++ = fp
->get();
2022 if (nameptr
== name
)
2024 // Just substitute this character...
2028 if (bufptr
< bufend
)
2029 *bufptr
++ = fp
->get();
2034 _cupsLangPrintf(stderr
,
2035 _("ppdc: Bad variable substitution ($%c) on line %d "
2036 "of %s.\n"), ch
, fp
->line
, fp
->filename
);
2038 if (bufptr
< bufend
)
2044 // Substitute the variable value...
2046 var
= find_variable(name
);
2049 strncpy(bufptr
, var
->value
->value
, bufend
- bufptr
);
2050 bufptr
+= strlen(var
->value
->value
);
2054 if (!(cond_state
& PPDC_COND_SKIP
))
2055 _cupsLangPrintf(stderr
,
2056 _("ppdc: Undefined variable (%s) on line %d of "
2057 "%s.\n"), name
, fp
->line
, fp
->filename
);
2059 snprintf(bufptr
, bufend
- bufptr
+ 1, "$%s", name
);
2060 bufptr
+= strlen(name
) + 1;
2064 else if (ch
== '/' && !quote
)
2066 // Possibly a comment...
2067 nextch
= fp
->peek();
2074 while ((nextch
= fp
->get()) != EOF
)
2076 if (ch
== '*' && nextch
== '/')
2085 else if (nextch
== '/')
2088 while ((nextch
= fp
->get()) != EOF
)
2100 if (bufptr
< bufend
)
2104 else if (ch
== '\'' || ch
== '\"')
2110 // Ending the current quoted string...
2115 // Insert the opposing quote char...
2116 if (bufptr
< bufend
)
2121 // Start a new quoted string...
2122 startline
= fp
->line
;
2126 else if ((ch
== '(' || ch
== '<') && !quote
)
2130 startline
= fp
->line
;
2132 if (bufptr
< bufend
)
2135 else if ((ch
== ')' && quote
== '(') || (ch
== '>' && quote
== '<'))
2139 if (bufptr
< bufend
)
2142 else if (ch
== '\\')
2146 if ((ch
= fp
->get()) == EOF
)
2149 if (bufptr
< bufend
)
2152 else if (bufptr
< bufend
)
2158 if ((ch
== '{' || ch
== '}') && !quote
)
2165 _cupsLangPrintf(stderr
,
2166 _("ppdc: Unterminated string starting with %c on line %d "
2167 "of %s!\n"), quote
, startline
, fp
->filename
);
2183 // 'ppdcSource::get_variable()' - Get a variable definition.
2186 ppdcVariable
* // O - Variable
2187 ppdcSource::get_variable(ppdcFile
*fp
) // I - File to read
2189 char name
[1024], // Name
2190 value
[1024]; // Value
2193 // Get the name and value:
2195 // #define name value
2196 if (!get_token(fp
, name
, sizeof(name
)))
2199 if (!get_token(fp
, value
, sizeof(value
)))
2202 // Set the variable...
2203 return (set_variable(name
, value
));
2208 // 'ppdcSource::quotef()' - Write a formatted, quoted string...
2211 int // O - Number bytes on success, -1 on failure
2212 ppdcSource::quotef(cups_file_t
*fp
, // I - File to write to
2213 const char *format
, // I - Printf-style format string
2214 ...) // I - Additional args as needed
2216 va_list ap
; // Pointer to additional arguments
2217 int bytes
; // Bytes written
2218 char sign
, // Sign of format width
2219 size
, // Size character (h, l, L)
2220 type
; // Format type character
2221 const char *bufformat
; // Start of format
2222 int width
, // Width of field
2223 prec
; // Number of characters of precision
2224 char tformat
[100]; // Temporary format string for fprintf()
2225 char *s
; // Pointer to string
2226 int slen
; // Length of string
2227 int i
; // Looping var
2230 // Range check input...
2234 // Loop through the format string, formatting as needed...
2235 va_start(ap
, format
);
2248 cupsFilePutChar(fp
, *format
++);
2252 else if (strchr(" -+#\'", *format
))
2258 while (isdigit(*format
))
2259 width
= width
* 10 + *format
++ - '0';
2266 while (isdigit(*format
))
2267 prec
= prec
* 10 + *format
++ - '0';
2272 if (*format
== 'l' && format
[1] == 'l')
2277 else if (*format
== 'h' || *format
== 'l' || *format
== 'L')
2287 case 'E' : // Floating point formats
2292 if ((format
- bufformat
+ 1) > (int)sizeof(tformat
))
2295 strncpy(tformat
, bufformat
, format
- bufformat
);
2296 tformat
[format
- bufformat
] = '\0';
2298 bytes
+= cupsFilePrintf(fp
, tformat
, va_arg(ap
, double));
2301 case 'B' : // Integer formats
2309 if ((format
- bufformat
+ 1) > (int)sizeof(tformat
))
2312 strncpy(tformat
, bufformat
, format
- bufformat
);
2313 tformat
[format
- bufformat
] = '\0';
2315 bytes
+= cupsFilePrintf(fp
, tformat
, va_arg(ap
, int));
2318 case 'p' : // Pointer value
2319 if ((format
- bufformat
+ 1) > (int)sizeof(tformat
))
2322 strncpy(tformat
, bufformat
, format
- bufformat
);
2323 tformat
[format
- bufformat
] = '\0';
2325 bytes
+= cupsFilePrintf(fp
, tformat
, va_arg(ap
, void *));
2328 case 'c' : // Character or character array
2332 cupsFilePutChar(fp
, va_arg(ap
, int));
2336 cupsFileWrite(fp
, va_arg(ap
, char *), width
);
2341 case 's' : // String
2342 if ((s
= va_arg(ap
, char *)) == NULL
)
2343 s
= (char *)"(nil)";
2346 if (slen
> width
&& prec
!= width
)
2354 for (i
= width
- slen
; i
> 0; i
--, bytes
++)
2355 cupsFilePutChar(fp
, ' ');
2358 for (i
= slen
; i
> 0; i
--, s
++, bytes
++)
2360 if (*s
== '\\' || *s
== '\"')
2362 cupsFilePutChar(fp
, '\\');
2366 cupsFilePutChar(fp
, *s
);
2371 for (i
= width
- slen
; i
> 0; i
--, bytes
++)
2372 cupsFilePutChar(fp
, ' ');
2379 cupsFilePutChar(fp
, *format
++);
2386 // Return the number of characters written.
2392 // 'ppdcSource::read_file()' - Read a driver source file.
2396 ppdcSource::read_file(const char *f
, // I - File to read
2397 cups_file_t
*ffp
) // I - File pointer to use
2399 ppdcFile
*fp
= new ppdcFile(f
, ffp
);
2403 if (cond_current
!= cond_stack
)
2404 _cupsLangPrintf(stderr
, _("ppdc: Missing #endif at end of \"%s\"!\n"), f
);
2409 // 'ppdcSource::scan_file()' - Scan a driver source file.
2413 ppdcSource::scan_file(ppdcFile
*fp
, // I - File to read
2414 ppdcDriver
*td
, // I - Driver template
2415 bool inc
) // I - Including?
2417 ppdcDriver
*d
; // Current driver
2418 ppdcGroup
*g
, // Current group
2419 *mg
, // Matching group
2420 *general
, // General options group
2421 *install
; // Installable options group
2422 ppdcOption
*o
; // Current option
2423 ppdcChoice
*c
; // Current choice
2424 char temp
[256], // Token from file...
2425 *ptr
; // Pointer into token
2426 int isdefault
; // Default option?
2429 // Initialize things as needed...
2436 d
= new ppdcDriver(td
);
2438 if ((general
= d
->find_group("General")) == NULL
)
2440 general
= new ppdcGroup("General", NULL
);
2441 d
->add_group(general
);
2444 if ((install
= d
->find_group("InstallableOptions")) == NULL
)
2446 install
= new ppdcGroup("InstallableOptions", "Installable Options");
2447 d
->add_group(install
);
2450 // Loop until EOF or }
2454 while (get_token(fp
, temp
, sizeof(temp
)))
2458 // Mark the next choice as the default
2461 for (ptr
= temp
; ptr
[1]; ptr
++)
2468 // Don't mark the next choice as the default
2472 if (!strcasecmp(temp
, "}"))
2474 // Close this one out...
2477 else if (!strcasecmp(temp
, "{"))
2479 // Open a new child...
2482 else if (!strcasecmp(temp
, "#if"))
2484 if ((cond_current
- cond_stack
) >= 100)
2486 _cupsLangPrintf(stderr
,
2487 _("ppdc: Too many nested #if's on line %d of %s!\n"),
2488 fp
->line
, fp
->filename
);
2493 if (get_integer(fp
) > 0)
2494 *cond_current
= PPDC_COND_SATISFIED
;
2497 *cond_current
= PPDC_COND_SKIP
;
2498 cond_state
|= PPDC_COND_SKIP
;
2501 else if (!strcasecmp(temp
, "#elif"))
2503 if (cond_current
== cond_stack
)
2505 _cupsLangPrintf(stderr
, _("ppdc: Missing #if on line %d of %s!\n"),
2506 fp
->line
, fp
->filename
);
2510 if (*cond_current
& PPDC_COND_SATISFIED
)
2513 *cond_current
|= PPDC_COND_SKIP
;
2515 else if (get_integer(fp
) > 0)
2517 *cond_current
|= PPDC_COND_SATISFIED
;
2518 *cond_current
&= ~PPDC_COND_SKIP
;
2521 *cond_current
|= PPDC_COND_SKIP
;
2523 // Update the current state
2524 int *cond_temp
= cond_current
; // Temporary stack pointer
2526 cond_state
= PPDC_COND_NORMAL
;
2527 while (cond_temp
> cond_stack
)
2528 if (*cond_temp
& PPDC_COND_SKIP
)
2530 cond_state
= PPDC_COND_SKIP
;
2536 else if (!strcasecmp(temp
, "#else"))
2538 if (cond_current
== cond_stack
)
2540 _cupsLangPrintf(stderr
, _("ppdc: Missing #if on line %d of %s!\n"),
2541 fp
->line
, fp
->filename
);
2545 if (*cond_current
& PPDC_COND_SATISFIED
)
2546 *cond_current
|= PPDC_COND_SKIP
;
2549 *cond_current
|= PPDC_COND_SATISFIED
;
2550 *cond_current
&= ~PPDC_COND_SKIP
;
2553 // Update the current state
2554 int *cond_temp
= cond_current
; // Temporary stack pointer
2556 cond_state
= PPDC_COND_NORMAL
;
2557 while (cond_temp
> cond_stack
)
2558 if (*cond_temp
& PPDC_COND_SKIP
)
2560 cond_state
= PPDC_COND_SKIP
;
2566 else if (!strcasecmp(temp
, "#endif"))
2568 if (cond_current
== cond_stack
)
2570 _cupsLangPrintf(stderr
, _("ppdc: Missing #if on line %d of %s!\n"),
2571 fp
->line
, fp
->filename
);
2577 // Update the current state
2578 int *cond_temp
= cond_current
; // Temporary stack pointer
2580 cond_state
= PPDC_COND_NORMAL
;
2581 while (cond_temp
> cond_stack
)
2582 if (*cond_temp
& PPDC_COND_SKIP
)
2584 cond_state
= PPDC_COND_SKIP
;
2590 else if (!strcasecmp(temp
, "#define"))
2592 // Get the variable...
2595 else if (!strcasecmp(temp
, "#include"))
2597 // #include filename
2598 char basedir
[1024], // Base directory
2599 *baseptr
, // Pointer into directory
2600 inctemp
[1024], // Initial filename
2601 incname
[1024]; // Include filename
2602 ppdcFile
*incfile
; // Include file
2603 int *old_current
= cond_current
;
2604 // Previous current stack
2607 // Get the include name...
2608 if (!get_token(fp
, inctemp
, sizeof(inctemp
)))
2610 _cupsLangPrintf(stderr
,
2611 _("ppdc: Expected include filename on line %d of "
2612 "%s!\n"), fp
->line
, fp
->filename
);
2619 // Figure out the current directory...
2620 strlcpy(basedir
, fp
->filename
, sizeof(basedir
));
2622 if ((baseptr
= strrchr(basedir
, '/')) != NULL
)
2625 strcpy(basedir
, ".");
2627 // Find the include file...
2628 if (find_include(inctemp
, basedir
, incname
, sizeof(incname
)))
2630 // Open the include file, scan it, and then close it...
2631 incfile
= new ppdcFile(incname
);
2632 scan_file(incfile
, d
, true);
2635 if (cond_current
!= old_current
)
2636 _cupsLangPrintf(stderr
, _("ppdc: Missing #endif at end of \"%s\"!\n"),
2642 _cupsLangPrintf(stderr
,
2643 _("ppdc: Unable to find include file \"%s\" on line %d "
2644 "of %s!\n"), inctemp
, fp
->line
, fp
->filename
);
2648 else if (!strcasecmp(temp
, "#media"))
2650 ppdcMediaSize
*m
; // Media size
2653 // Get a media size...
2663 else if (!strcasecmp(temp
, "#po"))
2665 ppdcCatalog
*cat
; // Message catalog
2668 // Get a message catalog...
2678 else if (!strcasecmp(temp
, "Attribute") ||
2679 !strcasecmp(temp
, "LocAttribute"))
2681 ppdcAttr
*a
; // Attribute
2684 // Get an attribute...
2685 a
= get_attr(fp
, !strcasecmp(temp
, "LocAttribute"));
2694 else if (!strcasecmp(temp
, "Choice"))
2707 // Add it to the current option...
2710 _cupsLangPrintf(stderr
,
2711 _("ppdc: Choice found on line %d of %s with no "
2712 "Option!\n"), fp
->line
, fp
->filename
);
2719 o
->set_defchoice(c
);
2721 else if (!strcasecmp(temp
, "ColorDevice"))
2723 // ColorDevice boolean
2727 d
->color_device
= get_boolean(fp
);
2729 else if (!strcasecmp(temp
, "ColorModel"))
2731 // Get the color model
2732 c
= get_color_model(fp
);
2742 // Add the choice to the ColorModel option...
2743 if ((o
= d
->find_option("ColorModel")) == NULL
)
2745 // Create the ColorModel option...
2746 o
= new ppdcOption(PPDC_PICKONE
, "ColorModel", "Color Mode", PPDC_SECTION_ANY
, 10.0f
);
2754 o
->set_defchoice(c
);
2758 else if (!strcasecmp(temp
, "ColorProfile"))
2760 ppdcProfile
*p
; // Color profile
2763 // Get the color profile...
2764 p
= get_color_profile(fp
);
2771 d
->profiles
->add(p
);
2774 else if (!strcasecmp(temp
, "Copyright"))
2777 char copytemp
[8192], // Copyright string
2778 *copyptr
, // Pointer into string
2779 *copyend
; // Pointer to end of string
2782 // Get the copyright string...
2783 if (!get_token(fp
, copytemp
, sizeof(temp
)))
2785 _cupsLangPrintf(stderr
,
2786 _("ppdc: Expected string after Copyright on line %d "
2787 "of %s!\n"), fp
->line
, fp
->filename
);
2794 // Break it up into individual lines...
2795 for (copyptr
= copytemp
; copyptr
; copyptr
= copyend
)
2797 if ((copyend
= strchr(copyptr
, '\n')) != NULL
)
2800 d
->copyright
->add(new ppdcString(copyptr
));
2803 else if (!strcasecmp(temp
, "CustomMedia"))
2805 ppdcMediaSize
*m
; // Media size
2808 // Get a custom media size...
2809 m
= get_custom_size(fp
);
2821 d
->set_default_size(m
);
2823 else if (!strcasecmp(temp
, "Cutter"))
2826 int have_cutter
; // Have a paper cutter?
2829 have_cutter
= get_boolean(fp
);
2830 if (have_cutter
<= 0 || cond_state
)
2833 if ((o
= d
->find_option("CutMedia")) == NULL
)
2835 o
= new ppdcOption(PPDC_BOOLEAN
, "CutMedia", "Cut Media", PPDC_SECTION_ANY
, 10.0f
);
2840 c
= new ppdcChoice("False", NULL
, "<</CutMedia 0>>setpagedevice");
2842 o
->set_defchoice(c
);
2844 c
= new ppdcChoice("True", NULL
, "<</CutMedia 4>>setpagedevice");
2850 else if (!strcasecmp(temp
, "Darkness"))
2852 // Get the darkness choice...
2853 c
= get_generic(fp
, "Darkness", NULL
, "cupsCompression");
2863 // Add the choice to the cupsDarkness option...
2864 if ((o
= d
->find_option_group("cupsDarkness", &mg
)) == NULL
)
2866 // Create the cupsDarkness option...
2867 o
= new ppdcOption(PPDC_PICKONE
, "cupsDarkness", "Darkness", PPDC_SECTION_ANY
, 10.0f
);
2871 else if (mg
!= general
)
2873 _cupsLangPrintf(stderr
,
2874 _("ppdc: Option %s defined in two different groups on "
2875 "line %d of %s!\n"), "cupsDarkness", fp
->line
,
2884 o
->set_defchoice(c
);
2888 else if (!strcasecmp(temp
, "DriverType"))
2890 int i
; // Looping var
2893 // DriverType keyword
2894 if (!get_token(fp
, temp
, sizeof(temp
)))
2896 _cupsLangPrintf(stderr
,
2897 _("ppdc: Expected driver type keyword following "
2898 "DriverType on line %d of %s!\n"),
2899 fp
->line
, fp
->filename
);
2906 for (i
= 0; i
< (int)(sizeof(driver_types
) / sizeof(driver_types
[0])); i
++)
2907 if (!strcasecmp(temp
, driver_types
[i
]))
2910 if (i
< (int)(sizeof(driver_types
) / sizeof(driver_types
[0])))
2911 d
->type
= (ppdcDrvType
)i
;
2912 else if (!strcasecmp(temp
, "dymo"))
2913 d
->type
= PPDC_DRIVER_LABEL
;
2915 _cupsLangPrintf(stderr
,
2916 _("ppdc: Unknown driver type %s on line %d of %s!\n"),
2917 temp
, fp
->line
, fp
->filename
);
2919 else if (!strcasecmp(temp
, "Duplex"))
2921 else if (!strcasecmp(temp
, "Filter"))
2923 ppdcFilter
*f
; // Filter
2926 // Get the filter value...
2936 else if (!strcasecmp(temp
, "Finishing"))
2938 // Get the finishing choice...
2939 c
= get_generic(fp
, "Finishing", "OutputType", NULL
);
2949 // Add the choice to the cupsFinishing option...
2950 if ((o
= d
->find_option_group("cupsFinishing", &mg
)) == NULL
)
2952 // Create the cupsFinishing option...
2953 o
= new ppdcOption(PPDC_PICKONE
, "cupsFinishing", "Finishing", PPDC_SECTION_ANY
, 10.0f
);
2957 else if (mg
!= general
)
2959 _cupsLangPrintf(stderr
,
2960 _("ppdc: Option %s defined in two different groups on "
2961 "line %d of %s!\n"), "cupsFinishing", fp
->line
,
2970 o
->set_defchoice(c
);
2974 else if (!strcasecmp(temp
, "Font") ||
2975 !strcasecmp(temp
, "#font"))
2977 ppdcFont
*f
; // Font
2988 if (!strcasecmp(temp
, "#font"))
2994 d
->set_default_font(f
);
2998 else if (!strcasecmp(temp
, "Group"))
3001 ppdcGroup
*tempg
= get_group(fp
, d
);
3008 if (!d
->find_group(tempg
->name
->value
))
3013 if (!d
->find_group(tempg
->name
->value
))
3014 d
->add_group(tempg
);
3019 else if (!strcasecmp(temp
, "HWMargins"))
3021 // HWMargins left bottom right top
3022 d
->left_margin
= get_measurement(fp
);
3023 d
->bottom_margin
= get_measurement(fp
);
3024 d
->right_margin
= get_measurement(fp
);
3025 d
->top_margin
= get_measurement(fp
);
3027 else if (!strcasecmp(temp
, "InputSlot"))
3029 // Get the input slot choice...
3030 c
= get_generic(fp
, "InputSlot", NULL
, "MediaPosition");
3040 // Add the choice to the InputSlot option...
3042 if ((o
= d
->find_option_group("InputSlot", &mg
)) == NULL
)
3044 // Create the InputSlot option...
3045 o
= new ppdcOption(PPDC_PICKONE
, "InputSlot", "Media Source",
3046 PPDC_SECTION_ANY
, 10.0f
);
3050 else if (mg
!= general
)
3052 _cupsLangPrintf(stderr
,
3053 _("ppdc: Option %s defined in two different groups on "
3054 "line %d of %s!\n"), "InputSlot", fp
->line
,
3063 o
->set_defchoice(c
);
3067 else if (!strcasecmp(temp
, "Installable"))
3069 // Get the installable option...
3070 o
= get_installable(fp
);
3072 // Add it as needed...
3078 install
->add_option(o
);
3083 else if (!strcasecmp(temp
, "ManualCopies"))
3085 // ManualCopies boolean
3089 d
->manual_copies
= get_boolean(fp
);
3091 else if (!strcasecmp(temp
, "Manufacturer"))
3093 // Manufacturer name
3094 char name
[256]; // Model name string
3097 if (!get_token(fp
, name
, sizeof(name
)))
3099 _cupsLangPrintf(stderr
,
3100 _("ppdc: Expected name after Manufacturer on line %d "
3101 "of %s!\n"), fp
->line
, fp
->filename
);
3106 d
->set_manufacturer(name
);
3108 else if (!strcasecmp(temp
, "MaxSize"))
3110 // MaxSize width length
3113 get_measurement(fp
);
3114 get_measurement(fp
);
3118 d
->max_width
= get_measurement(fp
);
3119 d
->max_length
= get_measurement(fp
);
3122 else if (!strcasecmp(temp
, "MediaSize"))
3124 // MediaSize keyword
3125 char name
[41]; // Media size name
3126 ppdcMediaSize
*m
, // Matching media size...
3127 *dm
; // Driver media size...
3130 if (get_token(fp
, name
, sizeof(name
)) == NULL
)
3132 _cupsLangPrintf(stderr
,
3133 _("ppdc: Expected name after MediaSize on line %d of "
3134 "%s!\n"), fp
->line
, fp
->filename
);
3141 m
= find_size(name
);
3145 _cupsLangPrintf(stderr
,
3146 _("ppdc: Unknown media size \"%s\" on line %d of "
3147 "%s!\n"), name
, fp
->line
, fp
->filename
);
3151 // Add this size to the driver...
3152 dm
= new ppdcMediaSize(m
->name
->value
, m
->text
->value
,
3153 m
->width
, m
->length
, d
->left_margin
,
3154 d
->bottom_margin
, d
->right_margin
,
3159 d
->set_default_size(dm
);
3161 else if (!strcasecmp(temp
, "MediaType"))
3163 // Get the media type choice...
3164 c
= get_generic(fp
, "MediaType", "MediaType", "cupsMediaType");
3174 // Add the choice to the MediaType option...
3175 if ((o
= d
->find_option_group("MediaType", &mg
)) == NULL
)
3177 // Create the MediaType option...
3178 o
= new ppdcOption(PPDC_PICKONE
, "MediaType", "Media Type",
3179 PPDC_SECTION_ANY
, 10.0f
);
3183 else if (mg
!= general
)
3185 _cupsLangPrintf(stderr
,
3186 _("ppdc: Option %s defined in two different groups on "
3187 "line %d of %s!\n"), "MediaType", fp
->line
,
3196 o
->set_defchoice(c
);
3200 else if (!strcasecmp(temp
, "MinSize"))
3202 // MinSize width length
3205 get_measurement(fp
);
3206 get_measurement(fp
);
3210 d
->min_width
= get_measurement(fp
);
3211 d
->min_length
= get_measurement(fp
);
3214 else if (!strcasecmp(temp
, "ModelName"))
3217 char name
[256]; // Model name string
3220 if (!get_token(fp
, name
, sizeof(name
)))
3222 _cupsLangPrintf(stderr
,
3223 _("ppdc: Expected name after ModelName on line %d of "
3224 "%s!\n"), fp
->line
, fp
->filename
);
3229 d
->set_model_name(name
);
3231 else if (!strcasecmp(temp
, "ModelNumber"))
3233 // ModelNumber number
3237 d
->model_number
= get_integer(fp
);
3239 else if (!strcasecmp(temp
, "Option"))
3242 ppdcOption
*tempo
= get_option(fp
, d
, g
);
3249 if (!g
->find_option(tempo
->name
->value
))
3254 if (!g
->find_option(tempo
->name
->value
))
3255 g
->add_option(tempo
);
3260 else if (!strcasecmp(temp
, "FileName"))
3263 char name
[256]; // Filename string
3266 if (!get_token(fp
, name
, sizeof(name
)))
3268 _cupsLangPrintf(stderr
,
3269 _("ppdc: Expected name after FileName on line %d of "
3270 "%s!\n"), fp
->line
, fp
->filename
);
3275 d
->set_file_name(name
);
3277 else if (!strcasecmp(temp
, "PCFileName"))
3280 char name
[256]; // PC filename string
3283 if (!get_token(fp
, name
, sizeof(name
)))
3285 _cupsLangPrintf(stderr
,
3286 _("ppdc: Expected name after PCFileName on line %d of "
3287 "%s!\n"), fp
->line
, fp
->filename
);
3292 d
->set_pc_file_name(name
);
3294 else if (!strcasecmp(temp
, "Resolution"))
3296 // Get the resolution choice...
3297 c
= get_resolution(fp
);
3307 // Add the choice to the Resolution option...
3308 if ((o
= d
->find_option_group("Resolution", &mg
)) == NULL
)
3310 // Create the Resolution option...
3311 o
= new ppdcOption(PPDC_PICKONE
, "Resolution", NULL
, PPDC_SECTION_ANY
,
3316 else if (mg
!= general
)
3318 _cupsLangPrintf(stderr
,
3319 _("ppdc: Option %s defined in two different groups on "
3320 "line %d of %s!\n"), "Resolution", fp
->line
,
3329 o
->set_defchoice(c
);
3333 else if (!strcasecmp(temp
, "SimpleColorProfile"))
3335 ppdcProfile
*p
; // Color profile
3338 // Get the color profile...
3339 p
= get_simple_profile(fp
);
3346 d
->profiles
->add(p
);
3349 else if (!strcasecmp(temp
, "Throughput"))
3351 // Throughput number
3355 d
->throughput
= get_integer(fp
);
3357 else if (!strcasecmp(temp
, "UIConstraints"))
3359 ppdcConstraint
*con
; // Constraint
3362 con
= get_constraint(fp
);
3369 d
->constraints
->add(con
);
3372 else if (!strcasecmp(temp
, "VariablePaperSize"))
3374 // VariablePaperSize boolean
3378 d
->variable_paper_size
= get_boolean(fp
);
3380 else if (!strcasecmp(temp
, "Version"))
3383 char name
[256]; // Model name string
3386 if (!get_token(fp
, name
, sizeof(name
)))
3388 _cupsLangPrintf(stderr
,
3389 _("ppdc: Expected string after Version on line %d of "
3390 "%s!\n"), fp
->line
, fp
->filename
);
3395 d
->set_version(name
);
3399 _cupsLangPrintf(stderr
,
3400 _("ppdc: Unknown token \"%s\" seen on line %d of %s!\n"),
3401 temp
, fp
->line
, fp
->filename
);
3406 // Done processing this block, is there anything to save?
3409 if (!d
->pc_file_name
|| !d
->model_name
|| !d
->manufacturer
|| !d
->version
||
3412 // Nothing to save...
3417 // Got a driver, save it...
3427 // 'ppdcSource::set_variable()' - Set a variable.
3430 ppdcVariable
* // O - Variable
3431 ppdcSource::set_variable(
3432 const char *name
, // I - Name
3433 const char *value
) // I - Value
3435 ppdcVariable
*v
; // Variable
3438 // See if the variable exists already...
3439 v
= find_variable(name
);
3442 // Change the variable value...
3443 v
->set_value(value
);
3447 // Create a new variable and add it...
3448 v
= new ppdcVariable(name
, value
);
3457 // 'ppdcSource::write_file()' - Write the current source data to a file.
3460 int // O - 0 on success, -1 on error
3461 ppdcSource::write_file(const char *f
) // I - File to write
3463 cups_file_t
*fp
; // Output file
3464 char bckname
[1024]; // Backup file
3465 ppdcDriver
*d
; // Current driver
3466 ppdcString
*st
; // Current string
3467 ppdcAttr
*a
; // Current attribute
3468 ppdcConstraint
*co
; // Current constraint
3469 ppdcFilter
*fi
; // Current filter
3470 ppdcFont
*fo
; // Current font
3471 ppdcGroup
*g
; // Current group
3472 ppdcOption
*o
; // Current option
3473 ppdcChoice
*ch
; // Current choice
3474 ppdcProfile
*p
; // Current color profile
3475 ppdcMediaSize
*si
; // Current media size
3476 float left
, // Current left margin
3477 bottom
, // Current bottom margin
3478 right
, // Current right margin
3479 top
; // Current top margin
3480 int dtused
[PPDC_DRIVER_MAX
];// Driver type usage...
3483 // Rename the current file, if any, to .bck...
3484 snprintf(bckname
, sizeof(bckname
), "%s.bck", f
);
3487 // Open the output file...
3488 fp
= cupsFileOpen(f
, "w");
3492 // Can't create file; restore backup and return...
3497 cupsFilePuts(fp
, "// CUPS PPD Compiler " CUPS_SVERSION
"\n\n");
3499 // Include standard files...
3500 cupsFilePuts(fp
, "// Include necessary files...\n");
3501 cupsFilePuts(fp
, "#include <font.defs>\n");
3502 cupsFilePuts(fp
, "#include <media.defs>\n");
3504 memset(dtused
, 0, sizeof(dtused
));
3506 for (d
= (ppdcDriver
*)drivers
->first(); d
; d
= (ppdcDriver
*)drivers
->next())
3507 if (d
->type
> PPDC_DRIVER_PS
&& !dtused
[d
->type
])
3509 cupsFilePrintf(fp
, "#include <%s.h>\n", driver_types
[d
->type
]);
3510 dtused
[d
->type
] = 1;
3513 // Output each driver...
3514 for (d
= (ppdcDriver
*)drivers
->first(); d
; d
= (ppdcDriver
*)drivers
->next())
3516 // Start the driver...
3517 cupsFilePrintf(fp
, "\n// %s %s\n", d
->manufacturer
->value
, d
->model_name
->value
);
3518 cupsFilePuts(fp
, "{\n");
3520 // Write the copyright stings...
3521 for (st
= (ppdcString
*)d
->copyright
->first();
3523 st
= (ppdcString
*)d
->copyright
->next())
3524 quotef(fp
, " Copyright \"%s\"\n", st
->value
);
3526 // Write other strings and values...
3527 if (d
->manufacturer
&& d
->manufacturer
->value
)
3528 quotef(fp
, " Manufacturer \"%s\"\n", d
->manufacturer
->value
);
3529 if (d
->model_name
->value
)
3530 quotef(fp
, " ModelName \"%s\"\n", d
->model_name
->value
);
3531 if (d
->file_name
&& d
->file_name
->value
)
3532 quotef(fp
, " FileName \"%s\"\n", d
->file_name
->value
);
3533 if (d
->pc_file_name
&& d
->pc_file_name
->value
)
3534 quotef(fp
, " PCFileName \"%s\"\n", d
->pc_file_name
->value
);
3535 if (d
->version
&& d
->version
->value
)
3536 quotef(fp
, " Version \"%s\"\n", d
->version
->value
);
3538 cupsFilePrintf(fp
, " DriverType %s\n", driver_types
[d
->type
]);
3540 if (d
->model_number
)
3544 case PPDC_DRIVER_ESCP
:
3545 cupsFilePuts(fp
, " ModelNumber (");
3547 if (d
->model_number
& ESCP_DOTMATRIX
)
3548 cupsFilePuts(fp
, " $ESCP_DOTMATRIX");
3549 if (d
->model_number
& ESCP_MICROWEAVE
)
3550 cupsFilePuts(fp
, " $ESCP_MICROWEAVE");
3551 if (d
->model_number
& ESCP_STAGGER
)
3552 cupsFilePuts(fp
, " $ESCP_STAGGER");
3553 if (d
->model_number
& ESCP_ESCK
)
3554 cupsFilePuts(fp
, " $ESCP_ESCK");
3555 if (d
->model_number
& ESCP_EXT_UNITS
)
3556 cupsFilePuts(fp
, " $ESCP_EXT_UNITS");
3557 if (d
->model_number
& ESCP_EXT_MARGINS
)
3558 cupsFilePuts(fp
, " $ESCP_EXT_MARGINS");
3559 if (d
->model_number
& ESCP_USB
)
3560 cupsFilePuts(fp
, " $ESCP_USB");
3561 if (d
->model_number
& ESCP_PAGE_SIZE
)
3562 cupsFilePuts(fp
, " $ESCP_PAGE_SIZE");
3563 if (d
->model_number
& ESCP_RASTER_ESCI
)
3564 cupsFilePuts(fp
, " $ESCP_RASTER_ESCI");
3565 if (d
->model_number
& ESCP_REMOTE
)
3566 cupsFilePuts(fp
, " $ESCP_REMOTE");
3568 cupsFilePuts(fp
, ")\n");
3571 case PPDC_DRIVER_PCL
:
3572 cupsFilePuts(fp
, " ModelNumber (");
3574 if (d
->model_number
& PCL_PAPER_SIZE
)
3575 cupsFilePuts(fp
, " $PCL_PAPER_SIZE");
3576 if (d
->model_number
& PCL_INKJET
)
3577 cupsFilePuts(fp
, " $PCL_INKJET");
3578 if (d
->model_number
& PCL_RASTER_END_COLOR
)
3579 cupsFilePuts(fp
, " $PCL_RASTER_END_COLOR");
3580 if (d
->model_number
& PCL_RASTER_CID
)
3581 cupsFilePuts(fp
, " $PCL_RASTER_CID");
3582 if (d
->model_number
& PCL_RASTER_CRD
)
3583 cupsFilePuts(fp
, " $PCL_RASTER_CRD");
3584 if (d
->model_number
& PCL_RASTER_SIMPLE
)
3585 cupsFilePuts(fp
, " $PCL_RASTER_SIMPLE");
3586 if (d
->model_number
& PCL_RASTER_RGB24
)
3587 cupsFilePuts(fp
, " $PCL_RASTER_RGB24");
3588 if (d
->model_number
& PCL_PJL
)
3589 cupsFilePuts(fp
, " $PCL_PJL");
3590 if (d
->model_number
& PCL_PJL_PAPERWIDTH
)
3591 cupsFilePuts(fp
, " $PCL_PJL_PAPERWIDTH");
3592 if (d
->model_number
& PCL_PJL_HPGL2
)
3593 cupsFilePuts(fp
, " $PCL_PJL_HPGL2");
3594 if (d
->model_number
& PCL_PJL_PCL3GUI
)
3595 cupsFilePuts(fp
, " $PCL_PJL_PCL3GUI");
3596 if (d
->model_number
& PCL_PJL_RESOLUTION
)
3597 cupsFilePuts(fp
, " $PCL_PJL_RESOLUTION");
3599 cupsFilePuts(fp
, ")\n");
3602 case PPDC_DRIVER_LABEL
:
3603 cupsFilePuts(fp
, " ModelNumber ");
3605 switch (d
->model_number
)
3608 cupsFilePuts(fp
, "$DYMO_3x0\n");
3611 case ZEBRA_EPL_LINE
:
3612 cupsFilePuts(fp
, "$ZEBRA_EPL_LINE\n");
3615 case ZEBRA_EPL_PAGE
:
3616 cupsFilePuts(fp
, "$ZEBRA_EPL_PAGE\n");
3620 cupsFilePuts(fp
, "$ZEBRA_ZPL\n");
3624 cupsFilePuts(fp
, "$ZEBRA_CPCL\n");
3627 case INTELLITECH_PCL
:
3628 cupsFilePuts(fp
, "$INTELLITECH_PCL\n");
3632 cupsFilePrintf(fp
, "%d\n", d
->model_number
);
3637 case PPDC_DRIVER_EPSON
:
3638 cupsFilePuts(fp
, " ModelNumber ");
3640 switch (d
->model_number
)
3643 cupsFilePuts(fp
, "$EPSON_9PIN\n");
3647 cupsFilePuts(fp
, "$EPSON_24PIN\n");
3651 cupsFilePuts(fp
, "$EPSON_COLOR\n");
3655 cupsFilePuts(fp
, "$EPSON_PHOTO\n");
3659 cupsFilePuts(fp
, "$EPSON_ICOLOR\n");
3663 cupsFilePuts(fp
, "$EPSON_IPHOTO\n");
3667 cupsFilePrintf(fp
, "%d\n", d
->model_number
);
3672 case PPDC_DRIVER_HP
:
3673 cupsFilePuts(fp
, " ModelNumber ");
3674 switch (d
->model_number
)
3677 cupsFilePuts(fp
, "$HP_LASERJET\n");
3681 cupsFilePuts(fp
, "$HP_DESKJET\n");
3685 cupsFilePuts(fp
, "$HP_DESKJET2\n");
3689 cupsFilePrintf(fp
, "%d\n", d
->model_number
);
3693 cupsFilePuts(fp
, ")\n");
3697 cupsFilePrintf(fp
, " ModelNumber %d\n", d
->model_number
);
3702 if (d
->manual_copies
)
3703 cupsFilePuts(fp
, " ManualCopies Yes\n");
3705 if (d
->color_device
)
3706 cupsFilePuts(fp
, " ColorDevice Yes\n");
3709 cupsFilePrintf(fp
, " Throughput %d\n", d
->throughput
);
3711 // Output all of the attributes...
3712 for (a
= (ppdcAttr
*)d
->attrs
->first();
3714 a
= (ppdcAttr
*)d
->attrs
->next())
3715 if (a
->text
->value
&& a
->text
->value
[0])
3716 quotef(fp
, " Attribute \"%s\" \"%s/%s\" \"%s\"\n",
3717 a
->name
->value
, a
->selector
->value
? a
->selector
->value
: "",
3718 a
->text
->value
, a
->value
->value
? a
->value
->value
: "");
3720 quotef(fp
, " Attribute \"%s\" \"%s\" \"%s\"\n",
3721 a
->name
->value
, a
->selector
->value
? a
->selector
->value
: "",
3722 a
->value
->value
? a
->value
->value
: "");
3724 // Output all of the constraints...
3725 for (co
= (ppdcConstraint
*)d
->constraints
->first();
3727 co
= (ppdcConstraint
*)d
->constraints
->next())
3729 if (co
->option1
->value
[0] == '*')
3730 cupsFilePrintf(fp
, " UIConstraints \"%s %s", co
->option1
->value
,
3731 co
->choice1
->value
? co
->choice1
->value
: "");
3733 cupsFilePrintf(fp
, " UIConstraints \"*%s %s", co
->option1
->value
,
3734 co
->choice1
->value
? co
->choice1
->value
: "");
3736 if (co
->option2
->value
[0] == '*')
3737 cupsFilePrintf(fp
, " %s %s\"\n", co
->option2
->value
,
3738 co
->choice2
->value
? co
->choice2
->value
: "");
3740 cupsFilePrintf(fp
, " *%s %s\"\n", co
->option2
->value
,
3741 co
->choice2
->value
? co
->choice2
->value
: "");
3744 // Output all of the filters...
3745 for (fi
= (ppdcFilter
*)d
->filters
->first();
3747 fi
= (ppdcFilter
*)d
->filters
->next())
3748 cupsFilePrintf(fp
, " Filter \"%s %d %s\"\n",
3749 fi
->mime_type
->value
, fi
->cost
, fi
->program
->value
);
3751 // Output all of the fonts...
3752 for (fo
= (ppdcFont
*)d
->fonts
->first();
3754 fo
= (ppdcFont
*)d
->fonts
->next())
3755 if (!strcmp(fo
->name
->value
, "*"))
3756 cupsFilePuts(fp
, " Font *\n");
3758 cupsFilePrintf(fp
, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n",
3759 fo
->name
->value
, fo
->encoding
->value
,
3760 fo
->version
->value
, fo
->charset
->value
,
3761 fo
->status
== PPDC_FONT_ROM
? "ROM" : "Disk");
3763 // Output all options...
3764 for (g
= (ppdcGroup
*)d
->groups
->first();
3766 g
= (ppdcGroup
*)d
->groups
->next())
3768 if (g
->options
->count
== 0)
3771 if (g
->text
->value
&& g
->text
->value
[0])
3772 quotef(fp
, " Group \"%s/%s\"\n", g
->name
->value
, g
->text
->value
);
3774 cupsFilePrintf(fp
, " Group \"%s\"\n", g
->name
->value
);
3776 for (o
= (ppdcOption
*)g
->options
->first();
3778 o
= (ppdcOption
*)g
->options
->next())
3780 if (o
->choices
->count
== 0)
3783 if (o
->text
->value
&& o
->text
->value
[0])
3784 quotef(fp
, " Option \"%s/%s\"", o
->name
->value
, o
->text
->value
);
3786 cupsFilePrintf(fp
, " Option \"%s\"", o
->name
->value
);
3788 cupsFilePrintf(fp
, " %s %s %.1f\n",
3789 o
->type
== PPDC_BOOLEAN
? "Boolean" :
3790 o
->type
== PPDC_PICKONE
? "PickOne" : "PickMany",
3791 o
->section
== PPDC_SECTION_ANY
? "AnySetup" :
3792 o
->section
== PPDC_SECTION_DOCUMENT
? "DocumentSetup" :
3793 o
->section
== PPDC_SECTION_EXIT
? "ExitServer" :
3794 o
->section
== PPDC_SECTION_JCL
? "JCLSetup" :
3795 o
->section
== PPDC_SECTION_PAGE
? "PageSetup" :
3799 for (ch
= (ppdcChoice
*)o
->choices
->first();
3801 ch
= (ppdcChoice
*)o
->choices
->next())
3803 if (ch
->text
->value
&& ch
->text
->value
[0])
3804 quotef(fp
, " %sChoice \"%s/%s\" \"%s\"\n",
3805 o
->defchoice
== ch
->name
? "*" : "",
3806 ch
->name
->value
, ch
->text
->value
,
3807 ch
->code
->value
? ch
->code
->value
: "");
3809 quotef(fp
, " %sChoice \"%s\" \"%s\"\n",
3810 o
->defchoice
== ch
->name
? "*" : "",
3812 ch
->code
->value
? ch
->code
->value
: "");
3817 // Output all of the color profiles...
3818 for (p
= (ppdcProfile
*)d
->profiles
->first();
3820 p
= (ppdcProfile
*)d
->profiles
->next())
3821 cupsFilePrintf(fp
, " ColorProfile \"%s/%s\" %.3f %.3f "
3822 "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
3823 p
->resolution
->value
, p
->media_type
->value
,
3824 p
->density
, p
->gamma
,
3825 p
->profile
[0], p
->profile
[1], p
->profile
[2],
3826 p
->profile
[3], p
->profile
[4], p
->profile
[5],
3827 p
->profile
[6], p
->profile
[7], p
->profile
[8]);
3829 // Output all of the media sizes...
3835 for (si
= (ppdcMediaSize
*)d
->sizes
->first();
3837 si
= (ppdcMediaSize
*)d
->sizes
->next())
3838 if (si
->size_code
->value
&& si
->region_code
->value
)
3840 // Output a custom media size...
3841 quotef(fp
, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n",
3842 si
->name
== d
->default_size
? "*" : "", si
->name
->value
,
3843 si
->text
->value
, si
->width
, si
->length
, si
->left
, si
->bottom
,
3844 si
->right
, si
->top
, si
->size_code
->value
,
3845 si
->region_code
->value
);
3849 // Output a standard media size...
3850 if (fabs(left
- si
->left
) > 0.1 ||
3851 fabs(bottom
- si
->bottom
) > 0.1 ||
3852 fabs(right
- si
->right
) > 0.1 ||
3853 fabs(top
- si
->top
) > 0.1)
3855 cupsFilePrintf(fp
, " HWMargins %.2f %.2f %.2f %.2f\n",
3856 si
->left
, si
->bottom
, si
->right
, si
->top
);
3859 bottom
= si
->bottom
;
3864 cupsFilePrintf(fp
, " %sMediaSize %s\n",
3865 si
->name
== d
->default_size
? "*" : "",
3869 if (d
->variable_paper_size
)
3871 cupsFilePuts(fp
, " VariablePaperSize Yes\n");
3873 if (fabs(left
- d
->left_margin
) > 0.1 ||
3874 fabs(bottom
- d
->bottom_margin
) > 0.1 ||
3875 fabs(right
- d
->right_margin
) > 0.1 ||
3876 fabs(top
- d
->top_margin
) > 0.1)
3878 cupsFilePrintf(fp
, " HWMargins %.2f %.2f %.2f %.2f\n",
3879 d
->left_margin
, d
->bottom_margin
, d
->right_margin
,
3883 cupsFilePrintf(fp
, " MinSize %.2f %.2f\n", d
->min_width
, d
->min_length
);
3884 cupsFilePrintf(fp
, " MaxSize %.2f %.2f\n", d
->max_width
, d
->max_length
);
3887 // End the driver...
3888 cupsFilePuts(fp
, "}\n");
3891 // Close the file and return...