]> 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 4980 2006-01-25 19:57:45Z mike $"
3 *
4 * Option marking routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 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 * ppdIsMarked() - Check to see if an option is marked...
35 * ppdMarkDefaults() - Mark all default options in the PPD file.
36 * ppdMarkOption() - Mark an option in a PPD file.
37 * ppd_defaults() - Set the defaults for this group and all sub-groups.
38 */
39
40 /*
41 * Include necessary headers...
42 */
43
44 #include "ppd.h"
45 #include "string.h"
46 #include "debug.h"
47
48
49 /*
50 * Local functions...
51 */
52
53 static void ppd_defaults(ppd_file_t *ppd, ppd_group_t *g);
54
55
56 /*
57 * 'ppdConflicts()' - Check to see if there are any conflicts.
58 */
59
60 int /* O - Number of conflicts found */
61 ppdConflicts(ppd_file_t *ppd) /* I - PPD to check */
62 {
63 int i, j, k, /* Looping variables */
64 conflicts; /* Number of conflicts */
65 ppd_const_t *c; /* Current constraint */
66 ppd_group_t *g, *sg; /* Groups */
67 ppd_option_t *o1, *o2; /* Options */
68 ppd_choice_t *c1, *c2; /* Choices */
69
70
71 if (ppd == NULL)
72 return (0);
73
74 /*
75 * Clear all conflicts...
76 */
77
78 conflicts = 0;
79
80 for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
81 {
82 for (j = g->num_options, o1 = g->options; j > 0; j --, o1 ++)
83 o1->conflicted = 0;
84
85 for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
86 for (k = sg->num_options, o1 = sg->options; k > 0; k --, o1 ++)
87 o1->conflicted = 0;
88 }
89
90 /*
91 * Loop through all of the UI constraints and flag any options
92 * that conflict...
93 */
94
95 for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
96 {
97 /*
98 * Grab pointers to the first option...
99 */
100
101 o1 = ppdFindOption(ppd, c->option1);
102
103 if (o1 == NULL)
104 continue;
105 else if (c->choice1[0] != '\0')
106 {
107 /*
108 * This constraint maps to a specific choice.
109 */
110
111 c1 = ppdFindChoice(o1, c->choice1);
112 }
113 else
114 {
115 /*
116 * This constraint applies to any choice for this option.
117 */
118
119 for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
120 if (c1->marked)
121 break;
122
123 if (j == 0 ||
124 strcasecmp(c1->choice, "None") == 0 ||
125 strcasecmp(c1->choice, "Off") == 0 ||
126 strcasecmp(c1->choice, "False") == 0)
127 c1 = NULL;
128 }
129
130 /*
131 * Grab pointers to the second option...
132 */
133
134 o2 = ppdFindOption(ppd, c->option2);
135
136 if (o2 == NULL)
137 continue;
138 else if (c->choice2[0] != '\0')
139 {
140 /*
141 * This constraint maps to a specific choice.
142 */
143
144 c2 = ppdFindChoice(o2, c->choice2);
145 }
146 else
147 {
148 /*
149 * This constraint applies to any choice for this option.
150 */
151
152 for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
153 if (c2->marked)
154 break;
155
156 if (j == 0 ||
157 strcasecmp(c2->choice, "None") == 0 ||
158 strcasecmp(c2->choice, "Off") == 0 ||
159 strcasecmp(c2->choice, "False") == 0)
160 c2 = NULL;
161 }
162
163 /*
164 * If both options are marked then there is a conflict...
165 */
166
167 if (c1 != NULL && c1->marked &&
168 c2 != NULL && c2->marked)
169 {
170 DEBUG_printf(("%s->%s conflicts with %s->%s (%s %s %s %s)\n",
171 o1->keyword, c1->choice, o2->keyword, c2->choice,
172 c->option1, c->choice1, c->option2, c->choice2));
173 conflicts ++;
174 o1->conflicted = 1;
175 o2->conflicted = 1;
176 }
177 }
178
179 /*
180 * Return the number of conflicts found...
181 */
182
183 return (conflicts);
184 }
185
186
187 /*
188 * 'ppdFindChoice()' - Return a pointer to an option choice.
189 */
190
191 ppd_choice_t * /* O - Choice pointer or NULL */
192 ppdFindChoice(ppd_option_t *o, /* I - Pointer to option */
193 const char *choice) /* I - Name of choice */
194 {
195 int i; /* Looping var */
196 ppd_choice_t *c; /* Current choice */
197
198
199 if (o == NULL || choice == NULL)
200 return (NULL);
201
202 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
203 if (strcasecmp(c->choice, choice) == 0)
204 return (c);
205
206 return (NULL);
207 }
208
209
210 /*
211 * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
212 */
213
214 ppd_choice_t * /* O - Pointer to choice or NULL */
215 ppdFindMarkedChoice(ppd_file_t *ppd, /* I - PPD file */
216 const char *option) /* I - Keyword/option name */
217 {
218 int i; /* Looping var */
219 ppd_option_t *o; /* Pointer to option */
220 ppd_choice_t *c; /* Pointer to choice */
221
222
223 if ((o = ppdFindOption(ppd, option)) == NULL)
224 return (NULL);
225
226 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
227 if (c->marked)
228 return (c);
229
230 return (NULL);
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 ppd_option_t key; /* Option search key */
243
244
245 /*
246 * Range check input...
247 */
248
249 if (!ppd || !option)
250 return (NULL);
251
252 /*
253 * Search...
254 */
255
256 strlcpy(key.keyword, option, sizeof(key.keyword));
257
258 return ((ppd_option_t *)cupsArrayFind(ppd->options, &key));
259 }
260
261
262 /*
263 * 'ppdIsMarked()' - Check to see if an option is marked...
264 */
265
266 int /* O - Non-zero if option is marked */
267 ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */
268 const char *option, /* I - Option/Keyword name */
269 const char *choice) /* I - Choice name */
270 {
271 ppd_option_t *o; /* Option pointer */
272 ppd_choice_t *c; /* Choice pointer */
273
274
275 if (ppd == NULL)
276 return (0);
277
278 if ((o = ppdFindOption(ppd, option)) == NULL)
279 return (0);
280
281 if ((c = ppdFindChoice(o, choice)) == NULL)
282 return (0);
283
284 return (c->marked);
285 }
286
287
288 /*
289 * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
290 */
291
292 void
293 ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */
294 {
295 int i; /* Looping variables */
296 ppd_group_t *g; /* Current group */
297
298
299 if (ppd == NULL)
300 return;
301
302 for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
303 ppd_defaults(ppd, g);
304 }
305
306
307 /*
308 * 'ppdMarkOption()' - Mark an option in a PPD file.
309 *
310 * Notes:
311 *
312 * -1 is returned if the given option would conflict with any currently
313 * selected option.
314 */
315
316 int /* O - Number of conflicts */
317 ppdMarkOption(ppd_file_t *ppd, /* I - PPD file record */
318 const char *option, /* I - Keyword */
319 const char *choice) /* I - Option name */
320 {
321 int i, j; /* Looping vars */
322 ppd_option_t *o; /* Option pointer */
323 ppd_choice_t *c; /* Choice pointer */
324
325
326 /*
327 * Range check input...
328 */
329
330 if (!ppd || !option || !choice)
331 return (0);
332
333 /*
334 * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
335 * it clears the regular InputSlot choices...
336 */
337
338 if (!strcasecmp(option, "AP_D_InputSlot"))
339 {
340 if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
341 for (i = 0; i < o->num_choices; i ++)
342 o->choices[i].marked = 0;
343 }
344
345 /*
346 * Check for custom options...
347 */
348
349 if ((o = ppdFindOption(ppd, option)) == NULL)
350 return (0);
351
352
353 if (!strncasecmp(choice, "Custom.", 7) /* TODO || strchr(choice, '=') */ )
354 {
355 /*
356 * Handle a custom option...
357 */
358
359 if ((c = ppdFindChoice(o, "Custom")) == NULL)
360 return (0);
361
362 if (!strcasecmp(option, "PageSize"))
363 {
364 /*
365 * Handle custom page sizes...
366 */
367
368 ppdPageSize(ppd, choice);
369 }
370 else
371 {
372 /*
373 * Handle other custom options...
374 */
375
376 ppd_coption_t *coption; /* Custom option */
377 ppd_cparam_t *cparam; /* Custom parameter */
378 char units[33]; /* Custom points units */
379
380
381 /*
382 * TODO: Detect and support custom option values using the
383 * collection format "{Name1=foo Name2=bar}". For now, just
384 * support Custom.value for single-valued custom options.
385 */
386
387 if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
388 {
389 if ((cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) == NULL)
390 return (0);
391
392 switch (cparam->type)
393 {
394 case PPD_CUSTOM_CURVE :
395 case PPD_CUSTOM_INVCURVE :
396 case PPD_CUSTOM_REAL :
397 cparam->current.custom_real = atof(choice + 7);
398 break;
399
400 case PPD_CUSTOM_POINTS :
401 if (sscanf(choice + 7, "%f%s", &(cparam->current.custom_points),
402 units) < 2)
403 strcpy(units, "pt");
404
405 if (!strcasecmp(units, "cm"))
406 cparam->current.custom_points *= 72.0 / 2.54;
407 else if (!strcasecmp(units, "mm"))
408 cparam->current.custom_points *= 72.0 / 25.4;
409 else if (!strcasecmp(units, "m"))
410 cparam->current.custom_points *= 72.0 / 0.0254;
411 else if (!strcasecmp(units, "in"))
412 cparam->current.custom_points *= 72.0;
413 else if (!strcasecmp(units, "ft"))
414 cparam->current.custom_points *= 12 * 72.0;
415 break;
416
417 case PPD_CUSTOM_INT :
418 cparam->current.custom_int = atoi(choice + 7);
419 break;
420
421 case PPD_CUSTOM_PASSCODE :
422 case PPD_CUSTOM_PASSWORD :
423 case PPD_CUSTOM_STRING :
424 if (cparam->current.custom_string)
425 free(cparam->current.custom_string);
426
427 cparam->current.custom_string = strdup(choice + 7);
428 break;
429 }
430 }
431 }
432 }
433 else
434 {
435 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
436 if (!strcasecmp(c->choice, choice))
437 break;
438
439 if (!i)
440 return (0);
441 }
442
443 /*
444 * Option found; mark it and then handle unmarking any other options.
445 */
446
447 c->marked = 1;
448
449 if (o->ui != PPD_UI_PICKMANY)
450 {
451 /*
452 * Unmark all other choices...
453 */
454
455 for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
456 if (strcasecmp(c->choice, choice))
457 {
458 c->marked = 0;
459
460 if (!strcasecmp(option, "PageSize") ||
461 !strcasecmp(option, "PageRegion"))
462 {
463 /*
464 * Mark current page size...
465 */
466
467 for (j = 0; j < ppd->num_sizes; j ++)
468 ppd->sizes[i].marked = !strcasecmp(ppd->sizes[i].name,
469 choice);
470
471 /*
472 * Unmark the current PageSize or PageRegion setting, as
473 * appropriate...
474 */
475
476 if (!strcasecmp(option, "PageSize"))
477 {
478 if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
479 for (j = 0; j < o->num_choices; j ++)
480 o->choices[i].marked = 0;
481 }
482 else
483 {
484 if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
485 for (j = 0; j < o->num_choices; j ++)
486 o->choices[j].marked = 0;
487 }
488 }
489 else if (!strcasecmp(option, "InputSlot"))
490 {
491 /*
492 * Unmark ManualFeed True and possibly mark ManualFeed False
493 * option...
494 */
495
496 if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
497 for (j = 0; j < o->num_choices; j ++)
498 o->choices[j].marked = !strcasecmp(o->choices[j].choice, "False");
499 }
500 else if (!strcasecmp(option, "ManualFeed") &&
501 !strcasecmp(choice, "True"))
502 {
503 /*
504 * Unmark InputSlot option...
505 */
506
507 if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
508 for (j = 0; j < o->num_choices; j ++)
509 o->choices[j].marked = 0;
510 }
511 }
512 }
513
514 /*
515 * Return the number of conflicts...
516 */
517
518 return (ppdConflicts(ppd));
519 }
520
521
522 /*
523 * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
524 */
525
526 static void
527 ppd_defaults(ppd_file_t *ppd, /* I - PPD file */
528 ppd_group_t *g) /* I - Group to default */
529 {
530 int i; /* Looping var */
531 ppd_option_t *o; /* Current option */
532 ppd_group_t *sg; /* Current sub-group */
533
534
535 if (g == NULL)
536 return;
537
538 for (i = g->num_options, o = g->options; i > 0; i --, o ++)
539 if (strcasecmp(o->keyword, "PageRegion") != 0)
540 ppdMarkOption(ppd, o->keyword, o->defchoice);
541
542 for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++)
543 ppd_defaults(ppd, sg);
544 }
545
546
547 /*
548 * End of "$Id: mark.c 4980 2006-01-25 19:57:45Z mike $".
549 */