]>
Commit | Line | Data |
---|---|---|
90a24de4 | 1 | /* |
1fcd229c | 2 | * "$Id: ppd.c,v 1.51.2.1 2001/04/11 00:24:11 mike Exp $" |
90a24de4 | 3 | * |
3a193f5e | 4 | * PPD file routines for the Common UNIX Printing System (CUPS). |
90a24de4 | 5 | * |
d2935a0f | 6 | * Copyright 1997-2001 by Easy Software Products, all rights reserved. |
90a24de4 | 7 | * |
3a193f5e | 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 | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
90a24de4 | 16 | * Easy Software Products |
58ec2a95 | 17 | * 44141 Airport View Drive, Suite 204 |
90a24de4 | 18 | * Hollywood, Maryland 20636-3111 USA |
19 | * | |
20 | * Voice: (301) 373-9603 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
2b85e375 | 24 | * PostScript is a trademark of Adobe Systems, Inc. |
25 | * | |
b87e43e9 | 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 | |
31 | * agreement. | |
32 | * | |
90a24de4 | 33 | * Contents: |
34 | * | |
2b85e375 | 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 | |
42 | * as necessary. | |
15166848 | 43 | * compare_strings() - Compare two strings. |
caab0820 | 44 | * compare_groups() - Compare two groups. |
45 | * compare_options() - Compare two options. | |
46 | * compare_choices() - Compare two choices. | |
90a24de4 | 47 | */ |
48 | ||
49 | /* | |
50 | * Include necessary headers. | |
51 | */ | |
52 | ||
2b85e375 | 53 | #include "ppd.h" |
3b960317 | 54 | #include <stdlib.h> |
2456b740 | 55 | #include <ctype.h> |
3b960317 | 56 | #include "string.h" |
11b9b0d7 | 57 | #include "language.h" |
58 | #include "debug.h" | |
2b85e375 | 59 | |
60 | ||
61 | /* | |
62 | * Definitions... | |
63 | */ | |
64 | ||
3b960317 | 65 | #if defined(WIN32) || defined(__EMX__) |
2b85e375 | 66 | # define READ_BINARY "rb" /* Open a binary file for reading */ |
67 | # define WRITE_BINARY "wb" /* Open a binary file for writing */ | |
68 | #else | |
69 | # define READ_BINARY "r" /* Open a binary file for reading */ | |
70 | # define WRITE_BINARY "w" /* Open a binary file for writing */ | |
3b960317 | 71 | #endif /* WIN32 || __EMX__ */ |
2b85e375 | 72 | |
08b247a9 | 73 | #define safe_free(p) if (p) free(p) /* Safe free macro */ |
74 | ||
2b85e375 | 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 */ | |
554fab97 | 79 | |
2b85e375 | 80 | |
81 | /* | |
82 | * Local functions... | |
83 | */ | |
84 | ||
15166848 | 85 | static int compare_strings(char *s, char *t); |
caab0820 | 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); | |
6fdf969a | 89 | static int ppd_read(FILE *fp, char *keyword, char *option, |
d23a857a | 90 | char *text, char **string); |
91 | static void ppd_decode(char *string); | |
2685c8f0 | 92 | static void ppd_fix(char *string); |
6fdf969a | 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); | |
2b85e375 | 98 | |
99 | ||
100 | /* | |
101 | * 'ppdClose()' - Free all memory used by the PPD file. | |
102 | */ | |
103 | ||
104 | void | |
105 | ppdClose(ppd_file_t *ppd) /* I - PPD file record */ | |
106 | { | |
107 | int i; /* Looping var */ | |
108 | ppd_emul_t *emul; /* Current emulation */ | |
109 | ppd_group_t *group; /* Current group */ | |
2b85e375 | 110 | char **font; /* Current font */ |
04de52f8 | 111 | char **filter; /* Current filter */ |
2b85e375 | 112 | |
113 | ||
114 | /* | |
115 | * Range check the PPD file record... | |
116 | */ | |
117 | ||
118 | if (ppd == NULL) | |
119 | return; | |
120 | ||
121 | /* | |
122 | * Free all strings at the top level... | |
123 | */ | |
124 | ||
04de52f8 | 125 | safe_free(ppd->patches); |
126 | safe_free(ppd->jcl_begin); | |
127 | safe_free(ppd->jcl_ps); | |
128 | safe_free(ppd->jcl_end); | |
08b247a9 | 129 | safe_free(ppd->lang_encoding); |
130 | safe_free(ppd->lang_version); | |
131 | safe_free(ppd->modelname); | |
132 | safe_free(ppd->ttrasterizer); | |
133 | safe_free(ppd->manufacturer); | |
134 | safe_free(ppd->product); | |
135 | safe_free(ppd->nickname); | |
136 | safe_free(ppd->shortnickname); | |
2b85e375 | 137 | |
138 | /* | |
139 | * Free any emulations... | |
140 | */ | |
141 | ||
142 | if (ppd->num_emulations > 0) | |
143 | { | |
144 | for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++) | |
145 | { | |
08b247a9 | 146 | safe_free(emul->start); |
147 | safe_free(emul->stop); | |
e8fda7b9 | 148 | } |
2b85e375 | 149 | |
08b247a9 | 150 | safe_free(ppd->emulations); |
e8fda7b9 | 151 | } |
2b85e375 | 152 | |
2b85e375 | 153 | /* |
154 | * Free any UI groups, subgroups, and options... | |
155 | */ | |
156 | ||
157 | if (ppd->num_groups > 0) | |
158 | { | |
159 | for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) | |
160 | ppd_free_group(group); | |
161 | ||
08b247a9 | 162 | safe_free(ppd->groups); |
e8fda7b9 | 163 | } |
2b85e375 | 164 | |
2b85e375 | 165 | /* |
166 | * Free any page sizes... | |
167 | */ | |
168 | ||
169 | if (ppd->num_sizes > 0) | |
08b247a9 | 170 | safe_free(ppd->sizes); |
2b85e375 | 171 | |
172 | /* | |
173 | * Free any constraints... | |
174 | */ | |
175 | ||
176 | if (ppd->num_consts > 0) | |
08b247a9 | 177 | safe_free(ppd->consts); |
2b85e375 | 178 | |
04de52f8 | 179 | /* |
180 | * Free any filters... | |
181 | */ | |
182 | ||
183 | if (ppd->num_filters > 0) | |
184 | { | |
185 | for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++) | |
186 | safe_free(*filter); | |
187 | ||
188 | safe_free(ppd->filters); | |
189 | } | |
190 | ||
2b85e375 | 191 | /* |
192 | * Free any fonts... | |
193 | */ | |
194 | ||
195 | if (ppd->num_fonts > 0) | |
196 | { | |
197 | for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++) | |
08b247a9 | 198 | safe_free(*font); |
2b85e375 | 199 | |
08b247a9 | 200 | safe_free(ppd->fonts); |
e8fda7b9 | 201 | } |
2b85e375 | 202 | |
b87e43e9 | 203 | /* |
204 | * Free any profiles... | |
205 | */ | |
206 | ||
207 | if (ppd->num_profiles > 0) | |
08b247a9 | 208 | safe_free(ppd->profiles); |
b87e43e9 | 209 | |
2b85e375 | 210 | /* |
211 | * Free the whole record... | |
212 | */ | |
213 | ||
08b247a9 | 214 | safe_free(ppd); |
2b85e375 | 215 | } |
216 | ||
217 | ||
218 | /* | |
219 | * 'ppd_free_group()' - Free a single UI group. | |
220 | */ | |
221 | ||
222 | static void | |
223 | ppd_free_group(ppd_group_t *group) /* I - Group to free */ | |
224 | { | |
225 | int i; /* Looping var */ | |
226 | ppd_option_t *option; /* Current option */ | |
227 | ppd_group_t *subgroup; /* Current sub-group */ | |
228 | ||
229 | ||
230 | if (group->num_options > 0) | |
231 | { | |
232 | for (i = group->num_options, option = group->options; | |
233 | i > 0; | |
234 | i --, option ++) | |
235 | ppd_free_option(option); | |
236 | ||
08b247a9 | 237 | safe_free(group->options); |
e8fda7b9 | 238 | } |
2b85e375 | 239 | |
240 | if (group->num_subgroups > 0) | |
241 | { | |
242 | for (i = group->num_subgroups, subgroup = group->subgroups; | |
243 | i > 0; | |
244 | i --, subgroup ++) | |
245 | ppd_free_group(subgroup); | |
246 | ||
08b247a9 | 247 | safe_free(group->subgroups); |
e8fda7b9 | 248 | } |
2b85e375 | 249 | } |
250 | ||
251 | ||
252 | /* | |
253 | * 'ppd_free_option()' - Free a single option. | |
254 | */ | |
255 | ||
256 | static void | |
257 | ppd_free_option(ppd_option_t *option) /* I - Option to free */ | |
258 | { | |
259 | int i; /* Looping var */ | |
260 | ppd_choice_t *choice; /* Current choice */ | |
261 | ||
262 | ||
263 | if (option->num_choices > 0) | |
264 | { | |
265 | for (i = option->num_choices, choice = option->choices; | |
266 | i > 0; | |
267 | i --, choice ++) | |
08b247a9 | 268 | safe_free(choice->code); |
2b85e375 | 269 | |
08b247a9 | 270 | safe_free(option->choices); |
e8fda7b9 | 271 | } |
2b85e375 | 272 | } |
273 | ||
274 | ||
6fdf969a | 275 | /* |
276 | * 'ppd_get_group()' - Find or create the named group as needed. | |
277 | */ | |
278 | ||
279 | static ppd_group_t * /* O - Named group */ | |
280 | ppd_get_group(ppd_file_t *ppd, /* I - PPD file */ | |
281 | char *name) /* I - Name of group */ | |
282 | { | |
283 | int i; /* Looping var */ | |
284 | ppd_group_t *group; /* Group */ | |
285 | ||
286 | ||
287 | for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) | |
d23a857a | 288 | if (strcmp(group->text, name) == 0) |
6fdf969a | 289 | break; |
290 | ||
291 | if (i == 0) | |
292 | { | |
293 | if (ppd->num_groups == 0) | |
294 | group = malloc(sizeof(ppd_group_t)); | |
295 | else | |
296 | group = realloc(ppd->groups, | |
297 | (ppd->num_groups + 1) * sizeof(ppd_group_t)); | |
298 | ||
299 | if (group == NULL) | |
300 | return (NULL); | |
301 | ||
302 | ppd->groups = group; | |
303 | group += ppd->num_groups; | |
304 | ppd->num_groups ++; | |
305 | ||
306 | memset(group, 0, sizeof(ppd_group_t)); | |
fafbba4f | 307 | strncpy(group->text, name, sizeof(group->text) - 1); |
6fdf969a | 308 | } |
309 | ||
310 | return (group); | |
311 | } | |
312 | ||
313 | ||
314 | /* | |
315 | * 'ppd_get_option()' - Find or create the named option as needed. | |
316 | */ | |
317 | ||
318 | static ppd_option_t * /* O - Named option */ | |
319 | ppd_get_option(ppd_group_t *group, /* I - Group */ | |
320 | char *name) /* I - Name of option */ | |
321 | { | |
322 | int i; /* Looping var */ | |
323 | ppd_option_t *option; /* Option */ | |
324 | ||
325 | ||
326 | for (i = group->num_options, option = group->options; i > 0; i --, option ++) | |
327 | if (strcmp(option->keyword, name) == 0) | |
328 | break; | |
329 | ||
330 | if (i == 0) | |
331 | { | |
332 | if (group->num_options == 0) | |
333 | option = malloc(sizeof(ppd_option_t)); | |
334 | else | |
335 | option = realloc(group->options, | |
336 | (group->num_options + 1) * sizeof(ppd_option_t)); | |
337 | ||
338 | if (option == NULL) | |
339 | return (NULL); | |
340 | ||
341 | group->options = option; | |
342 | option += group->num_options; | |
343 | group->num_options ++; | |
344 | ||
345 | memset(option, 0, sizeof(ppd_option_t)); | |
fafbba4f | 346 | strncpy(option->keyword, name, sizeof(option->keyword) - 1); |
6fdf969a | 347 | } |
348 | ||
349 | return (option); | |
350 | } | |
351 | ||
352 | ||
353 | /* | |
354 | * 'ppd_add_choice()' - Add a choice to an option. | |
355 | */ | |
356 | ||
357 | static ppd_choice_t * /* O - Named choice */ | |
358 | ppd_add_choice(ppd_option_t *option, /* I - Option */ | |
359 | char *name) /* I - Name of choice */ | |
360 | { | |
361 | ppd_choice_t *choice; /* Choice */ | |
362 | ||
363 | ||
364 | if (option->num_choices == 0) | |
365 | choice = malloc(sizeof(ppd_choice_t)); | |
366 | else | |
367 | choice = realloc(option->choices, | |
368 | sizeof(ppd_choice_t) * (option->num_choices + 1)); | |
369 | ||
370 | if (choice == NULL) | |
371 | return (NULL); | |
372 | ||
373 | option->choices = choice; | |
374 | choice += option->num_choices; | |
375 | option->num_choices ++; | |
376 | ||
377 | memset(choice, 0, sizeof(ppd_choice_t)); | |
fafbba4f | 378 | strncpy(choice->choice, name, sizeof(choice->choice) - 1); |
6fdf969a | 379 | |
380 | return (choice); | |
381 | } | |
382 | ||
383 | ||
384 | /* | |
385 | * 'ppd_add_size()' - Add a page size. | |
386 | */ | |
387 | ||
388 | static ppd_size_t * /* O - Named size */ | |
389 | ppd_add_size(ppd_file_t *ppd, /* I - PPD file */ | |
390 | char *name) /* I - Name of size */ | |
391 | { | |
392 | ppd_size_t *size; /* Size */ | |
393 | ||
394 | ||
395 | if (ppd->num_sizes == 0) | |
396 | size = malloc(sizeof(ppd_size_t)); | |
397 | else | |
398 | size = realloc(ppd->sizes, sizeof(ppd_size_t) * (ppd->num_sizes + 1)); | |
399 | ||
400 | if (size == NULL) | |
401 | return (NULL); | |
402 | ||
403 | ppd->sizes = size; | |
404 | size += ppd->num_sizes; | |
405 | ppd->num_sizes ++; | |
406 | ||
407 | memset(size, 0, sizeof(ppd_size_t)); | |
fafbba4f | 408 | strncpy(size->name, name, sizeof(size->name) - 1); |
6fdf969a | 409 | |
410 | return (size); | |
411 | } | |
412 | ||
413 | ||
2b85e375 | 414 | /* |
415 | * 'ppdOpen()' - Read a PPD file into memory. | |
416 | */ | |
417 | ||
418 | ppd_file_t * /* O - PPD file record */ | |
419 | ppdOpen(FILE *fp) /* I - File to read from */ | |
420 | { | |
58ec2a95 | 421 | int i, j, k, m; /* Looping vars */ |
8c1333e2 | 422 | int count; /* Temporary count */ |
2b85e375 | 423 | ppd_file_t *ppd; /* PPD file record */ |
424 | ppd_group_t *group, /* Current group */ | |
425 | *subgroup; /* Current sub-group */ | |
426 | ppd_option_t *option; /* Current option */ | |
427 | ppd_choice_t *choice; /* Current choice */ | |
428 | ppd_const_t *constraint; /* Current constraint */ | |
429 | ppd_size_t *size; /* Current page size */ | |
430 | int mask; /* Line data mask */ | |
d2e58bfa | 431 | char keyword[PPD_MAX_NAME], |
432 | /* Keyword from file */ | |
433 | name[PPD_MAX_NAME], | |
434 | /* Option from file */ | |
435 | text[PPD_MAX_TEXT], | |
436 | /* Human-readable text from file */ | |
d23a857a | 437 | *string, /* Code/text from file */ |
438 | *sptr, /* Pointer into string */ | |
0819478b | 439 | *nameptr, /* Pointer into name */ |
440 | *temp, /* Temporary string pointer */ | |
441 | **tempfonts; /* Temporary fonts pointer */ | |
2b85e375 | 442 | float order; /* Order dependency number */ |
443 | ppd_section_t section; /* Order dependency section */ | |
b87e43e9 | 444 | ppd_profile_t *profile; /* Pointer to color profile */ |
c493465a | 445 | char **filter; /* Pointer to filter */ |
11b9b0d7 | 446 | cups_lang_t *language; /* Default language */ |
2b85e375 | 447 | |
448 | ||
11b9b0d7 | 449 | /* |
450 | * Get the default language for the user... | |
451 | */ | |
452 | ||
453 | language = cupsLangDefault(); | |
454 | ||
2b85e375 | 455 | /* |
456 | * Range check input... | |
457 | */ | |
458 | ||
459 | if (fp == NULL) | |
460 | return (NULL); | |
461 | ||
462 | /* | |
463 | * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'... | |
464 | */ | |
465 | ||
554fab97 | 466 | mask = ppd_read(fp, keyword, name, text, &string); |
2b85e375 | 467 | |
468 | if (mask == 0 || | |
469 | strcmp(keyword, "PPD-Adobe") != 0 || | |
470 | string == NULL || string[0] != '4') | |
471 | { | |
472 | /* | |
473 | * Either this is not a PPD file, or it is not a 4.x PPD file. | |
474 | */ | |
475 | ||
08b247a9 | 476 | safe_free(string); |
2b85e375 | 477 | |
478 | return (NULL); | |
e8fda7b9 | 479 | } |
2b85e375 | 480 | |
923e8756 | 481 | DEBUG_printf(("ppdOpen: keyword = %s, string = %08x\n", keyword, string)); |
482 | ||
08b247a9 | 483 | safe_free(string); |
2b85e375 | 484 | |
485 | /* | |
486 | * Allocate memory for the PPD file record... | |
487 | */ | |
488 | ||
489 | if ((ppd = calloc(sizeof(ppd_file_t), 1)) == NULL) | |
490 | return (NULL); | |
491 | ||
492 | ppd->language_level = 1; | |
493 | ppd->color_device = 0; | |
494 | ppd->colorspace = PPD_CS_GRAY; | |
495 | ppd->landscape = 90; | |
496 | ||
497 | /* | |
498 | * Read lines from the PPD file and add them to the file record... | |
499 | */ | |
500 | ||
501 | group = NULL; | |
502 | subgroup = NULL; | |
503 | option = NULL; | |
504 | choice = NULL; | |
505 | ||
554fab97 | 506 | while ((mask = ppd_read(fp, keyword, name, text, &string)) != 0) |
2b85e375 | 507 | { |
508 | #ifdef DEBUG | |
509 | printf("mask = %x, keyword = \"%s\"", mask, keyword); | |
510 | ||
511 | if (name[0] != '\0') | |
512 | printf(", name = \"%s\"", name); | |
513 | ||
514 | if (text[0] != '\0') | |
515 | printf(", text = \"%s\"", text); | |
516 | ||
517 | if (string != NULL) | |
518 | { | |
d23a857a | 519 | if (strlen(string) > 40) |
2b85e375 | 520 | printf(", string = %08x", string); |
521 | else | |
522 | printf(", string = \"%s\"", string); | |
e8fda7b9 | 523 | } |
2b85e375 | 524 | |
525 | puts(""); | |
526 | #endif /* DEBUG */ | |
527 | ||
528 | if (strcmp(keyword, "LanguageLevel") == 0) | |
d23a857a | 529 | ppd->language_level = atoi(string); |
2b85e375 | 530 | else if (strcmp(keyword, "LanguageEncoding") == 0) |
531 | { | |
d23a857a | 532 | ppd->lang_encoding = string; |
2b85e375 | 533 | string = NULL; /* Don't free this string below */ |
534 | } | |
535 | else if (strcmp(keyword, "LanguageVersion") == 0) | |
536 | { | |
d23a857a | 537 | ppd->lang_version = string; |
2b85e375 | 538 | string = NULL; /* Don't free this string below */ |
539 | } | |
540 | else if (strcmp(keyword, "Manufacturer") == 0) | |
541 | { | |
542 | ppd->manufacturer = string; | |
543 | string = NULL; /* Don't free this string below */ | |
544 | } | |
545 | else if (strcmp(keyword, "ModelName") == 0) | |
546 | { | |
d23a857a | 547 | ppd->modelname = string; |
2b85e375 | 548 | string = NULL; /* Don't free this string below */ |
549 | } | |
1fcd229c | 550 | else if (strcmp(keyword, "PCFileName") == 0) |
551 | { | |
552 | ppd->pcfilename = string; | |
553 | string = NULL; /* Don't free this string below */ | |
554 | } | |
2b85e375 | 555 | else if (strcmp(keyword, "NickName") == 0) |
556 | { | |
557 | ppd->nickname = string; | |
558 | string = NULL; /* Don't free this string below */ | |
559 | } | |
560 | else if (strcmp(keyword, "Product") == 0) | |
561 | { | |
562 | ppd->product = string; | |
563 | string = NULL; /* Don't free this string below */ | |
564 | } | |
565 | else if (strcmp(keyword, "ShortNickName") == 0) | |
566 | { | |
567 | ppd->shortnickname = string; | |
568 | string = NULL; /* Don't free this string below */ | |
569 | } | |
570 | else if (strcmp(keyword, "TTRasterizer") == 0) | |
571 | { | |
d23a857a | 572 | ppd->ttrasterizer = string; |
2b85e375 | 573 | string = NULL; /* Don't free this string below */ |
574 | } | |
575 | else if (strcmp(keyword, "JCLBegin") == 0) | |
576 | { | |
577 | ppd_decode(string); /* Decode quoted string */ | |
578 | ppd->jcl_begin = string; | |
579 | string = NULL; /* Don't free this string below */ | |
580 | } | |
581 | else if (strcmp(keyword, "JCLEnd") == 0) | |
582 | { | |
583 | ppd_decode(string); /* Decode quoted string */ | |
584 | ppd->jcl_end = string; | |
585 | string = NULL; /* Don't free this string below */ | |
586 | } | |
587 | else if (strcmp(keyword, "JCLToPSInterpreter") == 0) | |
588 | { | |
589 | ppd_decode(string); /* Decode quoted string */ | |
590 | ppd->jcl_ps = string; | |
591 | string = NULL; /* Don't free this string below */ | |
592 | } | |
593 | else if (strcmp(keyword, "AccurateScreensSupport") == 0) | |
d23a857a | 594 | ppd->accurate_screens = strcmp(string, "True") == 0; |
2b85e375 | 595 | else if (strcmp(keyword, "ColorDevice") == 0) |
d23a857a | 596 | ppd->color_device = strcmp(string, "True") == 0; |
2b85e375 | 597 | else if (strcmp(keyword, "ContoneOnly") == 0) |
d23a857a | 598 | ppd->contone_only = strcmp(string, "True") == 0; |
2b85e375 | 599 | else if (strcmp(keyword, "DefaultColorSpace") == 0) |
600 | { | |
d23a857a | 601 | if (strcmp(string, "CMY") == 0) |
2b85e375 | 602 | ppd->colorspace = PPD_CS_CMY; |
d23a857a | 603 | else if (strcmp(string, "CMYK") == 0) |
2b85e375 | 604 | ppd->colorspace = PPD_CS_CMYK; |
d23a857a | 605 | else if (strcmp(string, "RGB") == 0) |
2b85e375 | 606 | ppd->colorspace = PPD_CS_RGB; |
d23a857a | 607 | else if (strcmp(string, "RGBK") == 0) |
58ec2a95 | 608 | ppd->colorspace = PPD_CS_RGBK; |
d23a857a | 609 | else if (strcmp(string, "N") == 0) |
58ec2a95 | 610 | ppd->colorspace = PPD_CS_N; |
2b85e375 | 611 | else |
612 | ppd->colorspace = PPD_CS_GRAY; | |
613 | } | |
632d3147 | 614 | else if (strcmp(keyword, "cupsFlipDuplex") == 0) |
615 | ppd->flip_duplex = strcmp(string, "True") == 0; | |
991a5d0d | 616 | else if (strcmp(keyword, "cupsManualCopies") == 0) |
d23a857a | 617 | ppd->manual_copies = strcmp(string, "True") == 0; |
991a5d0d | 618 | else if (strcmp(keyword, "cupsModelNumber") == 0) |
d23a857a | 619 | ppd->model_number = atoi(string); |
991a5d0d | 620 | else if (strcmp(keyword, "cupsColorProfile") == 0) |
b87e43e9 | 621 | { |
622 | if (ppd->num_profiles == 0) | |
623 | profile = malloc(sizeof(ppd_profile_t)); | |
624 | else | |
625 | profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * | |
626 | (ppd->num_profiles + 1)); | |
627 | ||
628 | ppd->profiles = profile; | |
629 | profile += ppd->num_profiles; | |
630 | ppd->num_profiles ++; | |
631 | ||
632 | memset(profile, 0, sizeof(ppd_profile_t)); | |
fafbba4f | 633 | strncpy(profile->resolution, name, sizeof(profile->resolution) - 1); |
634 | strncpy(profile->media_type, text, sizeof(profile->media_type) - 1); | |
af22b1d1 | 635 | sscanf(string, "%f%f%f%f%f%f%f%f%f%f%f", &(profile->density), |
636 | &(profile->gamma), | |
b87e43e9 | 637 | profile->matrix[0] + 0, profile->matrix[0] + 1, |
638 | profile->matrix[0] + 2, profile->matrix[1] + 0, | |
639 | profile->matrix[1] + 1, profile->matrix[1] + 2, | |
640 | profile->matrix[2] + 0, profile->matrix[2] + 1, | |
641 | profile->matrix[2] + 2); | |
642 | } | |
c493465a | 643 | else if (strcmp(keyword, "cupsFilter") == 0) |
644 | { | |
645 | if (ppd->num_filters == 0) | |
646 | filter = malloc(sizeof(char *)); | |
647 | else | |
648 | filter = realloc(ppd->filters, sizeof(char *) * (ppd->num_filters + 1)); | |
649 | ||
0819478b | 650 | if (filter == NULL) |
651 | { | |
652 | safe_free(filter); | |
653 | ppdClose(ppd); | |
654 | return (NULL); | |
655 | } | |
656 | ||
c493465a | 657 | ppd->filters = filter; |
658 | filter += ppd->num_filters; | |
659 | ppd->num_filters ++; | |
660 | ||
661 | /* | |
662 | * Copy filter string and prevent it from being freed below... | |
663 | */ | |
664 | ||
665 | *filter = string; | |
666 | string = NULL; | |
667 | } | |
7ebf3a09 | 668 | else if (strcmp(keyword, "Throughput") == 0) |
669 | ppd->throughput = atoi(string); | |
b03923b8 | 670 | else if (strcmp(keyword, "Font") == 0) |
671 | { | |
672 | /* | |
673 | * Add this font to the list of available fonts... | |
674 | */ | |
675 | ||
676 | if (ppd->num_fonts == 0) | |
0819478b | 677 | tempfonts = (char **)malloc(sizeof(char *)); |
b03923b8 | 678 | else |
0819478b | 679 | tempfonts = (char **)realloc(ppd->fonts, |
680 | sizeof(char *) * (ppd->num_fonts + 1)); | |
b03923b8 | 681 | |
0819478b | 682 | if (tempfonts == NULL) |
b03923b8 | 683 | { |
0819478b | 684 | safe_free(string); |
b03923b8 | 685 | ppdClose(ppd); |
686 | return (NULL); | |
687 | } | |
0819478b | 688 | |
689 | ppd->fonts = tempfonts; | |
26e73a82 | 690 | ppd->fonts[ppd->num_fonts] = strdup(name); |
b03923b8 | 691 | ppd->num_fonts ++; |
b03923b8 | 692 | } |
6fdf969a | 693 | else if (strcmp(keyword, "VariablePaperSize") == 0 && |
d1f2b9fe | 694 | strcmp(string, "True") == 0 && |
695 | !ppd->variable_sizes) | |
6fdf969a | 696 | { |
697 | ppd->variable_sizes = 1; | |
698 | ||
699 | /* | |
700 | * Add a "Custom" page size entry... | |
701 | */ | |
702 | ||
703 | ppd_add_size(ppd, "Custom"); | |
704 | ||
705 | /* | |
706 | * Add a "Custom" page size option... | |
707 | */ | |
708 | ||
7d75b814 | 709 | if ((option = ppdFindOption(ppd, "PageSize")) == NULL) |
6fdf969a | 710 | { |
7d75b814 | 711 | ppd_group_t *temp; |
6fdf969a | 712 | |
7d75b814 | 713 | |
714 | if ((temp = ppd_get_group(ppd, | |
715 | cupsLangString(language, | |
716 | CUPS_MSG_GENERAL))) == NULL) | |
717 | { | |
718 | ppdClose(ppd); | |
719 | safe_free(string); | |
720 | return (NULL); | |
721 | } | |
722 | ||
723 | if ((option = ppd_get_option(temp, "PageSize")) == NULL) | |
724 | { | |
725 | ppdClose(ppd); | |
726 | safe_free(string); | |
727 | return (NULL); | |
728 | } | |
6fdf969a | 729 | } |
730 | ||
731 | if ((choice = ppd_add_choice(option, "Custom")) == NULL) | |
732 | { | |
733 | ppdClose(ppd); | |
08b247a9 | 734 | safe_free(string); |
6fdf969a | 735 | return (NULL); |
736 | } | |
737 | ||
fafbba4f | 738 | strncpy(choice->text, cupsLangString(language, CUPS_MSG_VARIABLE), |
739 | sizeof(choice->text) - 1); | |
6fdf969a | 740 | option = NULL; |
741 | } | |
742 | else if (strcmp(keyword, "MaxMediaWidth") == 0) | |
977acbd3 | 743 | ppd->custom_max[0] = (float)atof(string); |
6fdf969a | 744 | else if (strcmp(keyword, "MaxMediaHeight") == 0) |
977acbd3 | 745 | ppd->custom_max[1] = (float)atof(string); |
6fdf969a | 746 | else if (strcmp(keyword, "ParamCustomPageSize") == 0) |
747 | { | |
748 | if (strcmp(name, "Width") == 0) | |
d23a857a | 749 | sscanf(string, "%*s%*s%f%f", ppd->custom_min + 0, |
6fdf969a | 750 | ppd->custom_max + 0); |
751 | else if (strcmp(name, "Height") == 0) | |
d23a857a | 752 | sscanf(string, "%*s%*s%f%f", ppd->custom_min + 1, |
6fdf969a | 753 | ppd->custom_max + 1); |
754 | } | |
755 | else if (strcmp(keyword, "HWMargins") == 0) | |
d23a857a | 756 | sscanf(string, "%f%f%f%f", ppd->custom_margins + 0, |
6fdf969a | 757 | ppd->custom_margins + 1, ppd->custom_margins + 2, |
758 | ppd->custom_margins + 3); | |
759 | else if (strcmp(keyword, "CustomPageSize") == 0 && | |
d1f2b9fe | 760 | strcmp(name, "True") == 0) |
6fdf969a | 761 | { |
d1f2b9fe | 762 | if (!ppd->variable_sizes) |
763 | { | |
764 | ppd->variable_sizes = 1; | |
765 | ||
766 | /* | |
767 | * Add a "Custom" page size entry... | |
768 | */ | |
769 | ||
770 | ppd_add_size(ppd, "Custom"); | |
771 | ||
772 | /* | |
773 | * Add a "Custom" page size option... | |
774 | */ | |
775 | ||
7d75b814 | 776 | if ((option = ppdFindOption(ppd, "PageSize")) == NULL) |
d1f2b9fe | 777 | { |
7d75b814 | 778 | ppd_group_t *temp; |
779 | ||
780 | ||
781 | if ((temp = ppd_get_group(ppd, | |
782 | cupsLangString(language, | |
783 | CUPS_MSG_GENERAL))) == NULL) | |
784 | { | |
785 | DEBUG_puts("Unable to get general group!"); | |
786 | ppdClose(ppd); | |
787 | safe_free(string); | |
788 | return (NULL); | |
789 | } | |
790 | ||
791 | if ((option = ppd_get_option(temp, "PageSize")) == NULL) | |
792 | { | |
793 | DEBUG_puts("Unable to get PageSize option!"); | |
794 | ppdClose(ppd); | |
795 | safe_free(string); | |
796 | return (NULL); | |
797 | } | |
798 | } | |
d1f2b9fe | 799 | |
800 | if ((choice = ppd_add_choice(option, "Custom")) == NULL) | |
801 | { | |
7d75b814 | 802 | DEBUG_puts("Unable to add Custom choice!"); |
d1f2b9fe | 803 | ppdClose(ppd); |
804 | safe_free(string); | |
805 | return (NULL); | |
806 | } | |
807 | ||
808 | strncpy(choice->text, cupsLangString(language, CUPS_MSG_VARIABLE), | |
809 | sizeof(choice->text) - 1); | |
d1f2b9fe | 810 | option = NULL; |
811 | } | |
812 | ||
6fdf969a | 813 | if ((option = ppdFindOption(ppd, "PageSize")) == NULL) |
814 | { | |
7d75b814 | 815 | DEBUG_puts("Unable to find PageSize option!"); |
627c58f3 | 816 | ppdClose(ppd); |
08b247a9 | 817 | safe_free(string); |
6fdf969a | 818 | return (NULL); |
819 | } | |
820 | ||
821 | if ((choice = ppdFindChoice(option, "Custom")) == NULL) | |
822 | { | |
7d75b814 | 823 | DEBUG_puts("Unable to find Custom choice!"); |
6fdf969a | 824 | ppdClose(ppd); |
08b247a9 | 825 | safe_free(string); |
6fdf969a | 826 | return (NULL); |
827 | } | |
828 | ||
829 | choice->code = string; | |
830 | string = NULL; | |
831 | option = NULL; | |
832 | } | |
2b85e375 | 833 | else if (strcmp(keyword, "LandscapeOrientation") == 0) |
834 | { | |
d23a857a | 835 | if (strcmp(string, "Minus90") == 0) |
2b85e375 | 836 | ppd->landscape = -90; |
837 | else | |
838 | ppd->landscape = 90; | |
839 | } | |
8c1333e2 | 840 | else if (strcmp(keyword, "Emulators") == 0) |
841 | { | |
d23a857a | 842 | for (count = 1, sptr = string; sptr != NULL;) |
8c1333e2 | 843 | if ((sptr = strchr(sptr, ' ')) != NULL) |
844 | { | |
845 | count ++; | |
846 | while (*sptr == ' ') | |
847 | sptr ++; | |
e8fda7b9 | 848 | } |
8c1333e2 | 849 | |
850 | ppd->num_emulations = count; | |
851 | ppd->emulations = calloc(sizeof(ppd_emul_t), count); | |
852 | ||
d23a857a | 853 | for (i = 0, sptr = string; i < count; i ++) |
8c1333e2 | 854 | { |
d2e58bfa | 855 | for (nameptr = ppd->emulations[i].name; |
856 | *sptr != '\0' && *sptr != ' '; | |
857 | sptr ++) | |
858 | if (nameptr < (ppd->emulations[i].name + sizeof(ppd->emulations[i].name) - 1)) | |
859 | *nameptr++ = *sptr; | |
8c1333e2 | 860 | |
861 | *nameptr = '\0'; | |
862 | ||
863 | while (*sptr == ' ') | |
864 | sptr ++; | |
865 | } | |
866 | } | |
867 | else if (strncmp(keyword, "StartEmulator_", 14) == 0) | |
868 | { | |
869 | ppd_decode(string); | |
870 | ||
871 | for (i = 0; i < ppd->num_emulations; i ++) | |
872 | if (strcmp(keyword + 14, ppd->emulations[i].name) == 0) | |
873 | { | |
874 | ppd->emulations[i].start = string; | |
875 | string = NULL; | |
876 | } | |
877 | } | |
878 | else if (strncmp(keyword, "StopEmulator_", 13) == 0) | |
879 | { | |
880 | ppd_decode(string); | |
881 | ||
882 | for (i = 0; i < ppd->num_emulations; i ++) | |
883 | if (strcmp(keyword + 13, ppd->emulations[i].name) == 0) | |
884 | { | |
885 | ppd->emulations[i].stop = string; | |
886 | string = NULL; | |
887 | } | |
888 | } | |
889 | else if (strcmp(keyword, "JobPatchFile") == 0) | |
890 | { | |
891 | if (ppd->patches == NULL) | |
892 | { | |
893 | ppd->patches = string; | |
894 | string = NULL; | |
895 | } | |
896 | else | |
897 | { | |
0819478b | 898 | temp = realloc(ppd->patches, strlen(ppd->patches) + |
899 | strlen(string) + 1); | |
900 | if (temp == NULL) | |
901 | { | |
902 | safe_free(string); | |
903 | ppdClose(ppd); | |
904 | return (NULL); | |
905 | } | |
906 | ||
907 | ppd->patches = temp; | |
8c1333e2 | 908 | |
d23a857a | 909 | strcpy(ppd->patches + strlen(ppd->patches), string); |
8c1333e2 | 910 | } |
911 | } | |
2b85e375 | 912 | else if (strcmp(keyword, "OpenUI") == 0) |
913 | { | |
914 | /* | |
915 | * Add an option record to the current sub-group, group, or file... | |
916 | */ | |
917 | ||
918 | if (name[0] == '*') | |
919 | strcpy(name, name + 1); | |
920 | ||
652e598f | 921 | if (string == NULL) |
2b85e375 | 922 | { |
652e598f | 923 | ppdClose(ppd); |
924 | return (NULL); | |
925 | } | |
c21064d2 | 926 | |
652e598f | 927 | if (subgroup != NULL) |
928 | option = ppd_get_option(subgroup, name); | |
929 | else if (group == NULL) | |
930 | { | |
931 | if (strcmp(name, "Collate") != 0 && | |
932 | strcmp(name, "Duplex") != 0 && | |
933 | strcmp(name, "InputSlot") != 0 && | |
934 | strcmp(name, "ManualFeed") != 0 && | |
935 | strcmp(name, "MediaType") != 0 && | |
936 | strcmp(name, "MediaColor") != 0 && | |
937 | strcmp(name, "MediaWeight") != 0 && | |
938 | strcmp(name, "OutputBin") != 0 && | |
939 | strcmp(name, "OutputMode") != 0 && | |
940 | strcmp(name, "OutputOrder") != 0 && | |
941 | strcmp(name, "PageSize") != 0 && | |
942 | strcmp(name, "PageRegion") != 0) | |
943 | group = ppd_get_group(ppd, cupsLangString(language, CUPS_MSG_EXTRA)); | |
caab0820 | 944 | else |
652e598f | 945 | group = ppd_get_group(ppd, cupsLangString(language, CUPS_MSG_GENERAL)); |
caab0820 | 946 | |
652e598f | 947 | if (group == NULL) |
2b85e375 | 948 | { |
caab0820 | 949 | ppdClose(ppd); |
08b247a9 | 950 | safe_free(string); |
caab0820 | 951 | return (NULL); |
58ec2a95 | 952 | } |
caab0820 | 953 | |
652e598f | 954 | option = ppd_get_option(group, name); |
955 | group = NULL; | |
956 | } | |
957 | else | |
958 | option = ppd_get_option(group, name); | |
2b85e375 | 959 | |
652e598f | 960 | if (option == NULL) |
961 | { | |
962 | ppdClose(ppd); | |
963 | safe_free(string); | |
964 | return (NULL); | |
965 | } | |
2b85e375 | 966 | |
652e598f | 967 | /* |
968 | * Now fill in the initial information for the option... | |
969 | */ | |
2b85e375 | 970 | |
652e598f | 971 | if (strcmp(string, "PickMany") == 0) |
972 | option->ui = PPD_UI_PICKMANY; | |
973 | else if (strcmp(string, "Boolean") == 0) | |
974 | option->ui = PPD_UI_BOOLEAN; | |
975 | else | |
976 | option->ui = PPD_UI_PICKONE; | |
977 | ||
978 | if (text[0]) | |
979 | { | |
980 | strncpy(option->text, text, sizeof(option->text) - 1); | |
981 | ppd_fix(option->text); | |
982 | } | |
983 | else | |
984 | { | |
985 | if (strcmp(name, "PageSize") == 0) | |
986 | strncpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SIZE), | |
987 | sizeof(option->text) - 1); | |
988 | else if (strcmp(name, "MediaType") == 0) | |
989 | strncpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_TYPE), | |
990 | sizeof(option->text) - 1); | |
991 | else if (strcmp(name, "InputSlot") == 0) | |
992 | strncpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SOURCE), | |
993 | sizeof(option->text) - 1); | |
994 | else if (strcmp(name, "ColorModel") == 0) | |
995 | strncpy(option->text, cupsLangString(language, CUPS_MSG_OUTPUT_MODE), | |
996 | sizeof(option->text) - 1); | |
997 | else if (strcmp(name, "Resolution") == 0) | |
998 | strncpy(option->text, cupsLangString(language, CUPS_MSG_RESOLUTION), | |
999 | sizeof(option->text) - 1); | |
1000 | else | |
1001 | strncpy(option->text, name, sizeof(option->text) - 1); | |
caab0820 | 1002 | } |
652e598f | 1003 | |
1004 | option->section = PPD_ORDER_ANY; | |
2b85e375 | 1005 | } |
1006 | else if (strcmp(keyword, "JCLOpenUI") == 0) | |
1007 | { | |
58ec2a95 | 1008 | /* |
1009 | * Find the JCL group, and add if needed... | |
1010 | */ | |
1011 | ||
6fdf969a | 1012 | group = ppd_get_group(ppd, "JCL"); |
58ec2a95 | 1013 | |
6fdf969a | 1014 | if (group == NULL) |
58ec2a95 | 1015 | { |
6fdf969a | 1016 | ppdClose(ppd); |
08b247a9 | 1017 | safe_free(string); |
6fdf969a | 1018 | return (NULL); |
58ec2a95 | 1019 | } |
1020 | ||
2b85e375 | 1021 | /* |
1022 | * Add an option record to the current JCLs... | |
1023 | */ | |
1024 | ||
1025 | if (name[0] == '*') | |
1026 | strcpy(name, name + 1); | |
1027 | ||
6fdf969a | 1028 | option = ppd_get_option(group, name); |
2b85e375 | 1029 | |
1030 | if (option == NULL) | |
1031 | { | |
6fdf969a | 1032 | ppdClose(ppd); |
08b247a9 | 1033 | safe_free(string); |
2b85e375 | 1034 | return (NULL); |
e8fda7b9 | 1035 | } |
2b85e375 | 1036 | |
2b85e375 | 1037 | /* |
1038 | * Now fill in the initial information for the option... | |
1039 | */ | |
1040 | ||
d23a857a | 1041 | if (strcmp(string, "PickMany") == 0) |
2b85e375 | 1042 | option->ui = PPD_UI_PICKMANY; |
d23a857a | 1043 | else if (strcmp(string, "Boolean") == 0) |
2b85e375 | 1044 | option->ui = PPD_UI_BOOLEAN; |
1045 | else | |
1046 | option->ui = PPD_UI_PICKONE; | |
1047 | ||
fafbba4f | 1048 | strncpy(option->text, text, sizeof(option->text) - 1); |
2b85e375 | 1049 | |
1050 | option->section = PPD_ORDER_JCL; | |
58ec2a95 | 1051 | group = NULL; |
2b85e375 | 1052 | } |
1053 | else if (strcmp(keyword, "CloseUI") == 0 || | |
1054 | strcmp(keyword, "JCLCloseUI") == 0) | |
1055 | option = NULL; | |
1056 | else if (strcmp(keyword, "OpenGroup") == 0) | |
1057 | { | |
1058 | /* | |
1059 | * Open a new group... | |
1060 | */ | |
1061 | ||
1062 | if (group != NULL) | |
1063 | { | |
1064 | ppdClose(ppd); | |
08b247a9 | 1065 | safe_free(string); |
2b85e375 | 1066 | return (NULL); |
e8fda7b9 | 1067 | } |
2b85e375 | 1068 | |
d23a857a | 1069 | if (strchr(string, '/') != NULL) /* Just show human readable text */ |
1070 | strcpy(string, strchr(string, '/') + 1); | |
2b85e375 | 1071 | |
ad781a11 | 1072 | ppd_decode(string); |
2685c8f0 | 1073 | ppd_fix(string); |
d23a857a | 1074 | group = ppd_get_group(ppd, string); |
2b85e375 | 1075 | } |
1076 | else if (strcmp(keyword, "CloseGroup") == 0) | |
1077 | group = NULL; | |
2b85e375 | 1078 | else if (strcmp(keyword, "OrderDependency") == 0 || |
1079 | strcmp(keyword, "NonUIOrderDependency") == 0) | |
1080 | { | |
04d61d56 | 1081 | if (sscanf(string, "%f%40s%40s", &order, name, keyword) != 3) |
2b85e375 | 1082 | { |
1083 | ppdClose(ppd); | |
08b247a9 | 1084 | safe_free(string); |
2b85e375 | 1085 | return (NULL); |
e8fda7b9 | 1086 | } |
2b85e375 | 1087 | |
1088 | if (keyword[0] == '*') | |
1089 | strcpy(keyword, keyword + 1); | |
1090 | ||
1091 | if (strcmp(name, "ExitServer") == 0) | |
1092 | section = PPD_ORDER_EXIT; | |
1093 | else if (strcmp(name, "Prolog") == 0) | |
1094 | section = PPD_ORDER_PROLOG; | |
1095 | else if (strcmp(name, "DocumentSetup") == 0) | |
1096 | section = PPD_ORDER_DOCUMENT; | |
1097 | else if (strcmp(name, "PageSetup") == 0) | |
1098 | section = PPD_ORDER_PAGE; | |
1099 | else if (strcmp(name, "JCLSetup") == 0) | |
1100 | section = PPD_ORDER_JCL; | |
1101 | else | |
1102 | section = PPD_ORDER_ANY; | |
1103 | ||
1104 | if (option == NULL) | |
1105 | { | |
7d75b814 | 1106 | ppd_group_t *temp; |
1107 | ||
1108 | ||
2b85e375 | 1109 | /* |
1110 | * Only valid for Non-UI options... | |
1111 | */ | |
1112 | ||
7d75b814 | 1113 | for (i = ppd->num_groups, temp = ppd->groups; i > 0; i --, temp ++) |
1114 | if (temp->text[0] == '\0') | |
2b85e375 | 1115 | break; |
58ec2a95 | 1116 | |
1117 | if (i > 0) | |
7d75b814 | 1118 | for (i = 0; i < temp->num_options; i ++) |
1119 | if (strcmp(keyword, temp->options[i].keyword) == 0) | |
58ec2a95 | 1120 | { |
7d75b814 | 1121 | temp->options[i].section = section; |
1122 | temp->options[i].order = order; | |
58ec2a95 | 1123 | break; |
1124 | } | |
2b85e375 | 1125 | } |
1126 | else | |
1127 | { | |
1128 | option->section = section; | |
1129 | option->order = order; | |
e8fda7b9 | 1130 | } |
2b85e375 | 1131 | } |
1132 | else if (strncmp(keyword, "Default", 7) == 0) | |
1133 | { | |
6c73d44f | 1134 | if (string == NULL) |
1135 | continue; | |
1136 | ||
d23a857a | 1137 | if (strchr(string, '/') != NULL) |
1138 | *strchr(string, '/') = '\0'; | |
58ec2a95 | 1139 | |
2b85e375 | 1140 | if (option == NULL) |
1141 | { | |
7d75b814 | 1142 | ppd_group_t *temp; |
1143 | ||
1144 | ||
2b85e375 | 1145 | /* |
1146 | * Only valid for Non-UI options... | |
1147 | */ | |
1148 | ||
7d75b814 | 1149 | for (i = ppd->num_groups, temp = ppd->groups; i > 0; i --, temp ++) |
1150 | if (temp->text[0] == '\0') | |
2b85e375 | 1151 | break; |
58ec2a95 | 1152 | |
1153 | if (i > 0) | |
7d75b814 | 1154 | for (i = 0; i < temp->num_options; i ++) |
1155 | if (strcmp(keyword, temp->options[i].keyword) == 0) | |
58ec2a95 | 1156 | { |
7d75b814 | 1157 | strncpy(temp->options[i].defchoice, string, |
1158 | sizeof(temp->options[i].defchoice) - 1); | |
58ec2a95 | 1159 | break; |
1160 | } | |
2b85e375 | 1161 | } |
1162 | else | |
fafbba4f | 1163 | strncpy(option->defchoice, string, sizeof(option->defchoice) - 1); |
2b85e375 | 1164 | } |
1165 | else if (strcmp(keyword, "UIConstraints") == 0 || | |
1166 | strcmp(keyword, "NonUIConstraints") == 0) | |
1167 | { | |
1168 | if (ppd->num_consts == 0) | |
1169 | constraint = calloc(sizeof(ppd_const_t), 1); | |
1170 | else | |
1171 | constraint = realloc(ppd->consts, | |
1172 | (ppd->num_consts + 1) * sizeof(ppd_const_t)); | |
1173 | ||
1174 | if (constraint == NULL) | |
1175 | { | |
1176 | ppdClose(ppd); | |
08b247a9 | 1177 | safe_free(string); |
2b85e375 | 1178 | return (NULL); |
e8fda7b9 | 1179 | } |
2b85e375 | 1180 | |
1181 | ppd->consts = constraint; | |
1182 | constraint += ppd->num_consts; | |
1183 | ppd->num_consts ++; | |
1184 | ||
fafbba4f | 1185 | switch (sscanf(string, "%40s%40s%40s%40s", constraint->option1, |
8c1333e2 | 1186 | constraint->choice1, constraint->option2, |
1187 | constraint->choice2)) | |
2b85e375 | 1188 | { |
1189 | case 0 : /* Error */ | |
1190 | case 1 : /* Error */ | |
1191 | ppdClose(ppd); | |
08b247a9 | 1192 | safe_free(string); |
2b85e375 | 1193 | break; |
1194 | ||
8c1333e2 | 1195 | case 2 : /* Two options... */ |
d2e58bfa | 1196 | /* |
1197 | * The following strcpy's are safe, as optionN and | |
1198 | * choiceN are all the same size (size defined by PPD spec...) | |
1199 | */ | |
1200 | ||
2b85e375 | 1201 | if (constraint->option1[0] == '*') |
8c1333e2 | 1202 | strcpy(constraint->option1, constraint->option1 + 1); |
1203 | ||
1204 | if (constraint->choice1[0] == '*') | |
1205 | strcpy(constraint->option2, constraint->choice1 + 1); | |
2b85e375 | 1206 | else |
8c1333e2 | 1207 | strcpy(constraint->option2, constraint->choice1); |
2b85e375 | 1208 | |
8c1333e2 | 1209 | constraint->choice1[0] = '\0'; |
1210 | constraint->choice2[0] = '\0'; | |
2b85e375 | 1211 | break; |
1212 | ||
8c1333e2 | 1213 | case 3 : /* Two options, one choice... */ |
d2e58bfa | 1214 | /* |
1215 | * The following strcpy's are safe, as optionN and | |
1216 | * choiceN are all the same size (size defined by PPD spec...) | |
1217 | */ | |
1218 | ||
2b85e375 | 1219 | if (constraint->option1[0] == '*') |
8c1333e2 | 1220 | strcpy(constraint->option1, constraint->option1 + 1); |
1221 | ||
1222 | if (constraint->choice1[0] == '*') | |
2b85e375 | 1223 | { |
9cbf7321 | 1224 | strcpy(constraint->choice2, constraint->option2); |
8c1333e2 | 1225 | strcpy(constraint->option2, constraint->choice1 + 1); |
1226 | constraint->choice1[0] = '\0'; | |
2b85e375 | 1227 | } |
9cbf7321 | 1228 | else |
1229 | { | |
1230 | if (constraint->option2[0] == '*') | |
1231 | strcpy(constraint->option2, constraint->option2 + 1); | |
2b85e375 | 1232 | |
9cbf7321 | 1233 | constraint->choice2[0] = '\0'; |
1234 | } | |
2b85e375 | 1235 | break; |
1236 | ||
8c1333e2 | 1237 | case 4 : /* Two options, two choices... */ |
1238 | if (constraint->option1[0] == '*') | |
1239 | strcpy(constraint->option1, constraint->option1 + 1); | |
2b85e375 | 1240 | |
8c1333e2 | 1241 | if (constraint->option2[0] == '*') |
1242 | strcpy(constraint->option2, constraint->option2 + 1); | |
2b85e375 | 1243 | break; |
e8fda7b9 | 1244 | } |
2b85e375 | 1245 | } |
1246 | else if (strcmp(keyword, "PaperDimension") == 0) | |
1247 | { | |
1248 | if ((size = ppdPageSize(ppd, name)) != NULL) | |
d23a857a | 1249 | sscanf(string, "%f%f", &(size->width), &(size->length)); |
2b85e375 | 1250 | } |
1251 | else if (strcmp(keyword, "ImageableArea") == 0) | |
1252 | { | |
1253 | if ((size = ppdPageSize(ppd, name)) != NULL) | |
d23a857a | 1254 | sscanf(string, "%f%f%f%f", &(size->left), &(size->bottom), |
2b85e375 | 1255 | &(size->right), &(size->top)); |
1256 | } | |
1257 | else if (option != NULL && | |
1258 | (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) == | |
1259 | (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) | |
1260 | { | |
7d75b814 | 1261 | DEBUG_printf(("group = %p, subgroup = %p\n", group, subgroup)); |
1262 | ||
2b85e375 | 1263 | if (strcmp(keyword, "PageSize") == 0) |
1264 | { | |
1265 | /* | |
1266 | * Add a page size... | |
1267 | */ | |
1268 | ||
6fdf969a | 1269 | ppd_add_size(ppd, name); |
e8fda7b9 | 1270 | } |
2b85e375 | 1271 | |
1272 | /* | |
1273 | * Add the option choice... | |
1274 | */ | |
1275 | ||
6fdf969a | 1276 | choice = ppd_add_choice(option, name); |
2b85e375 | 1277 | |
8c1333e2 | 1278 | if (mask & PPD_TEXT) |
2685c8f0 | 1279 | { |
fafbba4f | 1280 | strncpy(choice->text, text, sizeof(choice->text) - 1); |
2685c8f0 | 1281 | ppd_fix(choice->text); |
1282 | } | |
2b85e375 | 1283 | else if (strcmp(name, "True") == 0) |
d23a857a | 1284 | strcpy(choice->text, "Yes"); |
2b85e375 | 1285 | else if (strcmp(name, "False") == 0) |
d23a857a | 1286 | strcpy(choice->text, "No"); |
2b85e375 | 1287 | else |
fafbba4f | 1288 | strncpy(choice->text, name, sizeof(choice->text) - 1); |
2b85e375 | 1289 | |
1290 | if (strncmp(keyword, "JCL", 3) == 0) | |
1291 | ppd_decode(string); /* Decode quoted string */ | |
1292 | ||
1293 | choice->code = string; | |
1294 | string = NULL; /* Don't free this string below */ | |
e8fda7b9 | 1295 | } |
2b85e375 | 1296 | |
08b247a9 | 1297 | safe_free(string); |
e8fda7b9 | 1298 | } |
2b85e375 | 1299 | |
1300 | #ifdef DEBUG | |
1301 | if (!feof(fp)) | |
1302 | printf("Premature EOF at %d...\n", ftell(fp)); | |
1303 | #endif /* DEBUG */ | |
1304 | ||
58ec2a95 | 1305 | /* |
1306 | * Set the option back-pointer for each choice... | |
1307 | */ | |
1308 | ||
caab0820 | 1309 | qsort(ppd->groups, ppd->num_groups, sizeof(ppd_group_t), |
1310 | (int (*)(const void *, const void *))compare_groups); | |
1311 | ||
58ec2a95 | 1312 | for (i = ppd->num_groups, group = ppd->groups; |
1313 | i > 0; | |
1314 | i --, group ++) | |
1315 | { | |
caab0820 | 1316 | qsort(group->options, group->num_options, sizeof(ppd_option_t), |
1317 | (int (*)(const void *, const void *))compare_options); | |
1318 | ||
58ec2a95 | 1319 | for (j = group->num_options, option = group->options; |
1320 | j > 0; | |
1321 | j --, option ++) | |
caab0820 | 1322 | { |
1323 | qsort(option->choices, option->num_choices, sizeof(ppd_choice_t), | |
1324 | (int (*)(const void *, const void *))compare_choices); | |
1325 | ||
58ec2a95 | 1326 | for (k = 0; k < option->num_choices; k ++) |
1327 | option->choices[k].option = (void *)option; | |
caab0820 | 1328 | } |
1329 | ||
1330 | qsort(group->subgroups, group->num_subgroups, sizeof(ppd_group_t), | |
1331 | (int (*)(const void *, const void *))compare_groups); | |
58ec2a95 | 1332 | |
1333 | for (j = group->num_subgroups, subgroup = group->subgroups; | |
1334 | j > 0; | |
1335 | j --, subgroup ++) | |
caab0820 | 1336 | { |
1337 | qsort(subgroup->options, subgroup->num_options, sizeof(ppd_option_t), | |
1338 | (int (*)(const void *, const void *))compare_options); | |
1339 | ||
58ec2a95 | 1340 | for (k = group->num_options, option = group->options; |
1341 | k > 0; | |
1342 | k --, option ++) | |
caab0820 | 1343 | { |
1344 | qsort(option->choices, option->num_choices, sizeof(ppd_choice_t), | |
1345 | (int (*)(const void *, const void *))compare_choices); | |
1346 | ||
58ec2a95 | 1347 | for (m = 0; m < option->num_choices; m ++) |
1348 | option->choices[m].option = (void *)option; | |
caab0820 | 1349 | } |
1350 | } | |
58ec2a95 | 1351 | } |
1352 | ||
2b85e375 | 1353 | return (ppd); |
1354 | } | |
1355 | ||
1356 | ||
1357 | /* | |
1358 | * 'ppdOpenFd()' - Read a PPD file into memory. | |
1359 | */ | |
1360 | ||
1361 | ppd_file_t * /* O - PPD file record */ | |
1362 | ppdOpenFd(int fd) /* I - File to read from */ | |
1363 | { | |
1364 | FILE *fp; /* File pointer */ | |
1365 | ppd_file_t *ppd; /* PPD file record */ | |
1366 | ||
1367 | ||
1368 | /* | |
1369 | * Range check input... | |
1370 | */ | |
1371 | ||
1372 | if (fd < 0) | |
1373 | return (NULL); | |
1374 | ||
1375 | /* | |
1376 | * Try to open the file and parse it... | |
1377 | */ | |
1378 | ||
1379 | if ((fp = fdopen(fd, "r")) != NULL) | |
1380 | { | |
1381 | setbuf(fp, NULL); | |
1382 | ||
1383 | ppd = ppdOpen(fp); | |
1384 | ||
08b247a9 | 1385 | safe_free(fp); |
2b85e375 | 1386 | } |
1387 | else | |
1388 | ppd = NULL; | |
1389 | ||
1390 | return (ppd); | |
1391 | } | |
1392 | ||
1393 | ||
1394 | /* | |
1395 | * 'ppdOpenFile()' - Read a PPD file into memory. | |
1396 | */ | |
1397 | ||
1398 | ppd_file_t * /* O - PPD file record */ | |
063e1ac7 | 1399 | ppdOpenFile(const char *filename) /* I - File to read from */ |
2b85e375 | 1400 | { |
1401 | FILE *fp; /* File pointer */ | |
1402 | ppd_file_t *ppd; /* PPD file record */ | |
1403 | ||
1404 | ||
1405 | /* | |
1406 | * Range check input... | |
1407 | */ | |
1408 | ||
1409 | if (filename == NULL) | |
1410 | return (NULL); | |
1411 | ||
1412 | /* | |
1413 | * Try to open the file and parse it... | |
1414 | */ | |
1415 | ||
1416 | if ((fp = fopen(filename, "r")) != NULL) | |
1417 | { | |
1418 | ppd = ppdOpen(fp); | |
1419 | ||
1420 | fclose(fp); | |
1421 | } | |
1422 | else | |
1423 | ppd = NULL; | |
1424 | ||
1425 | return (ppd); | |
1426 | } | |
1427 | ||
1428 | ||
15166848 | 1429 | /* |
1430 | * 'compare_strings()' - Compare two strings. | |
1431 | */ | |
1432 | ||
1433 | int /* O - Result of comparison */ | |
1434 | compare_strings(char *s, /* I - First string */ | |
1435 | char *t) /* I - Second string */ | |
1436 | { | |
1437 | int diff, /* Difference between digits */ | |
1438 | digits; /* Number of digits */ | |
1439 | ||
1440 | ||
1441 | /* | |
1442 | * Loop through both strings, returning only when a difference is | |
1443 | * seen. Also, compare whole numbers rather than just characters, too! | |
1444 | */ | |
1445 | ||
1446 | while (*s && *t) | |
1447 | { | |
1448 | if (isdigit(*s) && isdigit(*t)) | |
1449 | { | |
1450 | /* | |
1451 | * Got a number; start by skipping leading 0's... | |
1452 | */ | |
1453 | ||
1454 | while (*s == '0') | |
1455 | s ++; | |
1456 | while (*t == '0') | |
1457 | t ++; | |
1458 | ||
1459 | /* | |
1460 | * Skip equal digits... | |
1461 | */ | |
1462 | ||
1463 | while (isdigit(*s) && *s == *t) | |
1464 | { | |
1465 | s ++; | |
1466 | t ++; | |
1467 | } | |
1468 | ||
1469 | /* | |
1470 | * Bounce out if *s and *t aren't both digits... | |
1471 | */ | |
1472 | ||
f4d16e74 | 1473 | if (isdigit(*s) && !isdigit(*t)) |
1474 | return (1); | |
1475 | else if (!isdigit(*s) && isdigit(*t)) | |
1476 | return (-1); | |
1477 | else if (!isdigit(*s) || !isdigit(*t)) | |
15166848 | 1478 | continue; |
1479 | ||
1480 | if (*s < *t) | |
1481 | diff = -1; | |
1482 | else | |
1483 | diff = 1; | |
1484 | ||
1485 | /* | |
1486 | * Figure out how many more digits there are... | |
1487 | */ | |
1488 | ||
1489 | digits = 0; | |
1490 | ||
1491 | while (isdigit(*s)) | |
1492 | { | |
1493 | digits ++; | |
1494 | s ++; | |
1495 | } | |
1496 | ||
1497 | while (isdigit(*t)) | |
1498 | { | |
1499 | digits --; | |
1500 | t ++; | |
1501 | } | |
1502 | ||
1503 | /* | |
1504 | * Return if the number or value of the digits is different... | |
1505 | */ | |
1506 | ||
1507 | if (digits < 0) | |
1508 | return (-1); | |
1509 | else if (digits > 0) | |
1510 | return (1); | |
1511 | else | |
1512 | return (diff); | |
1513 | } | |
1514 | else if (tolower(*s) < tolower(*t)) | |
1515 | return (-1); | |
1516 | else if (tolower(*s) > tolower(*t)) | |
1517 | return (1); | |
1518 | else | |
1519 | { | |
1520 | s ++; | |
1521 | t ++; | |
1522 | } | |
1523 | } | |
1524 | ||
1525 | /* | |
1526 | * Return the results of the final comparison... | |
1527 | */ | |
1528 | ||
1529 | if (*s) | |
1530 | return (1); | |
1531 | else if (*t) | |
1532 | return (-1); | |
1533 | else | |
1534 | return (0); | |
1535 | } | |
1536 | ||
1537 | ||
caab0820 | 1538 | /* |
1539 | * 'compare_groups()' - Compare two groups. | |
1540 | */ | |
1541 | ||
1542 | static int /* O - Result of comparison */ | |
1543 | compare_groups(ppd_group_t *g0, /* I - First group */ | |
1544 | ppd_group_t *g1) /* I - Second group */ | |
1545 | { | |
15166848 | 1546 | return (compare_strings(g0->text, g1->text)); |
caab0820 | 1547 | } |
1548 | ||
1549 | ||
1550 | /* | |
1551 | * 'compare_options()' - Compare two options. | |
1552 | */ | |
1553 | ||
1554 | static int /* O - Result of comparison */ | |
1555 | compare_options(ppd_option_t *o0,/* I - First option */ | |
1556 | ppd_option_t *o1)/* I - Second option */ | |
1557 | { | |
15166848 | 1558 | return (compare_strings(o0->text, o1->text)); |
caab0820 | 1559 | } |
1560 | ||
1561 | ||
1562 | /* | |
1563 | * 'compare_choices()' - Compare two choices. | |
1564 | */ | |
1565 | ||
1566 | static int /* O - Result of comparison */ | |
1567 | compare_choices(ppd_choice_t *c0,/* I - First choice */ | |
1568 | ppd_choice_t *c1)/* I - Second choice */ | |
1569 | { | |
15166848 | 1570 | return (compare_strings(c0->text, c1->text)); |
caab0820 | 1571 | } |
1572 | ||
1573 | ||
2b85e375 | 1574 | /* |
1575 | * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as | |
1576 | * necessary. | |
1577 | */ | |
1578 | ||
1579 | static int /* O - Bitmask of fields read */ | |
d23a857a | 1580 | ppd_read(FILE *fp, /* I - File to read from */ |
1581 | char *keyword, /* O - Keyword from line */ | |
1582 | char *option, /* O - Option from line */ | |
1583 | char *text, /* O - Human-readable text from line */ | |
1584 | char **string) /* O - Code/string data */ | |
2b85e375 | 1585 | { |
1586 | int ch, /* Character from file */ | |
1587 | endquote, /* Waiting for an end quote */ | |
1588 | mask; /* Mask to be returned */ | |
1589 | char *keyptr, /* Keyword pointer */ | |
d23a857a | 1590 | *optptr, /* Option pointer */ |
1591 | *textptr, /* Text pointer */ | |
1592 | *strptr, /* Pointer into string */ | |
1593 | *lineptr, /* Current position in line buffer */ | |
c5b83b99 | 1594 | line[65536]; /* Line buffer (64k) */ |
2b85e375 | 1595 | |
1596 | ||
1597 | /* | |
1598 | * Range check everything... | |
1599 | */ | |
1600 | ||
1601 | if (fp == NULL || keyword == NULL || option == NULL || text == NULL || | |
554fab97 | 1602 | string == NULL) |
2b85e375 | 1603 | return (0); |
1604 | ||
1605 | /* | |
1606 | * Now loop until we have a valid line... | |
1607 | */ | |
1608 | ||
c5b83b99 | 1609 | *string = NULL; |
1610 | ||
2b85e375 | 1611 | do |
1612 | { | |
1613 | /* | |
1614 | * Read the line... | |
1615 | */ | |
1616 | ||
1617 | lineptr = line; | |
1618 | endquote = 0; | |
1619 | ||
1620 | while ((ch = getc(fp)) != EOF && | |
1621 | (lineptr - line) < (sizeof(line) - 1)) | |
1622 | { | |
1623 | if (ch == '\r' || ch == '\n') | |
1624 | { | |
1625 | /* | |
1626 | * Line feed or carriage return... | |
1627 | */ | |
1628 | ||
1629 | if (lineptr == line) /* Skip blank lines */ | |
1630 | continue; | |
1631 | ||
1632 | if (ch == '\r') | |
1633 | { | |
1634 | /* | |
1635 | * Check for a trailing line feed... | |
1636 | */ | |
1637 | ||
1638 | if ((ch = getc(fp)) == EOF) | |
1639 | break; | |
1640 | if (ch != 0x0a) | |
1641 | ungetc(ch, fp); | |
e8fda7b9 | 1642 | } |
2b85e375 | 1643 | |
c5b83b99 | 1644 | ch = '\n'; |
2b85e375 | 1645 | |
1646 | if (!endquote) /* Continue for multi-line text */ | |
1647 | break; | |
c5b83b99 | 1648 | |
1649 | *lineptr++ = '\n'; | |
2b85e375 | 1650 | } |
1651 | else | |
1652 | { | |
1653 | /* | |
1654 | * Any other character... | |
1655 | */ | |
1656 | ||
1657 | *lineptr++ = ch; | |
1658 | ||
1659 | if (ch == '\"') | |
132e0c72 | 1660 | { |
1661 | endquote = !endquote; | |
1662 | ||
1663 | if (!endquote) | |
1664 | { | |
1665 | /* | |
1666 | * End of quoted string; ignore trailing characters... | |
1667 | */ | |
1668 | ||
1669 | while ((ch = getc(fp)) != EOF) | |
1670 | if (ch == '\n') | |
1671 | break; | |
1672 | else if (ch == '\r') | |
1673 | { | |
1674 | ch = getc(fp); | |
1675 | if (ch != '\n') | |
1676 | ungetc(ch, fp); | |
1677 | break; | |
1678 | } | |
1679 | ||
1680 | break; | |
1681 | } | |
1682 | } | |
e8fda7b9 | 1683 | } |
1684 | } | |
2b85e375 | 1685 | |
c5b83b99 | 1686 | if (endquote) |
1687 | { | |
1688 | /* | |
1689 | * Didn't finish this quoted string... | |
1690 | */ | |
1691 | ||
1692 | while ((ch = getc(fp)) != EOF) | |
1693 | if (ch == '\"') | |
1694 | break; | |
1695 | } | |
1696 | ||
1697 | if (ch != '\n') | |
1698 | { | |
1699 | /* | |
1700 | * Didn't finish this line... | |
1701 | */ | |
1702 | ||
1703 | while ((ch = getc(fp)) != EOF) | |
1704 | if (ch == '\r' || ch == '\n') | |
1705 | { | |
1706 | /* | |
1707 | * Line feed or carriage return... | |
1708 | */ | |
1709 | ||
1710 | if (ch == '\r') | |
1711 | { | |
1712 | /* | |
1713 | * Check for a trailing line feed... | |
1714 | */ | |
1715 | ||
1716 | if ((ch = getc(fp)) == EOF) | |
1717 | break; | |
1718 | if (ch != 0x0a) | |
1719 | ungetc(ch, fp); | |
1720 | } | |
1721 | ||
1722 | break; | |
1723 | } | |
1724 | } | |
1725 | ||
2b85e375 | 1726 | if (lineptr > line && lineptr[-1] == '\n') |
1727 | lineptr --; | |
1728 | ||
1729 | *lineptr = '\0'; | |
1730 | ||
1731 | if (ch == EOF && lineptr == line) | |
1732 | return (0); | |
1733 | ||
1734 | /* | |
1735 | * Now parse it... | |
1736 | */ | |
1737 | ||
1738 | mask = 0; | |
1739 | lineptr = line + 1; | |
1740 | ||
1741 | keyword[0] = '\0'; | |
1742 | option[0] = '\0'; | |
1743 | text[0] = '\0'; | |
1744 | *string = NULL; | |
1745 | ||
1746 | if (line[0] != '*') /* All lines start with an asterisk */ | |
1747 | continue; | |
1748 | ||
d23a857a | 1749 | if (strncmp(line, "*%", 2) == 0 || /* Comment line */ |
1750 | strncmp(line, "*?", 2) == 0 || /* Query line */ | |
1751 | strcmp(line, "*End") == 0) /* End of multi-line string */ | |
2b85e375 | 1752 | continue; |
1753 | ||
1754 | /* | |
1755 | * Get a keyword... | |
1756 | */ | |
1757 | ||
1758 | keyptr = keyword; | |
1759 | ||
1760 | while (*lineptr != '\0' && *lineptr != ':' && !isspace(*lineptr) && | |
d2e58bfa | 1761 | (keyptr - keyword) < (PPD_MAX_NAME - 1)) |
2b85e375 | 1762 | *keyptr++ = *lineptr++; |
1763 | ||
1764 | *keyptr = '\0'; | |
1765 | mask |= PPD_KEYWORD; | |
1766 | ||
1767 | if (*lineptr == ' ' || *lineptr == '\t') | |
1768 | { | |
1769 | /* | |
1770 | * Get an option name... | |
1771 | */ | |
1772 | ||
1773 | while (*lineptr == ' ' || *lineptr == '\t') | |
1774 | lineptr ++; | |
1775 | ||
1776 | optptr = option; | |
1777 | ||
1778 | while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':' && | |
1779 | *lineptr != '/' && (optptr - option) < 40) | |
1780 | *optptr++ = *lineptr++; | |
1781 | ||
1782 | *optptr = '\0'; | |
1783 | mask |= PPD_OPTION; | |
1784 | ||
1785 | if (*lineptr == '/') | |
1786 | { | |
1787 | /* | |
1788 | * Get human-readable text... | |
1789 | */ | |
1790 | ||
1791 | lineptr ++; | |
1792 | ||
1793 | textptr = text; | |
1794 | ||
1795 | while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':' && | |
d2e58bfa | 1796 | (textptr - text) < (PPD_MAX_TEXT - 1)) |
2b85e375 | 1797 | *textptr++ = *lineptr++; |
1798 | ||
1799 | *textptr = '\0'; | |
1800 | ppd_decode(text); | |
1801 | ||
1802 | mask |= PPD_TEXT; | |
e8fda7b9 | 1803 | } |
1804 | } | |
2b85e375 | 1805 | |
1806 | if (*lineptr == ':') | |
1807 | { | |
1808 | /* | |
1809 | * Get string... | |
1810 | */ | |
1811 | ||
d23a857a | 1812 | *string = malloc(strlen(lineptr) + 1); |
2b85e375 | 1813 | |
1814 | while (*lineptr == ':' || isspace(*lineptr)) | |
1815 | lineptr ++; | |
1816 | ||
1817 | strptr = *string; | |
1818 | ||
1819 | while (*lineptr != '\0') | |
1820 | { | |
1821 | if (*lineptr != '\"') | |
1822 | *strptr++ = *lineptr++; | |
1823 | else | |
1824 | lineptr ++; | |
e8fda7b9 | 1825 | } |
2b85e375 | 1826 | |
1827 | *strptr = '\0'; | |
58ec2a95 | 1828 | |
2b85e375 | 1829 | mask |= PPD_STRING; |
e8fda7b9 | 1830 | } |
2b85e375 | 1831 | } |
1832 | while (mask == 0); | |
1833 | ||
1834 | return (mask); | |
1835 | } | |
1836 | ||
1837 | ||
1838 | /* | |
1839 | * 'ppd_decode()' - Decode a string value... | |
1840 | */ | |
1841 | ||
1842 | static void | |
d23a857a | 1843 | ppd_decode(char *string) /* I - String to decode */ |
2b85e375 | 1844 | { |
d23a857a | 1845 | char *inptr, /* Input pointer */ |
1846 | *outptr; /* Output pointer */ | |
2b85e375 | 1847 | |
1848 | ||
1849 | inptr = string; | |
1850 | outptr = string; | |
1851 | ||
1852 | while (*inptr != '\0') | |
1853 | if (*inptr == '<' && isxdigit(inptr[1])) | |
1854 | { | |
1855 | /* | |
1856 | * Convert hex to 8-bit values... | |
1857 | */ | |
1858 | ||
1859 | inptr ++; | |
1860 | while (isxdigit(*inptr)) | |
1861 | { | |
1862 | if (isalpha(*inptr)) | |
0b83a6c8 | 1863 | *outptr = (tolower(*inptr) - 'a' + 10) << 4; |
2b85e375 | 1864 | else |
0b83a6c8 | 1865 | *outptr = (*inptr - '0') << 4; |
2b85e375 | 1866 | |
1867 | inptr ++; | |
1868 | ||
1869 | if (isalpha(*inptr)) | |
1870 | *outptr |= tolower(*inptr) - 'a' + 10; | |
1871 | else | |
1872 | *outptr |= *inptr - '0'; | |
1873 | ||
1874 | inptr ++; | |
1875 | outptr ++; | |
e8fda7b9 | 1876 | } |
2b85e375 | 1877 | |
1878 | while (*inptr != '>' && *inptr != '\0') | |
1879 | inptr ++; | |
1880 | while (*inptr == '>') | |
1881 | inptr ++; | |
1882 | } | |
1883 | else | |
1884 | *outptr++ = *inptr++; | |
1885 | ||
1886 | *outptr = '\0'; | |
1887 | } | |
1888 | ||
1889 | ||
90a24de4 | 1890 | /* |
2685c8f0 | 1891 | * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be |
1892 | * valid ISO-8859-1 characters... | |
1893 | */ | |
1894 | ||
1895 | static void | |
1896 | ppd_fix(char *string) /* IO - String to fix */ | |
1897 | { | |
1898 | unsigned char *p; /* Pointer into string */ | |
1899 | static unsigned char lut[32] =/* Lookup table for characters */ | |
1900 | { | |
1901 | 0x20, | |
1902 | 0x20, | |
1903 | 0x20, | |
1904 | 0x20, | |
1905 | 0x20, | |
1906 | 0x20, | |
1907 | 0x20, | |
1908 | 0x20, | |
1909 | 0x20, | |
1910 | 0x20, | |
1911 | 0x20, | |
1912 | 0x20, | |
1913 | 0x20, | |
1914 | 0x20, | |
1915 | 0x20, | |
1916 | 0x20, | |
1917 | 'l', | |
1918 | '`', | |
1919 | '\'', | |
1920 | '^', | |
1921 | '~', | |
1922 | 0x20, /* bar */ | |
1923 | 0x20, /* circumflex */ | |
1924 | 0x20, /* dot */ | |
1925 | 0x20, /* double dot */ | |
1926 | 0x20, | |
1927 | 0x20, /* circle */ | |
1928 | 0x20, /* ??? */ | |
1929 | 0x20, | |
1930 | '\"', /* should be right quotes */ | |
1931 | 0x20, /* ??? */ | |
1932 | 0x20 /* accent */ | |
1933 | }; | |
1934 | ||
1935 | ||
1936 | for (p = (unsigned char *)string; *p; p ++) | |
1937 | if (*p >= 0x80 && *p < 0xa0) | |
1938 | *p = lut[*p - 0x80]; | |
1939 | } | |
1940 | ||
1941 | ||
1942 | /* | |
1fcd229c | 1943 | * End of "$Id: ppd.c,v 1.51.2.1 2001/04/11 00:24:11 mike Exp $". |
90a24de4 | 1944 | */ |