]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/ppd.c
0e8c20fb881611aec99ccebf123ea501b071bef6
2 * "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $"
4 * PPD file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2001 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * PostScript is a trademark of Adobe Systems, Inc.
26 * This code and any derivative of it may be used and distributed
27 * freely under the terms of the GNU General Public License when
28 * used with GNU Ghostscript or its derivatives. Use of the code
29 * (or any derivative of it) with software other than GNU
30 * GhostScript (or its derivatives) is governed by the CUPS license
35 * ppdClose() - Free all memory used by the PPD file.
36 * ppd_free_group() - Free a single UI group.
37 * ppd_free_option() - Free a single option.
38 * ppdOpen() - Read a PPD file into memory.
39 * ppdOpenFd() - Read a PPD file into memory.
40 * ppdOpenFile() - Read a PPD file into memory.
41 * ppd_read() - Read a line from a PPD file, skipping comment lines
43 * compare_strings() - Compare two strings.
44 * compare_groups() - Compare two groups.
45 * compare_options() - Compare two options.
46 * compare_choices() - Compare two choices.
50 * Include necessary headers.
65 #if defined(WIN32) || defined(__EMX__)
66 # define READ_BINARY "rb" /* Open a binary file for reading */
67 # define WRITE_BINARY "wb" /* Open a binary file for writing */
69 # define READ_BINARY "r" /* Open a binary file for reading */
70 # define WRITE_BINARY "w" /* Open a binary file for writing */
71 #endif /* WIN32 || __EMX__ */
73 #define safe_free(p) if (p) free(p) /* Safe free macro */
75 #define PPD_KEYWORD 1 /* Line contained a keyword */
76 #define PPD_OPTION 2 /* Line contained an option name */
77 #define PPD_TEXT 4 /* Line contained human-readable text */
78 #define PPD_STRING 8 /* Line contained a string or code */
85 static int compare_strings(char *s
, char *t
);
86 static int compare_groups(ppd_group_t
*g0
, ppd_group_t
*g1
);
87 static int compare_options(ppd_option_t
*o0
, ppd_option_t
*o1
);
88 static int compare_choices(ppd_choice_t
*c0
, ppd_choice_t
*c1
);
89 static int ppd_read(FILE *fp
, char *keyword
, char *option
,
90 char *text
, char **string
);
91 static void ppd_decode(char *string
);
92 static void ppd_fix(char *string
);
93 static void ppd_free_group(ppd_group_t
*group
);
94 static void ppd_free_option(ppd_option_t
*option
);
95 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, char *name
);
96 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, char *name
);
97 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, char *name
);
101 * 'ppdClose()' - Free all memory used by the PPD file.
105 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
107 int i
; /* Looping var */
108 ppd_emul_t
*emul
; /* Current emulation */
109 ppd_group_t
*group
; /* Current group */
110 char **font
; /* Current font */
111 char **filter
; /* Current filter */
115 * Range check the PPD file record...
122 * Free all strings at the top level...
125 safe_free(ppd
->patches
);
126 safe_free(ppd
->jcl_begin
);
127 safe_free(ppd
->jcl_ps
);
128 safe_free(ppd
->jcl_end
);
129 safe_free(ppd
->lang_encoding
);
130 safe_free(ppd
->lang_version
);
131 safe_free(ppd
->modelname
);
132 safe_free(ppd
->ttrasterizer
);
133 safe_free(ppd
->manufacturer
);
134 safe_free(ppd
->product
);
135 safe_free(ppd
->nickname
);
136 safe_free(ppd
->shortnickname
);
139 * Free any emulations...
142 if (ppd
->num_emulations
> 0)
144 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
146 safe_free(emul
->start
);
147 safe_free(emul
->stop
);
150 safe_free(ppd
->emulations
);
154 * Free any UI groups, subgroups, and options...
157 if (ppd
->num_groups
> 0)
159 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
160 ppd_free_group(group
);
162 safe_free(ppd
->groups
);
166 * Free any page sizes...
169 if (ppd
->num_sizes
> 0)
170 safe_free(ppd
->sizes
);
173 * Free any constraints...
176 if (ppd
->num_consts
> 0)
177 safe_free(ppd
->consts
);
180 * Free any filters...
183 if (ppd
->num_filters
> 0)
185 for (i
= ppd
->num_filters
, filter
= ppd
->filters
; i
> 0; i
--, filter
++)
188 safe_free(ppd
->filters
);
195 if (ppd
->num_fonts
> 0)
197 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
200 safe_free(ppd
->fonts
);
204 * Free any profiles...
207 if (ppd
->num_profiles
> 0)
208 safe_free(ppd
->profiles
);
211 * Free the whole record...
219 * 'ppd_free_group()' - Free a single UI group.
223 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
225 int i
; /* Looping var */
226 ppd_option_t
*option
; /* Current option */
227 ppd_group_t
*subgroup
; /* Current sub-group */
230 if (group
->num_options
> 0)
232 for (i
= group
->num_options
, option
= group
->options
;
235 ppd_free_option(option
);
237 safe_free(group
->options
);
240 if (group
->num_subgroups
> 0)
242 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
245 ppd_free_group(subgroup
);
247 safe_free(group
->subgroups
);
253 * 'ppd_free_option()' - Free a single option.
257 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
259 int i
; /* Looping var */
260 ppd_choice_t
*choice
; /* Current choice */
263 if (option
->num_choices
> 0)
265 for (i
= option
->num_choices
, choice
= option
->choices
;
268 safe_free(choice
->code
);
270 safe_free(option
->choices
);
276 * 'ppd_get_group()' - Find or create the named group as needed.
279 static ppd_group_t
* /* O - Named group */
280 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
281 char *name
) /* I - Name of group */
283 int i
; /* Looping var */
284 ppd_group_t
*group
; /* Group */
287 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
288 if (strcmp(group
->text
, name
) == 0)
293 if (ppd
->num_groups
== 0)
294 group
= malloc(sizeof(ppd_group_t
));
296 group
= realloc(ppd
->groups
,
297 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
303 group
+= ppd
->num_groups
;
306 memset(group
, 0, sizeof(ppd_group_t
));
307 strncpy(group
->text
, name
, sizeof(group
->text
) - 1);
315 * 'ppd_get_option()' - Find or create the named option as needed.
318 static ppd_option_t
* /* O - Named option */
319 ppd_get_option(ppd_group_t
*group
, /* I - Group */
320 char *name
) /* I - Name of option */
322 int i
; /* Looping var */
323 ppd_option_t
*option
; /* Option */
326 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
327 if (strcmp(option
->keyword
, name
) == 0)
332 if (group
->num_options
== 0)
333 option
= malloc(sizeof(ppd_option_t
));
335 option
= realloc(group
->options
,
336 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
341 group
->options
= option
;
342 option
+= group
->num_options
;
343 group
->num_options
++;
345 memset(option
, 0, sizeof(ppd_option_t
));
346 strncpy(option
->keyword
, name
, sizeof(option
->keyword
) - 1);
354 * 'ppd_add_choice()' - Add a choice to an option.
357 static ppd_choice_t
* /* O - Named choice */
358 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
359 char *name
) /* I - Name of choice */
361 ppd_choice_t
*choice
; /* Choice */
364 if (option
->num_choices
== 0)
365 choice
= malloc(sizeof(ppd_choice_t
));
367 choice
= realloc(option
->choices
,
368 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
373 option
->choices
= choice
;
374 choice
+= option
->num_choices
;
375 option
->num_choices
++;
377 memset(choice
, 0, sizeof(ppd_choice_t
));
378 strncpy(choice
->choice
, name
, sizeof(choice
->choice
) - 1);
385 * 'ppd_add_size()' - Add a page size.
388 static ppd_size_t
* /* O - Named size */
389 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
390 char *name
) /* I - Name of size */
392 ppd_size_t
*size
; /* Size */
395 if (ppd
->num_sizes
== 0)
396 size
= malloc(sizeof(ppd_size_t
));
398 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
404 size
+= ppd
->num_sizes
;
407 memset(size
, 0, sizeof(ppd_size_t
));
408 strncpy(size
->name
, name
, sizeof(size
->name
) - 1);
415 * 'ppdOpen()' - Read a PPD file into memory.
418 ppd_file_t
* /* O - PPD file record */
419 ppdOpen(FILE *fp
) /* I - File to read from */
421 int i
, j
, k
, m
; /* Looping vars */
422 int count
; /* Temporary count */
423 ppd_file_t
*ppd
; /* PPD file record */
424 ppd_group_t
*group
, /* Current group */
425 *subgroup
; /* Current sub-group */
426 ppd_option_t
*option
; /* Current option */
427 ppd_choice_t
*choice
; /* Current choice */
428 ppd_const_t
*constraint
; /* Current constraint */
429 ppd_size_t
*size
; /* Current page size */
430 int mask
; /* Line data mask */
431 char keyword
[PPD_MAX_NAME
],
432 /* Keyword from file */
434 /* Option from file */
436 /* Human-readable text from file */
437 *string
, /* Code/text from file */
438 *sptr
, /* Pointer into string */
439 *nameptr
, /* Pointer into name */
440 *temp
, /* Temporary string pointer */
441 **tempfonts
; /* Temporary fonts pointer */
442 float order
; /* Order dependency number */
443 ppd_section_t section
; /* Order dependency section */
444 ppd_profile_t
*profile
; /* Pointer to color profile */
445 char **filter
; /* Pointer to filter */
446 cups_lang_t
*language
; /* Default language */
450 * Get the default language for the user...
453 language
= cupsLangDefault();
456 * Range check input...
463 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
466 mask
= ppd_read(fp
, keyword
, name
, text
, &string
);
469 strcmp(keyword
, "PPD-Adobe") != 0 ||
470 string
== NULL
|| string
[0] != '4')
473 * Either this is not a PPD file, or it is not a 4.x PPD file.
481 DEBUG_printf(("ppdOpen: keyword = %s, string = %08x\n", keyword
, string
));
486 * Allocate memory for the PPD file record...
489 if ((ppd
= calloc(sizeof(ppd_file_t
), 1)) == NULL
)
492 ppd
->language_level
= 1;
493 ppd
->color_device
= 0;
494 ppd
->colorspace
= PPD_CS_GRAY
;
498 * Read lines from the PPD file and add them to the file record...
506 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
)) != 0)
509 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
512 printf(", name = \"%s\"", name
);
515 printf(", text = \"%s\"", text
);
519 if (strlen(string
) > 40)
520 printf(", string = %08x", string
);
522 printf(", string = \"%s\"", string
);
528 if (strcmp(keyword
, "LanguageLevel") == 0)
529 ppd
->language_level
= atoi(string
);
530 else if (strcmp(keyword
, "LanguageEncoding") == 0)
532 ppd
->lang_encoding
= string
;
533 string
= NULL
; /* Don't free this string below */
535 else if (strcmp(keyword
, "LanguageVersion") == 0)
537 ppd
->lang_version
= string
;
538 string
= NULL
; /* Don't free this string below */
540 else if (strcmp(keyword
, "Manufacturer") == 0)
542 ppd
->manufacturer
= string
;
543 string
= NULL
; /* Don't free this string below */
545 else if (strcmp(keyword
, "ModelName") == 0)
547 ppd
->modelname
= string
;
548 string
= NULL
; /* Don't free this string below */
550 else if (strcmp(keyword
, "PCFileName") == 0)
552 ppd
->pcfilename
= string
;
553 string
= NULL
; /* Don't free this string below */
555 else if (strcmp(keyword
, "NickName") == 0)
557 ppd
->nickname
= string
;
558 string
= NULL
; /* Don't free this string below */
560 else if (strcmp(keyword
, "Product") == 0)
562 ppd
->product
= string
;
563 string
= NULL
; /* Don't free this string below */
565 else if (strcmp(keyword
, "ShortNickName") == 0)
567 ppd
->shortnickname
= string
;
568 string
= NULL
; /* Don't free this string below */
570 else if (strcmp(keyword
, "TTRasterizer") == 0)
572 ppd
->ttrasterizer
= string
;
573 string
= NULL
; /* Don't free this string below */
575 else if (strcmp(keyword
, "JCLBegin") == 0)
577 ppd_decode(string
); /* Decode quoted string */
578 ppd
->jcl_begin
= string
;
579 string
= NULL
; /* Don't free this string below */
581 else if (strcmp(keyword
, "JCLEnd") == 0)
583 ppd_decode(string
); /* Decode quoted string */
584 ppd
->jcl_end
= string
;
585 string
= NULL
; /* Don't free this string below */
587 else if (strcmp(keyword
, "JCLToPSInterpreter") == 0)
589 ppd_decode(string
); /* Decode quoted string */
590 ppd
->jcl_ps
= string
;
591 string
= NULL
; /* Don't free this string below */
593 else if (strcmp(keyword
, "AccurateScreensSupport") == 0)
594 ppd
->accurate_screens
= strcmp(string
, "True") == 0;
595 else if (strcmp(keyword
, "ColorDevice") == 0)
596 ppd
->color_device
= strcmp(string
, "True") == 0;
597 else if (strcmp(keyword
, "ContoneOnly") == 0)
598 ppd
->contone_only
= strcmp(string
, "True") == 0;
599 else if (strcmp(keyword
, "DefaultColorSpace") == 0)
601 if (strcmp(string
, "CMY") == 0)
602 ppd
->colorspace
= PPD_CS_CMY
;
603 else if (strcmp(string
, "CMYK") == 0)
604 ppd
->colorspace
= PPD_CS_CMYK
;
605 else if (strcmp(string
, "RGB") == 0)
606 ppd
->colorspace
= PPD_CS_RGB
;
607 else if (strcmp(string
, "RGBK") == 0)
608 ppd
->colorspace
= PPD_CS_RGBK
;
609 else if (strcmp(string
, "N") == 0)
610 ppd
->colorspace
= PPD_CS_N
;
612 ppd
->colorspace
= PPD_CS_GRAY
;
614 else if (strcmp(keyword
, "cupsFlipDuplex") == 0)
615 ppd
->flip_duplex
= strcmp(string
, "True") == 0;
616 else if (strcmp(keyword
, "cupsManualCopies") == 0)
617 ppd
->manual_copies
= strcmp(string
, "True") == 0;
618 else if (strcmp(keyword
, "cupsModelNumber") == 0)
619 ppd
->model_number
= atoi(string
);
620 else if (strcmp(keyword
, "cupsColorProfile") == 0)
622 if (ppd
->num_profiles
== 0)
623 profile
= malloc(sizeof(ppd_profile_t
));
625 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
626 (ppd
->num_profiles
+ 1));
628 ppd
->profiles
= profile
;
629 profile
+= ppd
->num_profiles
;
630 ppd
->num_profiles
++;
632 memset(profile
, 0, sizeof(ppd_profile_t
));
633 strncpy(profile
->resolution
, name
, sizeof(profile
->resolution
) - 1);
634 strncpy(profile
->media_type
, text
, sizeof(profile
->media_type
) - 1);
635 sscanf(string
, "%f%f%f%f%f%f%f%f%f%f%f", &(profile
->density
),
637 profile
->matrix
[0] + 0, profile
->matrix
[0] + 1,
638 profile
->matrix
[0] + 2, profile
->matrix
[1] + 0,
639 profile
->matrix
[1] + 1, profile
->matrix
[1] + 2,
640 profile
->matrix
[2] + 0, profile
->matrix
[2] + 1,
641 profile
->matrix
[2] + 2);
643 else if (strcmp(keyword
, "cupsFilter") == 0)
645 if (ppd
->num_filters
== 0)
646 filter
= malloc(sizeof(char *));
648 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
657 ppd
->filters
= filter
;
658 filter
+= ppd
->num_filters
;
662 * Copy filter string and prevent it from being freed below...
668 else if (strcmp(keyword
, "Throughput") == 0)
669 ppd
->throughput
= atoi(string
);
670 else if (strcmp(keyword
, "Font") == 0)
673 * Add this font to the list of available fonts...
676 if (ppd
->num_fonts
== 0)
677 tempfonts
= (char **)malloc(sizeof(char *));
679 tempfonts
= (char **)realloc(ppd
->fonts
,
680 sizeof(char *) * (ppd
->num_fonts
+ 1));
682 if (tempfonts
== NULL
)
689 ppd
->fonts
= tempfonts
;
690 ppd
->fonts
[ppd
->num_fonts
] = strdup(name
);
693 else if (strcmp(keyword
, "VariablePaperSize") == 0 &&
694 strcmp(string
, "True") == 0 &&
695 !ppd
->variable_sizes
)
697 ppd
->variable_sizes
= 1;
700 * Add a "Custom" page size entry...
703 ppd_add_size(ppd
, "Custom");
706 * Add a "Custom" page size option...
709 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
714 if ((temp
= ppd_get_group(ppd
,
715 cupsLangString(language
,
716 CUPS_MSG_GENERAL
))) == NULL
)
723 if ((option
= ppd_get_option(temp
, "PageSize")) == NULL
)
731 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
738 strncpy(choice
->text
, cupsLangString(language
, CUPS_MSG_VARIABLE
),
739 sizeof(choice
->text
) - 1);
742 else if (strcmp(keyword
, "MaxMediaWidth") == 0)
743 ppd
->custom_max
[0] = (float)atof(string
);
744 else if (strcmp(keyword
, "MaxMediaHeight") == 0)
745 ppd
->custom_max
[1] = (float)atof(string
);
746 else if (strcmp(keyword
, "ParamCustomPageSize") == 0)
748 if (strcmp(name
, "Width") == 0)
749 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 0,
750 ppd
->custom_max
+ 0);
751 else if (strcmp(name
, "Height") == 0)
752 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 1,
753 ppd
->custom_max
+ 1);
755 else if (strcmp(keyword
, "HWMargins") == 0)
756 sscanf(string
, "%f%f%f%f", ppd
->custom_margins
+ 0,
757 ppd
->custom_margins
+ 1, ppd
->custom_margins
+ 2,
758 ppd
->custom_margins
+ 3);
759 else if (strcmp(keyword
, "CustomPageSize") == 0 &&
760 strcmp(name
, "True") == 0)
762 if (!ppd
->variable_sizes
)
764 ppd
->variable_sizes
= 1;
767 * Add a "Custom" page size entry...
770 ppd_add_size(ppd
, "Custom");
773 * Add a "Custom" page size option...
776 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
781 if ((temp
= ppd_get_group(ppd
,
782 cupsLangString(language
,
783 CUPS_MSG_GENERAL
))) == NULL
)
785 DEBUG_puts("Unable to get general group!");
791 if ((option
= ppd_get_option(temp
, "PageSize")) == NULL
)
793 DEBUG_puts("Unable to get PageSize option!");
800 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
802 DEBUG_puts("Unable to add Custom choice!");
808 strncpy(choice
->text
, cupsLangString(language
, CUPS_MSG_VARIABLE
),
809 sizeof(choice
->text
) - 1);
813 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
815 DEBUG_puts("Unable to find PageSize option!");
821 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
823 DEBUG_puts("Unable to find Custom choice!");
829 choice
->code
= string
;
833 else if (strcmp(keyword
, "LandscapeOrientation") == 0)
835 if (strcmp(string
, "Minus90") == 0)
836 ppd
->landscape
= -90;
840 else if (strcmp(keyword
, "Emulators") == 0)
842 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
843 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
850 ppd
->num_emulations
= count
;
851 ppd
->emulations
= calloc(sizeof(ppd_emul_t
), count
);
853 for (i
= 0, sptr
= string
; i
< count
; i
++)
855 for (nameptr
= ppd
->emulations
[i
].name
;
856 *sptr
!= '\0' && *sptr
!= ' ';
858 if (nameptr
< (ppd
->emulations
[i
].name
+ sizeof(ppd
->emulations
[i
].name
) - 1))
867 else if (strncmp(keyword
, "StartEmulator_", 14) == 0)
871 for (i
= 0; i
< ppd
->num_emulations
; i
++)
872 if (strcmp(keyword
+ 14, ppd
->emulations
[i
].name
) == 0)
874 ppd
->emulations
[i
].start
= string
;
878 else if (strncmp(keyword
, "StopEmulator_", 13) == 0)
882 for (i
= 0; i
< ppd
->num_emulations
; i
++)
883 if (strcmp(keyword
+ 13, ppd
->emulations
[i
].name
) == 0)
885 ppd
->emulations
[i
].stop
= string
;
889 else if (strcmp(keyword
, "JobPatchFile") == 0)
891 if (ppd
->patches
== NULL
)
893 ppd
->patches
= string
;
898 temp
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
909 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
912 else if (strcmp(keyword
, "OpenUI") == 0)
915 * Add an option record to the current sub-group, group, or file...
919 strcpy(name
, name
+ 1);
927 if (subgroup
!= NULL
)
928 option
= ppd_get_option(subgroup
, name
);
929 else if (group
== NULL
)
931 if (strcmp(name
, "Collate") != 0 &&
932 strcmp(name
, "Duplex") != 0 &&
933 strcmp(name
, "InputSlot") != 0 &&
934 strcmp(name
, "ManualFeed") != 0 &&
935 strcmp(name
, "MediaType") != 0 &&
936 strcmp(name
, "MediaColor") != 0 &&
937 strcmp(name
, "MediaWeight") != 0 &&
938 strcmp(name
, "OutputBin") != 0 &&
939 strcmp(name
, "OutputMode") != 0 &&
940 strcmp(name
, "OutputOrder") != 0 &&
941 strcmp(name
, "PageSize") != 0 &&
942 strcmp(name
, "PageRegion") != 0)
943 group
= ppd_get_group(ppd
, cupsLangString(language
, CUPS_MSG_EXTRA
));
945 group
= ppd_get_group(ppd
, cupsLangString(language
, CUPS_MSG_GENERAL
));
954 option
= ppd_get_option(group
, name
);
958 option
= ppd_get_option(group
, name
);
968 * Now fill in the initial information for the option...
971 if (strcmp(string
, "PickMany") == 0)
972 option
->ui
= PPD_UI_PICKMANY
;
973 else if (strcmp(string
, "Boolean") == 0)
974 option
->ui
= PPD_UI_BOOLEAN
;
976 option
->ui
= PPD_UI_PICKONE
;
980 strncpy(option
->text
, text
, sizeof(option
->text
) - 1);
981 ppd_fix(option
->text
);
985 if (strcmp(name
, "PageSize") == 0)
986 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SIZE
),
987 sizeof(option
->text
) - 1);
988 else if (strcmp(name
, "MediaType") == 0)
989 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_TYPE
),
990 sizeof(option
->text
) - 1);
991 else if (strcmp(name
, "InputSlot") == 0)
992 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SOURCE
),
993 sizeof(option
->text
) - 1);
994 else if (strcmp(name
, "ColorModel") == 0)
995 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_OUTPUT_MODE
),
996 sizeof(option
->text
) - 1);
997 else if (strcmp(name
, "Resolution") == 0)
998 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_RESOLUTION
),
999 sizeof(option
->text
) - 1);
1001 strncpy(option
->text
, name
, sizeof(option
->text
) - 1);
1004 option
->section
= PPD_ORDER_ANY
;
1006 else if (strcmp(keyword
, "JCLOpenUI") == 0)
1009 * Find the JCL group, and add if needed...
1012 group
= ppd_get_group(ppd
, "JCL");
1022 * Add an option record to the current JCLs...
1026 strcpy(name
, name
+ 1);
1028 option
= ppd_get_option(group
, name
);
1038 * Now fill in the initial information for the option...
1041 if (strcmp(string
, "PickMany") == 0)
1042 option
->ui
= PPD_UI_PICKMANY
;
1043 else if (strcmp(string
, "Boolean") == 0)
1044 option
->ui
= PPD_UI_BOOLEAN
;
1046 option
->ui
= PPD_UI_PICKONE
;
1048 strncpy(option
->text
, text
, sizeof(option
->text
) - 1);
1050 option
->section
= PPD_ORDER_JCL
;
1053 else if (strcmp(keyword
, "CloseUI") == 0 ||
1054 strcmp(keyword
, "JCLCloseUI") == 0)
1056 else if (strcmp(keyword
, "OpenGroup") == 0)
1059 * Open a new group...
1069 if (strchr(string
, '/') != NULL
) /* Just show human readable text */
1070 strcpy(string
, strchr(string
, '/') + 1);
1074 group
= ppd_get_group(ppd
, string
);
1076 else if (strcmp(keyword
, "CloseGroup") == 0)
1078 else if (strcmp(keyword
, "OrderDependency") == 0 ||
1079 strcmp(keyword
, "NonUIOrderDependency") == 0)
1081 if (sscanf(string
, "%f%40s%40s", &order
, name
, keyword
) != 3)
1088 if (keyword
[0] == '*')
1089 strcpy(keyword
, keyword
+ 1);
1091 if (strcmp(name
, "ExitServer") == 0)
1092 section
= PPD_ORDER_EXIT
;
1093 else if (strcmp(name
, "Prolog") == 0)
1094 section
= PPD_ORDER_PROLOG
;
1095 else if (strcmp(name
, "DocumentSetup") == 0)
1096 section
= PPD_ORDER_DOCUMENT
;
1097 else if (strcmp(name
, "PageSetup") == 0)
1098 section
= PPD_ORDER_PAGE
;
1099 else if (strcmp(name
, "JCLSetup") == 0)
1100 section
= PPD_ORDER_JCL
;
1102 section
= PPD_ORDER_ANY
;
1110 * Only valid for Non-UI options...
1113 for (i
= ppd
->num_groups
, temp
= ppd
->groups
; i
> 0; i
--, temp
++)
1114 if (temp
->text
[0] == '\0')
1118 for (i
= 0; i
< temp
->num_options
; i
++)
1119 if (strcmp(keyword
, temp
->options
[i
].keyword
) == 0)
1121 temp
->options
[i
].section
= section
;
1122 temp
->options
[i
].order
= order
;
1128 option
->section
= section
;
1129 option
->order
= order
;
1132 else if (strncmp(keyword
, "Default", 7) == 0)
1137 if (strchr(string
, '/') != NULL
)
1138 *strchr(string
, '/') = '\0';
1146 * Only valid for Non-UI options...
1149 for (i
= ppd
->num_groups
, temp
= ppd
->groups
; i
> 0; i
--, temp
++)
1150 if (temp
->text
[0] == '\0')
1154 for (i
= 0; i
< temp
->num_options
; i
++)
1155 if (strcmp(keyword
, temp
->options
[i
].keyword
) == 0)
1157 strncpy(temp
->options
[i
].defchoice
, string
,
1158 sizeof(temp
->options
[i
].defchoice
) - 1);
1163 strncpy(option
->defchoice
, string
, sizeof(option
->defchoice
) - 1);
1165 else if (strcmp(keyword
, "UIConstraints") == 0 ||
1166 strcmp(keyword
, "NonUIConstraints") == 0)
1168 if (ppd
->num_consts
== 0)
1169 constraint
= calloc(sizeof(ppd_const_t
), 1);
1171 constraint
= realloc(ppd
->consts
,
1172 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1174 if (constraint
== NULL
)
1181 ppd
->consts
= constraint
;
1182 constraint
+= ppd
->num_consts
;
1185 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1186 constraint
->choice1
, constraint
->option2
,
1187 constraint
->choice2
))
1189 case 0 : /* Error */
1190 case 1 : /* Error */
1195 case 2 : /* Two options... */
1197 * The following strcpy's are safe, as optionN and
1198 * choiceN are all the same size (size defined by PPD spec...)
1201 if (constraint
->option1
[0] == '*')
1202 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1204 if (constraint
->choice1
[0] == '*')
1205 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1207 strcpy(constraint
->option2
, constraint
->choice1
);
1209 constraint
->choice1
[0] = '\0';
1210 constraint
->choice2
[0] = '\0';
1213 case 3 : /* Two options, one choice... */
1215 * The following strcpy's are safe, as optionN and
1216 * choiceN are all the same size (size defined by PPD spec...)
1219 if (constraint
->option1
[0] == '*')
1220 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1222 if (constraint
->choice1
[0] == '*')
1224 strcpy(constraint
->choice2
, constraint
->option2
);
1225 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1226 constraint
->choice1
[0] = '\0';
1230 if (constraint
->option2
[0] == '*')
1231 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1233 constraint
->choice2
[0] = '\0';
1237 case 4 : /* Two options, two choices... */
1238 if (constraint
->option1
[0] == '*')
1239 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1241 if (constraint
->option2
[0] == '*')
1242 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1246 else if (strcmp(keyword
, "PaperDimension") == 0)
1248 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1249 sscanf(string
, "%f%f", &(size
->width
), &(size
->length
));
1251 else if (strcmp(keyword
, "ImageableArea") == 0)
1253 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1254 sscanf(string
, "%f%f%f%f", &(size
->left
), &(size
->bottom
),
1255 &(size
->right
), &(size
->top
));
1257 else if (option
!= NULL
&&
1258 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1259 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
1261 DEBUG_printf(("group = %p, subgroup = %p\n", group
, subgroup
));
1263 if (strcmp(keyword
, "PageSize") == 0)
1266 * Add a page size...
1269 ppd_add_size(ppd
, name
);
1273 * Add the option choice...
1276 choice
= ppd_add_choice(option
, name
);
1278 if (mask
& PPD_TEXT
)
1280 strncpy(choice
->text
, text
, sizeof(choice
->text
) - 1);
1281 ppd_fix(choice
->text
);
1283 else if (strcmp(name
, "True") == 0)
1284 strcpy(choice
->text
, "Yes");
1285 else if (strcmp(name
, "False") == 0)
1286 strcpy(choice
->text
, "No");
1288 strncpy(choice
->text
, name
, sizeof(choice
->text
) - 1);
1290 if (strncmp(keyword
, "JCL", 3) == 0)
1291 ppd_decode(string
); /* Decode quoted string */
1293 choice
->code
= string
;
1294 string
= NULL
; /* Don't free this string below */
1302 printf("Premature EOF at %d...\n", ftell(fp
));
1306 * Set the option back-pointer for each choice...
1309 qsort(ppd
->groups
, ppd
->num_groups
, sizeof(ppd_group_t
),
1310 (int (*)(const void *, const void *))compare_groups
);
1312 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1316 qsort(group
->options
, group
->num_options
, sizeof(ppd_option_t
),
1317 (int (*)(const void *, const void *))compare_options
);
1319 for (j
= group
->num_options
, option
= group
->options
;
1323 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1324 (int (*)(const void *, const void *))compare_choices
);
1326 for (k
= 0; k
< option
->num_choices
; k
++)
1327 option
->choices
[k
].option
= (void *)option
;
1330 qsort(group
->subgroups
, group
->num_subgroups
, sizeof(ppd_group_t
),
1331 (int (*)(const void *, const void *))compare_groups
);
1333 for (j
= group
->num_subgroups
, subgroup
= group
->subgroups
;
1337 qsort(subgroup
->options
, subgroup
->num_options
, sizeof(ppd_option_t
),
1338 (int (*)(const void *, const void *))compare_options
);
1340 for (k
= group
->num_options
, option
= group
->options
;
1344 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1345 (int (*)(const void *, const void *))compare_choices
);
1347 for (m
= 0; m
< option
->num_choices
; m
++)
1348 option
->choices
[m
].option
= (void *)option
;
1358 * 'ppdOpenFd()' - Read a PPD file into memory.
1361 ppd_file_t
* /* O - PPD file record */
1362 ppdOpenFd(int fd
) /* I - File to read from */
1364 FILE *fp
; /* File pointer */
1365 ppd_file_t
*ppd
; /* PPD file record */
1369 * Range check input...
1376 * Try to open the file and parse it...
1379 if ((fp
= fdopen(fd
, "r")) != NULL
)
1395 * 'ppdOpenFile()' - Read a PPD file into memory.
1398 ppd_file_t
* /* O - PPD file record */
1399 ppdOpenFile(const char *filename
) /* I - File to read from */
1401 FILE *fp
; /* File pointer */
1402 ppd_file_t
*ppd
; /* PPD file record */
1406 * Range check input...
1409 if (filename
== NULL
)
1413 * Try to open the file and parse it...
1416 if ((fp
= fopen(filename
, "r")) != NULL
)
1430 * 'compare_strings()' - Compare two strings.
1433 static int /* O - Result of comparison */
1434 compare_strings(char *s
, /* I - First string */
1435 char *t
) /* I - Second string */
1437 int diff
, /* Difference between digits */
1438 digits
; /* Number of digits */
1442 * Loop through both strings, returning only when a difference is
1443 * seen. Also, compare whole numbers rather than just characters, too!
1448 if (isdigit(*s
) && isdigit(*t
))
1451 * Got a number; start by skipping leading 0's...
1460 * Skip equal digits...
1463 while (isdigit(*s
) && *s
== *t
)
1470 * Bounce out if *s and *t aren't both digits...
1473 if (isdigit(*s
) && !isdigit(*t
))
1475 else if (!isdigit(*s
) && isdigit(*t
))
1477 else if (!isdigit(*s
) || !isdigit(*t
))
1486 * Figure out how many more digits there are...
1504 * Return if the number or value of the digits is different...
1509 else if (digits
> 0)
1514 else if (tolower(*s
) < tolower(*t
))
1516 else if (tolower(*s
) > tolower(*t
))
1526 * Return the results of the final comparison...
1539 * 'compare_groups()' - Compare two groups.
1542 static int /* O - Result of comparison */
1543 compare_groups(ppd_group_t
*g0
, /* I - First group */
1544 ppd_group_t
*g1
) /* I - Second group */
1546 return (compare_strings(g0
->text
, g1
->text
));
1551 * 'compare_options()' - Compare two options.
1554 static int /* O - Result of comparison */
1555 compare_options(ppd_option_t
*o0
,/* I - First option */
1556 ppd_option_t
*o1
)/* I - Second option */
1558 return (compare_strings(o0
->text
, o1
->text
));
1563 * 'compare_choices()' - Compare two choices.
1566 static int /* O - Result of comparison */
1567 compare_choices(ppd_choice_t
*c0
,/* I - First choice */
1568 ppd_choice_t
*c1
)/* I - Second choice */
1570 return (compare_strings(c0
->text
, c1
->text
));
1575 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
1579 static int /* O - Bitmask of fields read */
1580 ppd_read(FILE *fp
, /* I - File to read from */
1581 char *keyword
, /* O - Keyword from line */
1582 char *option
, /* O - Option from line */
1583 char *text
, /* O - Human-readable text from line */
1584 char **string
) /* O - Code/string data */
1586 int ch
, /* Character from file */
1587 endquote
, /* Waiting for an end quote */
1588 mask
; /* Mask to be returned */
1589 char *keyptr
, /* Keyword pointer */
1590 *optptr
, /* Option pointer */
1591 *textptr
, /* Text pointer */
1592 *strptr
, /* Pointer into string */
1593 *lineptr
, /* Current position in line buffer */
1594 line
[65536]; /* Line buffer (64k) */
1598 * Range check everything...
1601 if (fp
== NULL
|| keyword
== NULL
|| option
== NULL
|| text
== NULL
||
1606 * Now loop until we have a valid line...
1620 while ((ch
= getc(fp
)) != EOF
&&
1621 (lineptr
- line
) < (sizeof(line
) - 1))
1623 if (ch
== '\r' || ch
== '\n')
1626 * Line feed or carriage return...
1629 if (lineptr
== line
) /* Skip blank lines */
1635 * Check for a trailing line feed...
1638 if ((ch
= getc(fp
)) == EOF
)
1646 if (!endquote
) /* Continue for multi-line text */
1654 * Any other character...
1661 endquote
= !endquote
;
1666 * End of quoted string; ignore trailing characters...
1669 while ((ch
= getc(fp
)) != EOF
)
1672 else if (ch
== '\r')
1689 * Didn't finish this quoted string...
1692 while ((ch
= getc(fp
)) != EOF
)
1700 * Didn't finish this line...
1703 while ((ch
= getc(fp
)) != EOF
)
1704 if (ch
== '\r' || ch
== '\n')
1707 * Line feed or carriage return...
1713 * Check for a trailing line feed...
1716 if ((ch
= getc(fp
)) == EOF
)
1726 if (lineptr
> line
&& lineptr
[-1] == '\n')
1731 if (ch
== EOF
&& lineptr
== line
)
1746 if (line
[0] != '*') /* All lines start with an asterisk */
1749 if (strncmp(line
, "*%", 2) == 0 || /* Comment line */
1750 strncmp(line
, "*?", 2) == 0 || /* Query line */
1751 strcmp(line
, "*End") == 0) /* End of multi-line string */
1760 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
) &&
1761 (keyptr
- keyword
) < (PPD_MAX_NAME
- 1))
1762 *keyptr
++ = *lineptr
++;
1765 mask
|= PPD_KEYWORD
;
1767 if (*lineptr
== ' ' || *lineptr
== '\t')
1770 * Get an option name...
1773 while (*lineptr
== ' ' || *lineptr
== '\t')
1778 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1779 *lineptr
!= '/' && (optptr
- option
) < 40)
1780 *optptr
++ = *lineptr
++;
1785 if (*lineptr
== '/')
1788 * Get human-readable text...
1795 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1796 (textptr
- text
) < (PPD_MAX_TEXT
- 1))
1797 *textptr
++ = *lineptr
++;
1806 if (*lineptr
== ':')
1812 *string
= malloc(strlen(lineptr
) + 1);
1814 while (*lineptr
== ':' || isspace(*lineptr
))
1819 while (*lineptr
!= '\0')
1821 if (*lineptr
!= '\"')
1822 *strptr
++ = *lineptr
++;
1839 * 'ppd_decode()' - Decode a string value...
1843 ppd_decode(char *string
) /* I - String to decode */
1845 char *inptr
, /* Input pointer */
1846 *outptr
; /* Output pointer */
1852 while (*inptr
!= '\0')
1853 if (*inptr
== '<' && isxdigit(inptr
[1]))
1856 * Convert hex to 8-bit values...
1860 while (isxdigit(*inptr
))
1862 if (isalpha(*inptr
))
1863 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
1865 *outptr
= (*inptr
- '0') << 4;
1869 if (isalpha(*inptr
))
1870 *outptr
|= tolower(*inptr
) - 'a' + 10;
1872 *outptr
|= *inptr
- '0';
1878 while (*inptr
!= '>' && *inptr
!= '\0')
1880 while (*inptr
== '>')
1884 *outptr
++ = *inptr
++;
1891 * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be
1892 * valid ISO-8859-1 characters...
1896 ppd_fix(char *string
) /* IO - String to fix */
1898 unsigned char *p
; /* Pointer into string */
1899 static unsigned char lut
[32] =/* Lookup table for characters */
1923 0x20, /* circumflex */
1925 0x20, /* double dot */
1930 '\"', /* should be right quotes */
1936 for (p
= (unsigned char *)string
; *p
; p
++)
1937 if (*p
>= 0x80 && *p
< 0xa0)
1938 *p
= lut
[*p
- 0x80];
1943 * End of "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $".