]> 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 6036 2006-10-13 22:06:43Z 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, /* 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 = _cupsStrScand(choice + 7, NULL,
413 loc);
414 break;
415
416 case PPD_CUSTOM_POINTS :
417 cparam->current.custom_points = _cupsStrScand(choice + 7,
418 &units, loc);
419
420 if (units)
421 {
422 if (!strcasecmp(units, "cm"))
423 cparam->current.custom_points *= 72.0 / 2.54;
424 else if (!strcasecmp(units, "mm"))
425 cparam->current.custom_points *= 72.0 / 25.4;
426 else if (!strcasecmp(units, "m"))
427 cparam->current.custom_points *= 72.0 / 0.0254;
428 else if (!strcasecmp(units, "in"))
429 cparam->current.custom_points *= 72.0;
430 else if (!strcasecmp(units, "ft"))
431 cparam->current.custom_points *= 12 * 72.0;
432 }
433 break;
434
435 case PPD_CUSTOM_INT :
436 cparam->current.custom_int = atoi(choice + 7);
437 break;
438
439 case PPD_CUSTOM_PASSCODE :
440 case PPD_CUSTOM_PASSWORD :
441 case PPD_CUSTOM_STRING :
442 if (cparam->current.custom_string)
443 free(cparam->current.custom_string);
444
445 cparam->current.custom_string = strdup(choice + 7);
446 break;
447 }
448 }
449 }
450
451 /*
452 * Make sure that we keep the option marked below...
453 */
454
455 choice = "Custom";
456 }
457 else if (choice[0] == '{')
458 {
459 /*
460 * Handle multi-value custom options...
461 */
462
463 ppd_coption_t *coption; /* Custom option */
464 ppd_cparam_t *cparam; /* Custom parameter */
465 char *units; /* Custom points units */
466 int num_vals; /* Number of values */
467 cups_option_t *vals, /* Values */
468 *val; /* Value */
469
470
471 if ((c = ppdFindChoice(o, "Custom")) == NULL)
472 return (0);
473
474 if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
475 {
476 num_vals = cupsParseOptions(choice + 1, 0, &vals);
477
478 for (i = 0, val = vals; i < num_vals; i ++, val ++)
479 {
480 if ((cparam = ppdFindCustomParam(coption, val->name)) == NULL)
481 continue;
482
483 switch (cparam->type)
484 {
485 case PPD_CUSTOM_CURVE :
486 case PPD_CUSTOM_INVCURVE :
487 case PPD_CUSTOM_REAL :
488 cparam->current.custom_real = _cupsStrScand(val->value, NULL,
489 loc);
490 break;
491
492 case PPD_CUSTOM_POINTS :
493 cparam->current.custom_points = _cupsStrScand(val->value, &units,
494 loc);
495
496 if (units)
497 {
498 if (!strcasecmp(units, "cm"))
499 cparam->current.custom_points *= 72.0 / 2.54;
500 else if (!strcasecmp(units, "mm"))
501 cparam->current.custom_points *= 72.0 / 25.4;
502 else if (!strcasecmp(units, "m"))
503 cparam->current.custom_points *= 72.0 / 0.0254;
504 else if (!strcasecmp(units, "in"))
505 cparam->current.custom_points *= 72.0;
506 else if (!strcasecmp(units, "ft"))
507 cparam->current.custom_points *= 12 * 72.0;
508 }
509 break;
510
511 case PPD_CUSTOM_INT :
512 cparam->current.custom_int = atoi(val->value);
513 break;
514
515 case PPD_CUSTOM_PASSCODE :
516 case PPD_CUSTOM_PASSWORD :
517 case PPD_CUSTOM_STRING :
518 if (cparam->current.custom_string)
519 free(cparam->current.custom_string);
520
521 cparam->current.custom_string = strdup(val->value);
522 break;
523 }
524 }
525
526 cupsFreeOptions(num_vals, vals);
527 }
528 }
529 else
530 {
531 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
532 if (!strcasecmp(c->choice, choice))
533 break;
534
535 if (!i)
536 return (0);
537 }
538
539 /*
540 * Option found; mark it and then handle unmarking any other options.
541 */
542
543 c->marked = 1;
544
545 if (o->ui != PPD_UI_PICKMANY)
546 {
547 /*
548 * Unmark all other choices...
549 */
550
551 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
552 if (strcasecmp(c->choice, choice))
553 {
554 c->marked = 0;
555
556 if (!strcasecmp(option, "PageSize") ||
557 !strcasecmp(option, "PageRegion"))
558 {
559 /*
560 * Mark current page size...
561 */
562
563 for (j = 0; j < ppd->num_sizes; j ++)
564 ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
565 choice);
566
567 /*
568 * Unmark the current PageSize or PageRegion setting, as
569 * appropriate...
570 */
571
572 if (!strcasecmp(option, "PageSize"))
573 {
574 if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
575 for (j = 0; j < o->num_choices; j ++)
576 o->choices[j].marked = 0;
577 }
578 else
579 {
580 if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
581 for (j = 0; j < o->num_choices; j ++)
582 o->choices[j].marked = 0;
583 }
584 }
585 else if (!strcasecmp(option, "InputSlot"))
586 {
587 /*
588 * Unmark ManualFeed True and possibly mark ManualFeed False
589 * option...
590 */
591
592 if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
593 for (j = 0; j < o->num_choices; j ++)
594 o->choices[j].marked = !strcasecmp(o->choices[j].choice, "False");
595 }
596 else if (!strcasecmp(option, "ManualFeed") &&
597 !strcasecmp(choice, "True"))
598 {
599 /*
600 * Unmark InputSlot option...
601 */
602
603 if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
604 for (j = 0; j < o->num_choices; j ++)
605 o->choices[j].marked = 0;
606 }
607 }
608 }
609
610 /*
611 * Return the number of conflicts...
612 */
613
614 return (ppdConflicts(ppd));
615 }
616
617
618 /*
619 * 'ppdFirstOption()' - Return the first option in the PPD file.
620 *
621 * Options are returned from all groups in sorted order.
622 *
623 * @since CUPS 1.2@
624 */
625
626 ppd_option_t * /* O - First option or NULL */
627 ppdFirstOption(ppd_file_t *ppd) /* I - PPD file */
628 {
629 if (!ppd)
630 return (NULL);
631 else
632 return ((ppd_option_t *)cupsArrayFirst(ppd->options));
633 }
634
635
636 /*
637 * 'ppdNextOption()' - Return the next option in the PPD file.
638 *
639 * Options are returned from all groups in sorted order.
640 *
641 * @since CUPS 1.2@
642 */
643
644 ppd_option_t * /* O - Next option or NULL */
645 ppdNextOption(ppd_file_t *ppd) /* I - PPD file */
646 {
647 if (!ppd)
648 return (NULL);
649 else
650 return ((ppd_option_t *)cupsArrayNext(ppd->options));
651 }
652
653
654 /*
655 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
656 */
657
658 static void
659 ppd_defaults(ppd_file_t *ppd, /* I - PPD file */
660 ppd_group_t *g) /* I - Group to default */
661 {
662 int i; /* Looping var */
663 ppd_option_t *o; /* Current option */
664 ppd_group_t *sg; /* Current sub-group */
665
666
667 if (g == NULL)
668 return;
669
670 for (i = g->num_options, o = g->options; i > 0; i --, o ++)
671 if (strcasecmp(o->keyword, "PageRegion") != 0)
672 ppdMarkOption(ppd, o->keyword, o->defchoice);
673
674 for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++)
675 ppd_defaults(ppd, sg);
676 }
677
678
679 /*
680 * End of "$Id: mark.c 6036 2006-10-13 22:06:43Z mike $".
681 */