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