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