]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/ppd.c
2 * "$Id: ppd.c,v 1.21 1999/06/04 21:04:29 mike Exp $"
4 * PPD file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-1999 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.
64 #if defined(WIN32) || defined(__EMX__)
65 # define READ_BINARY "rb" /* Open a binary file for reading */
66 # define WRITE_BINARY "wb" /* Open a binary file for writing */
68 # define READ_BINARY "r" /* Open a binary file for reading */
69 # define WRITE_BINARY "w" /* Open a binary file for writing */
70 #endif /* WIN32 || __EMX__ */
72 #define PPD_KEYWORD 1 /* Line contained a keyword */
73 #define PPD_OPTION 2 /* Line contained an option name */
74 #define PPD_TEXT 4 /* Line contained human-readable text */
75 #define PPD_STRING 8 /* Line contained a string or code */
82 static int compare_strings(char *s
, char *t
);
83 static int compare_groups(ppd_group_t
*g0
, ppd_group_t
*g1
);
84 static int compare_options(ppd_option_t
*o0
, ppd_option_t
*o1
);
85 static int compare_choices(ppd_choice_t
*c0
, ppd_choice_t
*c1
);
86 static int ppd_read(FILE *fp
, char *keyword
, char *option
,
87 char *text
, char **string
);
88 static void ppd_decode(char *string
);
89 static void ppd_free_group(ppd_group_t
*group
);
90 static void ppd_free_option(ppd_option_t
*option
);
91 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, char *name
);
92 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, char *name
);
93 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, char *name
);
97 * 'ppdClose()' - Free all memory used by the PPD file.
101 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
103 int i
; /* Looping var */
104 ppd_emul_t
*emul
; /* Current emulation */
105 ppd_group_t
*group
; /* Current group */
106 char **font
; /* Current font */
110 * Range check the PPD file record...
117 * Free all strings at the top level...
120 free(ppd
->lang_encoding
);
121 free(ppd
->lang_version
);
122 free(ppd
->modelname
);
123 free(ppd
->ttrasterizer
);
124 free(ppd
->manufacturer
);
127 free(ppd
->shortnickname
);
130 * Free any emulations...
133 if (ppd
->num_emulations
> 0)
135 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
141 free(ppd
->emulations
);
145 * Free any UI groups, subgroups, and options...
148 if (ppd
->num_groups
> 0)
150 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
151 ppd_free_group(group
);
157 * Free any page sizes...
160 if (ppd
->num_sizes
> 0)
164 * Free any constraints...
167 if (ppd
->num_consts
> 0)
174 if (ppd
->num_fonts
> 0)
176 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
183 * Free any profiles...
186 if (ppd
->num_profiles
> 0)
190 * Free the whole record...
198 * 'ppd_free_group()' - Free a single UI group.
202 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
204 int i
; /* Looping var */
205 ppd_option_t
*option
; /* Current option */
206 ppd_group_t
*subgroup
; /* Current sub-group */
209 if (group
->num_options
> 0)
211 for (i
= group
->num_options
, option
= group
->options
;
214 ppd_free_option(option
);
216 free(group
->options
);
219 if (group
->num_subgroups
> 0)
221 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
224 ppd_free_group(subgroup
);
226 free(group
->subgroups
);
232 * 'ppd_free_option()' - Free a single option.
236 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
238 int i
; /* Looping var */
239 ppd_choice_t
*choice
; /* Current choice */
242 if (option
->num_choices
> 0)
244 for (i
= option
->num_choices
, choice
= option
->choices
;
249 free(option
->choices
);
255 * 'ppd_get_group()' - Find or create the named group as needed.
258 static ppd_group_t
* /* O - Named group */
259 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
260 char *name
) /* I - Name of group */
262 int i
; /* Looping var */
263 ppd_group_t
*group
; /* Group */
266 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
267 if (strcmp(group
->text
, name
) == 0)
272 if (ppd
->num_groups
== 0)
273 group
= malloc(sizeof(ppd_group_t
));
275 group
= realloc(ppd
->groups
,
276 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
282 group
+= ppd
->num_groups
;
285 memset(group
, 0, sizeof(ppd_group_t
));
286 strcpy(group
->text
, name
);
294 * 'ppd_get_option()' - Find or create the named option as needed.
297 static ppd_option_t
* /* O - Named option */
298 ppd_get_option(ppd_group_t
*group
, /* I - Group */
299 char *name
) /* I - Name of option */
301 int i
; /* Looping var */
302 ppd_option_t
*option
; /* Option */
305 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
306 if (strcmp(option
->keyword
, name
) == 0)
311 if (group
->num_options
== 0)
312 option
= malloc(sizeof(ppd_option_t
));
314 option
= realloc(group
->options
,
315 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
320 group
->options
= option
;
321 option
+= group
->num_options
;
322 group
->num_options
++;
324 memset(option
, 0, sizeof(ppd_option_t
));
325 strcpy(option
->keyword
, name
);
333 * 'ppd_add_choice()' - Add a choice to an option.
336 static ppd_choice_t
* /* O - Named choice */
337 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
338 char *name
) /* I - Name of choice */
340 ppd_choice_t
*choice
; /* Choice */
343 if (option
->num_choices
== 0)
344 choice
= malloc(sizeof(ppd_choice_t
));
346 choice
= realloc(option
->choices
,
347 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
352 option
->choices
= choice
;
353 choice
+= option
->num_choices
;
354 option
->num_choices
++;
356 memset(choice
, 0, sizeof(ppd_choice_t
));
357 strcpy(choice
->choice
, name
);
364 * 'ppd_add_size()' - Add a page size.
367 static ppd_size_t
* /* O - Named size */
368 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
369 char *name
) /* I - Name of size */
371 ppd_size_t
*size
; /* Size */
374 if (ppd
->num_sizes
== 0)
375 size
= malloc(sizeof(ppd_size_t
));
377 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
383 size
+= ppd
->num_sizes
;
386 memset(size
, 0, sizeof(ppd_size_t
));
387 strcpy(size
->name
, name
);
394 * 'ppdOpen()' - Read a PPD file into memory.
397 ppd_file_t
* /* O - PPD file record */
398 ppdOpen(FILE *fp
) /* I - File to read from */
400 int i
, j
, k
, m
; /* Looping vars */
401 int count
; /* Temporary count */
402 ppd_file_t
*ppd
; /* PPD file record */
403 ppd_group_t
*group
, /* Current group */
404 *subgroup
; /* Current sub-group */
405 ppd_option_t
*option
; /* Current option */
406 ppd_choice_t
*choice
; /* Current choice */
407 ppd_const_t
*constraint
; /* Current constraint */
408 ppd_size_t
*size
; /* Current page size */
409 int mask
; /* Line data mask */
410 char keyword
[41], /* Keyword from file */
411 name
[41], /* Option from file */
412 text
[81], /* Human-readable text from file */
413 *string
, /* Code/text from file */
414 *sptr
, /* Pointer into string */
415 *nameptr
; /* Pointer into name */
416 float order
; /* Order dependency number */
417 ppd_section_t section
; /* Order dependency section */
418 ppd_profile_t
*profile
; /* Pointer to color profile */
419 char **filter
; /* Pointer to filter */
423 * Range check input...
430 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
433 mask
= ppd_read(fp
, keyword
, name
, text
, &string
);
436 strcmp(keyword
, "PPD-Adobe") != 0 ||
437 string
== NULL
|| string
[0] != '4')
440 * Either this is not a PPD file, or it is not a 4.x PPD file.
453 * Allocate memory for the PPD file record...
456 if ((ppd
= calloc(sizeof(ppd_file_t
), 1)) == NULL
)
459 ppd
->language_level
= 1;
460 ppd
->color_device
= 0;
461 ppd
->colorspace
= PPD_CS_GRAY
;
465 * Read lines from the PPD file and add them to the file record...
473 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
)) != 0)
476 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
479 printf(", name = \"%s\"", name
);
482 printf(", text = \"%s\"", text
);
486 if (strlen(string
) > 40)
487 printf(", string = %08x", string
);
489 printf(", string = \"%s\"", string
);
495 if (strcmp(keyword
, "LanguageLevel") == 0)
496 ppd
->language_level
= atoi(string
);
497 else if (strcmp(keyword
, "LanguageEncoding") == 0)
499 ppd
->lang_encoding
= string
;
500 string
= NULL
; /* Don't free this string below */
502 else if (strcmp(keyword
, "LanguageVersion") == 0)
504 ppd
->lang_version
= string
;
505 string
= NULL
; /* Don't free this string below */
507 else if (strcmp(keyword
, "Manufacturer") == 0)
509 ppd
->manufacturer
= string
;
510 string
= NULL
; /* Don't free this string below */
512 else if (strcmp(keyword
, "ModelName") == 0)
514 ppd
->modelname
= string
;
515 string
= NULL
; /* Don't free this string below */
517 else if (strcmp(keyword
, "NickName") == 0)
519 ppd
->nickname
= string
;
520 string
= NULL
; /* Don't free this string below */
522 else if (strcmp(keyword
, "Product") == 0)
524 ppd
->product
= string
;
525 string
= NULL
; /* Don't free this string below */
527 else if (strcmp(keyword
, "ShortNickName") == 0)
529 ppd
->shortnickname
= string
;
530 string
= NULL
; /* Don't free this string below */
532 else if (strcmp(keyword
, "TTRasterizer") == 0)
534 ppd
->ttrasterizer
= string
;
535 string
= NULL
; /* Don't free this string below */
537 else if (strcmp(keyword
, "JCLBegin") == 0)
539 ppd_decode(string
); /* Decode quoted string */
540 ppd
->jcl_begin
= string
;
541 string
= NULL
; /* Don't free this string below */
543 else if (strcmp(keyword
, "JCLEnd") == 0)
545 ppd_decode(string
); /* Decode quoted string */
546 ppd
->jcl_end
= string
;
547 string
= NULL
; /* Don't free this string below */
549 else if (strcmp(keyword
, "JCLToPSInterpreter") == 0)
551 ppd_decode(string
); /* Decode quoted string */
552 ppd
->jcl_ps
= string
;
553 string
= NULL
; /* Don't free this string below */
555 else if (strcmp(keyword
, "AccurateScreensSupport") == 0)
556 ppd
->accurate_screens
= strcmp(string
, "True") == 0;
557 else if (strcmp(keyword
, "ColorDevice") == 0)
558 ppd
->color_device
= strcmp(string
, "True") == 0;
559 else if (strcmp(keyword
, "ContoneOnly") == 0)
560 ppd
->contone_only
= strcmp(string
, "True") == 0;
561 else if (strcmp(keyword
, "DefaultColorSpace") == 0)
563 if (strcmp(string
, "CMY") == 0)
564 ppd
->colorspace
= PPD_CS_CMY
;
565 else if (strcmp(string
, "CMYK") == 0)
566 ppd
->colorspace
= PPD_CS_CMYK
;
567 else if (strcmp(string
, "RGB") == 0)
568 ppd
->colorspace
= PPD_CS_RGB
;
569 else if (strcmp(string
, "RGBK") == 0)
570 ppd
->colorspace
= PPD_CS_RGBK
;
571 else if (strcmp(string
, "N") == 0)
572 ppd
->colorspace
= PPD_CS_N
;
574 ppd
->colorspace
= PPD_CS_GRAY
;
576 else if (strcmp(keyword
, "cupsManualCopies") == 0)
577 ppd
->manual_copies
= strcmp(string
, "True") == 0;
578 else if (strcmp(keyword
, "cupsModelNumber") == 0)
579 ppd
->model_number
= atoi(string
);
580 else if (strcmp(keyword
, "cupsColorProfile") == 0)
582 if (ppd
->num_profiles
== 0)
583 profile
= malloc(sizeof(ppd_profile_t
));
585 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
586 (ppd
->num_profiles
+ 1));
588 ppd
->profiles
= profile
;
589 profile
+= ppd
->num_profiles
;
590 ppd
->num_profiles
++;
592 memset(profile
, 0, sizeof(ppd_profile_t
));
593 strcpy(profile
->resolution
, name
);
594 strcpy(profile
->media_type
, text
);
595 sscanf(string
, "%f%f%f%f%f%f%f%f%f%f", &(profile
->density
),
596 profile
->matrix
[0] + 0, profile
->matrix
[0] + 1,
597 profile
->matrix
[0] + 2, profile
->matrix
[1] + 0,
598 profile
->matrix
[1] + 1, profile
->matrix
[1] + 2,
599 profile
->matrix
[2] + 0, profile
->matrix
[2] + 1,
600 profile
->matrix
[2] + 2);
602 else if (strcmp(keyword
, "cupsFilter") == 0)
604 if (ppd
->num_filters
== 0)
605 filter
= malloc(sizeof(char *));
607 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
609 ppd
->filters
= filter
;
610 filter
+= ppd
->num_filters
;
614 * Copy filter string and prevent it from being freed below...
620 else if (strcmp(keyword
, "VariablePaperSize") == 0 &&
621 strcmp(string
, "True") == 0)
623 ppd
->variable_sizes
= 1;
626 * Add a "Custom" page size entry...
629 ppd_add_size(ppd
, "Custom");
632 * Add a "Custom" page size option...
635 if ((group
= ppd_get_group(ppd
, "General")) == NULL
)
642 if ((option
= ppd_get_option(group
, "PageSize")) == NULL
)
649 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
656 strcpy(choice
->text
, "Custom Size");
660 else if (strcmp(keyword
, "MaxMediaWidth") == 0)
661 ppd
->custom_max
[0] = atof(string
);
662 else if (strcmp(keyword
, "MaxMediaHeight") == 0)
663 ppd
->custom_max
[1] = atof(string
);
664 else if (strcmp(keyword
, "ParamCustomPageSize") == 0)
666 if (strcmp(name
, "Width") == 0)
667 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 0,
668 ppd
->custom_max
+ 0);
669 else if (strcmp(name
, "Height") == 0)
670 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 1,
671 ppd
->custom_max
+ 1);
673 else if (strcmp(keyword
, "HWMargins") == 0)
674 sscanf(string
, "%f%f%f%f", ppd
->custom_margins
+ 0,
675 ppd
->custom_margins
+ 1, ppd
->custom_margins
+ 2,
676 ppd
->custom_margins
+ 3);
677 else if (strcmp(keyword
, "CustomPageSize") == 0 &&
678 strcmp(name
, "True") == 0 &&
681 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
688 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
695 choice
->code
= string
;
699 else if (strcmp(keyword
, "LandscapeOrientation") == 0)
701 if (strcmp(string
, "Minus90") == 0)
702 ppd
->landscape
= -90;
706 else if (strcmp(keyword
, "Emulators") == 0)
708 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
709 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
716 ppd
->num_emulations
= count
;
717 ppd
->emulations
= calloc(sizeof(ppd_emul_t
), count
);
719 for (i
= 0, sptr
= string
; i
< count
; i
++)
721 for (nameptr
= ppd
->emulations
[i
].name
; *sptr
!= '\0' && *sptr
!= ' ';)
722 *nameptr
++ = *sptr
++;
730 else if (strncmp(keyword
, "StartEmulator_", 14) == 0)
734 for (i
= 0; i
< ppd
->num_emulations
; i
++)
735 if (strcmp(keyword
+ 14, ppd
->emulations
[i
].name
) == 0)
737 ppd
->emulations
[i
].start
= string
;
741 else if (strncmp(keyword
, "StopEmulator_", 13) == 0)
745 for (i
= 0; i
< ppd
->num_emulations
; i
++)
746 if (strcmp(keyword
+ 13, ppd
->emulations
[i
].name
) == 0)
748 ppd
->emulations
[i
].stop
= string
;
752 else if (strcmp(keyword
, "JobPatchFile") == 0)
754 if (ppd
->patches
== NULL
)
756 ppd
->patches
= string
;
761 ppd
->patches
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
764 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
767 else if (strcmp(keyword
, "OpenUI") == 0)
770 * Add an option record to the current sub-group, group, or file...
774 strcpy(name
, name
+ 1);
782 if (subgroup
!= NULL
)
783 option
= ppd_get_option(subgroup
, name
);
784 else if (group
== NULL
)
786 if (strcmp(name
, "Collate") != 0 &&
787 strcmp(name
, "Duplex") != 0 &&
788 strcmp(name
, "InputSlot") != 0 &&
789 strcmp(name
, "ManualFeed") != 0 &&
790 strcmp(name
, "MediaType") != 0 &&
791 strcmp(name
, "MediaColor") != 0 &&
792 strcmp(name
, "MediaWeight") != 0 &&
793 strcmp(name
, "OutputBin") != 0 &&
794 strcmp(name
, "OutputMode") != 0 &&
795 strcmp(name
, "OutputOrder") != 0 &&
796 strcmp(name
, "PageSize") != 0 &&
797 strcmp(name
, "PageRegion") != 0)
798 group
= ppd_get_group(ppd
, "Extra");
800 group
= ppd_get_group(ppd
, "General");
809 option
= ppd_get_option(group
, name
);
813 option
= ppd_get_option(group
, name
);
823 * Now fill in the initial information for the option...
826 if (strcmp(string
, "PickMany") == 0)
827 option
->ui
= PPD_UI_PICKMANY
;
828 else if (strcmp(string
, "Boolean") == 0)
829 option
->ui
= PPD_UI_BOOLEAN
;
831 option
->ui
= PPD_UI_PICKONE
;
834 strcpy(option
->text
, text
);
837 if (strcmp(name
, "PageSize") == 0)
838 strcpy(option
->text
, "Media Size");
839 else if (strcmp(name
, "MediaType") == 0)
840 strcpy(option
->text
, "Media Type");
841 else if (strcmp(name
, "InputSlot") == 0)
842 strcpy(option
->text
, "Media Source");
844 strcpy(option
->text
, name
);
847 option
->section
= PPD_ORDER_ANY
;
849 else if (strcmp(keyword
, "JCLOpenUI") == 0)
852 * Find the JCL group, and add if needed...
862 group
= ppd_get_group(ppd
, "JCL");
872 * Add an option record to the current JCLs...
876 strcpy(name
, name
+ 1);
878 option
= ppd_get_option(group
, name
);
888 * Now fill in the initial information for the option...
891 if (strcmp(string
, "PickMany") == 0)
892 option
->ui
= PPD_UI_PICKMANY
;
893 else if (strcmp(string
, "Boolean") == 0)
894 option
->ui
= PPD_UI_BOOLEAN
;
896 option
->ui
= PPD_UI_PICKONE
;
898 strcpy(option
->text
, text
);
900 option
->section
= PPD_ORDER_JCL
;
903 else if (strcmp(keyword
, "CloseUI") == 0 ||
904 strcmp(keyword
, "JCLCloseUI") == 0)
906 else if (strcmp(keyword
, "OpenGroup") == 0)
909 * Open a new group...
919 if (strchr(string
, '/') != NULL
) /* Just show human readable text */
920 strcpy(string
, strchr(string
, '/') + 1);
923 group
= ppd_get_group(ppd
, string
);
925 else if (strcmp(keyword
, "CloseGroup") == 0)
927 else if (strcmp(keyword
, "OpenSubGroup") == 0)
930 * Open a new sub-group...
933 if (group
== NULL
|| subgroup
!= NULL
)
940 if (group
->num_subgroups
== 0)
941 subgroup
= malloc(sizeof(ppd_group_t
));
943 subgroup
= realloc(group
->subgroups
,
944 (group
->num_subgroups
+ 1) * sizeof(ppd_group_t
));
946 if (subgroup
== NULL
)
953 group
->subgroups
= subgroup
;
954 subgroup
+= group
->num_subgroups
;
955 group
->num_subgroups
++;
957 memset(subgroup
, 0, sizeof(ppd_group_t
));
958 strcpy(subgroup
->text
, string
);
960 else if (strcmp(keyword
, "CloseSubGroup") == 0)
962 else if (strcmp(keyword
, "OrderDependency") == 0 ||
963 strcmp(keyword
, "NonUIOrderDependency") == 0)
965 if (sscanf(string
, "%f%s%s", &order
, name
, keyword
) != 3)
972 if (keyword
[0] == '*')
973 strcpy(keyword
, keyword
+ 1);
975 if (strcmp(name
, "ExitServer") == 0)
976 section
= PPD_ORDER_EXIT
;
977 else if (strcmp(name
, "Prolog") == 0)
978 section
= PPD_ORDER_PROLOG
;
979 else if (strcmp(name
, "DocumentSetup") == 0)
980 section
= PPD_ORDER_DOCUMENT
;
981 else if (strcmp(name
, "PageSetup") == 0)
982 section
= PPD_ORDER_PAGE
;
983 else if (strcmp(name
, "JCLSetup") == 0)
984 section
= PPD_ORDER_JCL
;
986 section
= PPD_ORDER_ANY
;
991 * Only valid for Non-UI options...
994 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
995 if (group
->text
[0] == '\0')
999 for (i
= 0; i
< group
->num_options
; i
++)
1000 if (strcmp(keyword
, group
->options
[i
].keyword
) == 0)
1002 group
->options
[i
].section
= section
;
1003 group
->options
[i
].order
= order
;
1011 option
->section
= section
;
1012 option
->order
= order
;
1015 else if (strncmp(keyword
, "Default", 7) == 0)
1017 if (strchr(string
, '/') != NULL
)
1018 *strchr(string
, '/') = '\0';
1023 * Only valid for Non-UI options...
1026 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
1027 if (group
->text
[0] == '\0')
1031 for (i
= 0; i
< group
->num_options
; i
++)
1032 if (strcmp(keyword
, group
->options
[i
].keyword
) == 0)
1034 strcpy(group
->options
[i
].defchoice
, string
);
1041 strcpy(option
->defchoice
, string
);
1043 else if (strcmp(keyword
, "UIConstraints") == 0 ||
1044 strcmp(keyword
, "NonUIConstraints") == 0)
1046 if (ppd
->num_consts
== 0)
1047 constraint
= calloc(sizeof(ppd_const_t
), 1);
1049 constraint
= realloc(ppd
->consts
,
1050 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1052 if (constraint
== NULL
)
1059 ppd
->consts
= constraint
;
1060 constraint
+= ppd
->num_consts
;
1063 switch (sscanf(string
, "%s%s%s%s", constraint
->option1
,
1064 constraint
->choice1
, constraint
->option2
,
1065 constraint
->choice2
))
1067 case 0 : /* Error */
1068 case 1 : /* Error */
1073 case 2 : /* Two options... */
1074 if (constraint
->option1
[0] == '*')
1075 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1077 if (constraint
->choice1
[0] == '*')
1078 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1080 strcpy(constraint
->option2
, constraint
->choice1
);
1082 constraint
->choice1
[0] = '\0';
1083 constraint
->choice2
[0] = '\0';
1086 case 3 : /* Two options, one choice... */
1087 if (constraint
->option1
[0] == '*')
1088 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1090 if (constraint
->choice1
[0] == '*')
1092 strcpy(constraint
->choice2
, constraint
->option2
);
1093 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1094 constraint
->choice1
[0] = '\0';
1098 if (constraint
->option2
[0] == '*')
1099 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1101 constraint
->choice2
[0] = '\0';
1105 case 4 : /* Two options, two choices... */
1106 if (constraint
->option1
[0] == '*')
1107 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1109 if (constraint
->option2
[0] == '*')
1110 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1114 else if (strcmp(keyword
, "PaperDimension") == 0)
1116 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1117 sscanf(string
, "%f%f", &(size
->width
), &(size
->length
));
1119 else if (strcmp(keyword
, "ImageableArea") == 0)
1121 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1122 sscanf(string
, "%f%f%f%f", &(size
->left
), &(size
->bottom
),
1123 &(size
->right
), &(size
->top
));
1125 else if (option
!= NULL
&&
1126 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1127 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
1129 if (strcmp(keyword
, "PageSize") == 0)
1132 * Add a page size...
1135 ppd_add_size(ppd
, name
);
1139 * Add the option choice...
1142 choice
= ppd_add_choice(option
, name
);
1144 if (mask
& PPD_TEXT
)
1145 strcpy(choice
->text
, text
);
1146 else if (strcmp(name
, "True") == 0)
1147 strcpy(choice
->text
, "Yes");
1148 else if (strcmp(name
, "False") == 0)
1149 strcpy(choice
->text
, "No");
1151 strcpy(choice
->text
, name
);
1153 if (strncmp(keyword
, "JCL", 3) == 0)
1154 ppd_decode(string
); /* Decode quoted string */
1156 choice
->code
= string
;
1157 string
= NULL
; /* Don't free this string below */
1166 printf("Premature EOF at %d...\n", ftell(fp
));
1170 * Set the option back-pointer for each choice...
1173 qsort(ppd
->groups
, ppd
->num_groups
, sizeof(ppd_group_t
),
1174 (int (*)(const void *, const void *))compare_groups
);
1176 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1180 qsort(group
->options
, group
->num_options
, sizeof(ppd_option_t
),
1181 (int (*)(const void *, const void *))compare_options
);
1183 for (j
= group
->num_options
, option
= group
->options
;
1187 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1188 (int (*)(const void *, const void *))compare_choices
);
1190 for (k
= 0; k
< option
->num_choices
; k
++)
1191 option
->choices
[k
].option
= (void *)option
;
1194 qsort(group
->subgroups
, group
->num_subgroups
, sizeof(ppd_group_t
),
1195 (int (*)(const void *, const void *))compare_groups
);
1197 for (j
= group
->num_subgroups
, subgroup
= group
->subgroups
;
1201 qsort(subgroup
->options
, subgroup
->num_options
, sizeof(ppd_option_t
),
1202 (int (*)(const void *, const void *))compare_options
);
1204 for (k
= group
->num_options
, option
= group
->options
;
1208 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1209 (int (*)(const void *, const void *))compare_choices
);
1211 for (m
= 0; m
< option
->num_choices
; m
++)
1212 option
->choices
[m
].option
= (void *)option
;
1222 * 'ppdOpenFd()' - Read a PPD file into memory.
1225 ppd_file_t
* /* O - PPD file record */
1226 ppdOpenFd(int fd
) /* I - File to read from */
1228 FILE *fp
; /* File pointer */
1229 ppd_file_t
*ppd
; /* PPD file record */
1233 * Range check input...
1240 * Try to open the file and parse it...
1243 if ((fp
= fdopen(fd
, "r")) != NULL
)
1259 * 'ppdOpenFile()' - Read a PPD file into memory.
1262 ppd_file_t
* /* O - PPD file record */
1263 ppdOpenFile(char *filename
) /* I - File to read from */
1265 FILE *fp
; /* File pointer */
1266 ppd_file_t
*ppd
; /* PPD file record */
1270 * Range check input...
1273 if (filename
== NULL
)
1277 * Try to open the file and parse it...
1280 if ((fp
= fopen(filename
, "r")) != NULL
)
1294 * 'compare_strings()' - Compare two strings.
1297 int /* O - Result of comparison */
1298 compare_strings(char *s
, /* I - First string */
1299 char *t
) /* I - Second string */
1301 int diff
, /* Difference between digits */
1302 digits
; /* Number of digits */
1306 * Loop through both strings, returning only when a difference is
1307 * seen. Also, compare whole numbers rather than just characters, too!
1312 if (isdigit(*s
) && isdigit(*t
))
1315 * Got a number; start by skipping leading 0's...
1324 * Skip equal digits...
1327 while (isdigit(*s
) && *s
== *t
)
1334 * Bounce out if *s and *t aren't both digits...
1337 if (!isdigit(*s
) || !isdigit(*t
))
1346 * Figure out how many more digits there are...
1364 * Return if the number or value of the digits is different...
1369 else if (digits
> 0)
1374 else if (tolower(*s
) < tolower(*t
))
1376 else if (tolower(*s
) > tolower(*t
))
1386 * Return the results of the final comparison...
1399 * 'compare_groups()' - Compare two groups.
1402 static int /* O - Result of comparison */
1403 compare_groups(ppd_group_t
*g0
, /* I - First group */
1404 ppd_group_t
*g1
) /* I - Second group */
1406 return (compare_strings(g0
->text
, g1
->text
));
1411 * 'compare_options()' - Compare two options.
1414 static int /* O - Result of comparison */
1415 compare_options(ppd_option_t
*o0
,/* I - First option */
1416 ppd_option_t
*o1
)/* I - Second option */
1418 return (compare_strings(o0
->text
, o1
->text
));
1423 * 'compare_choices()' - Compare two choices.
1426 static int /* O - Result of comparison */
1427 compare_choices(ppd_choice_t
*c0
,/* I - First choice */
1428 ppd_choice_t
*c1
)/* I - Second choice */
1430 return (compare_strings(c0
->text
, c1
->text
));
1435 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
1439 static int /* O - Bitmask of fields read */
1440 ppd_read(FILE *fp
, /* I - File to read from */
1441 char *keyword
, /* O - Keyword from line */
1442 char *option
, /* O - Option from line */
1443 char *text
, /* O - Human-readable text from line */
1444 char **string
) /* O - Code/string data */
1446 int ch
, /* Character from file */
1447 endquote
, /* Waiting for an end quote */
1448 mask
; /* Mask to be returned */
1449 char *keyptr
, /* Keyword pointer */
1450 *optptr
, /* Option pointer */
1451 *textptr
, /* Text pointer */
1452 *strptr
, /* Pointer into string */
1453 *lineptr
, /* Current position in line buffer */
1454 line
[262144]; /* Line buffer (256k) */
1458 * Range check everything...
1461 if (fp
== NULL
|| keyword
== NULL
|| option
== NULL
|| text
== NULL
||
1466 * Now loop until we have a valid line...
1478 while ((ch
= getc(fp
)) != EOF
&&
1479 (lineptr
- line
) < (sizeof(line
) - 1))
1481 if (ch
== '\r' || ch
== '\n')
1484 * Line feed or carriage return...
1487 if (lineptr
== line
) /* Skip blank lines */
1493 * Check for a trailing line feed...
1496 if ((ch
= getc(fp
)) == EOF
)
1504 if (!endquote
) /* Continue for multi-line text */
1510 * Any other character...
1516 endquote
= !endquote
;
1520 if (lineptr
> line
&& lineptr
[-1] == '\n')
1525 if (ch
== EOF
&& lineptr
== line
)
1540 if (line
[0] != '*') /* All lines start with an asterisk */
1543 if (strncmp(line
, "*%", 2) == 0 || /* Comment line */
1544 strncmp(line
, "*?", 2) == 0 || /* Query line */
1545 strcmp(line
, "*End") == 0) /* End of multi-line string */
1554 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
) &&
1555 (keyptr
- keyword
) < 40)
1556 *keyptr
++ = *lineptr
++;
1559 mask
|= PPD_KEYWORD
;
1561 if (*lineptr
== ' ' || *lineptr
== '\t')
1564 * Get an option name...
1567 while (*lineptr
== ' ' || *lineptr
== '\t')
1572 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1573 *lineptr
!= '/' && (optptr
- option
) < 40)
1574 *optptr
++ = *lineptr
++;
1579 if (*lineptr
== '/')
1582 * Get human-readable text...
1589 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1590 (textptr
- text
) < 80)
1591 *textptr
++ = *lineptr
++;
1600 if (*lineptr
== ':')
1606 *string
= malloc(strlen(lineptr
) + 1);
1608 while (*lineptr
== ':' || isspace(*lineptr
))
1613 while (*lineptr
!= '\0')
1615 if (*lineptr
!= '\"')
1616 *strptr
++ = *lineptr
++;
1633 * 'ppd_decode()' - Decode a string value...
1637 ppd_decode(char *string
) /* I - String to decode */
1639 char *inptr
, /* Input pointer */
1640 *outptr
; /* Output pointer */
1646 while (*inptr
!= '\0')
1647 if (*inptr
== '<' && isxdigit(inptr
[1]))
1650 * Convert hex to 8-bit values...
1654 while (isxdigit(*inptr
))
1656 if (isalpha(*inptr
))
1657 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
1659 *outptr
= (*inptr
- '0') << 4;
1663 if (isalpha(*inptr
))
1664 *outptr
|= tolower(*inptr
) - 'a' + 10;
1666 *outptr
|= *inptr
- '0';
1672 while (*inptr
!= '>' && *inptr
!= '\0')
1674 while (*inptr
== '>')
1678 *outptr
++ = *inptr
++;
1685 * End of "$Id: ppd.c,v 1.21 1999/06/04 21:04:29 mike Exp $".