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