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