]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/mark.c
bb29bcbcfceac78eb56cb8422b11fbbf9d98099c
[thirdparty/cups.git] / cups / mark.c
1 /*
2 * "$Id: mark.c 5190 2006-02-27 02:42:07Z mike $"
3 *
4 * Option marking routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
7 *
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
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * PostScript is a trademark of Adobe Systems, Inc.
25 *
26 * This file is subject to the Apple OS-Developed Software exception.
27 *
28 * Contents:
29 *
30 * ppdConflicts() - Check to see if there are any conflicts.
31 * ppdFindChoice() - Return a pointer to an option choice.
32 * ppdFindMarkedChoice() - Return the marked choice for the specified option.
33 * ppdFindOption() - Return a pointer to the specified option.
34 * ppdFirstOption() - Return the first option in the PPD file.
35 * ppdNextOption() - Return the next option in the PPD file.
36 * ppdIsMarked() - Check to see if an option is marked...
37 * ppdMarkDefaults() - Mark all default options in the PPD file.
38 * ppdMarkOption() - Mark an option in a PPD file.
39 * ppd_defaults() - Set the defaults for this group and all sub-groups.
40 */
41
42 /*
43 * Include necessary headers...
44 */
45
46 #include "cups.h"
47 #include "string.h"
48 #include "debug.h"
49
50
51 /*
52 * Local functions...
53 */
54
55 static void ppd_defaults(ppd_file_t *ppd, ppd_group_t *g);
56
57
58 /*
59 * 'ppdConflicts()' - Check to see if there are any conflicts.
60 */
61
62 int /* O - Number of conflicts found */
63 ppdConflicts(ppd_file_t *ppd) /* I - PPD to check */
64 {
65 int i, j, k, /* Looping variables */
66 conflicts; /* Number of conflicts */
67 ppd_const_t *c; /* Current constraint */
68 ppd_group_t *g, *sg; /* Groups */
69 ppd_option_t *o1, *o2; /* Options */
70 ppd_choice_t *c1, *c2; /* Choices */
71
72
73 if (ppd == NULL)
74 return (0);
75
76 /*
77 * Clear all conflicts...
78 */
79
80 conflicts = 0;
81
82 for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
83 {
84 for (j = g->num_options, o1 = g->options; j > 0; j --, o1 ++)
85 o1->conflicted = 0;
86
87 for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
88 for (k = sg->num_options, o1 = sg->options; k > 0; k --, o1 ++)
89 o1->conflicted = 0;
90 }
91
92 /*
93 * Loop through all of the UI constraints and flag any options
94 * that conflict...
95 */
96
97 for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
98 {
99 /*
100 * Grab pointers to the first option...
101 */
102
103 o1 = ppdFindOption(ppd, c->option1);
104
105 if (o1 == NULL)
106 continue;
107 else if (c->choice1[0] != '\0')
108 {
109 /*
110 * This constraint maps to a specific choice.
111 */
112
113 c1 = ppdFindChoice(o1, c->choice1);
114 }
115 else
116 {
117 /*
118 * This constraint applies to any choice for this option.
119 */
120
121 for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
122 if (c1->marked)
123 break;
124
125 if (j == 0 ||
126 strcasecmp(c1->choice, "None") == 0 ||
127 strcasecmp(c1->choice, "Off") == 0 ||
128 strcasecmp(c1->choice, "False") == 0)
129 c1 = NULL;
130 }
131
132 /*
133 * Grab pointers to the second option...
134 */
135
136 o2 = ppdFindOption(ppd, c->option2);
137
138 if (o2 == NULL)
139 continue;
140 else if (c->choice2[0] != '\0')
141 {
142 /*
143 * This constraint maps to a specific choice.
144 */
145
146 c2 = ppdFindChoice(o2, c->choice2);
147 }
148 else
149 {
150 /*
151 * This constraint applies to any choice for this option.
152 */
153
154 for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
155 if (c2->marked)
156 break;
157
158 if (j == 0 ||
159 strcasecmp(c2->choice, "None") == 0 ||
160 strcasecmp(c2->choice, "Off") == 0 ||
161 strcasecmp(c2->choice, "False") == 0)
162 c2 = NULL;
163 }
164
165 /*
166 * If both options are marked then there is a conflict...
167 */
168
169 if (c1 != NULL && c1->marked &&
170 c2 != NULL && c2->marked)
171 {
172 DEBUG_printf(("%s->%s conflicts with %s->%s (%s %s %s %s)\n",
173 o1->keyword, c1->choice, o2->keyword, c2->choice,
174 c->option1, c->choice1, c->option2, c->choice2));
175 conflicts ++;
176 o1->conflicted = 1;
177 o2->conflicted = 1;
178 }
179 }
180
181 /*
182 * Return the number of conflicts found...
183 */
184
185 return (conflicts);
186 }
187
188
189 /*
190 * 'ppdFindChoice()' - Return a pointer to an option choice.
191 */
192
193 ppd_choice_t * /* O - Choice pointer or NULL */
194 ppdFindChoice(ppd_option_t *o, /* I - Pointer to option */
195 const char *choice) /* I - Name of choice */
196 {
197 int i; /* Looping var */
198 ppd_choice_t *c; /* Current choice */
199
200
201 if (o == NULL || choice == NULL)
202 return (NULL);
203
204 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
205 if (strcasecmp(c->choice, choice) == 0)
206 return (c);
207
208 return (NULL);
209 }
210
211
212 /*
213 * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
214 */
215
216 ppd_choice_t * /* O - Pointer to choice or NULL */
217 ppdFindMarkedChoice(ppd_file_t *ppd, /* I - PPD file */
218 const char *option) /* I - Keyword/option name */
219 {
220 int i; /* Looping var */
221 ppd_option_t *o; /* Pointer to option */
222 ppd_choice_t *c; /* Pointer to choice */
223
224
225 if ((o = ppdFindOption(ppd, option)) == NULL)
226 return (NULL);
227
228 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
229 if (c->marked)
230 return (c);
231
232 return (NULL);
233 }
234
235
236 /*
237 * 'ppdFindOption()' - Return a pointer to the specified option.
238 */
239
240 ppd_option_t * /* O - Pointer to option or NULL */
241 ppdFindOption(ppd_file_t *ppd, /* I - PPD file data */
242 const char *option) /* I - Option/Keyword name */
243 {
244 ppd_option_t key; /* Option search key */
245
246
247 /*
248 * Range check input...
249 */
250
251 if (!ppd || !option)
252 return (NULL);
253
254 /*
255 * Search...
256 */
257
258 strlcpy(key.keyword, option, sizeof(key.keyword));
259
260 return ((ppd_option_t *)cupsArrayFind(ppd->options, &key));
261 }
262
263
264 /*
265 * 'ppdIsMarked()' - Check to see if an option is marked...
266 */
267
268 int /* O - Non-zero if option is marked */
269 ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */
270 const char *option, /* I - Option/Keyword name */
271 const char *choice) /* I - Choice name */
272 {
273 ppd_option_t *o; /* Option pointer */
274 ppd_choice_t *c; /* Choice pointer */
275
276
277 if (ppd == NULL)
278 return (0);
279
280 if ((o = ppdFindOption(ppd, option)) == NULL)
281 return (0);
282
283 if ((c = ppdFindChoice(o, choice)) == NULL)
284 return (0);
285
286 return (c->marked);
287 }
288
289
290 /*
291 * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
292 */
293
294 void
295 ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */
296 {
297 int i; /* Looping variables */
298 ppd_group_t *g; /* Current group */
299
300
301 if (ppd == NULL)
302 return;
303
304 for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
305 ppd_defaults(ppd, g);
306 }
307
308
309 /*
310 * 'ppdMarkOption()' - Mark an option in a PPD file.
311 *
312 * Notes:
313 *
314 * -1 is returned if the given option would conflict with any currently
315 * selected option.
316 */
317
318 int /* O - Number of conflicts */
319 ppdMarkOption(ppd_file_t *ppd, /* I - PPD file record */
320 const char *option, /* I - Keyword */
321 const char *choice) /* I - Option name */
322 {
323 int i, j; /* Looping vars */
324 ppd_option_t *o; /* Option pointer */
325 ppd_choice_t *c; /* Choice pointer */
326
327
328 DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")\n",
329 ppd, option, choice));
330
331 /*
332 * Range check input...
333 */
334
335 if (!ppd || !option || !choice)
336 return (0);
337
338 /*
339 * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
340 * it clears the regular InputSlot choices...
341 */
342
343 if (!strcasecmp(option, "AP_D_InputSlot"))
344 {
345 if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
346 for (i = 0; i < o->num_choices; i ++)
347 o->choices[i].marked = 0;
348 }
349
350 /*
351 * Check for custom options...
352 */
353
354 if ((o = ppdFindOption(ppd, option)) == NULL)
355 return (0);
356
357
358 if (!strncasecmp(choice, "Custom.", 7))
359 {
360 /*
361 * Handle a custom option...
362 */
363
364 if ((c = ppdFindChoice(o, "Custom")) == NULL)
365 return (0);
366
367 if (!strcasecmp(option, "PageSize"))
368 {
369 /*
370 * Handle custom page sizes...
371 */
372
373 ppdPageSize(ppd, choice);
374 }
375 else
376 {
377 /*
378 * Handle other custom options...
379 */
380
381 ppd_coption_t *coption; /* Custom option */
382 ppd_cparam_t *cparam; /* Custom parameter */
383 char units[33]; /* Custom points units */
384
385 if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
386 {
387 if ((cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) == NULL)
388 return (0);
389
390 switch (cparam->type)
391 {
392 case PPD_CUSTOM_CURVE :
393 case PPD_CUSTOM_INVCURVE :
394 case PPD_CUSTOM_REAL :
395 cparam->current.custom_real = atof(choice + 7);
396 break;
397
398 case PPD_CUSTOM_POINTS :
399 if (sscanf(choice + 7, "%f%s", &(cparam->current.custom_points),
400 units) < 2)
401 strcpy(units, "pt");
402
403 if (!strcasecmp(units, "cm"))
404 cparam->current.custom_points *= 72.0 / 2.54;
405 else if (!strcasecmp(units, "mm"))
406 cparam->current.custom_points *= 72.0 / 25.4;
407 else if (!strcasecmp(units, "m"))
408 cparam->current.custom_points *= 72.0 / 0.0254;
409 else if (!strcasecmp(units, "in"))
410 cparam->current.custom_points *= 72.0;
411 else if (!strcasecmp(units, "ft"))
412 cparam->current.custom_points *= 12 * 72.0;
413 break;
414
415 case PPD_CUSTOM_INT :
416 cparam->current.custom_int = atoi(choice + 7);
417 break;
418
419 case PPD_CUSTOM_PASSCODE :
420 case PPD_CUSTOM_PASSWORD :
421 case PPD_CUSTOM_STRING :
422 if (cparam->current.custom_string)
423 free(cparam->current.custom_string);
424
425 cparam->current.custom_string = strdup(choice + 7);
426 break;
427 }
428 }
429 }
430 }
431 else if (choice[0] == '{')
432 {
433 /*
434 * Handle multi-value custom options...
435 */
436
437 ppd_coption_t *coption; /* Custom option */
438 ppd_cparam_t *cparam; /* Custom parameter */
439 char units[33]; /* Custom points units */
440 int num_vals; /* Number of values */
441 cups_option_t *vals, /* Values */
442 *val; /* Value */
443
444
445 if ((c = ppdFindChoice(o, "Custom")) == NULL)
446 return (0);
447
448 if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
449 {
450 num_vals = cupsParseOptions(choice + 1, 0, &vals);
451
452 for (i = 0, val = vals; i < num_vals; i ++, val ++)
453 {
454 if ((cparam = ppdFindCustomParam(coption, val->name)) == NULL)
455 continue;
456
457 switch (cparam->type)
458 {
459 case PPD_CUSTOM_CURVE :
460 case PPD_CUSTOM_INVCURVE :
461 case PPD_CUSTOM_REAL :
462 cparam->current.custom_real = atof(val->value);
463 break;
464
465 case PPD_CUSTOM_POINTS :
466 if (sscanf(val->value, "%f%s", &(cparam->current.custom_points),
467 units) < 2)
468 strcpy(units, "pt");
469
470 if (!strcasecmp(units, "cm"))
471 cparam->current.custom_points *= 72.0 / 2.54;
472 else if (!strcasecmp(units, "mm"))
473 cparam->current.custom_points *= 72.0 / 25.4;
474 else if (!strcasecmp(units, "m"))
475 cparam->current.custom_points *= 72.0 / 0.0254;
476 else if (!strcasecmp(units, "in"))
477 cparam->current.custom_points *= 72.0;
478 else if (!strcasecmp(units, "ft"))
479 cparam->current.custom_points *= 12 * 72.0;
480 break;
481
482 case PPD_CUSTOM_INT :
483 cparam->current.custom_int = atoi(val->value);
484 break;
485
486 case PPD_CUSTOM_PASSCODE :
487 case PPD_CUSTOM_PASSWORD :
488 case PPD_CUSTOM_STRING :
489 if (cparam->current.custom_string)
490 free(cparam->current.custom_string);
491
492 cparam->current.custom_string = strdup(val->value);
493 break;
494 }
495 }
496
497 cupsFreeOptions(num_vals, vals);
498 }
499 }
500 else
501 {
502 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
503 if (!strcasecmp(c->choice, choice))
504 break;
505
506 if (!i)
507 return (0);
508 }
509
510 /*
511 * Option found; mark it and then handle unmarking any other options.
512 */
513
514 c->marked = 1;
515
516 if (o->ui != PPD_UI_PICKMANY)
517 {
518 /*
519 * Unmark all other choices...
520 */
521
522 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
523 if (strcasecmp(c->choice, choice))
524 {
525 c->marked = 0;
526
527 if (!strcasecmp(option, "PageSize") ||
528 !strcasecmp(option, "PageRegion"))
529 {
530 /*
531 * Mark current page size...
532 */
533
534 for (j = 0; j < ppd->num_sizes; j ++)
535 ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
536 choice);
537
538 /*
539 * Unmark the current PageSize or PageRegion setting, as
540 * appropriate...
541 */
542
543 if (!strcasecmp(option, "PageSize"))
544 {
545 if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
546 for (j = 0; j < o->num_choices; j ++)
547 o->choices[j].marked = 0;
548 }
549 else
550 {
551 if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
552 for (j = 0; j < o->num_choices; j ++)
553 o->choices[j].marked = 0;
554 }
555 }
556 else if (!strcasecmp(option, "InputSlot"))
557 {
558 /*
559 * Unmark ManualFeed True and possibly mark ManualFeed False
560 * option...
561 */
562
563 if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
564 for (j = 0; j < o->num_choices; j ++)
565 o->choices[j].marked = !strcasecmp(o->choices[j].choice, "False");
566 }
567 else if (!strcasecmp(option, "ManualFeed") &&
568 !strcasecmp(choice, "True"))
569 {
570 /*
571 * Unmark InputSlot option...
572 */
573
574 if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
575 for (j = 0; j < o->num_choices; j ++)
576 o->choices[j].marked = 0;
577 }
578 }
579 }
580
581 /*
582 * Return the number of conflicts...
583 */
584
585 return (ppdConflicts(ppd));
586 }
587
588
589 /*
590 * 'ppdFirstOption()' - Return the first option in the PPD file.
591 *
592 * Options are returned from all groups in sorted order.
593 *
594 * @since CUPS 1.2@
595 */
596
597 ppd_option_t * /* O - First option or NULL */
598 ppdFirstOption(ppd_file_t *ppd) /* I - PPD file */
599 {
600 if (!ppd)
601 return (NULL);
602 else
603 return ((ppd_option_t *)cupsArrayFirst(ppd->options));
604 }
605
606
607 /*
608 * 'ppdNextOption()' - Return the next option in the PPD file.
609 *
610 * Options are returned from all groups in sorted order.
611 *
612 * @since CUPS 1.2@
613 */
614
615 ppd_option_t * /* O - Next option or NULL */
616 ppdNextOption(ppd_file_t *ppd) /* I - PPD file */
617 {
618 if (!ppd)
619 return (NULL);
620 else
621 return ((ppd_option_t *)cupsArrayNext(ppd->options));
622 }
623
624
625 /*
626 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
627 */
628
629 static void
630 ppd_defaults(ppd_file_t *ppd, /* I - PPD file */
631 ppd_group_t *g) /* I - Group to default */
632 {
633 int i; /* Looping var */
634 ppd_option_t *o; /* Current option */
635 ppd_group_t *sg; /* Current sub-group */
636
637
638 if (g == NULL)
639 return;
640
641 for (i = g->num_options, o = g->options; i > 0; i --, o ++)
642 if (strcasecmp(o->keyword, "PageRegion") != 0)
643 ppdMarkOption(ppd, o->keyword, o->defchoice);
644
645 for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++)
646 ppd_defaults(ppd, sg);
647 }
648
649
650 /*
651 * End of "$Id: mark.c 5190 2006-02-27 02:42:07Z mike $".
652 */