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