]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/ppd.c
2 * "$Id: ppd.c,v 1.43 2000/06/12 15:42:46 mike Exp $"
4 * PPD file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2000 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 */
114 * Range check the PPD file record...
121 * Free all strings at the top level...
124 safe_free(ppd
->lang_encoding
);
125 safe_free(ppd
->lang_version
);
126 safe_free(ppd
->modelname
);
127 safe_free(ppd
->ttrasterizer
);
128 safe_free(ppd
->manufacturer
);
129 safe_free(ppd
->product
);
130 safe_free(ppd
->nickname
);
131 safe_free(ppd
->shortnickname
);
134 * Free any emulations...
137 if (ppd
->num_emulations
> 0)
139 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
141 safe_free(emul
->start
);
142 safe_free(emul
->stop
);
145 safe_free(ppd
->emulations
);
149 * Free any UI groups, subgroups, and options...
152 if (ppd
->num_groups
> 0)
154 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
155 ppd_free_group(group
);
157 safe_free(ppd
->groups
);
161 * Free any page sizes...
164 if (ppd
->num_sizes
> 0)
165 safe_free(ppd
->sizes
);
168 * Free any constraints...
171 if (ppd
->num_consts
> 0)
172 safe_free(ppd
->consts
);
178 if (ppd
->num_fonts
> 0)
180 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
183 safe_free(ppd
->fonts
);
187 * Free any profiles...
190 if (ppd
->num_profiles
> 0)
191 safe_free(ppd
->profiles
);
194 * Free the whole record...
202 * 'ppd_free_group()' - Free a single UI group.
206 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
208 int i
; /* Looping var */
209 ppd_option_t
*option
; /* Current option */
210 ppd_group_t
*subgroup
; /* Current sub-group */
213 if (group
->num_options
> 0)
215 for (i
= group
->num_options
, option
= group
->options
;
218 ppd_free_option(option
);
220 safe_free(group
->options
);
223 if (group
->num_subgroups
> 0)
225 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
228 ppd_free_group(subgroup
);
230 safe_free(group
->subgroups
);
236 * 'ppd_free_option()' - Free a single option.
240 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
242 int i
; /* Looping var */
243 ppd_choice_t
*choice
; /* Current choice */
246 if (option
->num_choices
> 0)
248 for (i
= option
->num_choices
, choice
= option
->choices
;
251 safe_free(choice
->code
);
253 safe_free(option
->choices
);
259 * 'ppd_get_group()' - Find or create the named group as needed.
262 static ppd_group_t
* /* O - Named group */
263 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
264 char *name
) /* I - Name of group */
266 int i
; /* Looping var */
267 ppd_group_t
*group
; /* Group */
270 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
271 if (strcmp(group
->text
, name
) == 0)
276 if (ppd
->num_groups
== 0)
277 group
= malloc(sizeof(ppd_group_t
));
279 group
= realloc(ppd
->groups
,
280 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
286 group
+= ppd
->num_groups
;
289 memset(group
, 0, sizeof(ppd_group_t
));
290 strncpy(group
->text
, name
, sizeof(group
->text
) - 1);
298 * 'ppd_get_option()' - Find or create the named option as needed.
301 static ppd_option_t
* /* O - Named option */
302 ppd_get_option(ppd_group_t
*group
, /* I - Group */
303 char *name
) /* I - Name of option */
305 int i
; /* Looping var */
306 ppd_option_t
*option
; /* Option */
309 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
310 if (strcmp(option
->keyword
, name
) == 0)
315 if (group
->num_options
== 0)
316 option
= malloc(sizeof(ppd_option_t
));
318 option
= realloc(group
->options
,
319 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
324 group
->options
= option
;
325 option
+= group
->num_options
;
326 group
->num_options
++;
328 memset(option
, 0, sizeof(ppd_option_t
));
329 strncpy(option
->keyword
, name
, sizeof(option
->keyword
) - 1);
337 * 'ppd_add_choice()' - Add a choice to an option.
340 static ppd_choice_t
* /* O - Named choice */
341 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
342 char *name
) /* I - Name of choice */
344 ppd_choice_t
*choice
; /* Choice */
347 if (option
->num_choices
== 0)
348 choice
= malloc(sizeof(ppd_choice_t
));
350 choice
= realloc(option
->choices
,
351 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
356 option
->choices
= choice
;
357 choice
+= option
->num_choices
;
358 option
->num_choices
++;
360 memset(choice
, 0, sizeof(ppd_choice_t
));
361 strncpy(choice
->choice
, name
, sizeof(choice
->choice
) - 1);
368 * 'ppd_add_size()' - Add a page size.
371 static ppd_size_t
* /* O - Named size */
372 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
373 char *name
) /* I - Name of size */
375 ppd_size_t
*size
; /* Size */
378 if (ppd
->num_sizes
== 0)
379 size
= malloc(sizeof(ppd_size_t
));
381 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
387 size
+= ppd
->num_sizes
;
390 memset(size
, 0, sizeof(ppd_size_t
));
391 strncpy(size
->name
, name
, sizeof(size
->name
) - 1);
398 * 'ppdOpen()' - Read a PPD file into memory.
401 ppd_file_t
* /* O - PPD file record */
402 ppdOpen(FILE *fp
) /* I - File to read from */
404 int i
, j
, k
, m
; /* Looping vars */
405 int count
; /* Temporary count */
406 ppd_file_t
*ppd
; /* PPD file record */
407 ppd_group_t
*group
, /* Current group */
408 *subgroup
; /* Current sub-group */
409 ppd_option_t
*option
; /* Current option */
410 ppd_choice_t
*choice
; /* Current choice */
411 ppd_const_t
*constraint
; /* Current constraint */
412 ppd_size_t
*size
; /* Current page size */
413 int mask
; /* Line data mask */
414 char keyword
[41], /* Keyword from file */
415 name
[41], /* Option from file */
416 text
[81], /* Human-readable text from file */
417 *string
, /* Code/text from file */
418 *sptr
, /* Pointer into string */
419 *nameptr
; /* Pointer into name */
420 float order
; /* Order dependency number */
421 ppd_section_t section
; /* Order dependency section */
422 ppd_profile_t
*profile
; /* Pointer to color profile */
423 char **filter
; /* Pointer to filter */
424 cups_lang_t
*language
; /* Default language */
428 * Get the default language for the user...
431 language
= cupsLangDefault();
434 * Range check input...
441 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
444 mask
= ppd_read(fp
, keyword
, name
, text
, &string
);
447 strcmp(keyword
, "PPD-Adobe") != 0 ||
448 string
== NULL
|| string
[0] != '4')
451 * Either this is not a PPD file, or it is not a 4.x PPD file.
459 DEBUG_printf(("ppdOpen: keyword = %s, string = %08x\n", keyword
, string
));
464 * Allocate memory for the PPD file record...
467 if ((ppd
= calloc(sizeof(ppd_file_t
), 1)) == NULL
)
470 ppd
->language_level
= 1;
471 ppd
->color_device
= 0;
472 ppd
->colorspace
= PPD_CS_GRAY
;
476 * Read lines from the PPD file and add them to the file record...
484 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
)) != 0)
487 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
490 printf(", name = \"%s\"", name
);
493 printf(", text = \"%s\"", text
);
497 if (strlen(string
) > 40)
498 printf(", string = %08x", string
);
500 printf(", string = \"%s\"", string
);
506 if (strcmp(keyword
, "LanguageLevel") == 0)
507 ppd
->language_level
= atoi(string
);
508 else if (strcmp(keyword
, "LanguageEncoding") == 0)
510 ppd
->lang_encoding
= string
;
511 string
= NULL
; /* Don't free this string below */
513 else if (strcmp(keyword
, "LanguageVersion") == 0)
515 ppd
->lang_version
= string
;
516 string
= NULL
; /* Don't free this string below */
518 else if (strcmp(keyword
, "Manufacturer") == 0)
520 ppd
->manufacturer
= string
;
521 string
= NULL
; /* Don't free this string below */
523 else if (strcmp(keyword
, "ModelName") == 0)
525 ppd
->modelname
= string
;
526 string
= NULL
; /* Don't free this string below */
528 else if (strcmp(keyword
, "NickName") == 0)
530 ppd
->nickname
= string
;
531 string
= NULL
; /* Don't free this string below */
533 else if (strcmp(keyword
, "Product") == 0)
535 ppd
->product
= string
;
536 string
= NULL
; /* Don't free this string below */
538 else if (strcmp(keyword
, "ShortNickName") == 0)
540 ppd
->shortnickname
= string
;
541 string
= NULL
; /* Don't free this string below */
543 else if (strcmp(keyword
, "TTRasterizer") == 0)
545 ppd
->ttrasterizer
= string
;
546 string
= NULL
; /* Don't free this string below */
548 else if (strcmp(keyword
, "JCLBegin") == 0)
550 ppd_decode(string
); /* Decode quoted string */
551 ppd
->jcl_begin
= string
;
552 string
= NULL
; /* Don't free this string below */
554 else if (strcmp(keyword
, "JCLEnd") == 0)
556 ppd_decode(string
); /* Decode quoted string */
557 ppd
->jcl_end
= string
;
558 string
= NULL
; /* Don't free this string below */
560 else if (strcmp(keyword
, "JCLToPSInterpreter") == 0)
562 ppd_decode(string
); /* Decode quoted string */
563 ppd
->jcl_ps
= string
;
564 string
= NULL
; /* Don't free this string below */
566 else if (strcmp(keyword
, "AccurateScreensSupport") == 0)
567 ppd
->accurate_screens
= strcmp(string
, "True") == 0;
568 else if (strcmp(keyword
, "ColorDevice") == 0)
569 ppd
->color_device
= strcmp(string
, "True") == 0;
570 else if (strcmp(keyword
, "ContoneOnly") == 0)
571 ppd
->contone_only
= strcmp(string
, "True") == 0;
572 else if (strcmp(keyword
, "DefaultColorSpace") == 0)
574 if (strcmp(string
, "CMY") == 0)
575 ppd
->colorspace
= PPD_CS_CMY
;
576 else if (strcmp(string
, "CMYK") == 0)
577 ppd
->colorspace
= PPD_CS_CMYK
;
578 else if (strcmp(string
, "RGB") == 0)
579 ppd
->colorspace
= PPD_CS_RGB
;
580 else if (strcmp(string
, "RGBK") == 0)
581 ppd
->colorspace
= PPD_CS_RGBK
;
582 else if (strcmp(string
, "N") == 0)
583 ppd
->colorspace
= PPD_CS_N
;
585 ppd
->colorspace
= PPD_CS_GRAY
;
587 else if (strcmp(keyword
, "cupsFlipDuplex") == 0)
588 ppd
->flip_duplex
= strcmp(string
, "True") == 0;
589 else if (strcmp(keyword
, "cupsManualCopies") == 0)
590 ppd
->manual_copies
= strcmp(string
, "True") == 0;
591 else if (strcmp(keyword
, "cupsModelNumber") == 0)
592 ppd
->model_number
= atoi(string
);
593 else if (strcmp(keyword
, "cupsColorProfile") == 0)
595 if (ppd
->num_profiles
== 0)
596 profile
= malloc(sizeof(ppd_profile_t
));
598 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
599 (ppd
->num_profiles
+ 1));
601 ppd
->profiles
= profile
;
602 profile
+= ppd
->num_profiles
;
603 ppd
->num_profiles
++;
605 memset(profile
, 0, sizeof(ppd_profile_t
));
606 strncpy(profile
->resolution
, name
, sizeof(profile
->resolution
) - 1);
607 strncpy(profile
->media_type
, text
, sizeof(profile
->media_type
) - 1);
608 sscanf(string
, "%f%f%f%f%f%f%f%f%f%f%f", &(profile
->density
),
610 profile
->matrix
[0] + 0, profile
->matrix
[0] + 1,
611 profile
->matrix
[0] + 2, profile
->matrix
[1] + 0,
612 profile
->matrix
[1] + 1, profile
->matrix
[1] + 2,
613 profile
->matrix
[2] + 0, profile
->matrix
[2] + 1,
614 profile
->matrix
[2] + 2);
616 else if (strcmp(keyword
, "cupsFilter") == 0)
618 if (ppd
->num_filters
== 0)
619 filter
= malloc(sizeof(char *));
621 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
623 ppd
->filters
= filter
;
624 filter
+= ppd
->num_filters
;
628 * Copy filter string and prevent it from being freed below...
634 else if (strcmp(keyword
, "Throughput") == 0)
635 ppd
->throughput
= atoi(string
);
636 else if (strcmp(keyword
, "Font") == 0)
639 * Add this font to the list of available fonts...
642 if (ppd
->num_fonts
== 0)
643 ppd
->fonts
= (char **)malloc(sizeof(char *));
645 ppd
->fonts
= (char **)realloc(ppd
->fonts
,
646 sizeof(char *) * (ppd
->num_fonts
+ 1));
648 if (ppd
->fonts
== NULL
)
654 ppd
->fonts
[ppd
->num_fonts
] = string
;
658 else if (strcmp(keyword
, "VariablePaperSize") == 0 &&
659 strcmp(string
, "True") == 0 &&
660 !ppd
->variable_sizes
)
662 ppd
->variable_sizes
= 1;
665 * Add a "Custom" page size entry...
668 ppd_add_size(ppd
, "Custom");
671 * Add a "Custom" page size option...
674 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
679 if ((temp
= ppd_get_group(ppd
,
680 cupsLangString(language
,
681 CUPS_MSG_GENERAL
))) == NULL
)
688 if ((option
= ppd_get_option(temp
, "PageSize")) == NULL
)
696 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
703 strncpy(choice
->text
, cupsLangString(language
, CUPS_MSG_VARIABLE
),
704 sizeof(choice
->text
) - 1);
707 else if (strcmp(keyword
, "MaxMediaWidth") == 0)
708 ppd
->custom_max
[0] = (float)atof(string
);
709 else if (strcmp(keyword
, "MaxMediaHeight") == 0)
710 ppd
->custom_max
[1] = (float)atof(string
);
711 else if (strcmp(keyword
, "ParamCustomPageSize") == 0)
713 if (strcmp(name
, "Width") == 0)
714 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 0,
715 ppd
->custom_max
+ 0);
716 else if (strcmp(name
, "Height") == 0)
717 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 1,
718 ppd
->custom_max
+ 1);
720 else if (strcmp(keyword
, "HWMargins") == 0)
721 sscanf(string
, "%f%f%f%f", ppd
->custom_margins
+ 0,
722 ppd
->custom_margins
+ 1, ppd
->custom_margins
+ 2,
723 ppd
->custom_margins
+ 3);
724 else if (strcmp(keyword
, "CustomPageSize") == 0 &&
725 strcmp(name
, "True") == 0)
727 if (!ppd
->variable_sizes
)
729 ppd
->variable_sizes
= 1;
732 * Add a "Custom" page size entry...
735 ppd_add_size(ppd
, "Custom");
738 * Add a "Custom" page size option...
741 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
746 if ((temp
= ppd_get_group(ppd
,
747 cupsLangString(language
,
748 CUPS_MSG_GENERAL
))) == NULL
)
750 DEBUG_puts("Unable to get general group!");
756 if ((option
= ppd_get_option(temp
, "PageSize")) == NULL
)
758 DEBUG_puts("Unable to get PageSize option!");
765 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
767 DEBUG_puts("Unable to add Custom choice!");
773 strncpy(choice
->text
, cupsLangString(language
, CUPS_MSG_VARIABLE
),
774 sizeof(choice
->text
) - 1);
778 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
780 DEBUG_puts("Unable to find PageSize option!");
786 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
788 DEBUG_puts("Unable to find Custom choice!");
794 choice
->code
= string
;
798 else if (strcmp(keyword
, "LandscapeOrientation") == 0)
800 if (strcmp(string
, "Minus90") == 0)
801 ppd
->landscape
= -90;
805 else if (strcmp(keyword
, "Emulators") == 0)
807 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
808 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
815 ppd
->num_emulations
= count
;
816 ppd
->emulations
= calloc(sizeof(ppd_emul_t
), count
);
818 for (i
= 0, sptr
= string
; i
< count
; i
++)
820 for (nameptr
= ppd
->emulations
[i
].name
; *sptr
!= '\0' && *sptr
!= ' ';)
821 *nameptr
++ = *sptr
++;
829 else if (strncmp(keyword
, "StartEmulator_", 14) == 0)
833 for (i
= 0; i
< ppd
->num_emulations
; i
++)
834 if (strcmp(keyword
+ 14, ppd
->emulations
[i
].name
) == 0)
836 ppd
->emulations
[i
].start
= string
;
840 else if (strncmp(keyword
, "StopEmulator_", 13) == 0)
844 for (i
= 0; i
< ppd
->num_emulations
; i
++)
845 if (strcmp(keyword
+ 13, ppd
->emulations
[i
].name
) == 0)
847 ppd
->emulations
[i
].stop
= string
;
851 else if (strcmp(keyword
, "JobPatchFile") == 0)
853 if (ppd
->patches
== NULL
)
855 ppd
->patches
= string
;
860 ppd
->patches
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
863 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
866 else if (strcmp(keyword
, "OpenUI") == 0)
869 * Add an option record to the current sub-group, group, or file...
873 strcpy(name
, name
+ 1);
881 if (subgroup
!= NULL
)
882 option
= ppd_get_option(subgroup
, name
);
883 else if (group
== NULL
)
885 if (strcmp(name
, "Collate") != 0 &&
886 strcmp(name
, "Duplex") != 0 &&
887 strcmp(name
, "InputSlot") != 0 &&
888 strcmp(name
, "ManualFeed") != 0 &&
889 strcmp(name
, "MediaType") != 0 &&
890 strcmp(name
, "MediaColor") != 0 &&
891 strcmp(name
, "MediaWeight") != 0 &&
892 strcmp(name
, "OutputBin") != 0 &&
893 strcmp(name
, "OutputMode") != 0 &&
894 strcmp(name
, "OutputOrder") != 0 &&
895 strcmp(name
, "PageSize") != 0 &&
896 strcmp(name
, "PageRegion") != 0)
897 group
= ppd_get_group(ppd
, cupsLangString(language
, CUPS_MSG_EXTRA
));
899 group
= ppd_get_group(ppd
, cupsLangString(language
, CUPS_MSG_GENERAL
));
908 option
= ppd_get_option(group
, name
);
912 option
= ppd_get_option(group
, name
);
922 * Now fill in the initial information for the option...
925 if (strcmp(string
, "PickMany") == 0)
926 option
->ui
= PPD_UI_PICKMANY
;
927 else if (strcmp(string
, "Boolean") == 0)
928 option
->ui
= PPD_UI_BOOLEAN
;
930 option
->ui
= PPD_UI_PICKONE
;
934 strncpy(option
->text
, text
, sizeof(option
->text
) - 1);
935 ppd_fix(option
->text
);
939 if (strcmp(name
, "PageSize") == 0)
940 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SIZE
),
941 sizeof(option
->text
) - 1);
942 else if (strcmp(name
, "MediaType") == 0)
943 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_TYPE
),
944 sizeof(option
->text
) - 1);
945 else if (strcmp(name
, "InputSlot") == 0)
946 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SOURCE
),
947 sizeof(option
->text
) - 1);
948 else if (strcmp(name
, "ColorModel") == 0)
949 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_OUTPUT_MODE
),
950 sizeof(option
->text
) - 1);
951 else if (strcmp(name
, "Resolution") == 0)
952 strncpy(option
->text
, cupsLangString(language
, CUPS_MSG_RESOLUTION
),
953 sizeof(option
->text
) - 1);
955 strncpy(option
->text
, name
, sizeof(option
->text
) - 1);
958 option
->section
= PPD_ORDER_ANY
;
960 else if (strcmp(keyword
, "JCLOpenUI") == 0)
963 * Find the JCL group, and add if needed...
966 group
= ppd_get_group(ppd
, "JCL");
976 * Add an option record to the current JCLs...
980 strcpy(name
, name
+ 1);
982 option
= ppd_get_option(group
, name
);
992 * Now fill in the initial information for the option...
995 if (strcmp(string
, "PickMany") == 0)
996 option
->ui
= PPD_UI_PICKMANY
;
997 else if (strcmp(string
, "Boolean") == 0)
998 option
->ui
= PPD_UI_BOOLEAN
;
1000 option
->ui
= PPD_UI_PICKONE
;
1002 strncpy(option
->text
, text
, sizeof(option
->text
) - 1);
1004 option
->section
= PPD_ORDER_JCL
;
1007 else if (strcmp(keyword
, "CloseUI") == 0 ||
1008 strcmp(keyword
, "JCLCloseUI") == 0)
1010 else if (strcmp(keyword
, "OpenGroup") == 0)
1013 * Open a new group...
1023 if (strchr(string
, '/') != NULL
) /* Just show human readable text */
1024 strcpy(string
, strchr(string
, '/') + 1);
1028 group
= ppd_get_group(ppd
, string
);
1030 else if (strcmp(keyword
, "CloseGroup") == 0)
1032 else if (strcmp(keyword
, "OpenSubGroup") == 0)
1035 * Open a new sub-group...
1038 DEBUG_printf(("group = %p, subgroup = %p\n", group
, subgroup
));
1040 if (group
== NULL
|| subgroup
!= NULL
)
1047 if (group
->num_subgroups
== 0)
1048 subgroup
= malloc(sizeof(ppd_group_t
));
1050 subgroup
= realloc(group
->subgroups
,
1051 (group
->num_subgroups
+ 1) * sizeof(ppd_group_t
));
1053 if (subgroup
== NULL
)
1060 group
->subgroups
= subgroup
;
1061 subgroup
+= group
->num_subgroups
;
1062 group
->num_subgroups
++;
1064 memset(subgroup
, 0, sizeof(ppd_group_t
));
1067 strncpy(subgroup
->text
, string
, sizeof(subgroup
->text
) - 1);
1069 else if (strcmp(keyword
, "CloseSubGroup") == 0)
1071 else if (strcmp(keyword
, "OrderDependency") == 0 ||
1072 strcmp(keyword
, "NonUIOrderDependency") == 0)
1074 if (sscanf(string
, "%f%40s%40s", &order
, name
, keyword
) != 3)
1081 if (keyword
[0] == '*')
1082 strcpy(keyword
, keyword
+ 1);
1084 if (strcmp(name
, "ExitServer") == 0)
1085 section
= PPD_ORDER_EXIT
;
1086 else if (strcmp(name
, "Prolog") == 0)
1087 section
= PPD_ORDER_PROLOG
;
1088 else if (strcmp(name
, "DocumentSetup") == 0)
1089 section
= PPD_ORDER_DOCUMENT
;
1090 else if (strcmp(name
, "PageSetup") == 0)
1091 section
= PPD_ORDER_PAGE
;
1092 else if (strcmp(name
, "JCLSetup") == 0)
1093 section
= PPD_ORDER_JCL
;
1095 section
= PPD_ORDER_ANY
;
1103 * Only valid for Non-UI options...
1106 for (i
= ppd
->num_groups
, temp
= ppd
->groups
; i
> 0; i
--, temp
++)
1107 if (temp
->text
[0] == '\0')
1111 for (i
= 0; i
< temp
->num_options
; i
++)
1112 if (strcmp(keyword
, temp
->options
[i
].keyword
) == 0)
1114 temp
->options
[i
].section
= section
;
1115 temp
->options
[i
].order
= order
;
1121 option
->section
= section
;
1122 option
->order
= order
;
1125 else if (strncmp(keyword
, "Default", 7) == 0)
1130 if (strchr(string
, '/') != NULL
)
1131 *strchr(string
, '/') = '\0';
1139 * Only valid for Non-UI options...
1142 for (i
= ppd
->num_groups
, temp
= ppd
->groups
; i
> 0; i
--, temp
++)
1143 if (temp
->text
[0] == '\0')
1147 for (i
= 0; i
< temp
->num_options
; i
++)
1148 if (strcmp(keyword
, temp
->options
[i
].keyword
) == 0)
1150 strncpy(temp
->options
[i
].defchoice
, string
,
1151 sizeof(temp
->options
[i
].defchoice
) - 1);
1156 strncpy(option
->defchoice
, string
, sizeof(option
->defchoice
) - 1);
1158 else if (strcmp(keyword
, "UIConstraints") == 0 ||
1159 strcmp(keyword
, "NonUIConstraints") == 0)
1161 if (ppd
->num_consts
== 0)
1162 constraint
= calloc(sizeof(ppd_const_t
), 1);
1164 constraint
= realloc(ppd
->consts
,
1165 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1167 if (constraint
== NULL
)
1174 ppd
->consts
= constraint
;
1175 constraint
+= ppd
->num_consts
;
1178 switch (sscanf(string
, "%40s%40s%40s%40s", constraint
->option1
,
1179 constraint
->choice1
, constraint
->option2
,
1180 constraint
->choice2
))
1182 case 0 : /* Error */
1183 case 1 : /* Error */
1188 case 2 : /* Two options... */
1189 if (constraint
->option1
[0] == '*')
1190 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1192 if (constraint
->choice1
[0] == '*')
1193 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1195 strcpy(constraint
->option2
, constraint
->choice1
);
1197 constraint
->choice1
[0] = '\0';
1198 constraint
->choice2
[0] = '\0';
1201 case 3 : /* Two options, one choice... */
1202 if (constraint
->option1
[0] == '*')
1203 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1205 if (constraint
->choice1
[0] == '*')
1207 strcpy(constraint
->choice2
, constraint
->option2
);
1208 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1209 constraint
->choice1
[0] = '\0';
1213 if (constraint
->option2
[0] == '*')
1214 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1216 constraint
->choice2
[0] = '\0';
1220 case 4 : /* Two options, two choices... */
1221 if (constraint
->option1
[0] == '*')
1222 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1224 if (constraint
->option2
[0] == '*')
1225 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1229 else if (strcmp(keyword
, "PaperDimension") == 0)
1231 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1232 sscanf(string
, "%f%f", &(size
->width
), &(size
->length
));
1234 else if (strcmp(keyword
, "ImageableArea") == 0)
1236 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1237 sscanf(string
, "%f%f%f%f", &(size
->left
), &(size
->bottom
),
1238 &(size
->right
), &(size
->top
));
1240 else if (option
!= NULL
&&
1241 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1242 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
1244 DEBUG_printf(("group = %p, subgroup = %p\n", group
, subgroup
));
1246 if (strcmp(keyword
, "PageSize") == 0)
1249 * Add a page size...
1252 ppd_add_size(ppd
, name
);
1256 * Add the option choice...
1259 choice
= ppd_add_choice(option
, name
);
1261 if (mask
& PPD_TEXT
)
1263 strncpy(choice
->text
, text
, sizeof(choice
->text
) - 1);
1264 ppd_fix(choice
->text
);
1266 else if (strcmp(name
, "True") == 0)
1267 strcpy(choice
->text
, "Yes");
1268 else if (strcmp(name
, "False") == 0)
1269 strcpy(choice
->text
, "No");
1271 strncpy(choice
->text
, name
, sizeof(choice
->text
) - 1);
1273 if (strncmp(keyword
, "JCL", 3) == 0)
1274 ppd_decode(string
); /* Decode quoted string */
1276 choice
->code
= string
;
1277 string
= NULL
; /* Don't free this string below */
1285 printf("Premature EOF at %d...\n", ftell(fp
));
1289 * Set the option back-pointer for each choice...
1292 qsort(ppd
->groups
, ppd
->num_groups
, sizeof(ppd_group_t
),
1293 (int (*)(const void *, const void *))compare_groups
);
1295 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1299 qsort(group
->options
, group
->num_options
, sizeof(ppd_option_t
),
1300 (int (*)(const void *, const void *))compare_options
);
1302 for (j
= group
->num_options
, option
= group
->options
;
1306 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1307 (int (*)(const void *, const void *))compare_choices
);
1309 for (k
= 0; k
< option
->num_choices
; k
++)
1310 option
->choices
[k
].option
= (void *)option
;
1313 qsort(group
->subgroups
, group
->num_subgroups
, sizeof(ppd_group_t
),
1314 (int (*)(const void *, const void *))compare_groups
);
1316 for (j
= group
->num_subgroups
, subgroup
= group
->subgroups
;
1320 qsort(subgroup
->options
, subgroup
->num_options
, sizeof(ppd_option_t
),
1321 (int (*)(const void *, const void *))compare_options
);
1323 for (k
= group
->num_options
, option
= group
->options
;
1327 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1328 (int (*)(const void *, const void *))compare_choices
);
1330 for (m
= 0; m
< option
->num_choices
; m
++)
1331 option
->choices
[m
].option
= (void *)option
;
1341 * 'ppdOpenFd()' - Read a PPD file into memory.
1344 ppd_file_t
* /* O - PPD file record */
1345 ppdOpenFd(int fd
) /* I - File to read from */
1347 FILE *fp
; /* File pointer */
1348 ppd_file_t
*ppd
; /* PPD file record */
1352 * Range check input...
1359 * Try to open the file and parse it...
1362 if ((fp
= fdopen(fd
, "r")) != NULL
)
1378 * 'ppdOpenFile()' - Read a PPD file into memory.
1381 ppd_file_t
* /* O - PPD file record */
1382 ppdOpenFile(const char *filename
) /* I - File to read from */
1384 FILE *fp
; /* File pointer */
1385 ppd_file_t
*ppd
; /* PPD file record */
1389 * Range check input...
1392 if (filename
== NULL
)
1396 * Try to open the file and parse it...
1399 if ((fp
= fopen(filename
, "r")) != NULL
)
1413 * 'compare_strings()' - Compare two strings.
1416 int /* O - Result of comparison */
1417 compare_strings(char *s
, /* I - First string */
1418 char *t
) /* I - Second string */
1420 int diff
, /* Difference between digits */
1421 digits
; /* Number of digits */
1425 * Loop through both strings, returning only when a difference is
1426 * seen. Also, compare whole numbers rather than just characters, too!
1431 if (isdigit(*s
) && isdigit(*t
))
1434 * Got a number; start by skipping leading 0's...
1443 * Skip equal digits...
1446 while (isdigit(*s
) && *s
== *t
)
1453 * Bounce out if *s and *t aren't both digits...
1456 if (isdigit(*s
) && !isdigit(*t
))
1458 else if (!isdigit(*s
) && isdigit(*t
))
1460 else if (!isdigit(*s
) || !isdigit(*t
))
1469 * Figure out how many more digits there are...
1487 * Return if the number or value of the digits is different...
1492 else if (digits
> 0)
1497 else if (tolower(*s
) < tolower(*t
))
1499 else if (tolower(*s
) > tolower(*t
))
1509 * Return the results of the final comparison...
1522 * 'compare_groups()' - Compare two groups.
1525 static int /* O - Result of comparison */
1526 compare_groups(ppd_group_t
*g0
, /* I - First group */
1527 ppd_group_t
*g1
) /* I - Second group */
1529 return (compare_strings(g0
->text
, g1
->text
));
1534 * 'compare_options()' - Compare two options.
1537 static int /* O - Result of comparison */
1538 compare_options(ppd_option_t
*o0
,/* I - First option */
1539 ppd_option_t
*o1
)/* I - Second option */
1541 return (compare_strings(o0
->text
, o1
->text
));
1546 * 'compare_choices()' - Compare two choices.
1549 static int /* O - Result of comparison */
1550 compare_choices(ppd_choice_t
*c0
,/* I - First choice */
1551 ppd_choice_t
*c1
)/* I - Second choice */
1553 return (compare_strings(c0
->text
, c1
->text
));
1558 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
1562 static int /* O - Bitmask of fields read */
1563 ppd_read(FILE *fp
, /* I - File to read from */
1564 char *keyword
, /* O - Keyword from line */
1565 char *option
, /* O - Option from line */
1566 char *text
, /* O - Human-readable text from line */
1567 char **string
) /* O - Code/string data */
1569 int ch
, /* Character from file */
1570 endquote
, /* Waiting for an end quote */
1571 mask
; /* Mask to be returned */
1572 char *keyptr
, /* Keyword pointer */
1573 *optptr
, /* Option pointer */
1574 *textptr
, /* Text pointer */
1575 *strptr
, /* Pointer into string */
1576 *lineptr
, /* Current position in line buffer */
1577 line
[262144]; /* Line buffer (256k) */
1581 * Range check everything...
1584 if (fp
== NULL
|| keyword
== NULL
|| option
== NULL
|| text
== NULL
||
1589 * Now loop until we have a valid line...
1601 while ((ch
= getc(fp
)) != EOF
&&
1602 (lineptr
- line
) < (sizeof(line
) - 1))
1604 if (ch
== '\r' || ch
== '\n')
1607 * Line feed or carriage return...
1610 if (lineptr
== line
) /* Skip blank lines */
1616 * Check for a trailing line feed...
1619 if ((ch
= getc(fp
)) == EOF
)
1627 if (!endquote
) /* Continue for multi-line text */
1633 * Any other character...
1639 endquote
= !endquote
;
1643 if (lineptr
> line
&& lineptr
[-1] == '\n')
1648 if (ch
== EOF
&& lineptr
== line
)
1663 if (line
[0] != '*') /* All lines start with an asterisk */
1666 if (strncmp(line
, "*%", 2) == 0 || /* Comment line */
1667 strncmp(line
, "*?", 2) == 0 || /* Query line */
1668 strcmp(line
, "*End") == 0) /* End of multi-line string */
1677 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
) &&
1678 (keyptr
- keyword
) < 40)
1679 *keyptr
++ = *lineptr
++;
1682 mask
|= PPD_KEYWORD
;
1684 if (*lineptr
== ' ' || *lineptr
== '\t')
1687 * Get an option name...
1690 while (*lineptr
== ' ' || *lineptr
== '\t')
1695 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1696 *lineptr
!= '/' && (optptr
- option
) < 40)
1697 *optptr
++ = *lineptr
++;
1702 if (*lineptr
== '/')
1705 * Get human-readable text...
1712 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1713 (textptr
- text
) < 80)
1714 *textptr
++ = *lineptr
++;
1723 if (*lineptr
== ':')
1729 *string
= malloc(strlen(lineptr
) + 1);
1731 while (*lineptr
== ':' || isspace(*lineptr
))
1736 while (*lineptr
!= '\0')
1738 if (*lineptr
!= '\"')
1739 *strptr
++ = *lineptr
++;
1756 * 'ppd_decode()' - Decode a string value...
1760 ppd_decode(char *string
) /* I - String to decode */
1762 char *inptr
, /* Input pointer */
1763 *outptr
; /* Output pointer */
1769 while (*inptr
!= '\0')
1770 if (*inptr
== '<' && isxdigit(inptr
[1]))
1773 * Convert hex to 8-bit values...
1777 while (isxdigit(*inptr
))
1779 if (isalpha(*inptr
))
1780 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
1782 *outptr
= (*inptr
- '0') << 4;
1786 if (isalpha(*inptr
))
1787 *outptr
|= tolower(*inptr
) - 'a' + 10;
1789 *outptr
|= *inptr
- '0';
1795 while (*inptr
!= '>' && *inptr
!= '\0')
1797 while (*inptr
== '>')
1801 *outptr
++ = *inptr
++;
1808 * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be
1809 * valid ISO-8859-1 characters...
1813 ppd_fix(char *string
) /* IO - String to fix */
1815 unsigned char *p
; /* Pointer into string */
1816 static unsigned char lut
[32] =/* Lookup table for characters */
1840 0x20, /* circumflex */
1842 0x20, /* double dot */
1847 '\"', /* should be right quotes */
1853 for (p
= (unsigned char *)string
; *p
; p
++)
1854 if (*p
>= 0x80 && *p
< 0xa0)
1855 *p
= lut
[*p
- 0x80];
1860 * End of "$Id: ppd.c,v 1.43 2000/06/12 15:42:46 mike Exp $".