]> git.ipfire.org Git - thirdparty/cups.git/blame - ppdc/ppdc-source.cxx
Merge changes from CUPS 1.4svn-r8252.
[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...
4509bb49
MS
1668 if (!pofilename[0] ||
1669 find_include(poname, basedir, pofilename, sizeof(pofilename)))
ac884b6a
MS
1670 {
1671 // Found it, so load it...
1672 cat = new ppdcCatalog(locale, pofilename);
1673
1674 // Reset the filename to the name supplied by the user...
e4572d57 1675 cat->filename->release();
ac884b6a
MS
1676 cat->filename = new ppdcString(poname);
1677
1678 // Return the catalog...
1679 return (cat);
1680 }
1681 else
1682 {
61cf44e2
MS
1683 _cupsLangPrintf(stderr,
1684 _("ppdc: Unable to find #po file %s on line %d of %s!\n"),
1685 poname, fp->line, fp->filename);
ac884b6a
MS
1686 return (NULL);
1687 }
1688}
1689
1690
1691//
1692// 'ppdcSource::get_resolution()' - Get an old-style resolution option.
1693//
1694
1695ppdcChoice * // O - Choice data
1696ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
1697{
1698 char name[1024], // Name
1699 *text, // Text
1700 temp[256], // Temporary string
1701 command[256], // Command string
1702 *commptr; // Pointer into command
1703 int xdpi, ydpi, // X + Y resolution
1704 color_order, // Color order
1705 color_space, // Colorspace
1706 compression, // Compression mode
1707 depth, // Bits per color
1708 row_count, // Row count
1709 row_feed, // Row feed
1710 row_step; // Row step/interval
1711
1712
1713 // Read the resolution parameters:
1714 //
1715 // Resolution colorspace bits row-count row-feed row-step name/text
1716 if (!get_token(fp, temp, sizeof(temp)))
1717 {
61cf44e2
MS
1718 _cupsLangPrintf(stderr,
1719 _("ppdc: Expected override field after Resolution on line "
1720 "%d of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
1721 return (NULL);
1722 }
1723
1724 color_order = get_color_order(temp);
1725 color_space = get_color_space(temp);
1726 compression = get_integer(temp);
1727
1728 depth = get_integer(fp);
1729 row_count = get_integer(fp);
1730 row_feed = get_integer(fp);
1731 row_step = get_integer(fp);
1732
1733 if (!get_token(fp, name, sizeof(name)))
1734 {
61cf44e2
MS
1735 _cupsLangPrintf(stderr,
1736 _("ppdc: Expected name/text after Resolution on line %d of "
1737 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
1738 return (NULL);
1739 }
1740
1741 if ((text = strchr(name, '/')) != NULL)
1742 *text++ = '\0';
1743 else
1744 text = name;
1745
1746 switch (sscanf(name, "%dx%d", &xdpi, &ydpi))
1747 {
1748 case 0 :
61cf44e2
MS
1749 _cupsLangPrintf(stderr,
1750 _("ppdc: Bad resolution name \"%s\" on line %d of "
1751 "%s!\n"), name, fp->line, fp->filename);
ac884b6a
MS
1752 break;
1753 case 1 :
1754 ydpi = xdpi;
1755 break;
1756 }
1757
1758 // Create the necessary PS commands...
1759 snprintf(command, sizeof(command),
1760 "<</HWResolution[%d %d]/cupsBitsPerColor %d/cupsRowCount %d"
1761 "/cupsRowFeed %d/cupsRowStep %d",
1762 xdpi, ydpi, depth, row_count, row_feed, row_step);
1763 commptr = command + strlen(command);
1764
1765 if (color_order >= 0)
1766 {
1767 snprintf(commptr, sizeof(command) - (commptr - command),
1768 "/cupsColorOrder %d", color_order);
1769 commptr += strlen(commptr);
1770 }
1771
1772 if (color_space >= 0)
1773 {
1774 snprintf(commptr, sizeof(command) - (commptr - command),
1775 "/cupsColorSpace %d", color_space);
1776 commptr += strlen(commptr);
1777 }
1778
1779 if (compression >= 0)
1780 {
1781 snprintf(commptr, sizeof(command) - (commptr - command),
1782 "/cupsCompression %d", compression);
1783 commptr += strlen(commptr);
1784 }
1785
1786 snprintf(commptr, sizeof(command) - (commptr - command), ">>setpagedevice");
1787
1788 // Return the new choice...
1789 return (new ppdcChoice(name, text, command));
1790}
1791
1792
1793//
1794// 'ppdcSource::get_simple_profile()' - Get a simple color profile definition.
1795//
1796
1797ppdcProfile * // O - Color profile
1798ppdcSource::get_simple_profile(ppdcFile *fp)
1799 // I - File to read
1800{
1801 char resolution[1024], // Resolution/media type
1802 *media_type; // Media type
1803 float m[9]; // Transform matrix
1804 float kd, rd, g; // Densities and gamma
1805 float red, green, blue; // RGB adjustments
1806 float yellow; // Yellow density
1807 float color; // Color density values
1808
1809
1810 // Get the SimpleColorProfile parameters:
1811 //
1812 // SimpleColorProfile resolution/mediatype black-density yellow-density
1813 // red-density gamma red-adjust green-adjust blue-adjust
1814 if (!get_token(fp, resolution, sizeof(resolution)))
1815 {
61cf44e2
MS
1816 _cupsLangPrintf(stderr,
1817 _("ppdc: Expected resolution/mediatype following "
1818 "SimpleColorProfile on line %d of %s!\n"),
1819 fp->line, fp->filename);
ac884b6a
MS
1820 return (NULL);
1821 }
1822
1823 if ((media_type = strchr(resolution, '/')) != NULL)
1824 *media_type++ = '\0';
1825 else
1826 media_type = resolution;
1827
1828 // Collect the profile parameters...
1829 kd = get_float(fp);
1830 yellow = get_float(fp);
1831 rd = get_float(fp);
1832 g = get_float(fp);
1833 red = get_float(fp);
1834 green = get_float(fp);
1835 blue = get_float(fp);
1836
1837 // Build the color profile...
1838 color = 0.5f * rd / kd - kd;
1839 m[0] = 1.0f; // C
1840 m[1] = color + blue; // C + M (blue)
1841 m[2] = color - green; // C + Y (green)
1842 m[3] = color - blue; // M + C (blue)
1843 m[4] = 1.0f; // M
1844 m[5] = color + red; // M + Y (red)
1845 m[6] = yellow * (color + green); // Y + C (green)
1846 m[7] = yellow * (color - red); // Y + M (red)
1847 m[8] = yellow; // Y
1848
1849 if (m[1] > 0.0f)
1850 {
1851 m[3] -= m[1];
1852 m[1] = 0.0f;
1853 }
1854 else if (m[3] > 0.0f)
1855 {
1856 m[1] -= m[3];
1857 m[3] = 0.0f;
1858 }
1859
1860 if (m[2] > 0.0f)
1861 {
1862 m[6] -= m[2];
1863 m[2] = 0.0f;
1864 }
1865 else if (m[6] > 0.0f)
1866 {
1867 m[2] -= m[6];
1868 m[6] = 0.0f;
1869 }
1870
1871 if (m[5] > 0.0f)
1872 {
1873 m[7] -= m[5];
1874 m[5] = 0.0f;
1875 }
1876 else if (m[7] > 0.0f)
1877 {
1878 m[5] -= m[7];
1879 m[7] = 0.0f;
1880 }
1881
1882 // Return the new profile...
1883 return (new ppdcProfile(resolution, media_type, g, kd, m));
1884}
1885
1886
1887//
1888// 'ppdcSource::get_size()' - Get a media size definition from a file.
1889//
1890
1891ppdcMediaSize * // O - Media size
1892ppdcSource::get_size(ppdcFile *fp) // I - File to read
1893{
1894 char name[1024], // Name
1895 *text; // Text
1896 float width, // Width
1897 length; // Length
1898
1899
1900 // Get the name, text, width, and length:
1901 //
1902 // #media name/text width length
1903 if (!get_token(fp, name, sizeof(name)))
1904 return (NULL);
1905
1906 if ((text = strchr(name, '/')) != NULL)
1907 *text++ = '\0';
1908 else
1909 text = name;
1910
1911 if ((width = get_measurement(fp)) < 0.0f)
1912 return (NULL);
1913
1914 if ((length = get_measurement(fp)) < 0.0f)
1915 return (NULL);
1916
1917 // Return the new media size...
1918 return (new ppdcMediaSize(name, text, width, length, 0.0f, 0.0f, 0.0f, 0.0f));
1919}
1920
1921
1922//
1923// 'ppdcSource::get_token()' - Get a token from a file.
1924//
1925
1926char * // O - Token string or NULL
1927ppdcSource::get_token(ppdcFile *fp, // I - File to read
1928 char *buffer, // I - Buffer
1929 int buflen) // I - Length of buffer
1930{
1931 char *bufptr, // Pointer into string buffer
1932 *bufend; // End of string buffer
1933 int ch, // Character from file
1934 nextch, // Next char in file
1935 quote, // Quote character used...
1936 empty, // Empty input?
1937 startline; // Start line for quote
1938 char name[256], // Name string
1939 *nameptr; // Name pointer
1940 ppdcVariable *var; // Variable pointer
1941
1942
1943 // Mark the beginning and end of the buffer...
1944 bufptr = buffer;
1945 bufend = buffer + buflen - 1;
1946
1947 // Loop intil we've read a token...
1948 quote = 0;
1949 startline = 0;
1950 empty = 1;
1951
1952 while ((ch = fp->get()) != EOF)
1953 {
1954 if (isspace(ch) && !quote)
1955 {
1956 if (empty)
1957 continue;
1958 else
1959 break;
1960 }
1961 else if (ch == '$')
1962 {
1963 // Variable substitution
1964 empty = 0;
1965
1966 for (nameptr = name; (ch = fp->peek()) != EOF;)
1967 {
1968 if (!isalnum(ch) && ch != '_')
1969 break;
1970 else if (nameptr < (name + sizeof(name) - 1))
1971 *nameptr++ = fp->get();
1972 }
1973
1974 if (nameptr == name)
1975 {
1976 // Just substitute this character...
1977 if (ch == '$')
1978 {
1979 // $$ = $
1980 if (bufptr < bufend)
1981 *bufptr++ = fp->get();
1982 }
1983 else
1984 {
1985 // $ch = $ch
61cf44e2
MS
1986 _cupsLangPrintf(stderr,
1987 _("ppdc: Bad variable substitution ($%c) on line %d "
1988 "of %s.\n"), ch, fp->line, fp->filename);
ac884b6a
MS
1989
1990 if (bufptr < bufend)
1991 *bufptr++ = '$';
1992 }
1993 }
1994 else
1995 {
1996 // Substitute the variable value...
1997 *nameptr = '\0';
1998 var = find_variable(name);
1999 if (var)
2000 {
2001 strncpy(bufptr, var->value->value, bufend - bufptr);
2002 bufptr += strlen(var->value->value);
2003 }
2004 else
2005 {
61cf44e2
MS
2006 _cupsLangPrintf(stderr,
2007 _("ppdc: Undefined variable (%s) on line %d of "
2008 "%s.\n"), name, fp->line, fp->filename);
ac884b6a
MS
2009 snprintf(bufptr, bufend - bufptr + 1, "$%s", name);
2010 bufptr += strlen(name) + 1;
2011 }
2012 }
2013 }
2014 else if (ch == '/' && !quote)
2015 {
2016 // Possibly a comment...
2017 nextch = fp->peek();
2018
2019 if (nextch == '*')
2020 {
2021 // C comment...
2022 fp->get();
2023 ch = fp->get();
2024 while ((nextch = fp->get()) != EOF)
2025 {
2026 if (ch == '*' && nextch == '/')
2027 break;
2028
2029 ch = nextch;
2030 }
2031
2032 if (nextch == EOF)
2033 break;
2034 }
2035 else if (nextch == '/')
2036 {
2037 // C++ comment...
2038 while ((nextch = fp->get()) != EOF)
2039 if (nextch == '\n')
2040 break;
2041
2042 if (nextch == EOF)
2043 break;
2044 }
2045 else
2046 {
2047 // Not a comment...
2048 empty = 0;
2049
2050 if (bufptr < bufend)
2051 *bufptr++ = ch;
2052 }
2053 }
2054 else if (ch == '\'' || ch == '\"')
2055 {
2056 empty = 0;
2057
2058 if (quote == ch)
2059 {
2060 // Ending the current quoted string...
2061 quote = 0;
2062 }
2063 else if (quote)
2064 {
2065 // Insert the opposing quote char...
2066 if (bufptr < bufend)
2067 *bufptr++ = ch;
2068 }
2069 else
2070 {
2071 // Start a new quoted string...
2072 startline = fp->line;
2073 quote = ch;
2074 }
2075 }
2076 else if ((ch == '(' || ch == '<') && !quote)
2077 {
2078 empty = 0;
2079 quote = ch;
2080 startline = fp->line;
2081
2082 if (bufptr < bufend)
2083 *bufptr++ = ch;
2084 }
2085 else if ((ch == ')' && quote == '(') || (ch == '>' && quote == '<'))
2086 {
2087 quote = 0;
2088
2089 if (bufptr < bufend)
2090 *bufptr++ = ch;
2091 }
2092 else if (ch == '\\')
2093 {
2094 empty = 0;
2095
2096 if ((ch = fp->get()) == EOF)
2097 break;
2098
2099 if (bufptr < bufend)
2100 *bufptr++ = ch;
2101 }
2102 else if (bufptr < bufend)
2103 {
2104 empty = 0;
2105
2106 *bufptr++ = ch;
2107
2108 if ((ch == '{' || ch == '}') && !quote)
2109 break;
2110 }
2111 }
2112
2113 if (quote)
2114 {
61cf44e2
MS
2115 _cupsLangPrintf(stderr,
2116 _("ppdc: Unterminated string starting with %c on line %d "
2117 "of %s!\n"), quote, startline, fp->filename);
ac884b6a
MS
2118 return (NULL);
2119 }
2120
2121 if (empty)
2122 return (NULL);
2123 else
2124 {
2125 *bufptr = '\0';
2126// puts(buffer);
2127 return (buffer);
2128 }
2129}
2130
2131
2132//
2133// 'ppdcSource::get_variable()' - Get a variable definition.
2134//
2135
2136ppdcVariable * // O - Variable
2137ppdcSource::get_variable(ppdcFile *fp) // I - File to read
2138{
2139 char name[1024], // Name
2140 value[1024]; // Value
2141
2142
2143 // Get the name and value:
2144 //
2145 // #define name value
2146 if (!get_token(fp, name, sizeof(name)))
2147 return (NULL);
2148
2149 if (!get_token(fp, value, sizeof(value)))
2150 return (NULL);
2151
2152 // Set the variable...
2153 return (set_variable(name, value));
2154}
2155
2156
2157//
2158// 'ppdcSource::quotef()' - Write a formatted, quoted string...
2159//
2160
2161int // O - Number bytes on success, -1 on failure
2162ppdcSource::quotef(cups_file_t *fp, // I - File to write to
2163 const char *format, // I - Printf-style format string
2164 ...) // I - Additional args as needed
2165{
2166 va_list ap; // Pointer to additional arguments
2167 int bytes; // Bytes written
2168 char sign, // Sign of format width
2169 size, // Size character (h, l, L)
2170 type; // Format type character
2171 const char *bufformat; // Start of format
2172 int width, // Width of field
2173 prec; // Number of characters of precision
2174 char tformat[100]; // Temporary format string for fprintf()
2175 char *s; // Pointer to string
2176 int slen; // Length of string
2177 int i; // Looping var
2178
2179
2180 // Range check input...
2181 if (!fp || !format)
2182 return (-1);
2183
2184 // Loop through the format string, formatting as needed...
2185 va_start(ap, format);
2186
2187 bytes = 0;
2188
2189 while (*format)
2190 {
2191 if (*format == '%')
2192 {
2193 bufformat = format;
2194 format ++;
2195
2196 if (*format == '%')
2197 {
2198 cupsFilePutChar(fp, *format++);
2199 bytes ++;
2200 continue;
2201 }
2202 else if (strchr(" -+#\'", *format))
2203 sign = *format++;
2204 else
2205 sign = 0;
2206
2207 width = 0;
2208 while (isdigit(*format))
2209 width = width * 10 + *format++ - '0';
2210
2211 if (*format == '.')
2212 {
2213 format ++;
2214 prec = 0;
2215
2216 while (isdigit(*format))
2217 prec = prec * 10 + *format++ - '0';
2218 }
2219 else
2220 prec = -1;
2221
2222 if (*format == 'l' && format[1] == 'l')
2223 {
2224 size = 'L';
2225 format += 2;
2226 }
2227 else if (*format == 'h' || *format == 'l' || *format == 'L')
2228 size = *format++;
2229
2230 if (!*format)
2231 break;
2232
2233 type = *format++;
2234
2235 switch (type)
2236 {
2237 case 'E' : // Floating point formats
2238 case 'G' :
2239 case 'e' :
2240 case 'f' :
2241 case 'g' :
2242 if ((format - bufformat + 1) > (int)sizeof(tformat))
2243 break;
2244
2245 strncpy(tformat, bufformat, format - bufformat);
2246 tformat[format - bufformat] = '\0';
2247
2248 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, double));
2249 break;
2250
2251 case 'B' : // Integer formats
2252 case 'X' :
2253 case 'b' :
2254 case 'd' :
2255 case 'i' :
2256 case 'o' :
2257 case 'u' :
2258 case 'x' :
2259 if ((format - bufformat + 1) > (int)sizeof(tformat))
2260 break;
2261
2262 strncpy(tformat, bufformat, format - bufformat);
2263 tformat[format - bufformat] = '\0';
2264
2265 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
2266 break;
2267
2268 case 'p' : // Pointer value
2269 if ((format - bufformat + 1) > (int)sizeof(tformat))
2270 break;
2271
2272 strncpy(tformat, bufformat, format - bufformat);
2273 tformat[format - bufformat] = '\0';
2274
2275 bytes += cupsFilePrintf(fp, tformat, va_arg(ap, void *));
2276 break;
2277
2278 case 'c' : // Character or character array
2279 if (width <= 1)
2280 {
2281 bytes ++;
2282 cupsFilePutChar(fp, va_arg(ap, int));
2283 }
2284 else
2285 {
2286 cupsFileWrite(fp, va_arg(ap, char *), width);
2287 bytes += width;
2288 }
2289 break;
2290
2291 case 's' : // String
2292 if ((s = va_arg(ap, char *)) == NULL)
2293 s = (char *)"(nil)";
2294
2295 slen = strlen(s);
2296 if (slen > width && prec != width)
2297 width = slen;
2298
2299 if (slen > width)
2300 slen = width;
2301
2302 if (sign != '-')
2303 {
2304 for (i = width - slen; i > 0; i --, bytes ++)
2305 cupsFilePutChar(fp, ' ');
2306 }
2307
2308 for (i = slen; i > 0; i --, s ++, bytes ++)
2309 {
2310 if (*s == '\\' || *s == '\"')
2311 {
2312 cupsFilePutChar(fp, '\\');
2313 bytes ++;
2314 }
2315
2316 cupsFilePutChar(fp, *s);
2317 }
2318
2319 if (sign == '-')
2320 {
2321 for (i = width - slen; i > 0; i --, bytes ++)
2322 cupsFilePutChar(fp, ' ');
2323 }
2324 break;
2325 }
2326 }
2327 else
2328 {
2329 cupsFilePutChar(fp, *format++);
2330 bytes ++;
2331 }
2332 }
2333
2334 va_end(ap);
2335
2336 // Return the number of characters written.
2337 return (bytes);
2338}
2339
2340
2341//
2342// 'ppdcSource::read_file()' - Read a driver source file.
2343//
2344
2345void
4509bb49
MS
2346ppdcSource::read_file(const char *f, // I - File to read
2347 cups_file_t *ffp) // I - File pointer to use
ac884b6a 2348{
4509bb49 2349 ppdcFile *fp = new ppdcFile(f, ffp);
ac884b6a
MS
2350 scan_file(fp);
2351 delete fp;
bdd6c45b
MS
2352
2353 if (cond_current != cond_stack)
61cf44e2 2354 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"), f);
ac884b6a
MS
2355}
2356
2357
2358//
2359// 'ppdcSource::scan_file()' - Scan a driver source file.
2360//
2361
2362void
2363ppdcSource::scan_file(ppdcFile *fp, // I - File to read
2364 ppdcDriver *td, // I - Driver template
2365 bool inc) // I - Including?
2366{
2367 ppdcDriver *d; // Current driver
2368 ppdcGroup *g, // Current group
2369 *general, // General options group
2370 *install; // Installable options group
2371 ppdcOption *o; // Current option
2372 ppdcChoice *c; // Current choice
2373 char temp[256], // Token from file...
2374 *ptr; // Pointer into token
2375 int isdefault; // Default option?
2376
2377
2378 // Initialize things as needed...
2379 if (inc && td)
2380 d = td;
2381 else
2382 d = new ppdcDriver(td);
2383
2384 if ((general = d->find_group("General")) == NULL)
2385 {
2386 general = new ppdcGroup("General", NULL);
2387 d->add_group(general);
2388 }
2389
2390 if ((install = d->find_group("InstallableOptions")) == NULL)
2391 {
2392 install = new ppdcGroup("InstallableOptions", "Installable Options");
2393 d->add_group(install);
2394 }
2395
2396 // Loop until EOF or }
2397 o = 0;
2398 g = general;
bdd6c45b 2399
ac884b6a
MS
2400 while (get_token(fp, temp, sizeof(temp)))
2401 {
2402 if (temp[0] == '*')
2403 {
2404 // Mark the next choice as the default
2405 isdefault = 1;
2406
2407 for (ptr = temp; ptr[1]; ptr ++)
2408 *ptr = ptr[1];
2409
2410 *ptr = '\0';
2411 }
2412 else
2413 {
2414 // Don't mark the next choice as the default
2415 isdefault = 0;
2416 }
2417
2418 if (!strcasecmp(temp, "}"))
2419 {
2420 // Close this one out...
2421 break;
2422 }
2423 else if (!strcasecmp(temp, "{"))
2424 {
2425 // Open a new child...
2426 scan_file(fp, d);
2427 }
bdd6c45b
MS
2428 else if (!strcasecmp(temp, "#if"))
2429 {
2430 if ((cond_current - cond_stack) >= 100)
2431 {
61cf44e2
MS
2432 _cupsLangPrintf(stderr,
2433 _("ppdc: Too many nested #if's on line %d of %s!\n"),
2434 fp->line, fp->filename);
bdd6c45b
MS
2435 break;
2436 }
2437
2438 cond_current ++;
2439 if (get_integer(fp))
2440 *cond_current = PPDC_COND_SATISFIED;
2441 else
2442 {
2443 *cond_current = PPDC_COND_SKIP;
2444 cond_state |= PPDC_COND_SKIP;
2445 }
2446 }
2447 else if (!strcasecmp(temp, "#elif"))
2448 {
2449 if (cond_current == cond_stack)
2450 {
61cf44e2
MS
2451 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
2452 fp->line, fp->filename);
bdd6c45b
MS
2453 break;
2454 }
2455
2456 if (*cond_current & PPDC_COND_SATISFIED)
2457 {
2458 get_integer(fp);
2459 *cond_current |= PPDC_COND_SKIP;
2460 }
2461 else if (get_integer(fp))
2462 {
2463 *cond_current |= PPDC_COND_SATISFIED;
2464 *cond_current &= ~PPDC_COND_SKIP;
2465 }
2466 else
2467 *cond_current |= PPDC_COND_SKIP;
2468
2469 // Update the current state
2470 int *cond_temp = cond_current; // Temporary stack pointer
2471
2472 cond_state = PPDC_COND_NORMAL;
2473 while (cond_temp > cond_stack)
2474 if (*cond_temp & PPDC_COND_SKIP)
2475 {
2476 cond_state = PPDC_COND_SKIP;
2477 break;
2478 }
2479 else
2480 cond_temp --;
2481 }
2482 else if (!strcasecmp(temp, "#else"))
2483 {
2484 if (cond_current == cond_stack)
2485 {
61cf44e2
MS
2486 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
2487 fp->line, fp->filename);
bdd6c45b
MS
2488 break;
2489 }
2490
2491 if (*cond_current & PPDC_COND_SATISFIED)
2492 *cond_current |= PPDC_COND_SKIP;
2493 else
2494 {
2495 *cond_current |= PPDC_COND_SATISFIED;
2496 *cond_current &= ~PPDC_COND_SKIP;
2497 }
2498
2499 // Update the current state
2500 int *cond_temp = cond_current; // Temporary stack pointer
2501
2502 cond_state = PPDC_COND_NORMAL;
2503 while (cond_temp > cond_stack)
2504 if (*cond_temp & PPDC_COND_SKIP)
2505 {
2506 cond_state = PPDC_COND_SKIP;
2507 break;
2508 }
2509 else
2510 cond_temp --;
2511 }
2512 else if (!strcasecmp(temp, "#endif"))
2513 {
2514 if (cond_current == cond_stack)
2515 {
61cf44e2
MS
2516 _cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
2517 fp->line, fp->filename);
bdd6c45b
MS
2518 break;
2519 }
2520
2521 cond_current --;
2522
2523 // Update the current state
2524 int *cond_temp = cond_current; // Temporary stack pointer
2525
2526 cond_state = PPDC_COND_NORMAL;
2527 while (cond_temp > cond_stack)
2528 if (*cond_temp & PPDC_COND_SKIP)
2529 {
2530 cond_state = PPDC_COND_SKIP;
2531 break;
2532 }
2533 else
2534 cond_temp --;
2535 }
ac884b6a
MS
2536 else if (!strcasecmp(temp, "#define"))
2537 {
2538 // Get the variable...
2539 get_variable(fp);
2540 }
2541 else if (!strcasecmp(temp, "#include"))
2542 {
2543 // #include filename
2544 char basedir[1024], // Base directory
2545 *baseptr, // Pointer into directory
2546 inctemp[1024], // Initial filename
2547 incname[1024]; // Include filename
2548 ppdcFile *incfile; // Include file
bdd6c45b
MS
2549 int *old_current = cond_current;
2550 // Previous current stack
ac884b6a
MS
2551
2552
2553 // Get the include name...
2554 if (!get_token(fp, inctemp, sizeof(inctemp)))
2555 {
61cf44e2
MS
2556 _cupsLangPrintf(stderr,
2557 _("ppdc: Expected include filename on line %d of "
2558 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
2559 break;
2560 }
2561
bdd6c45b
MS
2562 if (cond_state)
2563 continue;
2564
ac884b6a
MS
2565 // Figure out the current directory...
2566 strlcpy(basedir, fp->filename, sizeof(basedir));
2567
2568 if ((baseptr = strrchr(basedir, '/')) != NULL)
bdd6c45b 2569 *baseptr = '\0';
ac884b6a 2570 else
bdd6c45b 2571 strcpy(basedir, ".");
ac884b6a
MS
2572
2573 // Find the include file...
2574 if (find_include(inctemp, basedir, incname, sizeof(incname)))
2575 {
2576 // Open the include file, scan it, and then close it...
2577 incfile = new ppdcFile(incname);
2578 scan_file(incfile, d, true);
2579 delete incfile;
bdd6c45b
MS
2580
2581 if (cond_current != old_current)
61cf44e2
MS
2582 _cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"),
2583 incname);
ac884b6a
MS
2584 }
2585 else
2586 {
bdd6c45b 2587 // Can't find it!
61cf44e2
MS
2588 _cupsLangPrintf(stderr,
2589 _("ppdc: Unable to find include file \"%s\" on line %d "
2590 "of %s!\n"), inctemp, fp->line, fp->filename);
ac884b6a
MS
2591 break;
2592 }
2593 }
2594 else if (!strcasecmp(temp, "#media"))
2595 {
2596 ppdcMediaSize *m; // Media size
2597
2598
2599 // Get a media size...
2600 m = get_size(fp);
2601 if (m)
bdd6c45b
MS
2602 {
2603 if (cond_state)
2604 m->release();
2605 else
2606 sizes->add(m);
2607 }
ac884b6a
MS
2608 }
2609 else if (!strcasecmp(temp, "#po"))
2610 {
2611 ppdcCatalog *cat; // Message catalog
2612
2613
2614 // Get a message catalog...
2615 cat = get_po(fp);
2616 if (cat)
bdd6c45b
MS
2617 {
2618 if (cond_state)
2619 cat->release();
2620 else
2621 po_files->add(cat);
2622 }
ac884b6a 2623 }
bdd6c45b
MS
2624 else if (!strcasecmp(temp, "Attribute") ||
2625 !strcasecmp(temp, "LocAttribute"))
ac884b6a
MS
2626 {
2627 ppdcAttr *a; // Attribute
2628
2629
2630 // Get an attribute...
bdd6c45b 2631 a = get_attr(fp, !strcasecmp(temp, "LocAttribute"));
ac884b6a 2632 if (a)
bdd6c45b
MS
2633 {
2634 if (cond_state)
2635 a->release();
2636 else
2637 d->add_attr(a);
2638 }
ac884b6a
MS
2639 }
2640 else if (!strcasecmp(temp, "Choice"))
2641 {
2642 // Get a choice...
bdd6c45b
MS
2643 c = get_choice(fp);
2644 if (!c)
2645 break;
2646
2647 if (cond_state)
2648 {
2649 c->release();
2650 continue;
2651 }
2652
2653 // Add it to the current option...
ac884b6a
MS
2654 if (!o)
2655 {
61cf44e2
MS
2656 _cupsLangPrintf(stderr,
2657 _("ppdc: Choice found on line %d of %s with no "
2658 "Option!\n"), fp->line, fp->filename);
ac884b6a
MS
2659 break;
2660 }
2661
ac884b6a
MS
2662 o->add_choice(c);
2663
2664 if (isdefault)
2665 o->set_defchoice(c);
2666 }
2667 else if (!strcasecmp(temp, "ColorDevice"))
2668 {
2669 // ColorDevice boolean
bdd6c45b
MS
2670 if (cond_state)
2671 get_boolean(fp);
2672 else
2673 d->color_device = get_boolean(fp);
ac884b6a
MS
2674 }
2675 else if (!strcasecmp(temp, "ColorModel"))
2676 {
2677 // Get the color model
2678 c = get_color_model(fp);
2679 if (!c)
2680 continue;
2681
bdd6c45b
MS
2682 if (cond_state)
2683 {
2684 c->release();
2685 continue;
2686 }
2687
ac884b6a
MS
2688 // Add the choice to the ColorModel option...
2689 if ((o = d->find_option("ColorModel")) == NULL)
2690 {
2691 // Create the ColorModel option...
2692 o = new ppdcOption(PPDC_PICKONE, "ColorModel", "Color Mode", PPDC_SECTION_ANY, 10.0f);
2693 g = general;
2694 g->add_option(o);
2695 }
2696
2697 o->add_choice(c);
2698
2699 if (isdefault)
2700 o->set_defchoice(c);
2701
2702 o = NULL;
2703 }
2704 else if (!strcasecmp(temp, "ColorProfile"))
2705 {
2706 ppdcProfile *p; // Color profile
2707
2708
2709 // Get the color profile...
2710 p = get_color_profile(fp);
2711
2712 if (p)
bdd6c45b
MS
2713 {
2714 if (cond_state)
2715 p->release();
2716 else
2717 d->profiles->add(p);
2718 }
ac884b6a
MS
2719 }
2720 else if (!strcasecmp(temp, "Copyright"))
2721 {
2722 // Copyright string
2723 char copytemp[8192], // Copyright string
2724 *copyptr, // Pointer into string
2725 *copyend; // Pointer to end of string
2726
2727
2728 // Get the copyright string...
2729 if (!get_token(fp, copytemp, sizeof(temp)))
2730 {
61cf44e2
MS
2731 _cupsLangPrintf(stderr,
2732 _("ppdc: Expected string after Copyright on line %d "
2733 "of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
2734 break;
2735 }
2736
bdd6c45b
MS
2737 if (cond_state)
2738 continue;
2739
ac884b6a
MS
2740 // Break it up into individual lines...
2741 for (copyptr = copytemp; copyptr; copyptr = copyend)
2742 {
2743 if ((copyend = strchr(copyptr, '\n')) != NULL)
2744 *copyend++ = '\0';
2745
2746 d->copyright->add(new ppdcString(copyptr));
2747 }
2748 }
2749 else if (!strcasecmp(temp, "CustomMedia"))
2750 {
2751 ppdcMediaSize *m; // Media size
2752
2753
2754 // Get a custom media size...
2755 m = get_custom_size(fp);
bdd6c45b
MS
2756
2757 if (cond_state)
2758 {
2759 m->release();
2760 continue;
2761 }
2762
ac884b6a
MS
2763 if (m)
2764 d->sizes->add(m);
2765
2766 if (isdefault)
2767 d->set_default_size(m);
2768 }
2769 else if (!strcasecmp(temp, "Cutter"))
2770 {
2771 // Cutter boolean
2772 int have_cutter; // Have a paper cutter?
2773
2774
2775 have_cutter = get_boolean(fp);
bdd6c45b 2776 if (have_cutter <= 0 || cond_state)
ac884b6a
MS
2777 continue;
2778
2779 if ((o = d->find_option("CutMedia")) == NULL)
2780 {
2781 o = new ppdcOption(PPDC_BOOLEAN, "CutMedia", "Cut Media", PPDC_SECTION_ANY, 10.0f);
2782
2783 g = general;
2784 g->add_option(o);
2785
2786 c = new ppdcChoice("False", NULL, "<</CutMedia 0>>setpagedevice");
2787 o->add_choice(c);
2788 o->set_defchoice(c);
2789
2790 c = new ppdcChoice("True", NULL, "<</CutMedia 4>>setpagedevice");
2791 o->add_choice(c);
2792 }
2793
2794 o = NULL;
2795 }
2796 else if (!strcasecmp(temp, "Darkness"))
2797 {
2798 // Get the darkness choice...
2799 c = get_generic(fp, "Darkness", NULL, "cupsCompression");
2800 if (!c)
2801 continue;
2802
bdd6c45b
MS
2803 if (cond_state)
2804 {
2805 c->release();
2806 continue;
2807 }
2808
ac884b6a
MS
2809 // Add the choice to the cupsDarkness option...
2810 if ((o = d->find_option("cupsDarkness")) == NULL)
2811 {
2812 // Create the cupsDarkness option...
2813 o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
2814 g = general;
2815 g->add_option(o);
2816 }
2817
2818 o->add_choice(c);
2819
2820 if (isdefault)
2821 o->set_defchoice(c);
2822
2823 o = NULL;
2824 }
2825 else if (!strcasecmp(temp, "DriverType"))
2826 {
2827 int i; // Looping var
2828
2829
2830 // DriverType keyword
2831 if (!get_token(fp, temp, sizeof(temp)))
2832 {
61cf44e2
MS
2833 _cupsLangPrintf(stderr,
2834 _("ppdc: Expected driver type keyword following "
2835 "DriverType on line %d of %s!\n"),
2836 fp->line, fp->filename);
ac884b6a
MS
2837 continue;
2838 }
2839
bdd6c45b
MS
2840 if (cond_state)
2841 continue;
2842
ac884b6a
MS
2843 for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++)
2844 if (!strcasecmp(temp, driver_types[i]))
2845 break;
2846
2847 if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0])))
2848 d->type = (ppdcDrvType)i;
2849 else if (!strcasecmp(temp, "dymo"))
2850 d->type = PPDC_DRIVER_LABEL;
2851 else
61cf44e2
MS
2852 _cupsLangPrintf(stderr,
2853 _("ppdc: Unknown driver type %s on line %d of %s!\n"),
2854 temp, fp->line, fp->filename);
ac884b6a
MS
2855 }
2856 else if (!strcasecmp(temp, "Duplex"))
2857 get_duplex(fp, d);
2858 else if (!strcasecmp(temp, "Filter"))
2859 {
2860 ppdcFilter *f; // Filter
2861
2862
2863 // Get the filter value...
2864 f = get_filter(fp);
2865 if (f)
bdd6c45b
MS
2866 {
2867 if (cond_state)
2868 f->release();
2869 else
2870 d->filters->add(f);
2871 }
ac884b6a
MS
2872 }
2873 else if (!strcasecmp(temp, "Finishing"))
2874 {
2875 // Get the finishing choice...
2876 c = get_generic(fp, "Finishing", "OutputType", NULL);
2877 if (!c)
2878 continue;
2879
bdd6c45b
MS
2880 if (cond_state)
2881 {
2882 c->release();
2883 continue;
2884 }
2885
ac884b6a
MS
2886 // Add the choice to the cupsFinishing option...
2887 if ((o = d->find_option("cupsFinishing")) == NULL)
2888 {
2889 // Create the cupsFinishing option...
2890 o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
2891 g = general;
2892 g->add_option(o);
2893 }
2894
2895 o->add_choice(c);
2896
2897 if (isdefault)
2898 o->set_defchoice(c);
2899
2900 o = NULL;
2901 }
2902 else if (!strcasecmp(temp, "Font") ||
2903 !strcasecmp(temp, "#font"))
2904 {
2905 ppdcFont *f; // Font
2906
2907
2908 // Get a font...
2909 f = get_font(fp);
2910 if (f)
2911 {
bdd6c45b
MS
2912 if (cond_state)
2913 f->release();
2914 else
2915 {
2916 if (!strcasecmp(temp, "#font"))
2917 base_fonts->add(f);
2918 else
2919 d->add_font(f);
ac884b6a 2920
bdd6c45b
MS
2921 if (isdefault)
2922 d->set_default_font(f);
2923 }
ac884b6a
MS
2924 }
2925 }
2926 else if (!strcasecmp(temp, "Group"))
2927 {
2928 // Get a group...
bdd6c45b
MS
2929 ppdcGroup *tempg = get_group(fp, d);
2930
2931 if (!tempg)
ac884b6a 2932 break;
bdd6c45b
MS
2933
2934 if (cond_state)
2935 {
2936 if (!d->find_group(tempg->name->value))
2937 tempg->release();
2938 }
2939 else
2940 {
2941 if (!d->find_group(tempg->name->value))
2942 d->add_group(tempg);
2943
2944 g = tempg;
2945 }
ac884b6a
MS
2946 }
2947 else if (!strcasecmp(temp, "HWMargins"))
2948 {
2949 // HWMargins left bottom right top
2950 d->left_margin = get_measurement(fp);
2951 d->bottom_margin = get_measurement(fp);
2952 d->right_margin = get_measurement(fp);
2953 d->top_margin = get_measurement(fp);
2954 }
2955 else if (!strcasecmp(temp, "InputSlot"))
2956 {
2957 // Get the input slot choice...
2958 c = get_generic(fp, "InputSlot", NULL, "MediaPosition");
2959 if (!c)
2960 continue;
2961
bdd6c45b
MS
2962 if (cond_state)
2963 {
2964 c->release();
2965 continue;
2966 }
2967
ac884b6a
MS
2968 // Add the choice to the InputSlot option...
2969 if ((o = d->find_option("InputSlot")) == NULL)
2970 {
2971 // Create the InputSlot option...
2972 o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
2973 PPDC_SECTION_ANY, 10.0f);
2974 g = general;
2975 g->add_option(o);
2976 }
2977
2978 o->add_choice(c);
2979
2980 if (isdefault)
2981 o->set_defchoice(c);
2982
2983 o = NULL;
2984 }
2985 else if (!strcasecmp(temp, "Installable"))
2986 {
2987 // Get the installable option...
2988 o = get_installable(fp);
2989
2990 // Add it as needed...
2991 if (o)
2992 {
bdd6c45b
MS
2993 if (cond_state)
2994 o->release();
2995 else
2996 install->add_option(o);
2997
ac884b6a
MS
2998 o = NULL;
2999 }
3000 }
3001 else if (!strcasecmp(temp, "ManualCopies"))
3002 {
3003 // ManualCopies boolean
bdd6c45b
MS
3004 if (cond_state)
3005 get_boolean(fp);
3006 else
3007 d->manual_copies = get_boolean(fp);
ac884b6a
MS
3008 }
3009 else if (!strcasecmp(temp, "Manufacturer"))
3010 {
3011 // Manufacturer name
3012 char name[256]; // Model name string
3013
3014
3015 if (!get_token(fp, name, sizeof(name)))
3016 {
61cf44e2
MS
3017 _cupsLangPrintf(stderr,
3018 _("ppdc: Expected name after Manufacturer on line %d "
3019 "of %s!\n"), fp->line, fp->filename);
ac884b6a
MS
3020 break;
3021 }
3022
bdd6c45b
MS
3023 if (!cond_state)
3024 d->set_manufacturer(name);
ac884b6a
MS
3025 }
3026 else if (!strcasecmp(temp, "MaxSize"))
3027 {
3028 // MaxSize width length
bdd6c45b
MS
3029 if (cond_state)
3030 {
3031 get_measurement(fp);
3032 get_measurement(fp);
3033 }
3034 else
3035 {
3036 d->max_width = get_measurement(fp);
3037 d->max_length = get_measurement(fp);
3038 }
ac884b6a
MS
3039 }
3040 else if (!strcasecmp(temp, "MediaSize"))
3041 {
3042 // MediaSize keyword
3043 char name[41]; // Media size name
3044 ppdcMediaSize *m, // Matching media size...
3045 *dm; // Driver media size...
3046
3047
3048 if (get_token(fp, name, sizeof(name)) == NULL)
3049 {
61cf44e2
MS
3050 _cupsLangPrintf(stderr,
3051 _("ppdc: Expected name after MediaSize on line %d of "
3052 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3053 break;
3054 }
3055
bdd6c45b
MS
3056 if (cond_state)
3057 continue;
3058
ac884b6a
MS
3059 m = find_size(name);
3060
3061 if (!m)
3062 {
61cf44e2
MS
3063 _cupsLangPrintf(stderr,
3064 _("ppdc: Unknown media size \"%s\" on line %d of "
3065 "%s!\n"), name, fp->line, fp->filename);
ac884b6a
MS
3066 break;
3067 }
3068
3069 // Add this size to the driver...
3070 dm = new ppdcMediaSize(m->name->value, m->text->value,
3071 m->width, m->length, d->left_margin,
3072 d->bottom_margin, d->right_margin,
3073 d->top_margin);
3074 d->sizes->add(dm);
3075
3076 if (isdefault)
3077 d->set_default_size(dm);
3078 }
3079 else if (!strcasecmp(temp, "MediaType"))
3080 {
3081 // Get the media type choice...
3082 c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType");
3083 if (!c)
3084 continue;
3085
bdd6c45b
MS
3086 if (cond_state)
3087 {
3088 c->release();
3089 continue;
3090 }
3091
ac884b6a
MS
3092 // Add the choice to the MediaType option...
3093 if ((o = d->find_option("MediaType")) == NULL)
3094 {
3095 // Create the MediaType option...
3096 o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
3097 PPDC_SECTION_ANY, 10.0f);
3098 g = general;
3099 g->add_option(o);
3100 }
3101
3102 o->add_choice(c);
3103
3104 if (isdefault)
3105 o->set_defchoice(c);
3106
3107 o = NULL;
3108 }
3109 else if (!strcasecmp(temp, "MinSize"))
3110 {
3111 // MinSize width length
bdd6c45b
MS
3112 if (cond_state)
3113 {
3114 get_measurement(fp);
3115 get_measurement(fp);
3116 }
3117 else
3118 {
3119 d->min_width = get_measurement(fp);
3120 d->min_length = get_measurement(fp);
3121 }
ac884b6a
MS
3122 }
3123 else if (!strcasecmp(temp, "ModelName"))
3124 {
3125 // ModelName name
3126 char name[256]; // Model name string
3127
3128
3129 if (!get_token(fp, name, sizeof(name)))
3130 {
61cf44e2
MS
3131 _cupsLangPrintf(stderr,
3132 _("ppdc: Expected name after ModelName on line %d of "
3133 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3134 break;
3135 }
3136
bdd6c45b
MS
3137 if (!cond_state)
3138 d->set_model_name(name);
ac884b6a
MS
3139 }
3140 else if (!strcasecmp(temp, "ModelNumber"))
3141 {
3142 // ModelNumber number
bdd6c45b
MS
3143 if (cond_state)
3144 get_integer(fp);
3145 else
3146 d->model_number = get_integer(fp);
ac884b6a
MS
3147 }
3148 else if (!strcasecmp(temp, "Option"))
3149 {
3150 // Get an option...
bdd6c45b
MS
3151 ppdcOption *tempo = get_option(fp, d, g);
3152
3153 if (!tempo)
ac884b6a 3154 break;
bdd6c45b
MS
3155
3156 if (cond_state)
3157 {
3158 if (!g->find_option(tempo->name->value))
3159 tempo->release();
3160 }
3161 else
3162 {
3163 if (!g->find_option(tempo->name->value))
3164 g->add_option(tempo);
3165
3166 o = tempo;
3167 }
3168 }
3169 else if (!strcasecmp(temp, "FileName"))
3170 {
3171 // FileName name
3172 char name[256]; // Filename string
3173
3174
3175 if (!get_token(fp, name, sizeof(name)))
3176 {
61cf44e2
MS
3177 _cupsLangPrintf(stderr,
3178 _("ppdc: Expected name after FileName on line %d of "
3179 "%s!\n"), fp->line, fp->filename);
bdd6c45b
MS
3180 break;
3181 }
3182
3183 if (!cond_state)
3184 d->set_file_name(name);
ac884b6a
MS
3185 }
3186 else if (!strcasecmp(temp, "PCFileName"))
3187 {
3188 // PCFileName name
bdd6c45b 3189 char name[256]; // PC filename string
ac884b6a
MS
3190
3191
3192 if (!get_token(fp, name, sizeof(name)))
3193 {
61cf44e2
MS
3194 _cupsLangPrintf(stderr,
3195 _("ppdc: Expected name after PCFileName on line %d of "
3196 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3197 break;
3198 }
3199
bdd6c45b
MS
3200 if (!cond_state)
3201 d->set_pc_file_name(name);
ac884b6a
MS
3202 }
3203 else if (!strcasecmp(temp, "Resolution"))
3204 {
3205 // Get the resolution choice...
3206 c = get_resolution(fp);
3207 if (!c)
3208 continue;
3209
bdd6c45b
MS
3210 if (cond_state)
3211 {
3212 c->release();
3213 continue;
3214 }
3215
ac884b6a
MS
3216 // Add the choice to the Resolution option...
3217 if ((o = d->find_option("Resolution")) == NULL)
3218 {
3219 // Create the Resolution option...
bdd6c45b
MS
3220 o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
3221 10.0f);
ac884b6a
MS
3222 g = general;
3223 g->add_option(o);
3224 }
3225
3226 o->add_choice(c);
3227
3228 if (isdefault)
3229 o->set_defchoice(c);
3230
3231 o = NULL;
3232 }
3233 else if (!strcasecmp(temp, "SimpleColorProfile"))
3234 {
3235 ppdcProfile *p; // Color profile
3236
3237
3238 // Get the color profile...
3239 p = get_simple_profile(fp);
3240
3241 if (p)
bdd6c45b
MS
3242 {
3243 if (cond_state)
3244 p->release();
3245 else
3246 d->profiles->add(p);
3247 }
ac884b6a
MS
3248 }
3249 else if (!strcasecmp(temp, "Throughput"))
3250 {
3251 // Throughput number
bdd6c45b
MS
3252 if (cond_state)
3253 get_integer(fp);
3254 else
3255 d->throughput = get_integer(fp);
ac884b6a
MS
3256 }
3257 else if (!strcasecmp(temp, "UIConstraints"))
3258 {
3259 ppdcConstraint *con; // Constraint
3260
3261
3262 con = get_constraint(fp);
3263
3264 if (con)
bdd6c45b
MS
3265 {
3266 if (cond_state)
3267 con->release();
3268 else
3269 d->constraints->add(con);
3270 }
ac884b6a
MS
3271 }
3272 else if (!strcasecmp(temp, "VariablePaperSize"))
3273 {
3274 // VariablePaperSize boolean
bdd6c45b
MS
3275 if (cond_state)
3276 get_boolean(fp);
3277 else
3278 d->variable_paper_size = get_boolean(fp);
ac884b6a
MS
3279 }
3280 else if (!strcasecmp(temp, "Version"))
3281 {
3282 // Version string
3283 char name[256]; // Model name string
3284
3285
3286 if (!get_token(fp, name, sizeof(name)))
3287 {
61cf44e2
MS
3288 _cupsLangPrintf(stderr,
3289 _("ppdc: Expected string after Version on line %d of "
3290 "%s!\n"), fp->line, fp->filename);
ac884b6a
MS
3291 break;
3292 }
3293
bdd6c45b
MS
3294 if (!cond_state)
3295 d->set_version(name);
ac884b6a
MS
3296 }
3297 else
3298 {
61cf44e2
MS
3299 _cupsLangPrintf(stderr,
3300 _("ppdc: Unknown token \"%s\" seen on line %d of %s!\n"),
3301 temp, fp->line, fp->filename);
ac884b6a
MS
3302 break;
3303 }
3304 }
3305
3306 // Done processing this block, is there anything to save?
3307 if (!inc)
3308 {
3309 if (!d->pc_file_name || !d->model_name || !d->manufacturer || !d->version ||
3310 !d->sizes->count)
3311 {
3312 // Nothing to save...
3313 d->release();
3314 }
3315 else
3316 {
3317 // Got a driver, save it...
3318 drivers->add(d);
3319 }
3320 }
3321}
3322
3323
3324//
3325// 'ppdcSource::set_variable()' - Set a variable.
3326//
3327
3328ppdcVariable * // O - Variable
3329ppdcSource::set_variable(
3330 const char *name, // I - Name
3331 const char *value) // I - Value
3332{
3333 ppdcVariable *v; // Variable
3334
3335
3336 // See if the variable exists already...
3337 v = find_variable(name);
3338 if (v)
3339 {
3340 // Change the variable value...
3341 v->set_value(value);
3342 }
3343 else
3344 {
3345 // Create a new variable and add it...
3346 v = new ppdcVariable(name, value);
3347 vars->add(v);
3348 }
3349
3350 return (v);
3351}
3352
3353
3354//
3355// 'ppdcSource::write_file()' - Write the current source data to a file.
3356//
3357
3358int // O - 0 on success, -1 on error
3359ppdcSource::write_file(const char *f) // I - File to write
3360{
3361 cups_file_t *fp; // Output file
3362 char bckname[1024]; // Backup file
3363 ppdcDriver *d; // Current driver
3364 ppdcString *st; // Current string
3365 ppdcAttr *a; // Current attribute
3366 ppdcConstraint *co; // Current constraint
3367 ppdcFilter *fi; // Current filter
3368 ppdcFont *fo; // Current font
3369 ppdcGroup *g; // Current group
3370 ppdcOption *o; // Current option
3371 ppdcChoice *ch; // Current choice
3372 ppdcProfile *p; // Current color profile
3373 ppdcMediaSize *si; // Current media size
3374 float left, // Current left margin
3375 bottom, // Current bottom margin
3376 right, // Current right margin
3377 top; // Current top margin
3378 int dtused[PPDC_DRIVER_MAX];// Driver type usage...
3379
3380
3381 // Rename the current file, if any, to .bck...
3382 snprintf(bckname, sizeof(bckname), "%s.bck", f);
3383 rename(f, bckname);
3384
3385 // Open the output file...
3386 fp = cupsFileOpen(f, "w");
3387
3388 if (!fp)
3389 {
3390 // Can't create file; restore backup and return...
3391 rename(bckname, f);
3392 return (-1);
3393 }
3394
3395 cupsFilePuts(fp, "// CUPS PPD Compiler " CUPS_SVERSION "\n\n");
3396
3397 // Include standard files...
3398 cupsFilePuts(fp, "// Include necessary files...\n");
3399 cupsFilePuts(fp, "#include <font.defs>\n");
3400 cupsFilePuts(fp, "#include <media.defs>\n");
3401
3402 memset(dtused, 0, sizeof(dtused));
3403
3404 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3405 if (d->type > PPDC_DRIVER_PS && !dtused[d->type])
3406 {
3407 cupsFilePrintf(fp, "#include <%s.h>\n", driver_types[d->type]);
3408 dtused[d->type] = 1;
3409 }
3410
3411 // Output each driver...
3412 for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
3413 {
3414 // Start the driver...
3415 cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value, d->model_name->value);
3416 cupsFilePuts(fp, "{\n");
3417
3418 // Write the copyright stings...
3419 for (st = (ppdcString *)d->copyright->first();
3420 st;
3421 st = (ppdcString *)d->copyright->next())
3422 quotef(fp, " Copyright \"%s\"\n", st->value);
3423
3424 // Write other strings and values...
d2354e63 3425 if (d->manufacturer && d->manufacturer->value)
ac884b6a
MS
3426 quotef(fp, " Manufacturer \"%s\"\n", d->manufacturer->value);
3427 if (d->model_name->value)
3428 quotef(fp, " ModelName \"%s\"\n", d->model_name->value);
d2354e63 3429 if (d->file_name && d->file_name->value)
bdd6c45b 3430 quotef(fp, " FileName \"%s\"\n", d->file_name->value);
d2354e63 3431 if (d->pc_file_name && d->pc_file_name->value)
ac884b6a 3432 quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value);
d2354e63 3433 if (d->version && d->version->value)
ac884b6a
MS
3434 quotef(fp, " Version \"%s\"\n", d->version->value);
3435
3436 cupsFilePrintf(fp, " DriverType %s\n", driver_types[d->type]);
3437
3438 if (d->model_number)
3439 {
3440 switch (d->type)
3441 {
3442 case PPDC_DRIVER_ESCP :
3443 cupsFilePuts(fp, " ModelNumber (");
3444
3445 if (d->model_number & ESCP_DOTMATRIX)
3446 cupsFilePuts(fp, " $ESCP_DOTMATRIX");
3447 if (d->model_number & ESCP_MICROWEAVE)
3448 cupsFilePuts(fp, " $ESCP_MICROWEAVE");
3449 if (d->model_number & ESCP_STAGGER)
3450 cupsFilePuts(fp, " $ESCP_STAGGER");
3451 if (d->model_number & ESCP_ESCK)
3452 cupsFilePuts(fp, " $ESCP_ESCK");
3453 if (d->model_number & ESCP_EXT_UNITS)
3454 cupsFilePuts(fp, " $ESCP_EXT_UNITS");
3455 if (d->model_number & ESCP_EXT_MARGINS)
3456 cupsFilePuts(fp, " $ESCP_EXT_MARGINS");
3457 if (d->model_number & ESCP_USB)
3458 cupsFilePuts(fp, " $ESCP_USB");
3459 if (d->model_number & ESCP_PAGE_SIZE)
3460 cupsFilePuts(fp, " $ESCP_PAGE_SIZE");
3461 if (d->model_number & ESCP_RASTER_ESCI)
3462 cupsFilePuts(fp, " $ESCP_RASTER_ESCI");
3463 if (d->model_number & ESCP_REMOTE)
3464 cupsFilePuts(fp, " $ESCP_REMOTE");
3465
3466 cupsFilePuts(fp, ")\n");
3467 break;
3468
3469 case PPDC_DRIVER_PCL :
3470 cupsFilePuts(fp, " ModelNumber (");
3471
3472 if (d->model_number & PCL_PAPER_SIZE)
3473 cupsFilePuts(fp, " $PCL_PAPER_SIZE");
3474 if (d->model_number & PCL_INKJET)
3475 cupsFilePuts(fp, " $PCL_INKJET");
3476 if (d->model_number & PCL_RASTER_END_COLOR)
3477 cupsFilePuts(fp, " $PCL_RASTER_END_COLOR");
3478 if (d->model_number & PCL_RASTER_CID)
3479 cupsFilePuts(fp, " $PCL_RASTER_CID");
3480 if (d->model_number & PCL_RASTER_CRD)
3481 cupsFilePuts(fp, " $PCL_RASTER_CRD");
3482 if (d->model_number & PCL_RASTER_SIMPLE)
3483 cupsFilePuts(fp, " $PCL_RASTER_SIMPLE");
3484 if (d->model_number & PCL_RASTER_RGB24)
3485 cupsFilePuts(fp, " $PCL_RASTER_RGB24");
3486 if (d->model_number & PCL_PJL)
3487 cupsFilePuts(fp, " $PCL_PJL");
3488 if (d->model_number & PCL_PJL_PAPERWIDTH)
3489 cupsFilePuts(fp, " $PCL_PJL_PAPERWIDTH");
3490 if (d->model_number & PCL_PJL_HPGL2)
3491 cupsFilePuts(fp, " $PCL_PJL_HPGL2");
3492 if (d->model_number & PCL_PJL_PCL3GUI)
3493 cupsFilePuts(fp, " $PCL_PJL_PCL3GUI");
3494 if (d->model_number & PCL_PJL_RESOLUTION)
3495 cupsFilePuts(fp, " $PCL_PJL_RESOLUTION");
3496
3497 cupsFilePuts(fp, ")\n");
3498 break;
3499
3500 case PPDC_DRIVER_LABEL :
3501 cupsFilePuts(fp, " ModelNumber ");
3502
3503 switch (d->model_number)
3504 {
3505 case DYMO_3x0 :
3506 cupsFilePuts(fp, "$DYMO_3x0\n");
3507 break;
3508
3509 case ZEBRA_EPL_LINE :
3510 cupsFilePuts(fp, "$ZEBRA_EPL_LINE\n");
3511 break;
3512
3513 case ZEBRA_EPL_PAGE :
3514 cupsFilePuts(fp, "$ZEBRA_EPL_PAGE\n");
3515 break;
3516
3517 case ZEBRA_ZPL :
3518 cupsFilePuts(fp, "$ZEBRA_ZPL\n");
3519 break;
3520
3521 case ZEBRA_CPCL :
3522 cupsFilePuts(fp, "$ZEBRA_CPCL\n");
3523 break;
3524
3525 case INTELLITECH_PCL :
3526 cupsFilePuts(fp, "$INTELLITECH_PCL\n");
3527 break;
3528
3529 default :
3530 cupsFilePrintf(fp, "%d\n", d->model_number);
3531 break;
3532 }
3533 break;
3534
3535 case PPDC_DRIVER_EPSON :
3536 cupsFilePuts(fp, " ModelNumber ");
3537
3538 switch (d->model_number)
3539 {
3540 case EPSON_9PIN :
3541 cupsFilePuts(fp, "$EPSON_9PIN\n");
3542 break;
3543
3544 case EPSON_24PIN :
3545 cupsFilePuts(fp, "$EPSON_24PIN\n");
3546 break;
3547
3548 case EPSON_COLOR :
3549 cupsFilePuts(fp, "$EPSON_COLOR\n");
3550 break;
3551
3552 case EPSON_PHOTO :
3553 cupsFilePuts(fp, "$EPSON_PHOTO\n");
3554 break;
3555
3556 case EPSON_ICOLOR :
3557 cupsFilePuts(fp, "$EPSON_ICOLOR\n");
3558 break;
3559
3560 case EPSON_IPHOTO :
3561 cupsFilePuts(fp, "$EPSON_IPHOTO\n");
3562 break;
3563
3564 default :
3565 cupsFilePrintf(fp, "%d\n", d->model_number);
3566 break;
3567 }
3568 break;
3569
3570 case PPDC_DRIVER_HP :
3571 cupsFilePuts(fp, " ModelNumber ");
3572 switch (d->model_number)
3573 {
3574 case HP_LASERJET :
3575 cupsFilePuts(fp, "$HP_LASERJET\n");
3576 break;
3577
3578 case HP_DESKJET :
3579 cupsFilePuts(fp, "$HP_DESKJET\n");
3580 break;
3581
3582 case HP_DESKJET2 :
3583 cupsFilePuts(fp, "$HP_DESKJET2\n");
3584 break;
3585
3586 default :
3587 cupsFilePrintf(fp, "%d\n", d->model_number);
3588 break;
3589 }
3590
3591 cupsFilePuts(fp, ")\n");
3592 break;
3593
3594 default :
3595 cupsFilePrintf(fp, " ModelNumber %d\n", d->model_number);
3596 break;
3597 }
3598 }
3599
3600 if (d->manual_copies)
3601 cupsFilePuts(fp, " ManualCopies Yes\n");
3602
3603 if (d->color_device)
3604 cupsFilePuts(fp, " ColorDevice Yes\n");
3605
3606 if (d->throughput)
3607 cupsFilePrintf(fp, " Throughput %d\n", d->throughput);
3608
3609 // Output all of the attributes...
3610 for (a = (ppdcAttr *)d->attrs->first();
3611 a;
3612 a = (ppdcAttr *)d->attrs->next())
3613 if (a->text->value && a->text->value[0])
3614 quotef(fp, " Attribute \"%s\" \"%s/%s\" \"%s\"\n",
3615 a->name->value, a->selector->value ? a->selector->value : "",
3616 a->text->value, a->value->value ? a->value->value : "");
3617 else
3618 quotef(fp, " Attribute \"%s\" \"%s\" \"%s\"\n",
3619 a->name->value, a->selector->value ? a->selector->value : "",
3620 a->value->value ? a->value->value : "");
3621
3622 // Output all of the constraints...
3623 for (co = (ppdcConstraint *)d->constraints->first();
3624 co;
3625 co = (ppdcConstraint *)d->constraints->next())
3626 {
3627 if (co->option1->value[0] == '*')
3628 cupsFilePrintf(fp, " UIConstraints \"%s %s", co->option1->value,
3629 co->choice1->value ? co->choice1->value : "");
3630 else
3631 cupsFilePrintf(fp, " UIConstraints \"*%s %s", co->option1->value,
3632 co->choice1->value ? co->choice1->value : "");
3633
3634 if (co->option2->value[0] == '*')
3635 cupsFilePrintf(fp, " %s %s\"\n", co->option2->value,
3636 co->choice2->value ? co->choice2->value : "");
3637 else
3638 cupsFilePrintf(fp, " *%s %s\"\n", co->option2->value,
3639 co->choice2->value ? co->choice2->value : "");
3640 }
3641
3642 // Output all of the filters...
3643 for (fi = (ppdcFilter *)d->filters->first();
3644 fi;
3645 fi = (ppdcFilter *)d->filters->next())
3646 cupsFilePrintf(fp, " Filter \"%s %d %s\"\n",
3647 fi->mime_type->value, fi->cost, fi->program->value);
3648
3649 // Output all of the fonts...
3650 for (fo = (ppdcFont *)d->fonts->first();
3651 fo;
3652 fo = (ppdcFont *)d->fonts->next())
3653 if (!strcmp(fo->name->value, "*"))
3654 cupsFilePuts(fp, " Font *\n");
3655 else
3656 cupsFilePrintf(fp, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n",
3657 fo->name->value, fo->encoding->value,
3658 fo->version->value, fo->charset->value,
3659 fo->status == PPDC_FONT_ROM ? "ROM" : "Disk");
3660
3661 // Output all options...
3662 for (g = (ppdcGroup *)d->groups->first();
3663 g;
3664 g = (ppdcGroup *)d->groups->next())
3665 {
3666 if (g->options->count == 0)
3667 continue;
3668
3669 if (g->text->value && g->text->value[0])
3670 quotef(fp, " Group \"%s/%s\"\n", g->name->value, g->text->value);
3671 else
3672 cupsFilePrintf(fp, " Group \"%s\"\n", g->name->value);
3673
3674 for (o = (ppdcOption *)g->options->first();
3675 o;
3676 o = (ppdcOption *)g->options->next())
3677 {
3678 if (o->choices->count == 0)
3679 continue;
3680
3681 if (o->text->value && o->text->value[0])
3682 quotef(fp, " Option \"%s/%s\"", o->name->value, o->text->value);
3683 else
3684 cupsFilePrintf(fp, " Option \"%s\"", o->name->value);
3685
3686 cupsFilePrintf(fp, " %s %s %.1f\n",
3687 o->type == PPDC_BOOLEAN ? "Boolean" :
3688 o->type == PPDC_PICKONE ? "PickOne" : "PickMany",
3689 o->section == PPDC_SECTION_ANY ? "AnySetup" :
3690 o->section == PPDC_SECTION_DOCUMENT ? "DocumentSetup" :
3691 o->section == PPDC_SECTION_EXIT ? "ExitServer" :
3692 o->section == PPDC_SECTION_JCL ? "JCLSetup" :
3693 o->section == PPDC_SECTION_PAGE ? "PageSetup" :
3694 "Prolog",
3695 o->order);
3696
3697 for (ch = (ppdcChoice *)o->choices->first();
3698 ch;
3699 ch = (ppdcChoice *)o->choices->next())
3700 {
3701 if (ch->text->value && ch->text->value[0])
3702 quotef(fp, " %sChoice \"%s/%s\" \"%s\"\n",
3703 o->defchoice == ch->name ? "*" : "",
3704 ch->name->value, ch->text->value,
3705 ch->code->value ? ch->code->value : "");
3706 else
3707 quotef(fp, " %sChoice \"%s\" \"%s\"\n",
3708 o->defchoice == ch->name ? "*" : "",
3709 ch->name->value,
3710 ch->code->value ? ch->code->value : "");
3711 }
3712 }
3713 }
3714
3715 // Output all of the color profiles...
3716 for (p = (ppdcProfile *)d->profiles->first();
3717 p;
3718 p = (ppdcProfile *)d->profiles->next())
3719 cupsFilePrintf(fp, " ColorProfile \"%s/%s\" %.3f %.3f "
3720 "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
3721 p->resolution->value, p->media_type->value,
3722 p->density, p->gamma,
3723 p->profile[0], p->profile[1], p->profile[2],
3724 p->profile[3], p->profile[4], p->profile[5],
3725 p->profile[6], p->profile[7], p->profile[8]);
3726
3727 // Output all of the media sizes...
3728 left = 0.0;
3729 bottom = 0.0;
3730 right = 0.0;
3731 top = 0.0;
3732
3733 for (si = (ppdcMediaSize *)d->sizes->first();
3734 si;
3735 si = (ppdcMediaSize *)d->sizes->next())
3736 if (si->size_code->value && si->region_code->value)
3737 {
3738 // Output a custom media size...
3739 quotef(fp, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n",
3740 si->name == d->default_size ? "*" : "", si->name->value,
3741 si->text->value, si->width, si->length, si->left, si->bottom,
3742 si->right, si->top, si->size_code->value,
3743 si->region_code->value);
3744 }
3745 else
3746 {
3747 // Output a standard media size...
3748 if (fabs(left - si->left) > 0.1 ||
3749 fabs(bottom - si->bottom) > 0.1 ||
3750 fabs(right - si->right) > 0.1 ||
3751 fabs(top - si->top) > 0.1)
3752 {
3753 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3754 si->left, si->bottom, si->right, si->top);
3755
3756 left = si->left;
3757 bottom = si->bottom;
3758 right = si->right;
3759 top = si->top;
3760 }
3761
3762 cupsFilePrintf(fp, " %sMediaSize %s\n",
3763 si->name == d->default_size ? "*" : "",
3764 si->name->value);
3765 }
3766
3767 if (d->variable_paper_size)
3768 {
3769 cupsFilePuts(fp, " VariablePaperSize Yes\n");
3770
3771 if (fabs(left - d->left_margin) > 0.1 ||
3772 fabs(bottom - d->bottom_margin) > 0.1 ||
3773 fabs(right - d->right_margin) > 0.1 ||
3774 fabs(top - d->top_margin) > 0.1)
3775 {
3776 cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
3777 d->left_margin, d->bottom_margin, d->right_margin,
3778 d->top_margin);
3779 }
3780
3781 cupsFilePrintf(fp, " MinSize %.2f %.2f\n", d->min_width, d->min_length);
3782 cupsFilePrintf(fp, " MaxSize %.2f %.2f\n", d->max_width, d->max_length);
3783 }
3784
3785 // End the driver...
3786 cupsFilePuts(fp, "}\n");
3787 }
3788
3789 // Close the file and return...
3790 cupsFileClose(fp);
3791
3792 return (0);
3793}
3794
3795
3796//
3797// End of "$Id$".
3798//