]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/ppd.c
2 * "$Id: ppd.c,v 1.23 1999/06/15 21:27:09 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.
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 PPD_KEYWORD 1 /* Line contained a keyword */
74 #define PPD_OPTION 2 /* Line contained an option name */
75 #define PPD_TEXT 4 /* Line contained human-readable text */
76 #define PPD_STRING 8 /* Line contained a string or code */
83 static int compare_strings(char *s
, char *t
);
84 static int compare_groups(ppd_group_t
*g0
, ppd_group_t
*g1
);
85 static int compare_options(ppd_option_t
*o0
, ppd_option_t
*o1
);
86 static int compare_choices(ppd_choice_t
*c0
, ppd_choice_t
*c1
);
87 static int ppd_read(FILE *fp
, char *keyword
, char *option
,
88 char *text
, char **string
);
89 static void ppd_decode(char *string
);
90 static void ppd_free_group(ppd_group_t
*group
);
91 static void ppd_free_option(ppd_option_t
*option
);
92 static ppd_group_t
*ppd_get_group(ppd_file_t
*ppd
, char *name
);
93 static ppd_option_t
*ppd_get_option(ppd_group_t
*group
, char *name
);
94 static ppd_choice_t
*ppd_add_choice(ppd_option_t
*option
, char *name
);
98 * 'ppdClose()' - Free all memory used by the PPD file.
102 ppdClose(ppd_file_t
*ppd
) /* I - PPD file record */
104 int i
; /* Looping var */
105 ppd_emul_t
*emul
; /* Current emulation */
106 ppd_group_t
*group
; /* Current group */
107 char **font
; /* Current font */
111 * Range check the PPD file record...
118 * Free all strings at the top level...
121 free(ppd
->lang_encoding
);
122 free(ppd
->lang_version
);
123 free(ppd
->modelname
);
124 free(ppd
->ttrasterizer
);
125 free(ppd
->manufacturer
);
128 free(ppd
->shortnickname
);
131 * Free any emulations...
134 if (ppd
->num_emulations
> 0)
136 for (i
= ppd
->num_emulations
, emul
= ppd
->emulations
; i
> 0; i
--, emul
++)
142 free(ppd
->emulations
);
146 * Free any UI groups, subgroups, and options...
149 if (ppd
->num_groups
> 0)
151 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
152 ppd_free_group(group
);
158 * Free any page sizes...
161 if (ppd
->num_sizes
> 0)
165 * Free any constraints...
168 if (ppd
->num_consts
> 0)
175 if (ppd
->num_fonts
> 0)
177 for (i
= ppd
->num_fonts
, font
= ppd
->fonts
; i
> 0; i
--, font
++)
184 * Free any profiles...
187 if (ppd
->num_profiles
> 0)
191 * Free the whole record...
199 * 'ppd_free_group()' - Free a single UI group.
203 ppd_free_group(ppd_group_t
*group
) /* I - Group to free */
205 int i
; /* Looping var */
206 ppd_option_t
*option
; /* Current option */
207 ppd_group_t
*subgroup
; /* Current sub-group */
210 if (group
->num_options
> 0)
212 for (i
= group
->num_options
, option
= group
->options
;
215 ppd_free_option(option
);
217 free(group
->options
);
220 if (group
->num_subgroups
> 0)
222 for (i
= group
->num_subgroups
, subgroup
= group
->subgroups
;
225 ppd_free_group(subgroup
);
227 free(group
->subgroups
);
233 * 'ppd_free_option()' - Free a single option.
237 ppd_free_option(ppd_option_t
*option
) /* I - Option to free */
239 int i
; /* Looping var */
240 ppd_choice_t
*choice
; /* Current choice */
243 if (option
->num_choices
> 0)
245 for (i
= option
->num_choices
, choice
= option
->choices
;
250 free(option
->choices
);
256 * 'ppd_get_group()' - Find or create the named group as needed.
259 static ppd_group_t
* /* O - Named group */
260 ppd_get_group(ppd_file_t
*ppd
, /* I - PPD file */
261 char *name
) /* I - Name of group */
263 int i
; /* Looping var */
264 ppd_group_t
*group
; /* Group */
267 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
268 if (strcmp(group
->text
, name
) == 0)
273 if (ppd
->num_groups
== 0)
274 group
= malloc(sizeof(ppd_group_t
));
276 group
= realloc(ppd
->groups
,
277 (ppd
->num_groups
+ 1) * sizeof(ppd_group_t
));
283 group
+= ppd
->num_groups
;
286 memset(group
, 0, sizeof(ppd_group_t
));
287 strcpy(group
->text
, name
);
295 * 'ppd_get_option()' - Find or create the named option as needed.
298 static ppd_option_t
* /* O - Named option */
299 ppd_get_option(ppd_group_t
*group
, /* I - Group */
300 char *name
) /* I - Name of option */
302 int i
; /* Looping var */
303 ppd_option_t
*option
; /* Option */
306 for (i
= group
->num_options
, option
= group
->options
; i
> 0; i
--, option
++)
307 if (strcmp(option
->keyword
, name
) == 0)
312 if (group
->num_options
== 0)
313 option
= malloc(sizeof(ppd_option_t
));
315 option
= realloc(group
->options
,
316 (group
->num_options
+ 1) * sizeof(ppd_option_t
));
321 group
->options
= option
;
322 option
+= group
->num_options
;
323 group
->num_options
++;
325 memset(option
, 0, sizeof(ppd_option_t
));
326 strcpy(option
->keyword
, name
);
334 * 'ppd_add_choice()' - Add a choice to an option.
337 static ppd_choice_t
* /* O - Named choice */
338 ppd_add_choice(ppd_option_t
*option
, /* I - Option */
339 char *name
) /* I - Name of choice */
341 ppd_choice_t
*choice
; /* Choice */
344 if (option
->num_choices
== 0)
345 choice
= malloc(sizeof(ppd_choice_t
));
347 choice
= realloc(option
->choices
,
348 sizeof(ppd_choice_t
) * (option
->num_choices
+ 1));
353 option
->choices
= choice
;
354 choice
+= option
->num_choices
;
355 option
->num_choices
++;
357 memset(choice
, 0, sizeof(ppd_choice_t
));
358 strcpy(choice
->choice
, name
);
365 * 'ppd_add_size()' - Add a page size.
368 static ppd_size_t
* /* O - Named size */
369 ppd_add_size(ppd_file_t
*ppd
, /* I - PPD file */
370 char *name
) /* I - Name of size */
372 ppd_size_t
*size
; /* Size */
375 if (ppd
->num_sizes
== 0)
376 size
= malloc(sizeof(ppd_size_t
));
378 size
= realloc(ppd
->sizes
, sizeof(ppd_size_t
) * (ppd
->num_sizes
+ 1));
384 size
+= ppd
->num_sizes
;
387 memset(size
, 0, sizeof(ppd_size_t
));
388 strcpy(size
->name
, name
);
395 * 'ppdOpen()' - Read a PPD file into memory.
398 ppd_file_t
* /* O - PPD file record */
399 ppdOpen(FILE *fp
) /* I - File to read from */
401 int i
, j
, k
, m
; /* Looping vars */
402 int count
; /* Temporary count */
403 ppd_file_t
*ppd
; /* PPD file record */
404 ppd_group_t
*group
, /* Current group */
405 *subgroup
; /* Current sub-group */
406 ppd_option_t
*option
; /* Current option */
407 ppd_choice_t
*choice
; /* Current choice */
408 ppd_const_t
*constraint
; /* Current constraint */
409 ppd_size_t
*size
; /* Current page size */
410 int mask
; /* Line data mask */
411 char keyword
[41], /* Keyword from file */
412 name
[41], /* Option from file */
413 text
[81], /* Human-readable text from file */
414 *string
, /* Code/text from file */
415 *sptr
, /* Pointer into string */
416 *nameptr
; /* Pointer into name */
417 float order
; /* Order dependency number */
418 ppd_section_t section
; /* Order dependency section */
419 ppd_profile_t
*profile
; /* Pointer to color profile */
420 char **filter
; /* Pointer to filter */
421 cups_lang_t
*language
; /* Default language */
425 * Get the default language for the user...
428 language
= cupsLangDefault();
431 * Range check input...
438 * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
441 mask
= ppd_read(fp
, keyword
, name
, text
, &string
);
444 strcmp(keyword
, "PPD-Adobe") != 0 ||
445 string
== NULL
|| string
[0] != '4')
448 * Either this is not a PPD file, or it is not a 4.x PPD file.
461 * Allocate memory for the PPD file record...
464 if ((ppd
= calloc(sizeof(ppd_file_t
), 1)) == NULL
)
467 ppd
->language_level
= 1;
468 ppd
->color_device
= 0;
469 ppd
->colorspace
= PPD_CS_GRAY
;
473 * Read lines from the PPD file and add them to the file record...
481 while ((mask
= ppd_read(fp
, keyword
, name
, text
, &string
)) != 0)
484 printf("mask = %x, keyword = \"%s\"", mask
, keyword
);
487 printf(", name = \"%s\"", name
);
490 printf(", text = \"%s\"", text
);
494 if (strlen(string
) > 40)
495 printf(", string = %08x", string
);
497 printf(", string = \"%s\"", string
);
503 if (strcmp(keyword
, "LanguageLevel") == 0)
504 ppd
->language_level
= atoi(string
);
505 else if (strcmp(keyword
, "LanguageEncoding") == 0)
507 ppd
->lang_encoding
= string
;
508 string
= NULL
; /* Don't free this string below */
510 else if (strcmp(keyword
, "LanguageVersion") == 0)
512 ppd
->lang_version
= string
;
513 string
= NULL
; /* Don't free this string below */
515 else if (strcmp(keyword
, "Manufacturer") == 0)
517 ppd
->manufacturer
= string
;
518 string
= NULL
; /* Don't free this string below */
520 else if (strcmp(keyword
, "ModelName") == 0)
522 ppd
->modelname
= string
;
523 string
= NULL
; /* Don't free this string below */
525 else if (strcmp(keyword
, "NickName") == 0)
527 ppd
->nickname
= string
;
528 string
= NULL
; /* Don't free this string below */
530 else if (strcmp(keyword
, "Product") == 0)
532 ppd
->product
= string
;
533 string
= NULL
; /* Don't free this string below */
535 else if (strcmp(keyword
, "ShortNickName") == 0)
537 ppd
->shortnickname
= string
;
538 string
= NULL
; /* Don't free this string below */
540 else if (strcmp(keyword
, "TTRasterizer") == 0)
542 ppd
->ttrasterizer
= string
;
543 string
= NULL
; /* Don't free this string below */
545 else if (strcmp(keyword
, "JCLBegin") == 0)
547 ppd_decode(string
); /* Decode quoted string */
548 ppd
->jcl_begin
= string
;
549 string
= NULL
; /* Don't free this string below */
551 else if (strcmp(keyword
, "JCLEnd") == 0)
553 ppd_decode(string
); /* Decode quoted string */
554 ppd
->jcl_end
= string
;
555 string
= NULL
; /* Don't free this string below */
557 else if (strcmp(keyword
, "JCLToPSInterpreter") == 0)
559 ppd_decode(string
); /* Decode quoted string */
560 ppd
->jcl_ps
= string
;
561 string
= NULL
; /* Don't free this string below */
563 else if (strcmp(keyword
, "AccurateScreensSupport") == 0)
564 ppd
->accurate_screens
= strcmp(string
, "True") == 0;
565 else if (strcmp(keyword
, "ColorDevice") == 0)
566 ppd
->color_device
= strcmp(string
, "True") == 0;
567 else if (strcmp(keyword
, "ContoneOnly") == 0)
568 ppd
->contone_only
= strcmp(string
, "True") == 0;
569 else if (strcmp(keyword
, "DefaultColorSpace") == 0)
571 if (strcmp(string
, "CMY") == 0)
572 ppd
->colorspace
= PPD_CS_CMY
;
573 else if (strcmp(string
, "CMYK") == 0)
574 ppd
->colorspace
= PPD_CS_CMYK
;
575 else if (strcmp(string
, "RGB") == 0)
576 ppd
->colorspace
= PPD_CS_RGB
;
577 else if (strcmp(string
, "RGBK") == 0)
578 ppd
->colorspace
= PPD_CS_RGBK
;
579 else if (strcmp(string
, "N") == 0)
580 ppd
->colorspace
= PPD_CS_N
;
582 ppd
->colorspace
= PPD_CS_GRAY
;
584 else if (strcmp(keyword
, "cupsManualCopies") == 0)
585 ppd
->manual_copies
= strcmp(string
, "True") == 0;
586 else if (strcmp(keyword
, "cupsModelNumber") == 0)
587 ppd
->model_number
= atoi(string
);
588 else if (strcmp(keyword
, "cupsColorProfile") == 0)
590 if (ppd
->num_profiles
== 0)
591 profile
= malloc(sizeof(ppd_profile_t
));
593 profile
= realloc(ppd
->profiles
, sizeof(ppd_profile_t
) *
594 (ppd
->num_profiles
+ 1));
596 ppd
->profiles
= profile
;
597 profile
+= ppd
->num_profiles
;
598 ppd
->num_profiles
++;
600 memset(profile
, 0, sizeof(ppd_profile_t
));
601 strcpy(profile
->resolution
, name
);
602 strcpy(profile
->media_type
, text
);
603 sscanf(string
, "%f%f%f%f%f%f%f%f%f%f", &(profile
->density
),
604 profile
->matrix
[0] + 0, profile
->matrix
[0] + 1,
605 profile
->matrix
[0] + 2, profile
->matrix
[1] + 0,
606 profile
->matrix
[1] + 1, profile
->matrix
[1] + 2,
607 profile
->matrix
[2] + 0, profile
->matrix
[2] + 1,
608 profile
->matrix
[2] + 2);
610 else if (strcmp(keyword
, "cupsFilter") == 0)
612 if (ppd
->num_filters
== 0)
613 filter
= malloc(sizeof(char *));
615 filter
= realloc(ppd
->filters
, sizeof(char *) * (ppd
->num_filters
+ 1));
617 ppd
->filters
= filter
;
618 filter
+= ppd
->num_filters
;
622 * Copy filter string and prevent it from being freed below...
628 else if (strcmp(keyword
, "VariablePaperSize") == 0 &&
629 strcmp(string
, "True") == 0)
631 ppd
->variable_sizes
= 1;
634 * Add a "Custom" page size entry...
637 ppd_add_size(ppd
, "Custom");
640 * Add a "Custom" page size option...
643 if ((group
= ppd_get_group(ppd
,
644 cupsLangString(language
,
645 CUPS_MSG_GENERAL
))) == NULL
)
652 if ((option
= ppd_get_option(group
, "PageSize")) == NULL
)
659 if ((choice
= ppd_add_choice(option
, "Custom")) == NULL
)
666 strcpy(choice
->text
, cupsLangString(language
, CUPS_MSG_VARIABLE
));
670 else if (strcmp(keyword
, "MaxMediaWidth") == 0)
671 ppd
->custom_max
[0] = atof(string
);
672 else if (strcmp(keyword
, "MaxMediaHeight") == 0)
673 ppd
->custom_max
[1] = atof(string
);
674 else if (strcmp(keyword
, "ParamCustomPageSize") == 0)
676 if (strcmp(name
, "Width") == 0)
677 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 0,
678 ppd
->custom_max
+ 0);
679 else if (strcmp(name
, "Height") == 0)
680 sscanf(string
, "%*s%*s%f%f", ppd
->custom_min
+ 1,
681 ppd
->custom_max
+ 1);
683 else if (strcmp(keyword
, "HWMargins") == 0)
684 sscanf(string
, "%f%f%f%f", ppd
->custom_margins
+ 0,
685 ppd
->custom_margins
+ 1, ppd
->custom_margins
+ 2,
686 ppd
->custom_margins
+ 3);
687 else if (strcmp(keyword
, "CustomPageSize") == 0 &&
688 strcmp(name
, "True") == 0 &&
691 if ((option
= ppdFindOption(ppd
, "PageSize")) == NULL
)
698 if ((choice
= ppdFindChoice(option
, "Custom")) == NULL
)
705 choice
->code
= string
;
709 else if (strcmp(keyword
, "LandscapeOrientation") == 0)
711 if (strcmp(string
, "Minus90") == 0)
712 ppd
->landscape
= -90;
716 else if (strcmp(keyword
, "Emulators") == 0)
718 for (count
= 1, sptr
= string
; sptr
!= NULL
;)
719 if ((sptr
= strchr(sptr
, ' ')) != NULL
)
726 ppd
->num_emulations
= count
;
727 ppd
->emulations
= calloc(sizeof(ppd_emul_t
), count
);
729 for (i
= 0, sptr
= string
; i
< count
; i
++)
731 for (nameptr
= ppd
->emulations
[i
].name
; *sptr
!= '\0' && *sptr
!= ' ';)
732 *nameptr
++ = *sptr
++;
740 else if (strncmp(keyword
, "StartEmulator_", 14) == 0)
744 for (i
= 0; i
< ppd
->num_emulations
; i
++)
745 if (strcmp(keyword
+ 14, ppd
->emulations
[i
].name
) == 0)
747 ppd
->emulations
[i
].start
= string
;
751 else if (strncmp(keyword
, "StopEmulator_", 13) == 0)
755 for (i
= 0; i
< ppd
->num_emulations
; i
++)
756 if (strcmp(keyword
+ 13, ppd
->emulations
[i
].name
) == 0)
758 ppd
->emulations
[i
].stop
= string
;
762 else if (strcmp(keyword
, "JobPatchFile") == 0)
764 if (ppd
->patches
== NULL
)
766 ppd
->patches
= string
;
771 ppd
->patches
= realloc(ppd
->patches
, strlen(ppd
->patches
) +
774 strcpy(ppd
->patches
+ strlen(ppd
->patches
), string
);
777 else if (strcmp(keyword
, "OpenUI") == 0)
780 * Add an option record to the current sub-group, group, or file...
784 strcpy(name
, name
+ 1);
792 if (subgroup
!= NULL
)
793 option
= ppd_get_option(subgroup
, name
);
794 else if (group
== NULL
)
796 if (strcmp(name
, "Collate") != 0 &&
797 strcmp(name
, "Duplex") != 0 &&
798 strcmp(name
, "InputSlot") != 0 &&
799 strcmp(name
, "ManualFeed") != 0 &&
800 strcmp(name
, "MediaType") != 0 &&
801 strcmp(name
, "MediaColor") != 0 &&
802 strcmp(name
, "MediaWeight") != 0 &&
803 strcmp(name
, "OutputBin") != 0 &&
804 strcmp(name
, "OutputMode") != 0 &&
805 strcmp(name
, "OutputOrder") != 0 &&
806 strcmp(name
, "PageSize") != 0 &&
807 strcmp(name
, "PageRegion") != 0)
808 group
= ppd_get_group(ppd
, cupsLangString(language
, CUPS_MSG_EXTRA
));
810 group
= ppd_get_group(ppd
, cupsLangString(language
, CUPS_MSG_GENERAL
));
819 option
= ppd_get_option(group
, name
);
823 option
= ppd_get_option(group
, name
);
833 * Now fill in the initial information for the option...
836 if (strcmp(string
, "PickMany") == 0)
837 option
->ui
= PPD_UI_PICKMANY
;
838 else if (strcmp(string
, "Boolean") == 0)
839 option
->ui
= PPD_UI_BOOLEAN
;
841 option
->ui
= PPD_UI_PICKONE
;
844 strcpy(option
->text
, text
);
847 if (strcmp(name
, "PageSize") == 0)
848 strcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SIZE
));
849 else if (strcmp(name
, "MediaType") == 0)
850 strcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_TYPE
));
851 else if (strcmp(name
, "InputSlot") == 0)
852 strcpy(option
->text
, cupsLangString(language
, CUPS_MSG_MEDIA_SOURCE
));
854 strcpy(option
->text
, name
);
857 option
->section
= PPD_ORDER_ANY
;
859 else if (strcmp(keyword
, "JCLOpenUI") == 0)
862 * Find the JCL group, and add if needed...
872 group
= ppd_get_group(ppd
, "JCL");
882 * Add an option record to the current JCLs...
886 strcpy(name
, name
+ 1);
888 option
= ppd_get_option(group
, name
);
898 * Now fill in the initial information for the option...
901 if (strcmp(string
, "PickMany") == 0)
902 option
->ui
= PPD_UI_PICKMANY
;
903 else if (strcmp(string
, "Boolean") == 0)
904 option
->ui
= PPD_UI_BOOLEAN
;
906 option
->ui
= PPD_UI_PICKONE
;
908 strcpy(option
->text
, text
);
910 option
->section
= PPD_ORDER_JCL
;
913 else if (strcmp(keyword
, "CloseUI") == 0 ||
914 strcmp(keyword
, "JCLCloseUI") == 0)
916 else if (strcmp(keyword
, "OpenGroup") == 0)
919 * Open a new group...
929 if (strchr(string
, '/') != NULL
) /* Just show human readable text */
930 strcpy(string
, strchr(string
, '/') + 1);
933 group
= ppd_get_group(ppd
, string
);
935 else if (strcmp(keyword
, "CloseGroup") == 0)
937 else if (strcmp(keyword
, "OpenSubGroup") == 0)
940 * Open a new sub-group...
943 if (group
== NULL
|| subgroup
!= NULL
)
950 if (group
->num_subgroups
== 0)
951 subgroup
= malloc(sizeof(ppd_group_t
));
953 subgroup
= realloc(group
->subgroups
,
954 (group
->num_subgroups
+ 1) * sizeof(ppd_group_t
));
956 if (subgroup
== NULL
)
963 group
->subgroups
= subgroup
;
964 subgroup
+= group
->num_subgroups
;
965 group
->num_subgroups
++;
967 memset(subgroup
, 0, sizeof(ppd_group_t
));
968 strcpy(subgroup
->text
, string
);
970 else if (strcmp(keyword
, "CloseSubGroup") == 0)
972 else if (strcmp(keyword
, "OrderDependency") == 0 ||
973 strcmp(keyword
, "NonUIOrderDependency") == 0)
975 if (sscanf(string
, "%f%s%s", &order
, name
, keyword
) != 3)
982 if (keyword
[0] == '*')
983 strcpy(keyword
, keyword
+ 1);
985 if (strcmp(name
, "ExitServer") == 0)
986 section
= PPD_ORDER_EXIT
;
987 else if (strcmp(name
, "Prolog") == 0)
988 section
= PPD_ORDER_PROLOG
;
989 else if (strcmp(name
, "DocumentSetup") == 0)
990 section
= PPD_ORDER_DOCUMENT
;
991 else if (strcmp(name
, "PageSetup") == 0)
992 section
= PPD_ORDER_PAGE
;
993 else if (strcmp(name
, "JCLSetup") == 0)
994 section
= PPD_ORDER_JCL
;
996 section
= PPD_ORDER_ANY
;
1001 * Only valid for Non-UI options...
1004 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
1005 if (group
->text
[0] == '\0')
1009 for (i
= 0; i
< group
->num_options
; i
++)
1010 if (strcmp(keyword
, group
->options
[i
].keyword
) == 0)
1012 group
->options
[i
].section
= section
;
1013 group
->options
[i
].order
= order
;
1021 option
->section
= section
;
1022 option
->order
= order
;
1025 else if (strncmp(keyword
, "Default", 7) == 0)
1027 if (strchr(string
, '/') != NULL
)
1028 *strchr(string
, '/') = '\0';
1033 * Only valid for Non-UI options...
1036 for (i
= ppd
->num_groups
, group
= ppd
->groups
; i
> 0; i
--, group
++)
1037 if (group
->text
[0] == '\0')
1041 for (i
= 0; i
< group
->num_options
; i
++)
1042 if (strcmp(keyword
, group
->options
[i
].keyword
) == 0)
1044 strcpy(group
->options
[i
].defchoice
, string
);
1051 strcpy(option
->defchoice
, string
);
1053 else if (strcmp(keyword
, "UIConstraints") == 0 ||
1054 strcmp(keyword
, "NonUIConstraints") == 0)
1056 if (ppd
->num_consts
== 0)
1057 constraint
= calloc(sizeof(ppd_const_t
), 1);
1059 constraint
= realloc(ppd
->consts
,
1060 (ppd
->num_consts
+ 1) * sizeof(ppd_const_t
));
1062 if (constraint
== NULL
)
1069 ppd
->consts
= constraint
;
1070 constraint
+= ppd
->num_consts
;
1073 switch (sscanf(string
, "%s%s%s%s", constraint
->option1
,
1074 constraint
->choice1
, constraint
->option2
,
1075 constraint
->choice2
))
1077 case 0 : /* Error */
1078 case 1 : /* Error */
1083 case 2 : /* Two options... */
1084 if (constraint
->option1
[0] == '*')
1085 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1087 if (constraint
->choice1
[0] == '*')
1088 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1090 strcpy(constraint
->option2
, constraint
->choice1
);
1092 constraint
->choice1
[0] = '\0';
1093 constraint
->choice2
[0] = '\0';
1096 case 3 : /* Two options, one choice... */
1097 if (constraint
->option1
[0] == '*')
1098 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1100 if (constraint
->choice1
[0] == '*')
1102 strcpy(constraint
->choice2
, constraint
->option2
);
1103 strcpy(constraint
->option2
, constraint
->choice1
+ 1);
1104 constraint
->choice1
[0] = '\0';
1108 if (constraint
->option2
[0] == '*')
1109 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1111 constraint
->choice2
[0] = '\0';
1115 case 4 : /* Two options, two choices... */
1116 if (constraint
->option1
[0] == '*')
1117 strcpy(constraint
->option1
, constraint
->option1
+ 1);
1119 if (constraint
->option2
[0] == '*')
1120 strcpy(constraint
->option2
, constraint
->option2
+ 1);
1124 else if (strcmp(keyword
, "PaperDimension") == 0)
1126 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1127 sscanf(string
, "%f%f", &(size
->width
), &(size
->length
));
1129 else if (strcmp(keyword
, "ImageableArea") == 0)
1131 if ((size
= ppdPageSize(ppd
, name
)) != NULL
)
1132 sscanf(string
, "%f%f%f%f", &(size
->left
), &(size
->bottom
),
1133 &(size
->right
), &(size
->top
));
1135 else if (option
!= NULL
&&
1136 (mask
& (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
)) ==
1137 (PPD_KEYWORD
| PPD_OPTION
| PPD_STRING
))
1139 if (strcmp(keyword
, "PageSize") == 0)
1142 * Add a page size...
1145 ppd_add_size(ppd
, name
);
1149 * Add the option choice...
1152 choice
= ppd_add_choice(option
, name
);
1154 if (mask
& PPD_TEXT
)
1155 strcpy(choice
->text
, text
);
1156 else if (strcmp(name
, "True") == 0)
1157 strcpy(choice
->text
, "Yes");
1158 else if (strcmp(name
, "False") == 0)
1159 strcpy(choice
->text
, "No");
1161 strcpy(choice
->text
, name
);
1163 if (strncmp(keyword
, "JCL", 3) == 0)
1164 ppd_decode(string
); /* Decode quoted string */
1166 choice
->code
= string
;
1167 string
= NULL
; /* Don't free this string below */
1176 printf("Premature EOF at %d...\n", ftell(fp
));
1180 * Set the option back-pointer for each choice...
1183 qsort(ppd
->groups
, ppd
->num_groups
, sizeof(ppd_group_t
),
1184 (int (*)(const void *, const void *))compare_groups
);
1186 for (i
= ppd
->num_groups
, group
= ppd
->groups
;
1190 qsort(group
->options
, group
->num_options
, sizeof(ppd_option_t
),
1191 (int (*)(const void *, const void *))compare_options
);
1193 for (j
= group
->num_options
, option
= group
->options
;
1197 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1198 (int (*)(const void *, const void *))compare_choices
);
1200 for (k
= 0; k
< option
->num_choices
; k
++)
1201 option
->choices
[k
].option
= (void *)option
;
1204 qsort(group
->subgroups
, group
->num_subgroups
, sizeof(ppd_group_t
),
1205 (int (*)(const void *, const void *))compare_groups
);
1207 for (j
= group
->num_subgroups
, subgroup
= group
->subgroups
;
1211 qsort(subgroup
->options
, subgroup
->num_options
, sizeof(ppd_option_t
),
1212 (int (*)(const void *, const void *))compare_options
);
1214 for (k
= group
->num_options
, option
= group
->options
;
1218 qsort(option
->choices
, option
->num_choices
, sizeof(ppd_choice_t
),
1219 (int (*)(const void *, const void *))compare_choices
);
1221 for (m
= 0; m
< option
->num_choices
; m
++)
1222 option
->choices
[m
].option
= (void *)option
;
1232 * 'ppdOpenFd()' - Read a PPD file into memory.
1235 ppd_file_t
* /* O - PPD file record */
1236 ppdOpenFd(int fd
) /* I - File to read from */
1238 FILE *fp
; /* File pointer */
1239 ppd_file_t
*ppd
; /* PPD file record */
1243 * Range check input...
1250 * Try to open the file and parse it...
1253 if ((fp
= fdopen(fd
, "r")) != NULL
)
1269 * 'ppdOpenFile()' - Read a PPD file into memory.
1272 ppd_file_t
* /* O - PPD file record */
1273 ppdOpenFile(char *filename
) /* I - File to read from */
1275 FILE *fp
; /* File pointer */
1276 ppd_file_t
*ppd
; /* PPD file record */
1280 * Range check input...
1283 if (filename
== NULL
)
1287 * Try to open the file and parse it...
1290 if ((fp
= fopen(filename
, "r")) != NULL
)
1304 * 'compare_strings()' - Compare two strings.
1307 int /* O - Result of comparison */
1308 compare_strings(char *s
, /* I - First string */
1309 char *t
) /* I - Second string */
1311 int diff
, /* Difference between digits */
1312 digits
; /* Number of digits */
1316 * Loop through both strings, returning only when a difference is
1317 * seen. Also, compare whole numbers rather than just characters, too!
1322 if (isdigit(*s
) && isdigit(*t
))
1325 * Got a number; start by skipping leading 0's...
1334 * Skip equal digits...
1337 while (isdigit(*s
) && *s
== *t
)
1344 * Bounce out if *s and *t aren't both digits...
1347 if (!isdigit(*s
) || !isdigit(*t
))
1356 * Figure out how many more digits there are...
1374 * Return if the number or value of the digits is different...
1379 else if (digits
> 0)
1384 else if (tolower(*s
) < tolower(*t
))
1386 else if (tolower(*s
) > tolower(*t
))
1396 * Return the results of the final comparison...
1409 * 'compare_groups()' - Compare two groups.
1412 static int /* O - Result of comparison */
1413 compare_groups(ppd_group_t
*g0
, /* I - First group */
1414 ppd_group_t
*g1
) /* I - Second group */
1416 return (compare_strings(g0
->text
, g1
->text
));
1421 * 'compare_options()' - Compare two options.
1424 static int /* O - Result of comparison */
1425 compare_options(ppd_option_t
*o0
,/* I - First option */
1426 ppd_option_t
*o1
)/* I - Second option */
1428 return (compare_strings(o0
->text
, o1
->text
));
1433 * 'compare_choices()' - Compare two choices.
1436 static int /* O - Result of comparison */
1437 compare_choices(ppd_choice_t
*c0
,/* I - First choice */
1438 ppd_choice_t
*c1
)/* I - Second choice */
1440 return (compare_strings(c0
->text
, c1
->text
));
1445 * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
1449 static int /* O - Bitmask of fields read */
1450 ppd_read(FILE *fp
, /* I - File to read from */
1451 char *keyword
, /* O - Keyword from line */
1452 char *option
, /* O - Option from line */
1453 char *text
, /* O - Human-readable text from line */
1454 char **string
) /* O - Code/string data */
1456 int ch
, /* Character from file */
1457 endquote
, /* Waiting for an end quote */
1458 mask
; /* Mask to be returned */
1459 char *keyptr
, /* Keyword pointer */
1460 *optptr
, /* Option pointer */
1461 *textptr
, /* Text pointer */
1462 *strptr
, /* Pointer into string */
1463 *lineptr
, /* Current position in line buffer */
1464 line
[262144]; /* Line buffer (256k) */
1468 * Range check everything...
1471 if (fp
== NULL
|| keyword
== NULL
|| option
== NULL
|| text
== NULL
||
1476 * Now loop until we have a valid line...
1488 while ((ch
= getc(fp
)) != EOF
&&
1489 (lineptr
- line
) < (sizeof(line
) - 1))
1491 if (ch
== '\r' || ch
== '\n')
1494 * Line feed or carriage return...
1497 if (lineptr
== line
) /* Skip blank lines */
1503 * Check for a trailing line feed...
1506 if ((ch
= getc(fp
)) == EOF
)
1514 if (!endquote
) /* Continue for multi-line text */
1520 * Any other character...
1526 endquote
= !endquote
;
1530 if (lineptr
> line
&& lineptr
[-1] == '\n')
1535 if (ch
== EOF
&& lineptr
== line
)
1550 if (line
[0] != '*') /* All lines start with an asterisk */
1553 if (strncmp(line
, "*%", 2) == 0 || /* Comment line */
1554 strncmp(line
, "*?", 2) == 0 || /* Query line */
1555 strcmp(line
, "*End") == 0) /* End of multi-line string */
1564 while (*lineptr
!= '\0' && *lineptr
!= ':' && !isspace(*lineptr
) &&
1565 (keyptr
- keyword
) < 40)
1566 *keyptr
++ = *lineptr
++;
1569 mask
|= PPD_KEYWORD
;
1571 if (*lineptr
== ' ' || *lineptr
== '\t')
1574 * Get an option name...
1577 while (*lineptr
== ' ' || *lineptr
== '\t')
1582 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1583 *lineptr
!= '/' && (optptr
- option
) < 40)
1584 *optptr
++ = *lineptr
++;
1589 if (*lineptr
== '/')
1592 * Get human-readable text...
1599 while (*lineptr
!= '\0' && *lineptr
!= '\n' && *lineptr
!= ':' &&
1600 (textptr
- text
) < 80)
1601 *textptr
++ = *lineptr
++;
1610 if (*lineptr
== ':')
1616 *string
= malloc(strlen(lineptr
) + 1);
1618 while (*lineptr
== ':' || isspace(*lineptr
))
1623 while (*lineptr
!= '\0')
1625 if (*lineptr
!= '\"')
1626 *strptr
++ = *lineptr
++;
1643 * 'ppd_decode()' - Decode a string value...
1647 ppd_decode(char *string
) /* I - String to decode */
1649 char *inptr
, /* Input pointer */
1650 *outptr
; /* Output pointer */
1656 while (*inptr
!= '\0')
1657 if (*inptr
== '<' && isxdigit(inptr
[1]))
1660 * Convert hex to 8-bit values...
1664 while (isxdigit(*inptr
))
1666 if (isalpha(*inptr
))
1667 *outptr
= (tolower(*inptr
) - 'a' + 10) << 4;
1669 *outptr
= (*inptr
- '0') << 4;
1673 if (isalpha(*inptr
))
1674 *outptr
|= tolower(*inptr
) - 'a' + 10;
1676 *outptr
|= *inptr
- '0';
1682 while (*inptr
!= '>' && *inptr
!= '\0')
1684 while (*inptr
== '>')
1688 *outptr
++ = *inptr
++;
1695 * End of "$Id: ppd.c,v 1.23 1999/06/15 21:27:09 mike Exp $".