]> git.ipfire.org Git - thirdparty/cups.git/blame - ppdc/ppdc-source.cxx
Merge changes from CUPS 1.4svn-r8679.
[thirdparty/cups.git] / ppdc / ppdc-source.cxx
CommitLineData
ac884b6a
MS
1//
2// "$Id$"
3//
4// Source class for the CUPS PPD Compiler.
5//
d2354e63 6// Copyright 2007-2009 by Apple Inc.
ac884b6a
MS
7// Copyright 2002-2007 by Easy Software Products.
8//
9// These coded instructions, statements, and computer programs are the
10// property of Apple Inc. and are protected by Federal copyright
11// law. Distribution and use rights are outlined in the file "LICENSE.txt"
12// which should have been included with this file. If this file is
13// file is missing or damaged, see the license at "http://www.cups.org/".
14//
15// Contents:
16//
17// 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.
94da7e34
MS
22// ppdcSource::find_po() - Find a message catalog for the given
23// locale...
ac884b6a
MS
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.
94da7e34
MS
34// ppdcSource::get_custom_size() - Get a custom media size definition from
35// a file.
36// ppdcSource::get_duplex() - Get a duplex option.
ac884b6a
MS
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.
ac884b6a
MS
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.
94da7e34 46// ppdcSource::get_po() - Get a message catalog.
ac884b6a
MS
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.
57//
58
59//
60// Include necessary headers...
61//
62
38e73f87 63#include "ppdc-private.h"
ac884b6a
MS
64#include <cups/globals.h>
65#include <limits.h>
66#include <math.h>
67#include <unistd.h>
68#include <cups/raster.h>
69#include "data/epson.h"
70#include "data/escp.h"
71#include "data/hp.h"
72#include "data/label.h"
73#include "data/pcl.h"
b0f6947b
MS
74#ifndef WIN32
75# include <sys/utsname.h>
76#endif // !WIN32
ac884b6a
MS
77
78
79//
80// Class globals...
81//
82
83ppdcArray *ppdcSource::includes = 0;
84const char *ppdcSource::driver_types[] =
85 {
86 "custom",
87 "ps",
88 "escp",
89 "pcl",
90 "label",
91 "epson",
92 "hp"
93 };
94
95
96//
97// 'ppdcSource::ppdcSource()' - Load a driver source file.
98//
99
4509bb49
MS
100ppdcSource::ppdcSource(const char *f, // I - File to read
101 cups_file_t *ffp)// I - File pointer to use
94da7e34 102 : ppdcShared()
ac884b6a 103{
94da7e34
MS
104 PPDC_NEW;
105
bdd6c45b
MS
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;
ac884b6a 115
b0f6947b
MS
116 // Add standard #define variables...
117#define MAKE_STRING(x) #x
118
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)));
123
124#ifdef WIN32
125 vars->add(new ppdcVariable("PLATFORM_NAME", "Windows"));
126 vars->add(new ppdcVariable("PLATFORM_ARCH", "X86"));
127
128#else
129 struct utsname name; // uname information
130
131 vars->add(new ppdcVariable("PLATFORM_NAME", name.sysname));
132 vars->add(new ppdcVariable("PLATFORM_ARCH", name.machine));
133#endif // WIN32
134
ac884b6a 135 if (f)
4509bb49 136 read_file(f, ffp);
ac884b6a
MS
137}
138
139
140//
141// 'ppdcSource::~ppdcSource()' - Free a driver source file.
142//
143
144ppdcSource::~ppdcSource()
145{
94da7e34
MS
146 PPDC_DELETE;
147
e4572d57
MS
148 filename->release();
149 base_fonts->release();
150 drivers->release();
151 po_files->release();
152 sizes->release();
153 vars->release();
ac884b6a
MS
154}
155
156
157//
158// 'ppdcSource::add_include()' - Add an include directory.
159//
160
161void
162ppdcSource::add_include(const char *d) // I - Include directory
163{
164 if (!d)
165 return;
166
167 if (!includes)
168 includes = new ppdcArray();
169
170 includes->add(new ppdcString(d));
171}
172
173
174//
175// 'ppdcSource::find_driver()' - Find a driver.
176//
177
178ppdcDriver * // O - Driver
179ppdcSource::find_driver(const char *f) // I - Driver file name
180{
181 ppdcDriver *d; // Current driver
182
183
184 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
185 if (!strcasecmp(f, d->pc_file_name->value))
186 return (d);
187
188 return (NULL);
189}
190
191
192//
193// 'ppdcSource::find_include()' - Find an include file.
194//
195
196char * // O - Found path or NULL
197ppdcSource::find_include(
198 const char *f, // I - Include filename
199 const char *base, // I - Current directory
200 char *n, // I - Path buffer
201 int nlen) // I - Path buffer length
202{
203 ppdcString *dir; // Include directory
204 char temp[1024], // Temporary path
205 *ptr; // Pointer to end of path
206
207
208 // Range check input...
209 if (!f || !*f || !n || nlen < 2)
210 return (0);
211
212 // Check the first character to see if we have <name> or "name"...
213 if (*f == '<')
214 {
215 // Remove the surrounding <> from the name...
216 strlcpy(temp, f + 1, sizeof(temp));
217 ptr = temp + strlen(temp) - 1;
218
219 if (*ptr != '>')
220 {
61cf44e2
MS
221 _cupsLangPrintf(stderr,
222 _("ppdc: Invalid #include/#po filename \"%s\"!\n"), n);
ac884b6a
MS
223 return (0);
224 }
225
226 *ptr = '\0';
227 f = temp;
228 }
229 else
230 {
231 // Check for the local file relative to the current directory...
232 if (base && *base && f[0] != '/')
233 snprintf(n, nlen, "%s/%s", base, f);
234 else
235 strlcpy(n, f, nlen);
236
237 if (!access(n, 0))
238 return (n);
239 else if (*f == '/')
240 {
241 // Absolute path that doesn't exist...
242 return (0);
243 }
244 }
245
246 // Search the include directories, if any...
247 if (includes)
248 {
249 for (dir = (ppdcString *)includes->first(); dir; dir = (ppdcString *)includes->next())
250 {
251 snprintf(n, nlen, "%s/%s", dir->value, f);
252 if (!access(n, 0))
253 return (n);
254 }
255 }
256
257 // Search the standard include directories...
258 _cups_globals_t *cg = _cupsGlobals(); // Global data
259
260 snprintf(n, nlen, "%s/ppdc/%s", cg->cups_datadir, f);
261 if (!access(n, 0))
262 return (n);
263
264 snprintf(n, nlen, "%s/po/%s", cg->cups_datadir, f);
265 if (!access(n, 0))
266 return (n);
267 else
268 return (0);
269}
270
271
272//
273// 'ppdcSource::find_po()' - Find a message catalog for the given locale...
274//
275
276ppdcCatalog * // O - Message catalog or NULL
277ppdcSource::find_po(const char *l) // I - Locale name
278{
279 ppdcCatalog *cat; // Current message catalog
280
281
282 for (cat = (ppdcCatalog *)po_files->first();
283 cat;
284 cat = (ppdcCatalog *)po_files->next())
285 if (!strcasecmp(l, cat->locale->value))
286 return (cat);
287
288 return (NULL);
289}
290
291
292//
293// 'ppdcSource::find_size()' - Find a media size.
294//
295
296ppdcMediaSize * // O - Size
297ppdcSource::find_size(const char *s) // I - Size name
298{
299 ppdcMediaSize *m; // Current media size
300
301
302 for (m = (ppdcMediaSize *)sizes->first(); m; m = (ppdcMediaSize *)sizes->next())
303 if (!strcasecmp(s, m->name->value))
304 return (m);
305
306 return (NULL);
307}
308
309
310//
311// 'ppdcSource::find_variable()' - Find a variable.
312//
313
314ppdcVariable * // O - Variable
315ppdcSource::find_variable(const char *n)// I - Variable name
316{
317 ppdcVariable *v; // Current variable
318
319
320 for (v = (ppdcVariable *)vars->first(); v; v = (ppdcVariable *)vars->next())
321 if (!strcasecmp(n, v->name->value))
322 return (v);
323
324 return (NULL);
325}
326
327
328//
329// 'ppdcSource::get_attr()' - Get an attribute.
330//
331
332ppdcAttr * // O - Attribute
bdd6c45b
MS
333ppdcSource::get_attr(ppdcFile *fp, // I - File to read
334 bool loc) // I - Localize this attribute?
ac884b6a
MS
335{
336 char name[1024], // Name string
337 selector[1024], // Selector string
338 *text, // Text string
339 value[1024]; // Value string
340
341
342 // Get the attribute parameters:
343 //
344 // Attribute name selector value
345 if (!get_token(fp, name, sizeof(name)))
346 {
61cf44e2
MS
347 _cupsLangPrintf(stderr,
348 _("ppdc: Expected name after %s on line %d of %s!\n"),
349 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
ac884b6a
MS
350 return (0);
351 }
352
353 if (!get_token(fp, selector, sizeof(selector)))
354 {
61cf44e2
MS
355 _cupsLangPrintf(stderr,
356 _("ppdc: Expected selector after %s on line %d of %s!\n"),
357 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
ac884b6a
MS
358 return (0);
359 }
360
361 if ((text = strchr(selector, '/')) != NULL)
362 *text++ = '\0';
363
364 if (!get_token(fp, value, sizeof(value)))
365 {
61cf44e2
MS
366 _cupsLangPrintf(stderr,
367 _("ppdc: Expected value after %s on line %d of %s!\n"),
368 loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
ac884b6a
MS
369 return (0);
370 }
371
bdd6c45b 372 return (new ppdcAttr(name, selector, text, value, loc));
ac884b6a
MS
373}
374
375
376//
377// 'ppdcSource::get_boolean()' - Get a boolean value.
378//
379
380int // O - Boolean value
381ppdcSource::get_boolean(ppdcFile *fp) // I - File to read
382{
383 char buffer[256]; // String buffer
384
385
386 if (!get_token(fp, buffer, sizeof(buffer)))
387 {
61cf44e2
MS
388 _cupsLangPrintf(stderr,
389 _("ppdc: Expected boolean value on line %d of %s.\n"),
390 fp->line, fp->filename);
ac884b6a
MS
391 return (-1);
392 }
393
394 if (!strcasecmp(buffer, "on") ||
395 !strcasecmp(buffer, "yes") ||
396 !strcasecmp(buffer, "true"))
397 return (1);
398 else if (!strcasecmp(buffer, "off") ||
399 !strcasecmp(buffer, "no") ||
400 !strcasecmp(buffer, "false"))
401 return (0);
402 else
403 {
61cf44e2
MS
404 _cupsLangPrintf(stderr,
405 _("ppdc: Bad boolean value (%s) on line %d of %s.\n"),
406 buffer, fp->line, fp->filename);
ac884b6a
MS
407 return (-1);
408 }
409}
410
411
412//
413// 'ppdcSource::get_choice()' - Get a choice.
414//
415
416ppdcChoice * // O - Choice data
417ppdcSource::get_choice(ppdcFile *fp) // I - File to read
418{
419 char name[1024], // Name
420 *text, // Text
421 code[10240]; // Code
422
423
424 // Read a choice from the file:
425 //
426 // Choice name/text code
427 if (!get_token(fp, name, sizeof(name)))
428 {
61cf44e2
MS
429 _cupsLangPrintf(stderr,
430 _("ppdc: Expected choice name/text on line %d of %s.\n"),
431 fp->line, fp->filename);
ac884b6a
MS
432 return (NULL);
433 }
434
435 if ((text = strchr(name, '/')) != NULL)
436 *text++ = '\0';
437 else
438 text = name;
439
440 if (!get_token(fp, code, sizeof(code)))
441 {
61cf44e2
MS
442 _cupsLangPrintf(stderr, _("ppdc: Expected choice code on line %d of %s.\n"),
443 fp->line, fp->filename);
ac884b6a
MS
444 return (NULL);
445 }
446
447 // Return the new choice
448 return (new ppdcChoice(name, text, code));
449}
450
451
452//
453// 'ppdcSource::get_color_model()' - Get an old-style color model option.
454//
455
456ppdcChoice * // O - Choice data
457ppdcSource::get_color_model(ppdcFile *fp)
458 // I - File to read
459{
460 char name[1024], // Option name
461 *text, // Text option
462 temp[256]; // Temporary string
463 int color_space, // Colorspace
464 color_order, // Color order
465 compression; // Compression mode
466
467
468 // Get the ColorModel parameters:
469 //
470 // ColorModel name/text colorspace colororder compression
471 if (!get_token(fp, name, sizeof(name)))
472 {
61cf44e2
MS
473 _cupsLangPrintf(stderr,
474 _("ppdc: Expected name/text combination for ColorModel on "
475 "line %d of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
476 return (NULL);
477 }
478
479 if ((text = strchr(name, '/')) != NULL)
480 *text++ = '\0';
481 else
482 text = name;
483
484 if (!get_token(fp, temp, sizeof(temp)))
485 {
61cf44e2
MS
486 _cupsLangPrintf(stderr,
487 _("ppdc: Expected colorspace for ColorModel on line %d of "
488 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
489 return (NULL);
490 }
491
492 if ((color_space = get_color_space(temp)) < 0)
493 color_space = get_integer(temp);
494
495 if (!get_token(fp, temp, sizeof(temp)))
496 {
61cf44e2
MS
497 _cupsLangPrintf(stderr,
498 _("ppdc: Expected color order for ColorModel on line %d of "
499 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
500 return (NULL);
501 }
502
503 if ((color_order = get_color_order(temp)) < 0)
504 color_order = get_integer(temp);
505
506 if (!get_token(fp, temp, sizeof(temp)))
507 {
61cf44e2
MS
508 _cupsLangPrintf(stderr,
509 _("ppdc: Expected compression for ColorModel on line %d of "
510 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
511 return (NULL);
512 }
513
514 compression = get_integer(temp);
515
516 snprintf(temp, sizeof(temp),
517 "<</cupsColorSpace %d/cupsColorOrder %d/cupsCompression %d>>"
518 "setpagedevice",
519 color_space, color_order, compression);
520
521 return (new ppdcChoice(name, text, temp));
522}
523
524
525//
526// 'ppdcSource::get_color_order()' - Get an old-style color order value.
527//
528
529int // O - Color order value
530ppdcSource::get_color_order(
531 const char *co) // I - Color order string
532{
533 if (!strcasecmp(co, "chunked") ||
534 !strcasecmp(co, "chunky"))
535 return (CUPS_ORDER_CHUNKED);
536 else if (!strcasecmp(co, "banded"))
537 return (CUPS_ORDER_BANDED);
538 else if (!strcasecmp(co, "planar"))
539 return (CUPS_ORDER_PLANAR);
540 else
541 return (-1);
542}
543
544
545//
546// 'ppdcSource::get_color_profile()' - Get a color profile definition.
547//
548
549ppdcProfile * // O - Color profile
550ppdcSource::get_color_profile(
551 ppdcFile *fp) // I - File to read
552{
553 char resolution[1024], // Resolution/media type
554 *media_type; // Media type
555 int i; // Looping var
556 float g, // Gamma value
557 d, // Density value
558 m[9]; // Transform matrix
559
560
561 // Get the ColorProfile parameters:
562 //
563 // ColorProfile resolution/mediatype gamma density m00 m01 m02 ... m22
564 if (!get_token(fp, resolution, sizeof(resolution)))
565 {
61cf44e2
MS
566 _cupsLangPrintf(stderr,
567 _("ppdc: Expected resolution/mediatype following "
568 "ColorProfile on line %d of %s!\n"),
569 fp->line, fp->filename);
ac884b6a
MS
570 return (NULL);
571 }
572
573 if ((media_type = strchr(resolution, '/')) != NULL)
574 *media_type++ = '\0';
575 else
576 media_type = resolution;
577
578 g = get_float(fp);
579 d = get_float(fp);
580 for (i = 0; i < 9; i ++)
581 m[i] = get_float(fp);
582
583 return (new ppdcProfile(resolution, media_type, g, d, m));
584}
585
586
587//
588// 'ppdcSource::get_color_space()' - Get an old-style colorspace value.
589//
590
591int // O - Colorspace value
592ppdcSource::get_color_space(
593 const char *cs) // I - Colorspace string
594{
595 if (!strcasecmp(cs, "w"))
596 return (CUPS_CSPACE_W);
597 else if (!strcasecmp(cs, "rgb"))
598 return (CUPS_CSPACE_RGB);
599 else if (!strcasecmp(cs, "rgba"))
600 return (CUPS_CSPACE_RGBA);
601 else if (!strcasecmp(cs, "k"))
602 return (CUPS_CSPACE_K);
603 else if (!strcasecmp(cs, "cmy"))
604 return (CUPS_CSPACE_CMY);
605 else if (!strcasecmp(cs, "ymc"))
606 return (CUPS_CSPACE_YMC);
607 else if (!strcasecmp(cs, "cmyk"))
608 return (CUPS_CSPACE_CMYK);
609 else if (!strcasecmp(cs, "ymck"))
610 return (CUPS_CSPACE_YMCK);
611 else if (!strcasecmp(cs, "kcmy"))
612 return (CUPS_CSPACE_KCMY);
613 else if (!strcasecmp(cs, "kcmycm"))
614 return (CUPS_CSPACE_KCMYcm);
615 else if (!strcasecmp(cs, "gmck"))
616 return (CUPS_CSPACE_GMCK);
617 else if (!strcasecmp(cs, "gmcs"))
618 return (CUPS_CSPACE_GMCS);
619 else if (!strcasecmp(cs, "white"))
620 return (CUPS_CSPACE_WHITE);
621 else if (!strcasecmp(cs, "gold"))
622 return (CUPS_CSPACE_GOLD);
623 else if (!strcasecmp(cs, "silver"))
624 return (CUPS_CSPACE_SILVER);
625 else if (!strcasecmp(cs, "CIEXYZ"))
626 return (CUPS_CSPACE_CIEXYZ);
627 else if (!strcasecmp(cs, "CIELab"))
628 return (CUPS_CSPACE_CIELab);
629 else if (!strcasecmp(cs, "RGBW"))
630 return (CUPS_CSPACE_RGBW);
631 else if (!strcasecmp(cs, "ICC1"))
632 return (CUPS_CSPACE_ICC1);
633 else if (!strcasecmp(cs, "ICC2"))
634 return (CUPS_CSPACE_ICC2);
635 else if (!strcasecmp(cs, "ICC3"))
636 return (CUPS_CSPACE_ICC3);
637 else if (!strcasecmp(cs, "ICC4"))
638 return (CUPS_CSPACE_ICC4);
639 else if (!strcasecmp(cs, "ICC5"))
640 return (CUPS_CSPACE_ICC5);
641 else if (!strcasecmp(cs, "ICC6"))
642 return (CUPS_CSPACE_ICC6);
643 else if (!strcasecmp(cs, "ICC7"))
644 return (CUPS_CSPACE_ICC7);
645 else if (!strcasecmp(cs, "ICC8"))
646 return (CUPS_CSPACE_ICC8);
647 else if (!strcasecmp(cs, "ICC9"))
648 return (CUPS_CSPACE_ICC9);
649 else if (!strcasecmp(cs, "ICCA"))
650 return (CUPS_CSPACE_ICCA);
651 else if (!strcasecmp(cs, "ICCB"))
652 return (CUPS_CSPACE_ICCB);
653 else if (!strcasecmp(cs, "ICCC"))
654 return (CUPS_CSPACE_ICCC);
655 else if (!strcasecmp(cs, "ICCD"))
656 return (CUPS_CSPACE_ICCD);
657 else if (!strcasecmp(cs, "ICCE"))
658 return (CUPS_CSPACE_ICCE);
659 else if (!strcasecmp(cs, "ICCF"))
660 return (CUPS_CSPACE_ICCF);
661 else
662 return (-1);
663}
664
665
666//
667// 'ppdcSource::get_constraint()' - Get a constraint.
668//
669
670ppdcConstraint * // O - Constraint
671ppdcSource::get_constraint(ppdcFile *fp)// I - File to read
672{
673 char temp[1024], // One string to rule them all
674 *ptr, // Pointer into string
675 *option1, // Constraint option 1
676 *choice1, // Constraint choice 1
677 *option2, // Constraint option 2
678 *choice2; // Constraint choice 2
679
680
681 // Read the UIConstaints parameter in one of the following forms:
682 //
683 // UIConstraints "*Option1 *Option2"
684 // UIConstraints "*Option1 Choice1 *Option2"
685 // UIConstraints "*Option1 *Option2 Choice2"
686 // UIConstraints "*Option1 Choice1 *Option2 Choice2"
687 if (!get_token(fp, temp, sizeof(temp)))
688 {
61cf44e2
MS
689 _cupsLangPrintf(stderr,
690 _("ppdc: Expected constraints string for UIConstraints on "
691 "line %d of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
692 return (NULL);
693 }
694
695 for (ptr = temp; isspace(*ptr); ptr ++);
696
697 if (*ptr != '*')
698 {
61cf44e2
MS
699 _cupsLangPrintf(stderr,
700 _("ppdc: Option constraint must *name on line %d of %s!\n"),
701 fp->line, fp->filename);
ac884b6a
MS
702 return (NULL);
703 }
704
705 option1 = ptr;
706
707 for (; *ptr && !isspace(*ptr); ptr ++);
708 for (; isspace(*ptr); *ptr++ = '\0');
709
710 if (*ptr != '*')
711 {
712 choice1 = ptr;
713
714 for (; *ptr && !isspace(*ptr); ptr ++);
715 for (; isspace(*ptr); *ptr++ = '\0');
716 }
717 else
718 choice1 = NULL;
719
720 if (*ptr != '*')
721 {
61cf44e2
MS
722 _cupsLangPrintf(stderr,
723 _("ppdc: Expected two option names on line %d of %s!\n"),
724 fp->line, fp->filename);
ac884b6a
MS
725 return (NULL);
726 }
727
728 option2 = ptr;
729
730 for (; *ptr && !isspace(*ptr); ptr ++);
731 for (; isspace(*ptr); *ptr++ = '\0');
732
733 if (*ptr)
734 choice2 = ptr;
735 else
736 choice2 = NULL;
737
738 return (new ppdcConstraint(option1, choice1, option2, choice2));
739}
740
741
742//
743// 'ppdcSource::get_custom_size()' - Get a custom media size definition from a file.
744//
745
746ppdcMediaSize * // O - Media size
747ppdcSource::get_custom_size(ppdcFile *fp)
748 // I - File to read
749{
750 char name[1024], // Name
751 *text, // Text
752 size_code[10240], // PageSize code
753 region_code[10240]; // PageRegion
754 float width, // Width
755 length, // Length
756 left, // Left margin
757 bottom, // Bottom margin
758 right, // Right margin
759 top; // Top margin
760
761
762 // Get the name, text, width, length, margins, and code:
763 //
764 // CustomMedia name/text width length left bottom right top size-code region-code
765 if (!get_token(fp, name, sizeof(name)))
766 return (NULL);
767
768 if ((text = strchr(name, '/')) != NULL)
769 *text++ = '\0';
770 else
771 text = name;
772
773 if ((width = get_measurement(fp)) < 0.0f)
774 return (NULL);
775
776 if ((length = get_measurement(fp)) < 0.0f)
777 return (NULL);
778
779 if ((left = get_measurement(fp)) < 0.0f)
780 return (NULL);
781
782 if ((bottom = get_measurement(fp)) < 0.0f)
783 return (NULL);
784
785 if ((right = get_measurement(fp)) < 0.0f)
786 return (NULL);
787
788 if ((top = get_measurement(fp)) < 0.0f)
789 return (NULL);
790
791 if (!get_token(fp, size_code, sizeof(size_code)))
792 return (NULL);
793
794 if (!get_token(fp, region_code, sizeof(region_code)))
795 return (NULL);
796
797 // Return the new media size...
798 return (new ppdcMediaSize(name, text, width, length, left, bottom,
799 right, top, size_code, region_code));
800}
801
802
803//
804// 'ppdcSource::get_duplex()' - Get a duplex option.
805//
806
807void
808ppdcSource::get_duplex(ppdcFile *fp, // I - File to read from
809 ppdcDriver *d) // I - Current driver
810{
811 char temp[256]; // Duplex keyword
812 ppdcAttr *attr; // cupsFlipDuplex attribute
813 ppdcGroup *g; // Current group
814 ppdcOption *o; // Duplex option
815
816
817 // Duplex {boolean|none|normal|flip}
818 if (!get_token(fp, temp, sizeof(temp)))
819 {
61cf44e2
MS
820 _cupsLangPrintf(stderr,
821 _("ppdc: Expected duplex type after Duplex on line %d of "
822 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
823 return;
824 }
825
bdd6c45b
MS
826 if (cond_state)
827 return;
828
ac884b6a
MS
829 if (!strcasecmp(temp, "none") || !strcasecmp(temp, "false") ||
830 !strcasecmp(temp, "no") || !strcasecmp(temp, "off"))
831 {
832 g = d->find_group("General");
833 if ((o = g->find_option("Duplex")) != NULL)
834 g->options->remove(o);
835
836 for (attr = (ppdcAttr *)d->attrs->first();
837 attr;
838 attr = (ppdcAttr *)d->attrs->next())
839 if (!strcmp(attr->name->value, "cupsFlipDuplex"))
840 {
841 d->attrs->remove(attr);
842 break;
843 }
844 }
845 else if (!strcasecmp(temp, "normal") || !strcasecmp(temp, "true") ||
846 !strcasecmp(temp, "yes") || !strcasecmp(temp, "on") ||
61cf44e2
MS
847 !strcasecmp(temp, "flip") || !strcasecmp(temp, "rotated") ||
848 !strcasecmp(temp, "manualtumble"))
ac884b6a
MS
849 {
850 g = d->find_group("General");
851 o = g->find_option("Duplex");
852
853 if (!o)
854 {
855 o = new ppdcOption(PPDC_PICKONE, "Duplex", "2-Sided Printing",
856 !strcasecmp(temp, "flip") ? PPDC_SECTION_PAGE :
857 PPDC_SECTION_ANY, 10.0f);
858 o->add_choice(new ppdcChoice("None", "Off (1-Sided)",
859 "<</Duplex false>>setpagedevice"));
860 o->add_choice(new ppdcChoice("DuplexNoTumble", "Long-Edge (Portrait)",
861 "<</Duplex true/Tumble false>>setpagedevice"));
862 o->add_choice(new ppdcChoice("DuplexTumble", "Short-Edge (Landscape)",
863 "<</Duplex true/Tumble true>>setpagedevice"));
864
865 g->add_option(o);
866 }
867
868 for (attr = (ppdcAttr *)d->attrs->first();
869 attr;
870 attr = (ppdcAttr *)d->attrs->next())
871 if (!strcmp(attr->name->value, "cupsFlipDuplex"))
872 {
873 if (strcasecmp(temp, "flip"))
874 d->attrs->remove(attr);
875 break;
876 }
877
878 if (!strcasecmp(temp, "flip") && !attr)
879 d->add_attr(new ppdcAttr("cupsFlipDuplex", NULL, NULL, "true"));
61cf44e2
MS
880
881 for (attr = (ppdcAttr *)d->attrs->first();
882 attr;
883 attr = (ppdcAttr *)d->attrs->next())
884 if (!strcmp(attr->name->value, "cupsBackSide"))
885 {
886 d->attrs->remove(attr);
887 break;
888 }
889
890 if (!strcasecmp(temp, "flip"))
891 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Flipped"));
892 else if (!strcasecmp(temp, "rotated"))
893 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Rotated"));
894 else if (!strcasecmp(temp, "manualtumble"))
895 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "ManualTumble"));
896 else
897 d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Normal"));
ac884b6a
MS
898 }
899 else
61cf44e2
MS
900 _cupsLangPrintf(stderr,
901 _("ppdc: Unknown duplex type \"%s\" on line %d of %s!\n"),
902 temp, fp->line, fp->filename);
ac884b6a
MS
903}
904
905
906//
907// 'ppdcSource::get_filter()' - Get a filter.
908//
909
910ppdcFilter * // O - Filter
911ppdcSource::get_filter(ppdcFile *fp) // I - File to read
912{
913 char type[1024], // MIME type
914 program[1024], // Filter program
915 *ptr; // Pointer into MIME type
916 int cost; // Relative cost
917
918
919 // Read filter parameters in one of the following formats:
920 //
921 // Filter "type cost program"
922 // Filter type cost program
923
924 if (!get_token(fp, type, sizeof(type)))
925 {
61cf44e2
MS
926 _cupsLangPrintf(stderr,
927 _("ppdc: Expected a filter definition on line %d of %s!\n"),
928 fp->line, fp->filename);
ac884b6a
MS
929 return (NULL);
930 }
931
932 if ((ptr = strchr(type, ' ')) != NULL)
933 {
934 // Old-style filter definition in one string...
935 *ptr++ = '\0';
936 cost = strtol(ptr, &ptr, 10);
937
938 while (isspace(*ptr))
939 ptr ++;
940
941 strcpy(program, ptr);
942 }
943 else
944 {
945 cost = get_integer(fp);
946
947 if (!get_token(fp, program, sizeof(program)))
948 {
61cf44e2
MS
949 _cupsLangPrintf(stderr,
950 _("ppdc: Expected a program name on line %d of %s!\n"),
951 fp->line, fp->filename);
ac884b6a
MS
952 return (NULL);
953 }
954 }
955
956 if (!type[0])
957 {
61cf44e2
MS
958 _cupsLangPrintf(stderr,
959 _("ppdc: Invalid empty MIME type for filter on line %d of "
960 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
961 return (NULL);
962 }
963
964 if (cost < 0 || cost > 200)
965 {
61cf44e2
MS
966 _cupsLangPrintf(stderr,
967 _("ppdc: Invalid cost for filter on line %d of %s!\n"),
968 fp->line, fp->filename);
ac884b6a
MS
969 return (NULL);
970 }
971
972 if (!program[0])
973 {
61cf44e2
MS
974 _cupsLangPrintf(stderr,
975 _("ppdc: Invalid empty program name for filter on line %d "
976 "of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
977 return (NULL);
978 }
979
980 return (new ppdcFilter(type, program, cost));
981}
982
983
984//
985// 'ppdcSource::get_float()' - Get a single floating-point number.
986//
987
988float // O - Number
989ppdcSource::get_float(ppdcFile *fp) // I - File to read
990{
991 char temp[256], // String buffer
992 *ptr; // Pointer into buffer
993 float val; // Floating point value
994
995
996 // Get the number from the file and range-check...
997 if (!get_token(fp, temp, sizeof(temp)))
998 {
61cf44e2
MS
999 _cupsLangPrintf(stderr, _("ppdc: Expected real number on line %d of %s!\n"),
1000 fp->line, fp->filename);
ac884b6a
MS
1001 return (-1.0f);
1002 }
1003
1004 val = (float)strtod(temp, &ptr);
1005
1006 if (*ptr)
1007 {
61cf44e2
MS
1008 _cupsLangPrintf(stderr,
1009 _("ppdc: Unknown trailing characters in real number \"%s\" "
1010 "on line %d of %s!\n"), temp, fp->line, fp->filename);
ac884b6a
MS
1011 return (-1.0f);
1012 }
1013 else
1014 return (val);
1015}
1016
1017
1018//
1019// 'ppdcSource::get_font()' - Get a font definition.
1020//
1021
1022ppdcFont * // O - Font data
1023ppdcSource::get_font(ppdcFile *fp) // I - File to read
1024{
1025 char name[256], // Font name
1026 encoding[256], // Font encoding
1027 version[256], // Font version
1028 charset[256], // Font charset
1029 temp[256]; // Font status string
1030 ppdcFontStatus status; // Font status enumeration
1031
1032
1033 // Read font parameters as follows:
1034 //
1035 // Font *
1036 // Font name encoding version charset status
1037 // %font name encoding version charset status
1038 //
1039 // "Name" is the PostScript font name.
1040 //
1041 // "Encoding" is the default encoding of the font: Standard, ISOLatin1,
1042 // Special, Expert, ExpertSubset, etc.
1043 //
1044 // "Version" is the version number string.
1045 //
1046 // "Charset" specifies the characters that are included in the font:
1047 // Standard, Special, Expert, Adobe-Identity, etc.
1048 //
1049 // "Status" is the keyword ROM or Disk.
1050 if (!get_token(fp, name, sizeof(name)))
1051 {
61cf44e2
MS
1052 _cupsLangPrintf(stderr,
1053 _("ppdc: Expected name after Font on line %d of %s!\n"),
1054 fp->line, fp->filename);
ac884b6a
MS
1055 return (0);
1056 }
1057
1058 if (!strcmp(name, "*"))
1059 {
1060 // Include all base fonts...
1061 encoding[0] = '\0';
1062 version[0] = '\0';
1063 charset[0] = '\0';
1064 status = PPDC_FONT_ROM;
1065 }
1066 else
1067 {
1068 // Load a full font definition...
1069 if (!get_token(fp, encoding, sizeof(encoding)))
1070 {
61cf44e2
MS
1071 _cupsLangPrintf(stderr,
1072 _("ppdc: Expected encoding after Font on line %d of "
1073 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
1074 return (0);
1075 }
1076
1077 if (!get_token(fp, version, sizeof(version)))
1078 {
61cf44e2
MS
1079 _cupsLangPrintf(stderr,
1080 _("ppdc: Expected version after Font on line %d of "
1081 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
1082 return (0);
1083 }
1084
1085 if (!get_token(fp, charset, sizeof(charset)))
1086 {
61cf44e2
MS
1087 _cupsLangPrintf(stderr,
1088 _("ppdc: Expected charset after Font on line %d of "
1089 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
1090 return (0);
1091 }
1092
1093 if (!get_token(fp, temp, sizeof(temp)))
1094 {
61cf44e2
MS
1095 _cupsLangPrintf(stderr,
1096 _("ppdc: Expected status after Font on line %d of %s!\n"),
1097 fp->line, fp->filename);
ac884b6a
MS
1098 return (0);
1099 }
1100
1101 if (!strcasecmp(temp, "ROM"))
1102 status = PPDC_FONT_ROM;
1103 else if (!strcasecmp(temp, "Disk"))
1104 status = PPDC_FONT_DISK;
1105 else
1106 {
61cf44e2
MS
1107 _cupsLangPrintf(stderr,
1108 _("ppdc: Bad status keyword %s on line %d of %s!\n"),
1109 temp, fp->line, fp->filename);
ac884b6a
MS
1110 return (0);
1111 }
1112 }
1113
1114// printf("Font %s %s %s %s %s\n", name, encoding, version, charset, temp);
1115
1116 return (new ppdcFont(name, encoding, version, charset, status));
1117}
1118
1119
1120//
1121// 'ppdcSource::get_generic()' - Get a generic old-style option.
1122//
1123
1124ppdcChoice * // O - Choice data
1125ppdcSource::get_generic(ppdcFile *fp, // I - File to read
1126 const char *keyword,
1127 // I - Keyword name
1128 const char *tattr,
1129 // I - Text attribute
1130 const char *nattr)
1131 // I - Numeric attribute
1132{
1133 char name[1024], // Name
1134 *text, // Text
1135 command[256]; // Command string
1136 int val; // Numeric value
1137
1138
1139 // Read one of the following parameters:
1140 //
1141 // Foo name/text
1142 // Foo integer name/text
1143 if (nattr)
1144 val = get_integer(fp);
1145 else
1146 val = 0;
1147
1148 if (!get_token(fp, name, sizeof(name)))
1149 {
61cf44e2
MS
1150 _cupsLangPrintf(stderr,
1151 _("ppdc: Expected name/text after %s on line %d of %s!\n"),
1152 keyword, fp->line, fp->filename);
ac884b6a
MS
1153 return (NULL);
1154 }
1155
1156 if ((text = strchr(name, '/')) != NULL)
1157 *text++ = '\0';
1158 else
1159 text = name;
1160
1161 if (nattr)
1162 {
1163 if (tattr)
1164 snprintf(command, sizeof(command),
1165 "<</%s(%s)/%s %d>>setpagedevice",
1166 tattr, name, nattr, val);
1167 else
1168 snprintf(command, sizeof(command),
1169 "<</%s %d>>setpagedevice",
1170 nattr, val);
1171 }
1172 else
1173 snprintf(command, sizeof(command),
1174 "<</%s(%s)>>setpagedevice",
1175 tattr, name);
1176
1177 return (new ppdcChoice(name, text, command));
1178}
1179
1180
1181//
1182// 'ppdcSource::get_group()' - Get an option group.
1183//
1184
1185ppdcGroup * // O - Group
1186ppdcSource::get_group(ppdcFile *fp, // I - File to read
1187 ppdcDriver *d) // I - Printer driver
1188{
1189 char name[1024], // UI name
1190 *text; // UI text
1191 ppdcGroup *g; // Group
1192
1193
1194 // Read the Group parameters:
1195 //
1196 // Group name/text
1197 if (!get_token(fp, name, sizeof(name)))
1198 {
61cf44e2
MS
1199 _cupsLangPrintf(stderr,
1200 _("ppdc: Expected group name/text on line %d of %s!\n"),
1201 fp->line, fp->filename);
ac884b6a
MS
1202 return (NULL);
1203 }
1204
1205 if ((text = strchr(name, '/')) != NULL)
1206 *text++ = '\0';
1207 else
1208 text = name;
1209
1210 // See if the group already exists...
1211 if ((g = d->find_group(name)) == NULL)
1212 {
1213 // Nope, add a new one...
1214 g = new ppdcGroup(name, text);
ac884b6a
MS
1215 }
1216
1217 return (g);
1218}
1219
1220
1221//
1222// 'ppdcSource::get_installable()' - Get an installable option.
1223//
1224
1225ppdcOption * // O - Option
1226ppdcSource::get_installable(ppdcFile *fp)
1227 // I - File to read
1228{
1229 char name[1024], // Name for installable option
1230 *text; // Text for installable option
1231 ppdcOption *o; // Option
1232
1233
1234 // Read the parameter for an installable option:
1235 //
1236 // Installable name/text
1237 if (!get_token(fp, name, sizeof(name)))
1238 {
61cf44e2
MS
1239 _cupsLangPrintf(stderr,
1240 _("ppdc: Expected name/text after Installable on line %d "
1241 "of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
1242 return (NULL);
1243 }
1244
1245 if ((text = strchr(name, '/')) != NULL)
1246 *text++ = '\0';
1247 else
1248 text = name;
1249
1250 // Create the option...
1251 o = new ppdcOption(PPDC_BOOLEAN, name, text, PPDC_SECTION_ANY, 10.0f);
1252
1253 // Add the false and true choices...
1254 o->add_choice(new ppdcChoice("False", "Not Installed", ""));
1255 o->add_choice(new ppdcChoice("True", "Installed", ""));
1256
1257 return (o);
1258}
1259
1260
1261//
1262// 'ppdcSource::get_integer()' - Get an integer value from a string.
1263//
1264
bdd6c45b
MS
1265#define PPDC_XX -1 // Bad
1266#define PPDC_EQ 0 // ==
1267#define PPDC_NE 1 // !=
1268#define PPDC_LT 2 // <
1269#define PPDC_LE 3 // <=
1270#define PPDC_GT 4 // >
1271#define PPDC_GE 5 // >=
1272
ac884b6a
MS
1273int // O - Integer value
1274ppdcSource::get_integer(const char *v) // I - Value string
1275{
bdd6c45b
MS
1276 long val; // Value
1277 long temp, // Temporary value
1278 temp2; // Second temporary value
1279 char *newv, // New value string pointer
1280 ch; // Temporary character
1281 ppdcVariable *var; // #define variable
1282 int compop; // Comparison operator
ac884b6a
MS
1283
1284
1285 // Parse the value string...
1286 if (!v)
1287 return (-1);
1288
bdd6c45b 1289 if (isdigit(*v & 255) || *v == '-' || *v == '+')
ac884b6a
MS
1290 {
1291 // Return a simple integer value
1292 val = strtol(v, (char **)&v, 0);
1293 if (*v || val == LONG_MIN)
1294 return (-1);
1295 else
a603edef 1296 return ((int)val);
ac884b6a
MS
1297 }
1298 else if (*v == '(')
1299 {
bdd6c45b
MS
1300 // Evaluate and expression in any of the following formats:
1301 //
1302 // (number number ... number) Bitwise OR of all numbers
1303 // (NAME == value) 1 if equal, 0 otherwise
1304 // (NAME != value) 1 if not equal, 0 otherwise
1305 // (NAME < value) 1 if less than, 0 otherwise
1306 // (NAME <= value) 1 if less than or equal, 0 otherwise
1307 // (NAME > value) 1 if greater than, 0 otherwise
1308 // (NAME >= value) 1 if greater than or equal, 0 otherwise
1309
ac884b6a
MS
1310 v ++;
1311 val = 0;
1312
1313 while (*v && *v != ')')
1314 {
bdd6c45b
MS
1315 // Skip leading whitespace...
1316 while (*v && isspace(*v & 255));
1317 v ++;
1318
1319 if (!*v || *v == ')')
1320 break;
ac884b6a 1321
bdd6c45b
MS
1322 if (isdigit(*v & 255) || *v == '-' || *v == '+')
1323 {
1324 // Bitwise OR a number...
1325 temp = strtol(v, &newv, 0);
1326
1327 if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
1328 temp == LONG_MIN)
1329 return (-1);
1330 }
1331 else
1332 {
1333 // NAME logicop value
1334 for (newv = (char *)v + 1;
1335 *newv && (isalnum(*newv & 255) || *newv == '_');
1336 newv ++);
1337
1338 ch = *newv;
1339 *newv = '\0';
1340
1341 if ((var = find_variable(v)) != NULL)
1342 {
1343 if (!var->value || !var->value->value || !var->value->value[0])
1344 temp = 0;
1345 else if (isdigit(var->value->value[0] & 255) ||
1346 var->value->value[0] == '-' ||
1347 var->value->value[0] == '+')
1348 temp = strtol(var->value->value, NULL, 0);
1349 else
1350 temp = 1;
1351 }
1352 else
1353 temp = 0;
1354
1355 *newv = ch;
1356 while (isspace(*newv & 255))
1357 newv ++;
1358
1359 if (strncmp(newv, "==", 2))
1360 {
1361 compop = PPDC_EQ;
1362 newv += 2;
1363 }
1364 else if (strncmp(newv, "!=", 2))
1365 {
1366 compop = PPDC_NE;
1367 newv += 2;
1368 }
1369 else if (strncmp(newv, "<=", 2))
1370 {
1371 compop = PPDC_LE;
1372 newv += 2;
1373 }
1374 else if (*newv == '<')
1375 {
1376 compop = PPDC_LT;
1377 newv ++;
1378 }
1379 else if (strncmp(newv, ">=", 2))
1380 {
1381 compop = PPDC_GE;
1382 newv += 2;
1383 }
1384 else if (*newv == '>')
1385 {
1386 compop = PPDC_GT;
1387 newv ++;
1388 }
1389 else
1390 compop = PPDC_XX;
1391
1392 if (compop != PPDC_XX)
1393 {
1394 while (isspace(*newv & 255))
1395 newv ++;
1396
1397 if (*newv == ')' || !*newv)
1398 return (-1);
1399
1400 if (isdigit(*v & 255) || *v == '-' || *v == '+')
1401 {
1402 // Get the second number...
1403 temp2 = strtol(newv, &newv, 0);
1404 if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
1405 temp == LONG_MIN)
1406 return (-1);
1407 }
1408 else
1409 {
1410 // Lookup the second name...
1411 for (v = newv, newv ++;
1412 *newv && (isalnum(*newv & 255) || *newv == '_');
1413 newv ++);
1414
1415 ch = *newv;
1416 *newv = '\0';
1417
1418 if ((var = find_variable(v)) != NULL)
1419 {
1420 if (!var->value || !var->value->value || !var->value->value[0])
1421 temp2 = 0;
1422 else if (isdigit(var->value->value[0] & 255) ||
1423 var->value->value[0] == '-' ||
1424 var->value->value[0] == '+')
1425 temp2 = strtol(var->value->value, NULL, 0);
1426 else
1427 temp2 = 1;
1428 }
1429 else
1430 temp2 = 0;
1431
1432 *newv = ch;
1433 }
1434
1435 // Do the comparison...
1436 switch (compop)
1437 {
1438 case PPDC_EQ :
1439 temp = temp == temp2;
1440 break;
1441 case PPDC_NE :
1442 temp = temp != temp2;
1443 break;
1444 case PPDC_LT :
1445 temp = temp < temp2;
1446 break;
1447 case PPDC_LE :
1448 temp = temp <= temp2;
1449 break;
1450 case PPDC_GT :
1451 temp = temp > temp2;
1452 break;
1453 case PPDC_GE :
1454 temp = temp >= temp2;
1455 break;
1456 }
1457 }
1458 }
ac884b6a
MS
1459
1460 val |= temp;
1461 v = newv;
1462 }
1463
bdd6c45b 1464 if (*v == ')' && !v[1])
a603edef 1465 return ((int)val);
ac884b6a
MS
1466 else
1467 return (-1);
1468 }
bdd6c45b
MS
1469 else if ((var = find_variable(v)) != NULL)
1470 {
1471 // NAME by itself returns 1 if the #define variable is not blank and
1472 // not "0"...
1473 return (var->value->value && var->value->value[0] &&
1474 strcmp(var->value->value, "0"));
1475 }
ac884b6a 1476 else
bdd6c45b
MS
1477 {
1478 // Anything else is an error...
ac884b6a 1479 return (-1);
bdd6c45b 1480 }
ac884b6a
MS
1481}
1482
1483
1484//
1485// 'ppdcSource::get_integer()' - Get an integer value from a file.
1486//
1487
1488int // O - Integer value
1489ppdcSource::get_integer(ppdcFile *fp) // I - File to read
1490{
1491 char temp[1024]; // String buffer
1492
1493
1494 if (!get_token(fp, temp, sizeof(temp)))
1495 {
61cf44e2
MS
1496 _cupsLangPrintf(stderr, _("ppdc: Expected integer on line %d of %s!\n"),
1497 fp->line, fp->filename);
ac884b6a
MS
1498 return (-1);
1499 }
1500 else
1501 return (get_integer(temp));
1502}
1503
1504
1505//
1506// 'ppdcSource::get_measurement()' - Get a measurement value.
1507//
1508
1509float // O - Measurement value in points
1510ppdcSource::get_measurement(ppdcFile *fp)
1511 // I - File to read
1512{
1513 char buffer[256], // Number buffer
1514 *ptr; // Pointer into buffer
1515 float val; // Measurement value
1516
1517
1518 // Grab a token from the file...
1519 if (!get_token(fp, buffer, sizeof(buffer)))
1520 return (-1.0f);
1521
1522 // Get the floating point value of "s" and skip all digits and decimal points.
1523 val = (float)strtod(buffer, &ptr);
1524
1525 // Check for a trailing unit specifier...
1526 if (!strcasecmp(ptr, "mm"))
1527 val *= 72.0f / 25.4f;
1528 else if (!strcasecmp(ptr, "cm"))
1529 val *= 72.0f / 2.54f;
1530 else if (!strcasecmp(ptr, "m"))
1531 val *= 72.0f / 0.0254f;
1532 else if (!strcasecmp(ptr, "in"))
1533 val *= 72.0f;
1534 else if (!strcasecmp(ptr, "ft"))
1535 val *= 72.0f * 12.0f;
1536 else if (strcasecmp(ptr, "pt") && *ptr)
1537 return (-1.0f);
1538
1539 return (val);
1540}
1541
1542
1543//
1544// 'ppdcSource::get_option()' - Get an option definition.
1545//
1546
1547ppdcOption * // O - Option
1548ppdcSource::get_option(ppdcFile *fp, // I - File to read
1549 ppdcDriver *d, // I - Printer driver
1550 ppdcGroup *g) // I - Current group
1551{
1552 char name[1024], // UI name
1553 *text, // UI text
1554 type[256]; // UI type string
1555 ppdcOptType ot; // Option type value
1556 ppdcOptSection section; // Option section
1557 float order; // Option order
1558 ppdcOption *o; // Option
1559
1560
1561 // Read the Option parameters:
1562 //
1563 // Option name/text type section order
1564 if (!get_token(fp, name, sizeof(name)))
1565 {
61cf44e2
MS
1566 _cupsLangPrintf(stderr,
1567 _("ppdc: Expected option name/text on line %d of %s!\n"),
1568 fp->line, fp->filename);
ac884b6a
MS
1569 return (NULL);
1570 }
1571
1572 if ((text = strchr(name, '/')) != NULL)
1573 *text++ = '\0';
1574 else
1575 text = name;
1576
1577 if (!get_token(fp, type, sizeof(type)))
1578 {
61cf44e2
MS
1579 _cupsLangPrintf(stderr, _("ppdc: Expected option type on line %d of %s!\n"),
1580 fp->line, fp->filename);
ac884b6a
MS
1581 return (NULL);
1582 }
1583
1584 if (!strcasecmp(type, "boolean"))
1585 ot = PPDC_BOOLEAN;
1586 else if (!strcasecmp(type, "pickone"))
1587 ot = PPDC_PICKONE;
1588 else if (!strcasecmp(type, "pickmany"))
1589 ot = PPDC_PICKMANY;
1590 else
1591 {
61cf44e2
MS
1592 _cupsLangPrintf(stderr,
1593 _("ppdc: Invalid option type \"%s\" on line %d of %s!\n"),
1594 type, fp->line, fp->filename);
ac884b6a
MS
1595 return (NULL);
1596 }
1597
1598 if (!get_token(fp, type, sizeof(type)))
1599 {
61cf44e2
MS
1600 _cupsLangPrintf(stderr,
1601 _("ppdc: Expected option section on line %d of %s!\n"),
1602 fp->line, fp->filename);
ac884b6a
MS
1603 return (NULL);
1604 }
1605
1606 if (!strcasecmp(type, "AnySetup"))
1607 section = PPDC_SECTION_ANY;
1608 else if (!strcasecmp(type, "DocumentSetup"))
1609 section = PPDC_SECTION_DOCUMENT;
1610 else if (!strcasecmp(type, "ExitServer"))
1611 section = PPDC_SECTION_EXIT;
1612 else if (!strcasecmp(type, "JCLSetup"))
1613 section = PPDC_SECTION_JCL;
1614 else if (!strcasecmp(type, "PageSetup"))
1615 section = PPDC_SECTION_PAGE;
1616 else if (!strcasecmp(type, "Prolog"))
1617 section = PPDC_SECTION_PROLOG;
1618 else
1619 {
61cf44e2
MS
1620 _cupsLangPrintf(stderr,
1621 _("ppdc: Invalid option section \"%s\" on line %d of "
1622 "%s!\n"), type, fp->line, fp->filename);
ac884b6a
MS
1623 return (NULL);
1624 }
1625
1626 order = get_float(fp);
1627
1628 // See if the option already exists...
1629 if ((o = d->find_option(name)) == NULL)
1630 {
1631 // Nope, add a new one...
1632 o = new ppdcOption(ot, name, text, section, order);
ac884b6a
MS
1633 }
1634 else if (o->type != ot)
1635 {
61cf44e2
MS
1636 _cupsLangPrintf(stderr,
1637 _("ppdc: Option %s redefined with a different type on line "
1638 "%d of %s!\n"), name, fp->line, fp->filename);
ac884b6a
MS
1639 return (NULL);
1640 }
1641
1642 return (o);
1643}
1644
1645
1646//
1647// 'ppdcSource::get_po()' - Get a message catalog.
1648//
1649
1650ppdcCatalog * // O - Message catalog
1651ppdcSource::get_po(ppdcFile *fp) // I - File to read
1652{
1653 char locale[32], // Locale name
1654 poname[1024], // Message catalog filename
1655 basedir[1024], // Base directory
1656 *baseptr, // Pointer into directory
1657 pofilename[1024]; // Full filename of message catalog
1658 ppdcCatalog *cat; // Message catalog
1659
1660
1661 // Read the #po parameters:
1662 //
1663 // #po locale "filename.po"
1664 if (!get_token(fp, locale, sizeof(locale)))
1665 {
61cf44e2
MS
1666 _cupsLangPrintf(stderr,
1667 _("ppdc: Expected locale after #po on line %d of %s!\n"),
1668 fp->line, fp->filename);
ac884b6a
MS
1669 return (NULL);
1670 }
1671
1672 if (!get_token(fp, poname, sizeof(poname)))
1673 {
61cf44e2
MS
1674 _cupsLangPrintf(stderr,
1675 _("ppdc: Expected filename after #po %s on line %d of "
1676 "%s!\n"), locale, fp->line, fp->filename);
ac884b6a
MS
1677 return (NULL);
1678 }
1679
1680 // See if the locale is already loaded...
1681 if (find_po(locale))
1682 {
61cf44e2
MS
1683 _cupsLangPrintf(stderr,
1684 _("ppdc: Duplicate #po for locale %s on line %d of %s!\n"),
1685 locale, fp->line, fp->filename);
ac884b6a
MS
1686 return (NULL);
1687 }
1688
1689 // Figure out the current directory...
1690 strlcpy(basedir, fp->filename, sizeof(basedir));
1691
1692 if ((baseptr = strrchr(basedir, '/')) != NULL)
1693 *baseptr = '\0';
1694 else
1695 strcpy(basedir, ".");
1696
1697 // Find the po file...
745129be
MS
1698 pofilename[0] = '\0';
1699
1700 if (!poname[0] ||
4509bb49 1701 find_include(poname, basedir, pofilename, sizeof(pofilename)))
ac884b6a
MS
1702 {
1703 // Found it, so load it...
1704 cat = new ppdcCatalog(locale, pofilename);
1705
1706 // Reset the filename to the name supplied by the user...
e4572d57 1707 cat->filename->release();
ac884b6a
MS
1708 cat->filename = new ppdcString(poname);
1709
1710 // Return the catalog...
1711 return (cat);
1712 }
1713 else
1714 {
61cf44e2
MS
1715 _cupsLangPrintf(stderr,
1716 _("ppdc: Unable to find #po file %s on line %d of %s!\n"),
1717 poname, fp->line, fp->filename);
ac884b6a
MS
1718 return (NULL);
1719 }
1720}
1721
1722
1723//
1724// 'ppdcSource::get_resolution()' - Get an old-style resolution option.
1725//
1726
1727ppdcChoice * // O - Choice data
1728ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
1729{
1730 char name[1024], // Name
1731 *text, // Text
1732 temp[256], // Temporary string
1733 command[256], // Command string
1734 *commptr; // Pointer into command
1735 int xdpi, ydpi, // X + Y resolution
1736 color_order, // Color order
1737 color_space, // Colorspace
1738 compression, // Compression mode
1739 depth, // Bits per color
1740 row_count, // Row count
1741 row_feed, // Row feed
1742 row_step; // Row step/interval
1743
1744
1745 // Read the resolution parameters:
1746 //
1747 // Resolution colorspace bits row-count row-feed row-step name/text
1748 if (!get_token(fp, temp, sizeof(temp)))
1749 {
61cf44e2
MS
1750 _cupsLangPrintf(stderr,
1751 _("ppdc: Expected override field after Resolution on line "
1752 "%d of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
1753 return (NULL);
1754 }
1755
1756 color_order = get_color_order(temp);
1757 color_space = get_color_space(temp);
1758 compression = get_integer(temp);
1759
1760 depth = get_integer(fp);
1761 row_count = get_integer(fp);
1762 row_feed = get_integer(fp);
1763 row_step = get_integer(fp);
1764
1765 if (!get_token(fp, name, sizeof(name)))
1766 {
61cf44e2
MS
1767 _cupsLangPrintf(stderr,
1768 _("ppdc: Expected name/text after Resolution on line %d of "
1769 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
1770 return (NULL);
1771 }
1772
1773 if ((text = strchr(name, '/')) != NULL)
1774 *text++ = '\0';
1775 else
1776 text = name;
1777
1778 switch (sscanf(name, "%dx%d", &xdpi, &ydpi))
1779 {
1780 case 0 :
61cf44e2
MS
1781 _cupsLangPrintf(stderr,
1782 _("ppdc: Bad resolution name \"%s\" on line %d of "
1783 "%s!\n"), name, fp->line, fp->filename);
ac884b6a
MS
1784 break;
1785 case 1 :
1786 ydpi = xdpi;
1787 break;
1788 }
1789
1790 // Create the necessary PS commands...
1791 snprintf(command, sizeof(command),
1792 "<</HWResolution[%d %d]/cupsBitsPerColor %d/cupsRowCount %d"
1793 "/cupsRowFeed %d/cupsRowStep %d",
1794 xdpi, ydpi, depth, row_count, row_feed, row_step);
1795 commptr = command + strlen(command);
1796
1797 if (color_order >= 0)
1798 {
1799 snprintf(commptr, sizeof(command) - (commptr - command),
1800 "/cupsColorOrder %d", color_order);
1801 commptr += strlen(commptr);
1802 }
1803
1804 if (color_space >= 0)
1805 {
1806 snprintf(commptr, sizeof(command) - (commptr - command),
1807 "/cupsColorSpace %d", color_space);
1808 commptr += strlen(commptr);
1809 }
1810
1811 if (compression >= 0)
1812 {
1813 snprintf(commptr, sizeof(command) - (commptr - command),
1814 "/cupsCompression %d", compression);
1815 commptr += strlen(commptr);
1816 }
1817
1818 snprintf(commptr, sizeof(command) - (commptr - command), ">>setpagedevice");
1819
1820 // Return the new choice...
1821 return (new ppdcChoice(name, text, command));
1822}
1823
1824
1825//
1826// 'ppdcSource::get_simple_profile()' - Get a simple color profile definition.
1827//
1828
1829ppdcProfile * // O - Color profile
1830ppdcSource::get_simple_profile(ppdcFile *fp)
1831 // I - File to read
1832{
1833 char resolution[1024], // Resolution/media type
1834 *media_type; // Media type
1835 float m[9]; // Transform matrix
1836 float kd, rd, g; // Densities and gamma
1837 float red, green, blue; // RGB adjustments
1838 float yellow; // Yellow density
1839 float color; // Color density values
1840
1841
1842 // Get the SimpleColorProfile parameters:
1843 //
1844 // SimpleColorProfile resolution/mediatype black-density yellow-density
1845 // red-density gamma red-adjust green-adjust blue-adjust
1846 if (!get_token(fp, resolution, sizeof(resolution)))
1847 {
61cf44e2
MS
1848 _cupsLangPrintf(stderr,
1849 _("ppdc: Expected resolution/mediatype following "
1850 "SimpleColorProfile on line %d of %s!\n"),
1851 fp->line, fp->filename);
ac884b6a
MS
1852 return (NULL);
1853 }
1854
1855 if ((media_type = strchr(resolution, '/')) != NULL)
1856 *media_type++ = '\0';
1857 else
1858 media_type = resolution;
1859
1860 // Collect the profile parameters...
1861 kd = get_float(fp);
1862 yellow = get_float(fp);
1863 rd = get_float(fp);
1864 g = get_float(fp);
1865 red = get_float(fp);
1866 green = get_float(fp);
1867 blue = get_float(fp);
1868
1869 // Build the color profile...
1870 color = 0.5f * rd / kd - kd;
1871 m[0] = 1.0f; // C
1872 m[1] = color + blue; // C + M (blue)
1873 m[2] = color - green; // C + Y (green)
1874 m[3] = color - blue; // M + C (blue)
1875 m[4] = 1.0f; // M
1876 m[5] = color + red; // M + Y (red)
1877 m[6] = yellow * (color + green); // Y + C (green)
1878 m[7] = yellow * (color - red); // Y + M (red)
1879 m[8] = yellow; // Y
1880
1881 if (m[1] > 0.0f)
1882 {
1883 m[3] -= m[1];
1884 m[1] = 0.0f;
1885 }
1886 else if (m[3] > 0.0f)
1887 {
1888 m[1] -= m[3];
1889 m[3] = 0.0f;
1890 }
1891
1892 if (m[2] > 0.0f)
1893 {
1894 m[6] -= m[2];
1895 m[2] = 0.0f;
1896 }
1897 else if (m[6] > 0.0f)
1898 {
1899 m[2] -= m[6];
1900 m[6] = 0.0f;
1901 }
1902
1903 if (m[5] > 0.0f)
1904 {
1905 m[7] -= m[5];
1906 m[5] = 0.0f;
1907 }
1908 else if (m[7] > 0.0f)
1909 {
1910 m[5] -= m[7];
1911 m[7] = 0.0f;
1912 }
1913
1914 // Return the new profile...
1915 return (new ppdcProfile(resolution, media_type, g, kd, m));
1916}
1917
1918
1919//
1920// 'ppdcSource::get_size()' - Get a media size definition from a file.
1921//
1922
1923ppdcMediaSize * // O - Media size
1924ppdcSource::get_size(ppdcFile *fp) // I - File to read
1925{
1926 char name[1024], // Name
1927 *text; // Text
1928 float width, // Width
1929 length; // Length
1930
1931
1932 // Get the name, text, width, and length:
1933 //
1934 // #media name/text width length
1935 if (!get_token(fp, name, sizeof(name)))
1936 return (NULL);
1937
1938 if ((text = strchr(name, '/')) != NULL)
1939 *text++ = '\0';
1940 else
1941 text = name;
1942
1943 if ((width = get_measurement(fp)) < 0.0f)
1944 return (NULL);
1945
1946 if ((length = get_measurement(fp)) < 0.0f)
1947 return (NULL);
1948
1949 // Return the new media size...
1950 return (new ppdcMediaSize(name, text, width, length, 0.0f, 0.0f, 0.0f, 0.0f));
1951}
1952
1953
1954//
1955// 'ppdcSource::get_token()' - Get a token from a file.
1956//
1957
1958char * // O - Token string or NULL
1959ppdcSource::get_token(ppdcFile *fp, // I - File to read
1960 char *buffer, // I - Buffer
1961 int buflen) // I - Length of buffer
1962{
1963 char *bufptr, // Pointer into string buffer
1964 *bufend; // End of string buffer
1965 int ch, // Character from file
1966 nextch, // Next char in file
1967 quote, // Quote character used...
1968 empty, // Empty input?
1969 startline; // Start line for quote
1970 char name[256], // Name string
1971 *nameptr; // Name pointer
1972 ppdcVariable *var; // Variable pointer
1973
1974
1975 // Mark the beginning and end of the buffer...
1976 bufptr = buffer;
1977 bufend = buffer + buflen - 1;
1978
1979 // Loop intil we've read a token...
1980 quote = 0;
1981 startline = 0;
1982 empty = 1;
1983
1984 while ((ch = fp->get()) != EOF)
1985 {
1986 if (isspace(ch) && !quote)
1987 {
1988 if (empty)
1989 continue;
1990 else
1991 break;
1992 }
1993 else if (ch == '$')
1994 {
1995 // Variable substitution
1996 empty = 0;
1997
1998 for (nameptr = name; (ch = fp->peek()) != EOF;)
1999 {
2000 if (!isalnum(ch) && ch != '_')
2001 break;
2002 else if (nameptr < (name + sizeof(name) - 1))
2003 *nameptr++ = fp->get();
2004 }
2005
2006 if (nameptr == name)
2007 {
2008 // Just substitute this character...
2009 if (ch == '$')
2010 {
2011 // $$ = $
2012 if (bufptr < bufend)
2013 *bufptr++ = fp->get();
2014 }
2015 else
2016 {
2017 // $ch = $ch
61cf44e2
MS
2018 _cupsLangPrintf(stderr,
2019 _("ppdc: Bad variable substitution ($%c) on line %d "
2020 "of %s.\n"), ch, fp->line, fp->filename);
ac884b6a
MS
2021
2022 if (bufptr < bufend)
2023 *bufptr++ = '$';
2024 }
2025 }
2026 else
2027 {
2028 // Substitute the variable value...
2029 *nameptr = '\0';
2030 var = find_variable(name);
2031 if (var)
2032 {
2033 strncpy(bufptr, var->value->value, bufend - bufptr);
2034 bufptr += strlen(var->value->value);
2035 }
2036 else
2037 {
61cf44e2
MS
2038 _cupsLangPrintf(stderr,
2039 _("ppdc: Undefined variable (%s) on line %d of "
2040 "%s.\n"), name, fp->line, fp->filename);
ac884b6a
MS
2041 snprintf(bufptr, bufend - bufptr + 1, "$%s", name);
2042 bufptr += strlen(name) + 1;
2043 }
2044 }
2045 }
2046 else if (ch == '/' && !quote)
2047 {
2048 // Possibly a comment...
2049 nextch = fp->peek();
2050
2051 if (nextch == '*')
2052 {
2053 // C comment...
2054 fp->get();
2055 ch = fp->get();
2056 while ((nextch = fp->get()) != EOF)
2057 {
2058 if (ch == '*' && nextch == '/')
2059 break;
2060
2061 ch = nextch;
2062 }
2063
2064 if (nextch == EOF)
2065 break;
2066 }
2067 else if (nextch == '/')
2068 {
2069 // C++ comment...
2070 while ((nextch = fp->get()) != EOF)
2071 if (nextch == '\n')
2072 break;
2073
2074 if (nextch == EOF)
2075 break;
2076 }
2077 else
2078 {
2079 // Not a comment...
2080 empty = 0;
2081
2082 if (bufptr < bufend)
2083 *bufptr++ = ch;
2084 }
2085 }
2086 else if (ch == '\'' || ch == '\"')
2087 {
2088 empty = 0;
2089
2090 if (quote == ch)
2091 {
2092 // Ending the current quoted string...
2093 quote = 0;
2094 }
2095 else if (quote)
2096 {
2097 // Insert the opposing quote char...
2098 if (bufptr < bufend)
2099 *bufptr++ = ch;
2100 }
2101 else
2102 {
2103 // Start a new quoted string...
2104 startline = fp->line;
2105 quote = ch;
2106 }
2107 }
2108 else if ((ch == '(' || ch == '<') && !quote)
2109 {
2110 empty = 0;
2111 quote = ch;
2112 startline = fp->line;
2113
2114 if (bufptr < bufend)
2115 *bufptr++ = ch;
2116 }
2117 else if ((ch == ')' && quote == '(') || (ch == '>' && quote == '<'))
2118 {
2119 quote = 0;
2120
2121 if (bufptr < bufend)
2122 *bufptr++ = ch;
2123 }
2124 else if (ch == '\\')
2125 {
2126 empty = 0;
2127
2128 if ((ch = fp->get()) == EOF)
2129 break;
2130
2131 if (bufptr < bufend)
2132 *bufptr++ = ch;
2133 }
2134 else if (bufptr < bufend)
2135 {
2136 empty = 0;
2137
2138 *bufptr++ = ch;
2139
2140 if ((ch == '{' || ch == '}') && !quote)
2141 break;
2142 }
2143 }
2144
2145 if (quote)
2146 {
61cf44e2
MS
2147 _cupsLangPrintf(stderr,
2148 _("ppdc: Unterminated string starting with %c on line %d "
2149 "of %s!\n"), quote, startline, fp->filename);
ac884b6a
MS
2150 return (NULL);
2151 }
2152
2153 if (empty)
2154 return (NULL);
2155 else
2156 {
2157 *bufptr = '\0';
2158// puts(buffer);
2159 return (buffer);
2160 }
2161}
2162
2163
2164//
2165// 'ppdcSource::get_variable()' - Get a variable definition.
2166//
2167
2168ppdcVariable * // O - Variable
2169ppdcSource::get_variable(ppdcFile *fp) // I - File to read
2170{
2171 char name[1024], // Name
2172 value[1024]; // Value
2173
2174
2175 // Get the name and value:
2176 //
2177 // #define name value
2178 if (!get_token(fp, name, sizeof(name)))
2179 return (NULL);
2180
2181 if (!get_token(fp, value, sizeof(value)))
2182 return (NULL);
2183
2184 // Set the variable...
2185 return (set_variable(name, value));
2186}
2187
2188
2189//
2190// 'ppdcSource::quotef()' - Write a formatted, quoted string...
2191//
2192
2193int // O - Number bytes on success, -1 on failure
2194ppdcSource::quotef(cups_file_t *fp, // I - File to write to
2195 const char *format, // I - Printf-style format string
2196 ...) // I - Additional args as needed
2197{
2198 va_list ap; // Pointer to additional arguments
2199 int bytes; // Bytes written
2200 char sign, // Sign of format width
2201 size, // Size character (h, l, L)
2202 type; // Format type character
2203 const char *bufformat; // Start of format
2204 int width, // Width of field
2205 prec; // Number of characters of precision
2206 char tformat[100]; // Temporary format string for fprintf()
2207 char *s; // Pointer to string
2208 int slen; // Length of string
2209 int i; // Looping var
2210
2211
2212 // Range check input...
2213 if (!fp || !format)
2214 return (-1);
2215
2216 // Loop through the format string, formatting as needed...
2217 va_start(ap, format);
2218
2219 bytes = 0;
2220
2221 while (*format)
2222 {
2223 if (*format == '%')
2224 {
2225 bufformat = format;
2226 format ++;
2227
2228 if (*format == '%')
2229 {
2230 cupsFilePutChar(fp, *format++);
2231 bytes ++;
2232 continue;
2233 }
2234 else if (strchr(" -+#\'", *format))
2235 sign = *format++;
2236 else
2237 sign = 0;
2238
2239 width = 0;
2240 while (isdigit(*format))
2241 width = width * 10 + *format++ - '0';
2242
2243 if (*format == '.')
2244 {
2245 format ++;
2246 prec = 0;
2247
2248 while (isdigit(*format))
2249 prec = prec * 10 + *format++ - '0';
2250 }
2251 else
2252 prec = -1;
2253
2254 if (*format == 'l' && format[1] == 'l')
2255 {
2256 size = 'L';
2257 format += 2;
2258 }
2259 else if (*format == 'h' || *format == 'l' || *format == 'L')
2260 size = *format++;
2261
2262 if (!*format)
2263 break;
2264
2265 type = *format++;
2266
2267 switch (type)
2268 {
2269 case 'E' : // Floating point formats
2270 case 'G' :
2271 case 'e' :
2272 case 'f' :
2273 case 'g' :
2274 if ((format - bufformat + 1) > (int)sizeof(tformat))
2275 break;
2276
2277 strncpy(tformat, bufformat, format - bufformat);
2278 tformat[format - bufformat] = '\0';
2279
2280 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, double));
2281 break;
2282
2283 case 'B' : // Integer formats
2284 case 'X' :
2285 case 'b' :
2286 case 'd' :
2287 case 'i' :
2288 case 'o' :
2289 case 'u' :
2290 case 'x' :
2291 if ((format - bufformat + 1) > (int)sizeof(tformat))
2292 break;
2293
2294 strncpy(tformat, bufformat, format - bufformat);
2295 tformat[format - bufformat] = '\0';
2296
2297 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
2298 break;
2299
2300 case 'p' : // Pointer value
2301 if ((format - bufformat + 1) > (int)sizeof(tformat))
2302 break;
2303
2304 strncpy(tformat, bufformat, format - bufformat);
2305 tformat[format - bufformat] = '\0';
2306
2307 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, void *));
2308 break;
2309
2310 case 'c' : // Character or character array
2311 if (width <= 1)
2312 {
2313 bytes ++;
2314 cupsFilePutChar(fp, va_arg(ap, int));
2315 }
2316 else
2317 {
2318 cupsFileWrite(fp, va_arg(ap, char *), width);
2319 bytes += width;
2320 }
2321 break;
2322
2323 case 's' : // String
2324 if ((s = va_arg(ap, char *)) == NULL)
2325 s = (char *)"(nil)";
2326
2327 slen = strlen(s);
2328 if (slen > width && prec != width)
2329 width = slen;
2330
2331 if (slen > width)
2332 slen = width;
2333
2334 if (sign != '-')
2335 {
2336 for (i = width - slen; i > 0; i --, bytes ++)
2337 cupsFilePutChar(fp, ' ');
2338 }
2339
2340 for (i = slen; i > 0; i --, s ++, bytes ++)
2341 {
2342 if (*s == '\\' || *s == '\"')
2343 {
2344 cupsFilePutChar(fp, '\\');
2345 bytes ++;
2346 }
2347
2348 cupsFilePutChar(fp, *s);
2349 }
2350
2351 if (sign == '-')
2352 {
2353 for (i = width - slen; i > 0; i --, bytes ++)
2354 cupsFilePutChar(fp, ' ');
2355 }
2356 break;
2357 }
2358 }
2359 else
2360 {
2361 cupsFilePutChar(fp, *format++);
2362 bytes ++;
2363 }
2364 }
2365
2366 va_end(ap);
2367
2368 // Return the number of characters written.
2369 return (bytes);
2370}
2371
2372
2373//
2374// 'ppdcSource::read_file()' - Read a driver source file.
2375//
2376
2377void
4509bb49
MS
2378ppdcSource::read_file(const char *f, // I - File to read
2379 cups_file_t *ffp) // I - File pointer to use
ac884b6a 2380{
4509bb49 2381 ppdcFile *fp = new ppdcFile(f, ffp);
ac884b6a
MS
2382 scan_file(fp);
2383 delete fp;
bdd6c45b
MS
2384
2385 if (cond_current != cond_stack)
61cf44e2 2386 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"), f);
ac884b6a
MS
2387}
2388
2389
2390//
2391// 'ppdcSource::scan_file()' - Scan a driver source file.
2392//
2393
2394void
2395ppdcSource::scan_file(ppdcFile *fp, // I - File to read
2396 ppdcDriver *td, // I - Driver template
2397 bool inc) // I - Including?
2398{
2399 ppdcDriver *d; // Current driver
2400 ppdcGroup *g, // Current group
2401 *general, // General options group
2402 *install; // Installable options group
2403 ppdcOption *o; // Current option
2404 ppdcChoice *c; // Current choice
2405 char temp[256], // Token from file...
2406 *ptr; // Pointer into token
2407 int isdefault; // Default option?
2408
2409
2410 // Initialize things as needed...
2411 if (inc && td)
2412 d = td;
2413 else
2414 d = new ppdcDriver(td);
2415
2416 if ((general = d->find_group("General")) == NULL)
2417 {
2418 general = new ppdcGroup("General", NULL);
2419 d->add_group(general);
2420 }
2421
2422 if ((install = d->find_group("InstallableOptions")) == NULL)
2423 {
2424 install = new ppdcGroup("InstallableOptions", "Installable Options");
2425 d->add_group(install);
2426 }
2427
2428 // Loop until EOF or }
2429 o = 0;
2430 g = general;
bdd6c45b 2431
ac884b6a
MS
2432 while (get_token(fp, temp, sizeof(temp)))
2433 {
2434 if (temp[0] == '*')
2435 {
2436 // Mark the next choice as the default
2437 isdefault = 1;
2438
2439 for (ptr = temp; ptr[1]; ptr ++)
2440 *ptr = ptr[1];
2441
2442 *ptr = '\0';
2443 }
2444 else
2445 {
2446 // Don't mark the next choice as the default
2447 isdefault = 0;
2448 }
2449
2450 if (!strcasecmp(temp, "}"))
2451 {
2452 // Close this one out...
2453 break;
2454 }
2455 else if (!strcasecmp(temp, "{"))
2456 {
2457 // Open a new child...
2458 scan_file(fp, d);
2459 }
bdd6c45b
MS
2460 else if (!strcasecmp(temp, "#if"))
2461 {
2462 if ((cond_current - cond_stack) >= 100)
2463 {
61cf44e2
MS
2464 _cupsLangPrintf(stderr,
2465 _("ppdc: Too many nested #if's on line %d of %s!\n"),
2466 fp->line, fp->filename);
bdd6c45b
MS
2467 break;
2468 }
2469
2470 cond_current ++;
2471 if (get_integer(fp))
2472 *cond_current = PPDC_COND_SATISFIED;
2473 else
2474 {
2475 *cond_current = PPDC_COND_SKIP;
2476 cond_state |= PPDC_COND_SKIP;
2477 }
2478 }
2479 else if (!strcasecmp(temp, "#elif"))
2480 {
2481 if (cond_current == cond_stack)
2482 {
61cf44e2
MS
2483 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
2484 fp->line, fp->filename);
bdd6c45b
MS
2485 break;
2486 }
2487
2488 if (*cond_current & PPDC_COND_SATISFIED)
2489 {
2490 get_integer(fp);
2491 *cond_current |= PPDC_COND_SKIP;
2492 }
2493 else if (get_integer(fp))
2494 {
2495 *cond_current |= PPDC_COND_SATISFIED;
2496 *cond_current &= ~PPDC_COND_SKIP;
2497 }
2498 else
2499 *cond_current |= PPDC_COND_SKIP;
2500
2501 // Update the current state
2502 int *cond_temp = cond_current; // Temporary stack pointer
2503
2504 cond_state = PPDC_COND_NORMAL;
2505 while (cond_temp > cond_stack)
2506 if (*cond_temp & PPDC_COND_SKIP)
2507 {
2508 cond_state = PPDC_COND_SKIP;
2509 break;
2510 }
2511 else
2512 cond_temp --;
2513 }
2514 else if (!strcasecmp(temp, "#else"))
2515 {
2516 if (cond_current == cond_stack)
2517 {
61cf44e2
MS
2518 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
2519 fp->line, fp->filename);
bdd6c45b
MS
2520 break;
2521 }
2522
2523 if (*cond_current & PPDC_COND_SATISFIED)
2524 *cond_current |= PPDC_COND_SKIP;
2525 else
2526 {
2527 *cond_current |= PPDC_COND_SATISFIED;
2528 *cond_current &= ~PPDC_COND_SKIP;
2529 }
2530
2531 // Update the current state
2532 int *cond_temp = cond_current; // Temporary stack pointer
2533
2534 cond_state = PPDC_COND_NORMAL;
2535 while (cond_temp > cond_stack)
2536 if (*cond_temp & PPDC_COND_SKIP)
2537 {
2538 cond_state = PPDC_COND_SKIP;
2539 break;
2540 }
2541 else
2542 cond_temp --;
2543 }
2544 else if (!strcasecmp(temp, "#endif"))
2545 {
2546 if (cond_current == cond_stack)
2547 {
61cf44e2
MS
2548 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
2549 fp->line, fp->filename);
bdd6c45b
MS
2550 break;
2551 }
2552
2553 cond_current --;
2554
2555 // Update the current state
2556 int *cond_temp = cond_current; // Temporary stack pointer
2557
2558 cond_state = PPDC_COND_NORMAL;
2559 while (cond_temp > cond_stack)
2560 if (*cond_temp & PPDC_COND_SKIP)
2561 {
2562 cond_state = PPDC_COND_SKIP;
2563 break;
2564 }
2565 else
2566 cond_temp --;
2567 }
ac884b6a
MS
2568 else if (!strcasecmp(temp, "#define"))
2569 {
2570 // Get the variable...
2571 get_variable(fp);
2572 }
2573 else if (!strcasecmp(temp, "#include"))
2574 {
2575 // #include filename
2576 char basedir[1024], // Base directory
2577 *baseptr, // Pointer into directory
2578 inctemp[1024], // Initial filename
2579 incname[1024]; // Include filename
2580 ppdcFile *incfile; // Include file
bdd6c45b
MS
2581 int *old_current = cond_current;
2582 // Previous current stack
ac884b6a
MS
2583
2584
2585 // Get the include name...
2586 if (!get_token(fp, inctemp, sizeof(inctemp)))
2587 {
61cf44e2
MS
2588 _cupsLangPrintf(stderr,
2589 _("ppdc: Expected include filename on line %d of "
2590 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
2591 break;
2592 }
2593
bdd6c45b
MS
2594 if (cond_state)
2595 continue;
2596
ac884b6a
MS
2597 // Figure out the current directory...
2598 strlcpy(basedir, fp->filename, sizeof(basedir));
2599
2600 if ((baseptr = strrchr(basedir, '/')) != NULL)
bdd6c45b 2601 *baseptr = '\0';
ac884b6a 2602 else
bdd6c45b 2603 strcpy(basedir, ".");
ac884b6a
MS
2604
2605 // Find the include file...
2606 if (find_include(inctemp, basedir, incname, sizeof(incname)))
2607 {
2608 // Open the include file, scan it, and then close it...
2609 incfile = new ppdcFile(incname);
2610 scan_file(incfile, d, true);
2611 delete incfile;
bdd6c45b
MS
2612
2613 if (cond_current != old_current)
61cf44e2
MS
2614 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"),
2615 incname);
ac884b6a
MS
2616 }
2617 else
2618 {
bdd6c45b 2619 // Can't find it!
61cf44e2
MS
2620 _cupsLangPrintf(stderr,
2621 _("ppdc: Unable to find include file \"%s\" on line %d "
2622 "of %s!\n"), inctemp, fp->line, fp->filename);
ac884b6a
MS
2623 break;
2624 }
2625 }
2626 else if (!strcasecmp(temp, "#media"))
2627 {
2628 ppdcMediaSize *m; // Media size
2629
2630
2631 // Get a media size...
2632 m = get_size(fp);
2633 if (m)
bdd6c45b
MS
2634 {
2635 if (cond_state)
2636 m->release();
2637 else
2638 sizes->add(m);
2639 }
ac884b6a
MS
2640 }
2641 else if (!strcasecmp(temp, "#po"))
2642 {
2643 ppdcCatalog *cat; // Message catalog
2644
2645
2646 // Get a message catalog...
2647 cat = get_po(fp);
2648 if (cat)
bdd6c45b
MS
2649 {
2650 if (cond_state)
2651 cat->release();
2652 else
2653 po_files->add(cat);
2654 }
ac884b6a 2655 }
bdd6c45b
MS
2656 else if (!strcasecmp(temp, "Attribute") ||
2657 !strcasecmp(temp, "LocAttribute"))
ac884b6a
MS
2658 {
2659 ppdcAttr *a; // Attribute
2660
2661
2662 // Get an attribute...
bdd6c45b 2663 a = get_attr(fp, !strcasecmp(temp, "LocAttribute"));
ac884b6a 2664 if (a)
bdd6c45b
MS
2665 {
2666 if (cond_state)
2667 a->release();
2668 else
2669 d->add_attr(a);
2670 }
ac884b6a
MS
2671 }
2672 else if (!strcasecmp(temp, "Choice"))
2673 {
2674 // Get a choice...
bdd6c45b
MS
2675 c = get_choice(fp);
2676 if (!c)
2677 break;
2678
2679 if (cond_state)
2680 {
2681 c->release();
2682 continue;
2683 }
2684
2685 // Add it to the current option...
ac884b6a
MS
2686 if (!o)
2687 {
61cf44e2
MS
2688 _cupsLangPrintf(stderr,
2689 _("ppdc: Choice found on line %d of %s with no "
2690 "Option!\n"), fp->line, fp->filename);
ac884b6a
MS
2691 break;
2692 }
2693
ac884b6a
MS
2694 o->add_choice(c);
2695
2696 if (isdefault)
2697 o->set_defchoice(c);
2698 }
2699 else if (!strcasecmp(temp, "ColorDevice"))
2700 {
2701 // ColorDevice boolean
bdd6c45b
MS
2702 if (cond_state)
2703 get_boolean(fp);
2704 else
2705 d->color_device = get_boolean(fp);
ac884b6a
MS
2706 }
2707 else if (!strcasecmp(temp, "ColorModel"))
2708 {
2709 // Get the color model
2710 c = get_color_model(fp);
2711 if (!c)
2712 continue;
2713
bdd6c45b
MS
2714 if (cond_state)
2715 {
2716 c->release();
2717 continue;
2718 }
2719
ac884b6a
MS
2720 // Add the choice to the ColorModel option...
2721 if ((o = d->find_option("ColorModel")) == NULL)
2722 {
2723 // Create the ColorModel option...
2724 o = new ppdcOption(PPDC_PICKONE, "ColorModel", "Color Mode", PPDC_SECTION_ANY, 10.0f);
2725 g = general;
2726 g->add_option(o);
2727 }
2728
2729 o->add_choice(c);
2730
2731 if (isdefault)
2732 o->set_defchoice(c);
2733
2734 o = NULL;
2735 }
2736 else if (!strcasecmp(temp, "ColorProfile"))
2737 {
2738 ppdcProfile *p; // Color profile
2739
2740
2741 // Get the color profile...
2742 p = get_color_profile(fp);
2743
2744 if (p)
bdd6c45b
MS
2745 {
2746 if (cond_state)
2747 p->release();
2748 else
2749 d->profiles->add(p);
2750 }
ac884b6a
MS
2751 }
2752 else if (!strcasecmp(temp, "Copyright"))
2753 {
2754 // Copyright string
2755 char copytemp[8192], // Copyright string
2756 *copyptr, // Pointer into string
2757 *copyend; // Pointer to end of string
2758
2759
2760 // Get the copyright string...
2761 if (!get_token(fp, copytemp, sizeof(temp)))
2762 {
61cf44e2
MS
2763 _cupsLangPrintf(stderr,
2764 _("ppdc: Expected string after Copyright on line %d "
2765 "of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
2766 break;
2767 }
2768
bdd6c45b
MS
2769 if (cond_state)
2770 continue;
2771
ac884b6a
MS
2772 // Break it up into individual lines...
2773 for (copyptr = copytemp; copyptr; copyptr = copyend)
2774 {
2775 if ((copyend = strchr(copyptr, '\n')) != NULL)
2776 *copyend++ = '\0';
2777
2778 d->copyright->add(new ppdcString(copyptr));
2779 }
2780 }
2781 else if (!strcasecmp(temp, "CustomMedia"))
2782 {
2783 ppdcMediaSize *m; // Media size
2784
2785
2786 // Get a custom media size...
2787 m = get_custom_size(fp);
bdd6c45b
MS
2788
2789 if (cond_state)
2790 {
2791 m->release();
2792 continue;
2793 }
2794
ac884b6a
MS
2795 if (m)
2796 d->sizes->add(m);
2797
2798 if (isdefault)
2799 d->set_default_size(m);
2800 }
2801 else if (!strcasecmp(temp, "Cutter"))
2802 {
2803 // Cutter boolean
2804 int have_cutter; // Have a paper cutter?
2805
2806
2807 have_cutter = get_boolean(fp);
bdd6c45b 2808 if (have_cutter <= 0 || cond_state)
ac884b6a
MS
2809 continue;
2810
2811 if ((o = d->find_option("CutMedia")) == NULL)
2812 {
2813 o = new ppdcOption(PPDC_BOOLEAN, "CutMedia", "Cut Media", PPDC_SECTION_ANY, 10.0f);
2814
2815 g = general;
2816 g->add_option(o);
2817
2818 c = new ppdcChoice("False", NULL, "<</CutMedia 0>>setpagedevice");
2819 o->add_choice(c);
2820 o->set_defchoice(c);
2821
2822 c = new ppdcChoice("True", NULL, "<</CutMedia 4>>setpagedevice");
2823 o->add_choice(c);
2824 }
2825
2826 o = NULL;
2827 }
2828 else if (!strcasecmp(temp, "Darkness"))
2829 {
2830 // Get the darkness choice...
2831 c = get_generic(fp, "Darkness", NULL, "cupsCompression");
2832 if (!c)
2833 continue;
2834
bdd6c45b
MS
2835 if (cond_state)
2836 {
2837 c->release();
2838 continue;
2839 }
2840
ac884b6a
MS
2841 // Add the choice to the cupsDarkness option...
2842 if ((o = d->find_option("cupsDarkness")) == NULL)
2843 {
2844 // Create the cupsDarkness option...
2845 o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
2846 g = general;
2847 g->add_option(o);
2848 }
2849
2850 o->add_choice(c);
2851
2852 if (isdefault)
2853 o->set_defchoice(c);
2854
2855 o = NULL;
2856 }
2857 else if (!strcasecmp(temp, "DriverType"))
2858 {
2859 int i; // Looping var
2860
2861
2862 // DriverType keyword
2863 if (!get_token(fp, temp, sizeof(temp)))
2864 {
61cf44e2
MS
2865 _cupsLangPrintf(stderr,
2866 _("ppdc: Expected driver type keyword following "
2867 "DriverType on line %d of %s!\n"),
2868 fp->line, fp->filename);
ac884b6a
MS
2869 continue;
2870 }
2871
bdd6c45b
MS
2872 if (cond_state)
2873 continue;
2874
ac884b6a
MS
2875 for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++)
2876 if (!strcasecmp(temp, driver_types[i]))
2877 break;
2878
2879 if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0])))
2880 d->type = (ppdcDrvType)i;
2881 else if (!strcasecmp(temp, "dymo"))
2882 d->type = PPDC_DRIVER_LABEL;
2883 else
61cf44e2
MS
2884 _cupsLangPrintf(stderr,
2885 _("ppdc: Unknown driver type %s on line %d of %s!\n"),
2886 temp, fp->line, fp->filename);
ac884b6a
MS
2887 }
2888 else if (!strcasecmp(temp, "Duplex"))
2889 get_duplex(fp, d);
2890 else if (!strcasecmp(temp, "Filter"))
2891 {
2892 ppdcFilter *f; // Filter
2893
2894
2895 // Get the filter value...
2896 f = get_filter(fp);
2897 if (f)
bdd6c45b
MS
2898 {
2899 if (cond_state)
2900 f->release();
2901 else
2902 d->filters->add(f);
2903 }
ac884b6a
MS
2904 }
2905 else if (!strcasecmp(temp, "Finishing"))
2906 {
2907 // Get the finishing choice...
2908 c = get_generic(fp, "Finishing", "OutputType", NULL);
2909 if (!c)
2910 continue;
2911
bdd6c45b
MS
2912 if (cond_state)
2913 {
2914 c->release();
2915 continue;
2916 }
2917
ac884b6a
MS
2918 // Add the choice to the cupsFinishing option...
2919 if ((o = d->find_option("cupsFinishing")) == NULL)
2920 {
2921 // Create the cupsFinishing option...
2922 o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
2923 g = general;
2924 g->add_option(o);
2925 }
2926
2927 o->add_choice(c);
2928
2929 if (isdefault)
2930 o->set_defchoice(c);
2931
2932 o = NULL;
2933 }
2934 else if (!strcasecmp(temp, "Font") ||
2935 !strcasecmp(temp, "#font"))
2936 {
2937 ppdcFont *f; // Font
2938
2939
2940 // Get a font...
2941 f = get_font(fp);
2942 if (f)
2943 {
bdd6c45b
MS
2944 if (cond_state)
2945 f->release();
2946 else
2947 {
2948 if (!strcasecmp(temp, "#font"))
2949 base_fonts->add(f);
2950 else
2951 d->add_font(f);
ac884b6a 2952
bdd6c45b
MS
2953 if (isdefault)
2954 d->set_default_font(f);
2955 }
ac884b6a
MS
2956 }
2957 }
2958 else if (!strcasecmp(temp, "Group"))
2959 {
2960 // Get a group...
bdd6c45b
MS
2961 ppdcGroup *tempg = get_group(fp, d);
2962
2963 if (!tempg)
ac884b6a 2964 break;
bdd6c45b
MS
2965
2966 if (cond_state)
2967 {
2968 if (!d->find_group(tempg->name->value))
2969 tempg->release();
2970 }
2971 else
2972 {
2973 if (!d->find_group(tempg->name->value))
2974 d->add_group(tempg);
2975
2976 g = tempg;
2977 }
ac884b6a
MS
2978 }
2979 else if (!strcasecmp(temp, "HWMargins"))
2980 {
2981 // HWMargins left bottom right top
2982 d->left_margin = get_measurement(fp);
2983 d->bottom_margin = get_measurement(fp);
2984 d->right_margin = get_measurement(fp);
2985 d->top_margin = get_measurement(fp);
2986 }
2987 else if (!strcasecmp(temp, "InputSlot"))
2988 {
2989 // Get the input slot choice...
2990 c = get_generic(fp, "InputSlot", NULL, "MediaPosition");
2991 if (!c)
2992 continue;
2993
bdd6c45b
MS
2994 if (cond_state)
2995 {
2996 c->release();
2997 continue;
2998 }
2999
ac884b6a
MS
3000 // Add the choice to the InputSlot option...
3001 if ((o = d->find_option("InputSlot")) == NULL)
3002 {
3003 // Create the InputSlot option...
3004 o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
3005 PPDC_SECTION_ANY, 10.0f);
3006 g = general;
3007 g->add_option(o);
3008 }
3009
3010 o->add_choice(c);
3011
3012 if (isdefault)
3013 o->set_defchoice(c);
3014
3015 o = NULL;
3016 }
3017 else if (!strcasecmp(temp, "Installable"))
3018 {
3019 // Get the installable option...
3020 o = get_installable(fp);
3021
3022 // Add it as needed...
3023 if (o)
3024 {
bdd6c45b
MS
3025 if (cond_state)
3026 o->release();
3027 else
3028 install->add_option(o);
3029
ac884b6a
MS
3030 o = NULL;
3031 }
3032 }
3033 else if (!strcasecmp(temp, "ManualCopies"))
3034 {
3035 // ManualCopies boolean
bdd6c45b
MS
3036 if (cond_state)
3037 get_boolean(fp);
3038 else
3039 d->manual_copies = get_boolean(fp);
ac884b6a
MS
3040 }
3041 else if (!strcasecmp(temp, "Manufacturer"))
3042 {
3043 // Manufacturer name
3044 char name[256]; // Model name string
3045
3046
3047 if (!get_token(fp, name, sizeof(name)))
3048 {
61cf44e2
MS
3049 _cupsLangPrintf(stderr,
3050 _("ppdc: Expected name after Manufacturer on line %d "
3051 "of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
3052 break;
3053 }
3054
bdd6c45b
MS
3055 if (!cond_state)
3056 d->set_manufacturer(name);
ac884b6a
MS
3057 }
3058 else if (!strcasecmp(temp, "MaxSize"))
3059 {
3060 // MaxSize width length
bdd6c45b
MS
3061 if (cond_state)
3062 {
3063 get_measurement(fp);
3064 get_measurement(fp);
3065 }
3066 else
3067 {
3068 d->max_width = get_measurement(fp);
3069 d->max_length = get_measurement(fp);
3070 }
ac884b6a
MS
3071 }
3072 else if (!strcasecmp(temp, "MediaSize"))
3073 {
3074 // MediaSize keyword
3075 char name[41]; // Media size name
3076 ppdcMediaSize *m, // Matching media size...
3077 *dm; // Driver media size...
3078
3079
3080 if (get_token(fp, name, sizeof(name)) == NULL)
3081 {
61cf44e2
MS
3082 _cupsLangPrintf(stderr,
3083 _("ppdc: Expected name after MediaSize on line %d of "
3084 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3085 break;
3086 }
3087
bdd6c45b
MS
3088 if (cond_state)
3089 continue;
3090
ac884b6a
MS
3091 m = find_size(name);
3092
3093 if (!m)
3094 {
61cf44e2
MS
3095 _cupsLangPrintf(stderr,
3096 _("ppdc: Unknown media size \"%s\" on line %d of "
3097 "%s!\n"), name, fp->line, fp->filename);
ac884b6a
MS
3098 break;
3099 }
3100
3101 // Add this size to the driver...
3102 dm = new ppdcMediaSize(m->name->value, m->text->value,
3103 m->width, m->length, d->left_margin,
3104 d->bottom_margin, d->right_margin,
3105 d->top_margin);
3106 d->sizes->add(dm);
3107
3108 if (isdefault)
3109 d->set_default_size(dm);
3110 }
3111 else if (!strcasecmp(temp, "MediaType"))
3112 {
3113 // Get the media type choice...
3114 c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType");
3115 if (!c)
3116 continue;
3117
bdd6c45b
MS
3118 if (cond_state)
3119 {
3120 c->release();
3121 continue;
3122 }
3123
ac884b6a
MS
3124 // Add the choice to the MediaType option...
3125 if ((o = d->find_option("MediaType")) == NULL)
3126 {
3127 // Create the MediaType option...
3128 o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
3129 PPDC_SECTION_ANY, 10.0f);
3130 g = general;
3131 g->add_option(o);
3132 }
3133
3134 o->add_choice(c);
3135
3136 if (isdefault)
3137 o->set_defchoice(c);
3138
3139 o = NULL;
3140 }
3141 else if (!strcasecmp(temp, "MinSize"))
3142 {
3143 // MinSize width length
bdd6c45b
MS
3144 if (cond_state)
3145 {
3146 get_measurement(fp);
3147 get_measurement(fp);
3148 }
3149 else
3150 {
3151 d->min_width = get_measurement(fp);
3152 d->min_length = get_measurement(fp);
3153 }
ac884b6a
MS
3154 }
3155 else if (!strcasecmp(temp, "ModelName"))
3156 {
3157 // ModelName name
3158 char name[256]; // Model name string
3159
3160
3161 if (!get_token(fp, name, sizeof(name)))
3162 {
61cf44e2
MS
3163 _cupsLangPrintf(stderr,
3164 _("ppdc: Expected name after ModelName on line %d of "
3165 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3166 break;
3167 }
3168
bdd6c45b
MS
3169 if (!cond_state)
3170 d->set_model_name(name);
ac884b6a
MS
3171 }
3172 else if (!strcasecmp(temp, "ModelNumber"))
3173 {
3174 // ModelNumber number
bdd6c45b
MS
3175 if (cond_state)
3176 get_integer(fp);
3177 else
3178 d->model_number = get_integer(fp);
ac884b6a
MS
3179 }
3180 else if (!strcasecmp(temp, "Option"))
3181 {
3182 // Get an option...
bdd6c45b
MS
3183 ppdcOption *tempo = get_option(fp, d, g);
3184
3185 if (!tempo)
ac884b6a 3186 break;
bdd6c45b
MS
3187
3188 if (cond_state)
3189 {
3190 if (!g->find_option(tempo->name->value))
3191 tempo->release();
3192 }
3193 else
3194 {
3195 if (!g->find_option(tempo->name->value))
3196 g->add_option(tempo);
3197
3198 o = tempo;
3199 }
3200 }
3201 else if (!strcasecmp(temp, "FileName"))
3202 {
3203 // FileName name
3204 char name[256]; // Filename string
3205
3206
3207 if (!get_token(fp, name, sizeof(name)))
3208 {
61cf44e2
MS
3209 _cupsLangPrintf(stderr,
3210 _("ppdc: Expected name after FileName on line %d of "
3211 "%s!\n"), fp->line, fp->filename);
bdd6c45b
MS
3212 break;
3213 }
3214
3215 if (!cond_state)
3216 d->set_file_name(name);
ac884b6a
MS
3217 }
3218 else if (!strcasecmp(temp, "PCFileName"))
3219 {
3220 // PCFileName name
bdd6c45b 3221 char name[256]; // PC filename string
ac884b6a
MS
3222
3223
3224 if (!get_token(fp, name, sizeof(name)))
3225 {
61cf44e2
MS
3226 _cupsLangPrintf(stderr,
3227 _("ppdc: Expected name after PCFileName on line %d of "
3228 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3229 break;
3230 }
3231
bdd6c45b
MS
3232 if (!cond_state)
3233 d->set_pc_file_name(name);
ac884b6a
MS
3234 }
3235 else if (!strcasecmp(temp, "Resolution"))
3236 {
3237 // Get the resolution choice...
3238 c = get_resolution(fp);
3239 if (!c)
3240 continue;
3241
bdd6c45b
MS
3242 if (cond_state)
3243 {
3244 c->release();
3245 continue;
3246 }
3247
ac884b6a
MS
3248 // Add the choice to the Resolution option...
3249 if ((o = d->find_option("Resolution")) == NULL)
3250 {
3251 // Create the Resolution option...
bdd6c45b
MS
3252 o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
3253 10.0f);
ac884b6a
MS
3254 g = general;
3255 g->add_option(o);
3256 }
3257
3258 o->add_choice(c);
3259
3260 if (isdefault)
3261 o->set_defchoice(c);
3262
3263 o = NULL;
3264 }
3265 else if (!strcasecmp(temp, "SimpleColorProfile"))
3266 {
3267 ppdcProfile *p; // Color profile
3268
3269
3270 // Get the color profile...
3271 p = get_simple_profile(fp);
3272
3273 if (p)
bdd6c45b
MS
3274 {
3275 if (cond_state)
3276 p->release();
3277 else
3278 d->profiles->add(p);
3279 }
ac884b6a
MS
3280 }
3281 else if (!strcasecmp(temp, "Throughput"))
3282 {
3283 // Throughput number
bdd6c45b
MS
3284 if (cond_state)
3285 get_integer(fp);
3286 else
3287 d->throughput = get_integer(fp);
ac884b6a
MS
3288 }
3289 else if (!strcasecmp(temp, "UIConstraints"))
3290 {
3291 ppdcConstraint *con; // Constraint
3292
3293
3294 con = get_constraint(fp);
3295
3296 if (con)
bdd6c45b
MS
3297 {
3298 if (cond_state)
3299 con->release();
3300 else
3301 d->constraints->add(con);
3302 }
ac884b6a
MS
3303 }
3304 else if (!strcasecmp(temp, "VariablePaperSize"))
3305 {
3306 // VariablePaperSize boolean
bdd6c45b
MS
3307 if (cond_state)
3308 get_boolean(fp);
3309 else
3310 d->variable_paper_size = get_boolean(fp);
ac884b6a
MS
3311 }
3312 else if (!strcasecmp(temp, "Version"))
3313 {
3314 // Version string
3315 char name[256]; // Model name string
3316
3317
3318 if (!get_token(fp, name, sizeof(name)))
3319 {
61cf44e2
MS
3320 _cupsLangPrintf(stderr,
3321 _("ppdc: Expected string after Version on line %d of "
3322 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3323 break;
3324 }
3325
bdd6c45b
MS
3326 if (!cond_state)
3327 d->set_version(name);
ac884b6a
MS
3328 }
3329 else
3330 {
61cf44e2
MS
3331 _cupsLangPrintf(stderr,
3332 _("ppdc: Unknown token \"%s\" seen on line %d of %s!\n"),
3333 temp, fp->line, fp->filename);
ac884b6a
MS
3334 break;
3335 }
3336 }
3337
3338 // Done processing this block, is there anything to save?
3339 if (!inc)
3340 {
3341 if (!d->pc_file_name || !d->model_name || !d->manufacturer || !d->version ||
3342 !d->sizes->count)
3343 {
3344 // Nothing to save...
3345 d->release();
3346 }
3347 else
3348 {
3349 // Got a driver, save it...
3350 drivers->add(d);
3351 }
3352 }
3353}
3354
3355
3356//
3357// 'ppdcSource::set_variable()' - Set a variable.
3358//
3359
3360ppdcVariable * // O - Variable
3361ppdcSource::set_variable(
3362 const char *name, // I - Name
3363 const char *value) // I - Value
3364{
3365 ppdcVariable *v; // Variable
3366
3367
3368 // See if the variable exists already...
3369 v = find_variable(name);
3370 if (v)
3371 {
3372 // Change the variable value...
3373 v->set_value(value);
3374 }
3375 else
3376 {
3377 // Create a new variable and add it...
3378 v = new ppdcVariable(name, value);
3379 vars->add(v);
3380 }
3381
3382 return (v);
3383}
3384
3385
3386//
3387// 'ppdcSource::write_file()' - Write the current source data to a file.
3388//
3389
3390int // O - 0 on success, -1 on error
3391ppdcSource::write_file(const char *f) // I - File to write
3392{
3393 cups_file_t *fp; // Output file
3394 char bckname[1024]; // Backup file
3395 ppdcDriver *d; // Current driver
3396 ppdcString *st; // Current string
3397 ppdcAttr *a; // Current attribute
3398 ppdcConstraint *co; // Current constraint
3399 ppdcFilter *fi; // Current filter
3400 ppdcFont *fo; // Current font
3401 ppdcGroup *g; // Current group
3402 ppdcOption *o; // Current option
3403 ppdcChoice *ch; // Current choice
3404 ppdcProfile *p; // Current color profile
3405 ppdcMediaSize *si; // Current media size
3406 float left, // Current left margin
3407 bottom, // Current bottom margin
3408 right, // Current right margin
3409 top; // Current top margin
3410 int dtused[PPDC_DRIVER_MAX];// Driver type usage...
3411
3412
3413 // Rename the current file, if any, to .bck...
3414 snprintf(bckname, sizeof(bckname), "%s.bck", f);
3415 rename(f, bckname);
3416
3417 // Open the output file...
3418 fp = cupsFileOpen(f, "w");
3419
3420 if (!fp)
3421 {
3422 // Can't create file; restore backup and return...
3423 rename(bckname, f);
3424 return (-1);
3425 }
3426
3427 cupsFilePuts(fp, "// CUPS PPD Compiler " CUPS_SVERSION "\n\n");
3428
3429 // Include standard files...
3430 cupsFilePuts(fp, "// Include necessary files...\n");
3431 cupsFilePuts(fp, "#include <font.defs>\n");
3432 cupsFilePuts(fp, "#include <media.defs>\n");
3433
3434 memset(dtused, 0, sizeof(dtused));
3435
3436 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3437 if (d->type > PPDC_DRIVER_PS && !dtused[d->type])
3438 {
3439 cupsFilePrintf(fp, "#include <%s.h>\n", driver_types[d->type]);
3440 dtused[d->type] = 1;
3441 }
3442
3443 // Output each driver...
3444 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3445 {
3446 // Start the driver...
3447 cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value, d->model_name->value);
3448 cupsFilePuts(fp, "{\n");
3449
3450 // Write the copyright stings...
3451 for (st = (ppdcString *)d->copyright->first();
3452 st;
3453 st = (ppdcString *)d->copyright->next())
3454 quotef(fp, " Copyright \"%s\"\n", st->value);
3455
3456 // Write other strings and values...
d2354e63 3457 if (d->manufacturer && d->manufacturer->value)
ac884b6a
MS
3458 quotef(fp, " Manufacturer \"%s\"\n", d->manufacturer->value);
3459 if (d->model_name->value)
3460 quotef(fp, " ModelName \"%s\"\n", d->model_name->value);
d2354e63 3461 if (d->file_name && d->file_name->value)
bdd6c45b 3462 quotef(fp, " FileName \"%s\"\n", d->file_name->value);
d2354e63 3463 if (d->pc_file_name && d->pc_file_name->value)
ac884b6a 3464 quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value);
d2354e63 3465 if (d->version && d->version->value)
ac884b6a
MS
3466 quotef(fp, " Version \"%s\"\n", d->version->value);
3467
3468 cupsFilePrintf(fp, " DriverType %s\n", driver_types[d->type]);
3469
3470 if (d->model_number)
3471 {
3472 switch (d->type)
3473 {
3474 case PPDC_DRIVER_ESCP :
3475 cupsFilePuts(fp, " ModelNumber (");
3476
3477 if (d->model_number & ESCP_DOTMATRIX)
3478 cupsFilePuts(fp, " $ESCP_DOTMATRIX");
3479 if (d->model_number & ESCP_MICROWEAVE)
3480 cupsFilePuts(fp, " $ESCP_MICROWEAVE");
3481 if (d->model_number & ESCP_STAGGER)
3482 cupsFilePuts(fp, " $ESCP_STAGGER");
3483 if (d->model_number & ESCP_ESCK)
3484 cupsFilePuts(fp, " $ESCP_ESCK");
3485 if (d->model_number & ESCP_EXT_UNITS)
3486 cupsFilePuts(fp, " $ESCP_EXT_UNITS");
3487 if (d->model_number & ESCP_EXT_MARGINS)
3488 cupsFilePuts(fp, " $ESCP_EXT_MARGINS");
3489 if (d->model_number & ESCP_USB)
3490 cupsFilePuts(fp, " $ESCP_USB");
3491 if (d->model_number & ESCP_PAGE_SIZE)
3492 cupsFilePuts(fp, " $ESCP_PAGE_SIZE");
3493 if (d->model_number & ESCP_RASTER_ESCI)
3494 cupsFilePuts(fp, " $ESCP_RASTER_ESCI");
3495 if (d->model_number & ESCP_REMOTE)
3496 cupsFilePuts(fp, " $ESCP_REMOTE");
3497
3498 cupsFilePuts(fp, ")\n");
3499 break;
3500
3501 case PPDC_DRIVER_PCL :
3502 cupsFilePuts(fp, " ModelNumber (");
3503
3504 if (d->model_number & PCL_PAPER_SIZE)
3505 cupsFilePuts(fp, " $PCL_PAPER_SIZE");
3506 if (d->model_number & PCL_INKJET)
3507 cupsFilePuts(fp, " $PCL_INKJET");
3508 if (d->model_number & PCL_RASTER_END_COLOR)
3509 cupsFilePuts(fp, " $PCL_RASTER_END_COLOR");
3510 if (d->model_number & PCL_RASTER_CID)
3511 cupsFilePuts(fp, " $PCL_RASTER_CID");
3512 if (d->model_number & PCL_RASTER_CRD)
3513 cupsFilePuts(fp, " $PCL_RASTER_CRD");
3514 if (d->model_number & PCL_RASTER_SIMPLE)
3515 cupsFilePuts(fp, " $PCL_RASTER_SIMPLE");
3516 if (d->model_number & PCL_RASTER_RGB24)
3517 cupsFilePuts(fp, " $PCL_RASTER_RGB24");
3518 if (d->model_number & PCL_PJL)
3519 cupsFilePuts(fp, " $PCL_PJL");
3520 if (d->model_number & PCL_PJL_PAPERWIDTH)
3521 cupsFilePuts(fp, " $PCL_PJL_PAPERWIDTH");
3522 if (d->model_number & PCL_PJL_HPGL2)
3523 cupsFilePuts(fp, " $PCL_PJL_HPGL2");
3524 if (d->model_number & PCL_PJL_PCL3GUI)
3525 cupsFilePuts(fp, " $PCL_PJL_PCL3GUI");
3526 if (d->model_number & PCL_PJL_RESOLUTION)
3527 cupsFilePuts(fp, " $PCL_PJL_RESOLUTION");
3528
3529 cupsFilePuts(fp, ")\n");
3530 break;
3531
3532 case PPDC_DRIVER_LABEL :
3533 cupsFilePuts(fp, " ModelNumber ");
3534
3535 switch (d->model_number)
3536 {
3537 case DYMO_3x0 :
3538 cupsFilePuts(fp, "$DYMO_3x0\n");
3539 break;
3540
3541 case ZEBRA_EPL_LINE :
3542 cupsFilePuts(fp, "$ZEBRA_EPL_LINE\n");
3543 break;
3544
3545 case ZEBRA_EPL_PAGE :
3546 cupsFilePuts(fp, "$ZEBRA_EPL_PAGE\n");
3547 break;
3548
3549 case ZEBRA_ZPL :
3550 cupsFilePuts(fp, "$ZEBRA_ZPL\n");
3551 break;
3552
3553 case ZEBRA_CPCL :
3554 cupsFilePuts(fp, "$ZEBRA_CPCL\n");
3555 break;
3556
3557 case INTELLITECH_PCL :
3558 cupsFilePuts(fp, "$INTELLITECH_PCL\n");
3559 break;
3560
3561 default :
3562 cupsFilePrintf(fp, "%d\n", d->model_number);
3563 break;
3564 }
3565 break;
3566
3567 case PPDC_DRIVER_EPSON :
3568 cupsFilePuts(fp, " ModelNumber ");
3569
3570 switch (d->model_number)
3571 {
3572 case EPSON_9PIN :
3573 cupsFilePuts(fp, "$EPSON_9PIN\n");
3574 break;
3575
3576 case EPSON_24PIN :
3577 cupsFilePuts(fp, "$EPSON_24PIN\n");
3578 break;
3579
3580 case EPSON_COLOR :
3581 cupsFilePuts(fp, "$EPSON_COLOR\n");
3582 break;
3583
3584 case EPSON_PHOTO :
3585 cupsFilePuts(fp, "$EPSON_PHOTO\n");
3586 break;
3587
3588 case EPSON_ICOLOR :
3589 cupsFilePuts(fp, "$EPSON_ICOLOR\n");
3590 break;
3591
3592 case EPSON_IPHOTO :
3593 cupsFilePuts(fp, "$EPSON_IPHOTO\n");
3594 break;
3595
3596 default :
3597 cupsFilePrintf(fp, "%d\n", d->model_number);
3598 break;
3599 }
3600 break;
3601
3602 case PPDC_DRIVER_HP :
3603 cupsFilePuts(fp, " ModelNumber ");
3604 switch (d->model_number)
3605 {
3606 case HP_LASERJET :
3607 cupsFilePuts(fp, "$HP_LASERJET\n");
3608 break;
3609
3610 case HP_DESKJET :
3611 cupsFilePuts(fp, "$HP_DESKJET\n");
3612 break;
3613
3614 case HP_DESKJET2 :
3615 cupsFilePuts(fp, "$HP_DESKJET2\n");
3616 break;
3617
3618 default :
3619 cupsFilePrintf(fp, "%d\n", d->model_number);
3620 break;
3621 }
3622
3623 cupsFilePuts(fp, ")\n");
3624 break;
3625
3626 default :
3627 cupsFilePrintf(fp, " ModelNumber %d\n", d->model_number);
3628 break;
3629 }
3630 }
3631
3632 if (d->manual_copies)
3633 cupsFilePuts(fp, " ManualCopies Yes\n");
3634
3635 if (d->color_device)
3636 cupsFilePuts(fp, " ColorDevice Yes\n");
3637
3638 if (d->throughput)
3639 cupsFilePrintf(fp, " Throughput %d\n", d->throughput);
3640
3641 // Output all of the attributes...
3642 for (a = (ppdcAttr *)d->attrs->first();
3643 a;
3644 a = (ppdcAttr *)d->attrs->next())
3645 if (a->text->value && a->text->value[0])
3646 quotef(fp, " Attribute \"%s\" \"%s/%s\" \"%s\"\n",
3647 a->name->value, a->selector->value ? a->selector->value : "",
3648 a->text->value, a->value->value ? a->value->value : "");
3649 else
3650 quotef(fp, " Attribute \"%s\" \"%s\" \"%s\"\n",
3651 a->name->value, a->selector->value ? a->selector->value : "",
3652 a->value->value ? a->value->value : "");
3653
3654 // Output all of the constraints...
3655 for (co = (ppdcConstraint *)d->constraints->first();
3656 co;
3657 co = (ppdcConstraint *)d->constraints->next())
3658 {
3659 if (co->option1->value[0] == '*')
3660 cupsFilePrintf(fp, " UIConstraints \"%s %s", co->option1->value,
3661 co->choice1->value ? co->choice1->value : "");
3662 else
3663 cupsFilePrintf(fp, " UIConstraints \"*%s %s", co->option1->value,
3664 co->choice1->value ? co->choice1->value : "");
3665
3666 if (co->option2->value[0] == '*')
3667 cupsFilePrintf(fp, " %s %s\"\n", co->option2->value,
3668 co->choice2->value ? co->choice2->value : "");
3669 else
3670 cupsFilePrintf(fp, " *%s %s\"\n", co->option2->value,
3671 co->choice2->value ? co->choice2->value : "");
3672 }
3673
3674 // Output all of the filters...
3675 for (fi = (ppdcFilter *)d->filters->first();
3676 fi;
3677 fi = (ppdcFilter *)d->filters->next())
3678 cupsFilePrintf(fp, " Filter \"%s %d %s\"\n",
3679 fi->mime_type->value, fi->cost, fi->program->value);
3680
3681 // Output all of the fonts...
3682 for (fo = (ppdcFont *)d->fonts->first();
3683 fo;
3684 fo = (ppdcFont *)d->fonts->next())
3685 if (!strcmp(fo->name->value, "*"))
3686 cupsFilePuts(fp, " Font *\n");
3687 else
3688 cupsFilePrintf(fp, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n",
3689 fo->name->value, fo->encoding->value,
3690 fo->version->value, fo->charset->value,
3691 fo->status == PPDC_FONT_ROM ? "ROM" : "Disk");
3692
3693 // Output all options...
3694 for (g = (ppdcGroup *)d->groups->first();
3695 g;
3696 g = (ppdcGroup *)d->groups->next())
3697 {
3698 if (g->options->count == 0)
3699 continue;
3700
3701 if (g->text->value && g->text->value[0])
3702 quotef(fp, " Group \"%s/%s\"\n", g->name->value, g->text->value);
3703 else
3704 cupsFilePrintf(fp, " Group \"%s\"\n", g->name->value);
3705
3706 for (o = (ppdcOption *)g->options->first();
3707 o;
3708 o = (ppdcOption *)g->options->next())
3709 {
3710 if (o->choices->count == 0)
3711 continue;
3712
3713 if (o->text->value && o->text->value[0])
3714 quotef(fp, " Option \"%s/%s\"", o->name->value, o->text->value);
3715 else
3716 cupsFilePrintf(fp, " Option \"%s\"", o->name->value);
3717
3718 cupsFilePrintf(fp, " %s %s %.1f\n",
3719 o->type == PPDC_BOOLEAN ? "Boolean" :
3720 o->type == PPDC_PICKONE ? "PickOne" : "PickMany",
3721 o->section == PPDC_SECTION_ANY ? "AnySetup" :
3722 o->section == PPDC_SECTION_DOCUMENT ? "DocumentSetup" :
3723 o->section == PPDC_SECTION_EXIT ? "ExitServer" :
3724 o->section == PPDC_SECTION_JCL ? "JCLSetup" :
3725 o->section == PPDC_SECTION_PAGE ? "PageSetup" :
3726 "Prolog",
3727 o->order);
3728
3729 for (ch = (ppdcChoice *)o->choices->first();
3730 ch;
3731 ch = (ppdcChoice *)o->choices->next())
3732 {
3733 if (ch->text->value && ch->text->value[0])
3734 quotef(fp, " %sChoice \"%s/%s\" \"%s\"\n",
3735 o->defchoice == ch->name ? "*" : "",
3736 ch->name->value, ch->text->value,
3737 ch->code->value ? ch->code->value : "");
3738 else
3739 quotef(fp, " %sChoice \"%s\" \"%s\"\n",
3740 o->defchoice == ch->name ? "*" : "",
3741 ch->name->value,
3742 ch->code->value ? ch->code->value : "");
3743 }
3744 }
3745 }
3746
3747 // Output all of the color profiles...
3748 for (p = (ppdcProfile *)d->profiles->first();
3749 p;
3750 p = (ppdcProfile *)d->profiles->next())
3751 cupsFilePrintf(fp, " ColorProfile \"%s/%s\" %.3f %.3f "
3752 "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
3753 p->resolution->value, p->media_type->value,
3754 p->density, p->gamma,
3755 p->profile[0], p->profile[1], p->profile[2],
3756 p->profile[3], p->profile[4], p->profile[5],
3757 p->profile[6], p->profile[7], p->profile[8]);
3758
3759 // Output all of the media sizes...
3760 left = 0.0;
3761 bottom = 0.0;
3762 right = 0.0;
3763 top = 0.0;
3764
3765 for (si = (ppdcMediaSize *)d->sizes->first();
3766 si;
3767 si = (ppdcMediaSize *)d->sizes->next())
3768 if (si->size_code->value && si->region_code->value)
3769 {
3770 // Output a custom media size...
3771 quotef(fp, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n",
3772 si->name == d->default_size ? "*" : "", si->name->value,
3773 si->text->value, si->width, si->length, si->left, si->bottom,
3774 si->right, si->top, si->size_code->value,
3775 si->region_code->value);
3776 }
3777 else
3778 {
3779 // Output a standard media size...
3780 if (fabs(left - si->left) > 0.1 ||
3781 fabs(bottom - si->bottom) > 0.1 ||
3782 fabs(right - si->right) > 0.1 ||
3783 fabs(top - si->top) > 0.1)
3784 {
3785 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3786 si->left, si->bottom, si->right, si->top);
3787
3788 left = si->left;
3789 bottom = si->bottom;
3790 right = si->right;
3791 top = si->top;
3792 }
3793
3794 cupsFilePrintf(fp, " %sMediaSize %s\n",
3795 si->name == d->default_size ? "*" : "",
3796 si->name->value);
3797 }
3798
3799 if (d->variable_paper_size)
3800 {
3801 cupsFilePuts(fp, " VariablePaperSize Yes\n");
3802
3803 if (fabs(left - d->left_margin) > 0.1 ||
3804 fabs(bottom - d->bottom_margin) > 0.1 ||
3805 fabs(right - d->right_margin) > 0.1 ||
3806 fabs(top - d->top_margin) > 0.1)
3807 {
3808 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3809 d->left_margin, d->bottom_margin, d->right_margin,
3810 d->top_margin);
3811 }
3812
3813 cupsFilePrintf(fp, " MinSize %.2f %.2f\n", d->min_width, d->min_length);
3814 cupsFilePrintf(fp, " MaxSize %.2f %.2f\n", d->max_width, d->max_length);
3815 }
3816
3817 // End the driver...
3818 cupsFilePuts(fp, "}\n");
3819 }
3820
3821 // Close the file and return...
3822 cupsFileClose(fp);
3823
3824 return (0);
3825}
3826
3827
3828//
3829// End of "$Id$".
3830//