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