]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/mark.c
Remove svn:keywords since they cause svn_load_dirs.pl to complain about every file.
[thirdparty/cups.git] / cups / mark.c
CommitLineData
ef416fc2 1/*
c07d5b2d 2 * "$Id: mark.c 177 2006-06-21 00:20:03Z jlovell $"
ef416fc2 3 *
4 * Option marking routines for the Common UNIX Printing System (CUPS).
5 *
bd7854cb 6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 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.
bd7854cb 34 * ppdFirstOption() - Return the first option in the PPD file.
35 * ppdNextOption() - Return the next option in the PPD file.
ef416fc2 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
b423cd4c 46#include "cups.h"
ef416fc2 47#include "string.h"
48#include "debug.h"
49
50
51/*
52 * Local functions...
53 */
54
55static 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
62int /* O - Number of conflicts found */
63ppdConflicts(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
193ppd_choice_t * /* O - Choice pointer or NULL */
194ppdFindChoice(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
216ppd_choice_t * /* O - Pointer to choice or NULL */
217ppdFindMarkedChoice(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
240ppd_option_t * /* O - Pointer to option or NULL */
241ppdFindOption(ppd_file_t *ppd, /* I - PPD file data */
242 const char *option) /* I - Option/Keyword name */
243{
fa73b229 244 /*
245 * Range check input...
246 */
ef416fc2 247
fa73b229 248 if (!ppd || !option)
ef416fc2 249 return (NULL);
250
f301802f 251 if (ppd->options)
252 {
253 /*
254 * Search in the array...
255 */
256
257 ppd_option_t key; /* Option search key */
258
259
260 strlcpy(key.keyword, option, sizeof(key.keyword));
ef416fc2 261
f301802f 262 return ((ppd_option_t *)cupsArrayFind(ppd->options, &key));
263 }
264 else
265 {
266 /*
267 * Search in each group...
268 */
ef416fc2 269
f301802f 270 int i, j; /* Looping vars */
271 ppd_group_t *group; /* Current group */
272 ppd_option_t *optptr; /* Current option */
273
274
275 for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
276 for (j = group->num_options, optptr = group->options;
277 j > 0;
278 j --, optptr ++)
279 if (!strcasecmp(optptr->keyword, option))
280 return (optptr);
281
282 return (NULL);
283 }
ef416fc2 284}
285
286
287/*
288 * 'ppdIsMarked()' - Check to see if an option is marked...
289 */
290
291int /* O - Non-zero if option is marked */
292ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */
293 const char *option, /* I - Option/Keyword name */
294 const char *choice) /* I - Choice name */
295{
296 ppd_option_t *o; /* Option pointer */
297 ppd_choice_t *c; /* Choice pointer */
298
299
300 if (ppd == NULL)
301 return (0);
302
303 if ((o = ppdFindOption(ppd, option)) == NULL)
304 return (0);
305
306 if ((c = ppdFindChoice(o, choice)) == NULL)
307 return (0);
308
309 return (c->marked);
310}
311
312
313/*
314 * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
315 */
316
317void
318ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */
319{
320 int i; /* Looping variables */
321 ppd_group_t *g; /* Current group */
322
323
324 if (ppd == NULL)
325 return;
326
327 for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
328 ppd_defaults(ppd, g);
329}
330
331
332/*
333 * 'ppdMarkOption()' - Mark an option in a PPD file.
334 *
335 * Notes:
336 *
337 * -1 is returned if the given option would conflict with any currently
338 * selected option.
339 */
340
341int /* O - Number of conflicts */
342ppdMarkOption(ppd_file_t *ppd, /* I - PPD file record */
343 const char *option, /* I - Keyword */
344 const char *choice) /* I - Option name */
345{
fa73b229 346 int i, j; /* Looping vars */
347 ppd_option_t *o; /* Option pointer */
348 ppd_choice_t *c; /* Choice pointer */
757d2cad 349 struct lconv *loc; /* Locale data */
ef416fc2 350
351
bd7854cb 352 DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")\n",
353 ppd, option, choice));
354
fa73b229 355 /*
356 * Range check input...
357 */
358
359 if (!ppd || !option || !choice)
ef416fc2 360 return (0);
361
fa73b229 362 /*
363 * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
364 * it clears the regular InputSlot choices...
365 */
ef416fc2 366
fa73b229 367 if (!strcasecmp(option, "AP_D_InputSlot"))
368 {
369 if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
370 for (i = 0; i < o->num_choices; i ++)
371 o->choices[i].marked = 0;
ef416fc2 372 }
373
fa73b229 374 /*
375 * Check for custom options...
376 */
377
ef416fc2 378 if ((o = ppdFindOption(ppd, option)) == NULL)
379 return (0);
380
757d2cad 381 loc = localeconv();
ef416fc2 382
b423cd4c 383 if (!strncasecmp(choice, "Custom.", 7))
ef416fc2 384 {
385 /*
fa73b229 386 * Handle a custom option...
ef416fc2 387 */
388
fa73b229 389 if ((c = ppdFindChoice(o, "Custom")) == NULL)
390 return (0);
ef416fc2 391
fa73b229 392 if (!strcasecmp(option, "PageSize"))
393 {
394 /*
395 * Handle custom page sizes...
396 */
ef416fc2 397
fa73b229 398 ppdPageSize(ppd, choice);
399 }
400 else
ef416fc2 401 {
402 /*
fa73b229 403 * Handle other custom options...
ef416fc2 404 */
405
fa73b229 406 ppd_coption_t *coption; /* Custom option */
407 ppd_cparam_t *cparam; /* Custom parameter */
757d2cad 408 char *units; /* Custom points units */
fa73b229 409
fa73b229 410 if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
ef416fc2 411 {
fa73b229 412 if ((cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) == NULL)
413 return (0);
414
415 switch (cparam->type)
416 {
417 case PPD_CUSTOM_CURVE :
418 case PPD_CUSTOM_INVCURVE :
419 case PPD_CUSTOM_REAL :
757d2cad 420 cparam->current.custom_real = _cupsStrScand(choice + 7, NULL,
421 loc);
fa73b229 422 break;
423
424 case PPD_CUSTOM_POINTS :
757d2cad 425 cparam->current.custom_points = _cupsStrScand(choice + 7,
426 &units, loc);
427
428 if (units)
429 {
430 if (!strcasecmp(units, "cm"))
431 cparam->current.custom_points *= 72.0 / 2.54;
432 else if (!strcasecmp(units, "mm"))
433 cparam->current.custom_points *= 72.0 / 25.4;
434 else if (!strcasecmp(units, "m"))
435 cparam->current.custom_points *= 72.0 / 0.0254;
436 else if (!strcasecmp(units, "in"))
437 cparam->current.custom_points *= 72.0;
438 else if (!strcasecmp(units, "ft"))
439 cparam->current.custom_points *= 12 * 72.0;
440 }
fa73b229 441 break;
442
443 case PPD_CUSTOM_INT :
444 cparam->current.custom_int = atoi(choice + 7);
445 break;
446
447 case PPD_CUSTOM_PASSCODE :
448 case PPD_CUSTOM_PASSWORD :
449 case PPD_CUSTOM_STRING :
450 if (cparam->current.custom_string)
451 free(cparam->current.custom_string);
452
453 cparam->current.custom_string = strdup(choice + 7);
454 break;
455 }
ef416fc2 456 }
457 }
fa73b229 458 }
b423cd4c 459 else if (choice[0] == '{')
460 {
461 /*
462 * Handle multi-value custom options...
463 */
464
465 ppd_coption_t *coption; /* Custom option */
466 ppd_cparam_t *cparam; /* Custom parameter */
757d2cad 467 char *units; /* Custom points units */
b423cd4c 468 int num_vals; /* Number of values */
469 cups_option_t *vals, /* Values */
470 *val; /* Value */
471
472
473 if ((c = ppdFindChoice(o, "Custom")) == NULL)
474 return (0);
475
476 if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
477 {
478 num_vals = cupsParseOptions(choice + 1, 0, &vals);
479
480 for (i = 0, val = vals; i < num_vals; i ++, val ++)
481 {
482 if ((cparam = ppdFindCustomParam(coption, val->name)) == NULL)
483 continue;
484
485 switch (cparam->type)
486 {
487 case PPD_CUSTOM_CURVE :
488 case PPD_CUSTOM_INVCURVE :
489 case PPD_CUSTOM_REAL :
757d2cad 490 cparam->current.custom_real = _cupsStrScand(val->value, NULL,
491 loc);
b423cd4c 492 break;
493
494 case PPD_CUSTOM_POINTS :
757d2cad 495 cparam->current.custom_points = _cupsStrScand(val->value, &units,
496 loc);
497
498 if (units)
499 {
500 if (!strcasecmp(units, "cm"))
501 cparam->current.custom_points *= 72.0 / 2.54;
502 else if (!strcasecmp(units, "mm"))
503 cparam->current.custom_points *= 72.0 / 25.4;
504 else if (!strcasecmp(units, "m"))
505 cparam->current.custom_points *= 72.0 / 0.0254;
506 else if (!strcasecmp(units, "in"))
507 cparam->current.custom_points *= 72.0;
508 else if (!strcasecmp(units, "ft"))
509 cparam->current.custom_points *= 12 * 72.0;
510 }
b423cd4c 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 }
fa73b229 531 else
532 {
533 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
534 if (!strcasecmp(c->choice, choice))
535 break;
ef416fc2 536
fa73b229 537 if (!i)
538 return (0);
539 }
ef416fc2 540
fa73b229 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 ++)
bd7854cb 566 ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
fa73b229 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 ++)
bd7854cb 578 o->choices[j].marked = 0;
fa73b229 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 }
ef416fc2 610 }
611
fa73b229 612 /*
613 * Return the number of conflicts...
614 */
615
ef416fc2 616 return (ppdConflicts(ppd));
617}
618
619
bd7854cb 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
628ppd_option_t * /* O - First option or NULL */
629ppdFirstOption(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
646ppd_option_t * /* O - Next option or NULL */
647ppdNextOption(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
ef416fc2 656/*
657 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
658 */
659
660static void
661ppd_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/*
c07d5b2d 682 * End of "$Id: mark.c 177 2006-06-21 00:20:03Z jlovell $".
ef416fc2 683 */