]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/emit.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / emit.c
CommitLineData
ef416fc2 1/*
fa73b229 2 * "$Id: emit.c 4980 2006-01-25 19:57:45Z mike $"
ef416fc2 3 *
4 * PPD code emission 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 *
fa73b229 30 * ppdCollect() - Collect all marked options that reside in the
31 * specified section.
32 * ppdCollect2() - Collect all marked options that reside in the
33 * specified section and minimum order.
34 * ppdEmit() - Emit code for marked options to a file.
35 * ppdEmitAfterOrder() - Emit a subset of the code for marked options to a file.
36 * ppdEmitFd() - Emit code for marked options to a file.
37 * ppdEmitJCL() - Emit code for JCL options to a file.
38 * ppdEmitJCLEnd() - Emit JCLEnd code to a file.
39 * ppd_handle_media() - Handle media selection...
40 * ppd_sort() - Sort options by ordering numbers...
ef416fc2 41 */
42
43/*
44 * Include necessary headers...
45 */
46
47#include "ppd.h"
48#include <stdlib.h>
49#include "string.h"
50
51#if defined(WIN32) || defined(__EMX__)
52# include <io.h>
53#else
54# include <unistd.h>
55#endif /* WIN32 || __EMX__ */
56
57
58/*
59 * Local functions...
60 */
61
62static void ppd_handle_media(ppd_file_t *ppd);
63static int ppd_sort(ppd_choice_t **c1, ppd_choice_t **c2);
64
65
66/*
67 * Local globals...
68 */
69
70static const char ppd_custom_code[] =
71 "pop pop pop\n"
72 "<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n";
73
74
75/*
76 * 'ppdCollect()' - Collect all marked options that reside in the specified
77 * section.
78 */
79
80int /* O - Number of options marked */
81ppdCollect(ppd_file_t *ppd, /* I - PPD file data */
82 ppd_section_t section, /* I - Section to collect */
83 ppd_choice_t ***choices) /* O - Pointers to choices */
fa73b229 84{
85 return (ppdCollect2(ppd, section, 0.0, choices));
86}
87
88
89/*
90 * 'ppdCollect2()' - Collect all marked options that reside in the
91 * specified section and minimum order.
92 *
93 * @since CUPS 1.2@
94 */
95
96int /* O - Number of options marked */
97ppdCollect2(ppd_file_t *ppd, /* I - PPD file data */
98 ppd_section_t section, /* I - Section to collect */
99 float min_order, /* I - Minimum OrderDependency value */
100 ppd_choice_t ***choices) /* O - Pointers to choices */
ef416fc2 101{
102 int i, j, k, m; /* Looping vars */
103 ppd_group_t *g, /* Current group */
104 *sg; /* Current sub-group */
105 ppd_option_t *o; /* Current option */
106 ppd_choice_t *c; /* Current choice */
107 int count; /* Number of choices collected */
108 ppd_choice_t **collect; /* Collected choices */
109
110
111 if (ppd == NULL)
112 return (0);
113
114 /*
115 * Allocate memory for up to 1000 selected choices...
116 */
117
118 count = 0;
119 collect = calloc(sizeof(ppd_choice_t *), 1000);
120
121 /*
122 * Loop through all options and add choices as needed...
123 */
124
125 for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
126 {
127 for (j = g->num_options, o = g->options; j > 0; j --, o ++)
fa73b229 128 if (o->section == section && o->order >= min_order)
ef416fc2 129 for (k = o->num_choices, c = o->choices; k > 0; k --, c ++)
130 if (c->marked && count < 1000)
131 {
132 collect[count] = c;
133 count ++;
134 }
135
136 for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
137 for (k = sg->num_options, o = sg->options; k > 0; k --, o ++)
fa73b229 138 if (o->section == section && o->order >= min_order)
ef416fc2 139 for (m = o->num_choices, c = o->choices; m > 0; m --, c ++)
140 if (c->marked && count < 1000)
141 {
142 collect[count] = c;
143 count ++;
144 }
145 }
146
147 /*
148 * If we have more than 1 marked choice, sort them...
149 */
150
151 if (count > 1)
152 qsort(collect, count, sizeof(ppd_choice_t *),
153 (int (*)(const void *, const void *))ppd_sort);
154
155 /*
156 * Return the array and number of choices; if 0, free the array since
157 * it isn't needed.
158 */
159
160 if (count > 0)
161 {
162 *choices = collect;
163 return (count);
164 }
165 else
166 {
167 *choices = NULL;
168 free(collect);
169 return (0);
170 }
171}
172
173
174/*
175 * 'ppdEmit()' - Emit code for marked options to a file.
176 */
177
178int /* O - 0 on success, -1 on failure */
179ppdEmit(ppd_file_t *ppd, /* I - PPD file record */
180 FILE *fp, /* I - File to write to */
181 ppd_section_t section) /* I - Section to write */
fa73b229 182{
183 return (ppdEmitAfterOrder(ppd, fp, section, 0, 0.0));
184}
185
186
187/*
188 * 'ppdEmitAfterOrder()' - Emit a subset of the code for marked options to a file.
189 *
190 * When "limit" is non-zero, this function only emits options whose
191 * OrderDependency value is greater than or equal to "min_order".
192 *
193 * When "limit" is zero, this function is identical to ppdEmit().
194 *
195 * @since CUPS 1.2@
196 */
197
198int /* O - 0 on success, -1 on failure */
199ppdEmitAfterOrder(
200 ppd_file_t *ppd, /* I - PPD file record */
201 FILE *fp, /* I - File to write to */
202 ppd_section_t section, /* I - Section to write */
203 int limit, /* I - Non-zero to use min_order, 0 to include all */
204 float min_order) /* I - Lowest order dependency to include */
ef416fc2 205{
206 int i, /* Looping var */
207 count; /* Number of choices */
208 ppd_choice_t **choices; /* Choices */
209 ppd_size_t *size; /* Custom page size */
210
211
212 /*
213 * Use PageSize or PageRegion as required...
214 */
215
216 ppd_handle_media(ppd);
217
218 /*
219 * Collect the options we need to emit and emit them!
220 */
221
fa73b229 222 if ((count = ppdCollect2(ppd, section, min_order, &choices)) == 0)
ef416fc2 223 return (0);
224
225 for (i = 0; i < count; i ++)
226 if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
227 {
228 /*
229 * Send wrapper commands to prevent printer errors for unsupported
230 * options...
231 */
232
233 if (fputs("[{\n", fp) < 0)
234 {
235 free(choices);
236 return (-1);
237 }
238
239 /*
240 * Send DSC comments with option...
241 */
242
fa73b229 243 if ((!strcasecmp(choices[i]->option->keyword, "PageSize") ||
244 !strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
245 !strcasecmp(choices[i]->choice, "Custom"))
ef416fc2 246 {
247 /*
248 * Variable size; write out standard size options, using the
249 * parameter positions defined in the PPD file...
250 */
251
252 ppd_attr_t *attr; /* PPD attribute */
253 int pos, /* Position of custom value */
ef416fc2 254 orientation; /* Orientation to use */
fa73b229 255 float values[5]; /* Values for custom command */
256 int isfloat[5]; /* Whether each value is float or int */
ef416fc2 257
258 fputs("%%BeginFeature: *CustomPageSize True\n", fp);
259
260 size = ppdPageSize(ppd, "Custom");
261
262 memset(values, 0, sizeof(values));
fa73b229 263 memset(isfloat, 0, sizeof(isfloat));
ef416fc2 264
265 if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
266 {
267 pos = atoi(attr->value) - 1;
268
269 if (pos < 0 || pos > 4)
270 pos = 0;
271 }
272 else
273 pos = 0;
274
fa73b229 275 values[pos] = size->width;
276 isfloat[pos] = 1;
ef416fc2 277
278 if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
279 {
280 pos = atoi(attr->value) - 1;
281
282 if (pos < 0 || pos > 4)
283 pos = 1;
284 }
285 else
286 pos = 1;
287
fa73b229 288 values[pos] = size->length;
289 isfloat[pos] = 1;
ef416fc2 290
291 /*
292 * According to the Adobe PPD specification, an orientation of 1
293 * will produce a print that comes out upside-down with the X
294 * axis perpendicular to the direction of feed, which is exactly
295 * what we want to be consistent with non-PS printers.
296 *
297 * We could also use an orientation of 3 to produce output that
298 * comes out rightside-up (this is the default for many large format
299 * printer PPDs), however for consistency we will stick with the
300 * value 1.
301 *
302 * If we wanted to get fancy, we could use orientations of 0 or
303 * 2 and swap the width and length, however we don't want to get
304 * fancy, we just want it to work consistently.
305 *
306 * The orientation value is range limited by the Orientation
307 * parameter definition, so certain non-PS printer drivers that
308 * only support an Orientation of 0 will get the value 0 as
309 * expected.
310 */
311
312 orientation = 1;
313
314 if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
315 "Orientation")) != NULL)
316 {
317 int min_orient, max_orient; /* Minimum and maximum orientations */
318
319
320 if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
321 &max_orient) != 3)
322 pos = 4;
323 else
324 {
325 pos --;
326
327 if (pos < 0 || pos > 4)
328 pos = 4;
329
330 if (orientation > max_orient)
331 orientation = max_orient;
332 else if (orientation < min_orient)
333 orientation = min_orient;
334 }
335 }
336 else
337 pos = 4;
338
339 values[pos] = orientation;
340
fa73b229 341 for (pos = 0; pos < 5; pos ++)
342 if (isfloat[pos])
343 fprintf(fp, "%.2f\n", values[pos]);
344 else
345 fprintf(fp, "%.0f\n", values[pos]);
ef416fc2 346
347 if (choices[i]->code == NULL)
348 {
349 /*
350 * This can happen with certain buggy PPD files that don't include
351 * a CustomPageSize command sequence... We just use a generic
352 * Level 2 command sequence...
353 */
354
355 fputs(ppd_custom_code, fp);
356 }
357 }
fa73b229 358 else if (!strcasecmp(choices[i]->choice, "Custom"))
359 {
360 /*
361 * Custom option...
362 */
363
364 ppd_coption_t *coption; /* Custom option */
365 ppd_cparam_t *cparam; /* Custom parameter */
366 const char *s; /* Pointer into string value */
367
368
369 /*
370 * TODO: Support custom options with more than 1 parameter...
371 */
372
373 if ((coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
374 != NULL &&
375 (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) != NULL)
376 {
377 if (fprintf(fp, "%%%%BeginFeature: *Custom%s True\n",
378 coption->keyword) < 0)
379 {
380 free(choices);
381 return (-1);
382 }
383
384 switch (cparam->type)
385 {
386 case PPD_CUSTOM_CURVE :
387 case PPD_CUSTOM_INVCURVE :
388 case PPD_CUSTOM_POINTS :
389 case PPD_CUSTOM_REAL :
390 if (fprintf(fp, "%f\n", cparam->current.custom_real) < 0)
391 {
392 free(choices);
393 return (-1);
394 }
395 break;
396
397 case PPD_CUSTOM_INT :
398 if (fprintf(fp, "%d\n", cparam->current.custom_int) < 0)
399 {
400 free(choices);
401 return (-1);
402 }
403 break;
404
405 case PPD_CUSTOM_PASSCODE :
406 case PPD_CUSTOM_PASSWORD :
407 case PPD_CUSTOM_STRING :
408 putc('(', fp);
409
410 for (s = cparam->current.custom_string; *s; s ++)
411 if (*s < ' ' || *s == '(' || *s == ')' || *s >= 127)
412 fprintf(fp, "\\%03o", *s & 255);
413 else
414 putc(*s, fp);
415
416 if (fputs(")\n", fp) < 0)
417 {
418 free(choices);
419 return (-1);
420 }
421 break;
422 }
423 }
424 }
ef416fc2 425 else if (fprintf(fp, "%%%%BeginFeature: *%s %s\n",
fa73b229 426 choices[i]->option->keyword,
ef416fc2 427 choices[i]->choice) < 0)
428 {
429 free(choices);
430 return (-1);
431 }
432
433 if (choices[i]->code != NULL && choices[i]->code[0] != '\0')
434 {
435 if (fputs(choices[i]->code, fp) < 0)
436 {
437 free(choices);
438 return (-1);
439 }
440
441 if (choices[i]->code[strlen(choices[i]->code) - 1] != '\n')
442 putc('\n', fp);
443 }
444
445 if (fputs("%%EndFeature\n", fp) < 0)
446 {
447 free(choices);
448 return (-1);
449 }
450
451 if (fputs("} stopped cleartomark\n", fp) < 0)
452 {
453 free(choices);
454 return (-1);
455 }
456 }
457 else if (fputs(choices[i]->code, fp) < 0)
458 {
459 free(choices);
460 return (-1);
461 }
462
463 free(choices);
464 return (0);
465}
466
467
468/*
469 * 'ppdEmitFd()' - Emit code for marked options to a file.
470 */
471
472int /* O - 0 on success, -1 on failure */
473ppdEmitFd(ppd_file_t *ppd, /* I - PPD file record */
474 int fd, /* I - File to write to */
475 ppd_section_t section) /* I - Section to write */
476{
477 int i, /* Looping var */
478 count, /* Number of choices */
479 custom_size; /* Non-zero if this option is a custom size */
480 ppd_choice_t **choices; /* Choices */
481 ppd_size_t *size; /* Custom page size */
482 char buf[1024]; /* Output buffer for feature */
483
484
485 /*
486 * Use PageSize or PageRegion as required...
487 */
488
489 ppd_handle_media(ppd);
490
491 /*
492 * Collect the options we need to emit and emit them!
493 */
494
495 if ((count = ppdCollect(ppd, section, &choices)) == 0)
496 return (0);
497
498 for (i = 0; i < count; i ++)
499 if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
500 {
501 /*
502 * Send wrapper commands to prevent printer errors for unsupported
503 * options...
504 */
505
506 if (write(fd, "[{\n", 3) < 1)
507 {
508 free(choices);
509 return (-1);
510 }
511
512 /*
513 * Send DSC comments with option...
514 */
515
fa73b229 516 if ((!strcasecmp(choices[i]->option->keyword, "PageSize") ||
517 !strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
518 !strcasecmp(choices[i]->choice, "Custom"))
ef416fc2 519 {
520 custom_size = 1;
521
522 strcpy(buf, "%%BeginFeature: *CustomPageSize True\n");
523 }
524 else
525 {
526 custom_size = 0;
527
528 snprintf(buf, sizeof(buf), "%%%%BeginFeature: *%s %s\n",
fa73b229 529 choices[i]->option->keyword, choices[i]->choice);
ef416fc2 530 }
531
532 if (write(fd, buf, strlen(buf)) < 1)
533 {
534 free(choices);
535 return (-1);
536 }
537
538 if (custom_size)
539 {
540 /*
541 * Variable size; write out standard size options, using the
542 * parameter positions defined in the PPD file...
543 */
544
545 ppd_attr_t *attr; /* PPD attribute */
546 int pos, /* Position of custom value */
547 values[5], /* Values for custom command */
548 orientation; /* Orientation to use */
549
550
551 size = ppdPageSize(ppd, "Custom");
552
553 memset(values, 0, sizeof(values));
554
555 if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
556 {
557 pos = atoi(attr->value) - 1;
558
559 if (pos < 0 || pos > 4)
560 pos = 0;
561 }
562 else
563 pos = 0;
564
565 values[pos] = (int)size->width;
566
567 if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
568 {
569 pos = atoi(attr->value) - 1;
570
571 if (pos < 0 || pos > 4)
572 pos = 1;
573 }
574 else
575 pos = 1;
576
577 values[pos] = (int)size->length;
578
579 if (size->width < size->length)
580 orientation = 1;
581 else
582 orientation = 0;
583
584 if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
585 "Orientation")) != NULL)
586 {
587 int min_orient, max_orient; /* Minimum and maximum orientations */
588
589
590 if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
591 &max_orient) != 3)
592 pos = 4;
593 else
594 {
595 pos --;
596
597 if (pos < 0 || pos > 4)
598 pos = 4;
599
600 if (orientation > max_orient)
601 orientation = max_orient;
602 else if (orientation < min_orient)
603 orientation = min_orient;
604 }
605 }
606 else
607 pos = 4;
608
609 values[pos] = orientation;
610
611 snprintf(buf, sizeof(buf), "%d %d %d %d %d\n", values[0], values[1],
612 values[2], values[3], values[4]);
613
614 if (write(fd, buf, strlen(buf)) < 1)
615 {
616 free(choices);
617 return (-1);
618 }
619
620 if (choices[i]->code == NULL)
621 {
622 /*
623 * This can happen with certain buggy PPD files that don't include
624 * a CustomPageSize command sequence... We just use a generic
625 * Level 2 command sequence...
626 */
627
628 if (write(fd, ppd_custom_code, strlen(ppd_custom_code)) < 1)
629 {
630 free(choices);
631 return (-1);
632 }
633 }
634 }
635
636 if (choices[i]->code != NULL && choices[i]->code[0] != '\0')
637 {
638 if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
639 {
640 free(choices);
641 return (-1);
642 }
643 }
644
645 if (write(fd, "%%EndFeature\n", 13) < 1)
646 {
647 free(choices);
648 return (-1);
649 }
650
651 if (write(fd, "} stopped cleartomark\n", 22) < 1)
652 {
653 free(choices);
654 return (-1);
655 }
656 }
657 else if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
658 {
659 free(choices);
660 return (-1);
661 }
662
663 free(choices);
664 return (0);
665}
666
667
668/*
669 * 'ppdEmitJCL()' - Emit code for JCL options to a file.
670 */
671
672int /* O - 0 on success, -1 on failure */
673ppdEmitJCL(ppd_file_t *ppd, /* I - PPD file record */
674 FILE *fp, /* I - File to write to */
675 int job_id, /* I - Job ID */
676 const char *user, /* I - Username */
677 const char *title) /* I - Title */
678{
679 char *ptr; /* Pointer into JCL string */
680 char temp[81]; /* Local title string */
681
682
683 /*
684 * Range check the input...
685 */
686
687 if (ppd == NULL || ppd->jcl_begin == NULL || ppd->jcl_ps == NULL)
688 return (0);
689
690 /*
691 * See if the printer supports HP PJL...
692 */
693
694 if (!strncmp(ppd->jcl_begin, "\033%-12345X@", 10))
695 {
696 /*
697 * This printer uses HP PJL commands for output; filter the output
698 * so that we only have a single "@PJL JOB" command in the header...
699 *
700 * To avoid bugs in the PJL implementation of certain vendors' products
701 * (Xerox in particular), we add a dummy "@PJL" command at the beginning
702 * of the PJL commands to initialize PJL processing.
703 */
704
705 fputs("\033%-12345X@PJL\n", fp);
706 for (ptr = ppd->jcl_begin + 9; *ptr;)
707 if (!strncmp(ptr, "@PJL JOB", 8))
708 {
709 /*
710 * Skip job command...
711 */
712
713 for (;*ptr; ptr ++)
714 if (*ptr == '\n')
715 break;
716
717 if (*ptr)
718 ptr ++;
719 }
720 else
721 {
722 /*
723 * Copy line...
724 */
725
726 for (;*ptr; ptr ++)
727 {
728 putc(*ptr, fp);
729 if (*ptr == '\n')
730 break;
731 }
732
733 if (*ptr)
734 ptr ++;
735 }
736
737 /*
738 * Eliminate any path info from the job title...
739 */
740
741 if ((ptr = strrchr(title, '/')) != NULL)
742 title = ptr + 1;
743
744 /*
745 * Replace double quotes with single quotes so that the title
746 * does not cause a PJL syntax error.
747 */
748
749 strlcpy(temp, title, sizeof(temp));
750
751 for (ptr = temp; *ptr; ptr ++)
752 if (*ptr == '\"')
753 *ptr = '\'';
754
755 /*
756 * Send PJL JOB and PJL RDYMSG commands before we enter PostScript mode...
757 */
758
759 fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%d %s %s\"\n", temp,
760 job_id, user, temp);
761 fprintf(fp, "@PJL RDYMSG DISPLAY = \"%d %s %s\"\n", job_id, user, temp);
762 }
763 else
764 fputs(ppd->jcl_begin, fp);
765
766 ppdEmit(ppd, fp, PPD_ORDER_JCL);
767 fputs(ppd->jcl_ps, fp);
768
769 return (0);
770}
771
772
773/*
774 * 'ppdEmitJCLEnd()' - Emit JCLEnd code to a file.
775 *
776 * @since CUPS 1.2@
777 */
778
779int /* O - 0 on success, -1 on failure */
780ppdEmitJCLEnd(ppd_file_t *ppd, /* I - PPD file record */
781 FILE *fp) /* I - File to write to */
782{
783 ppd_attr_t *attr; /* PPD attributes */
784
785
786 /*
787 * Range check the input...
788 */
789
790 if (ppd == NULL)
791 return (0);
792
793 if (ppd->jcl_end == NULL)
794 {
795 if (ppd->num_filters == 0)
796 fputc(0x04, fp);
797
798 if ((attr = ppdFindAttr(ppd, "cupsProtocol", NULL)) != NULL &&
799 attr->value != NULL && !strcasecmp(attr->value, "TBCP"))
800 fputs("\033%-12345X", stdout);
801
802 return (0);
803 }
804
805 /*
806 * See if the printer supports HP PJL...
807 */
808
809 if (!strncmp(ppd->jcl_end, "\033%-12345X@", 10))
810 {
811 /*
812 * This printer uses HP PJL commands for output; filter the output
813 * so that we only have a single "@PJL JOB" command in the header...
814 *
815 * To avoid bugs in the PJL implementation of certain vendors' products
816 * (Xerox in particular), we add a dummy "@PJL" command at the beginning
817 * of the PJL commands to initialize PJL processing.
818 */
819
820 fputs("\033%-12345X@PJL\n", fp);
821 fputs("@PJL RDYMSG DISPLAY = \"READY\"\n", fp);
822 fputs(ppd->jcl_end + 9, fp);
823 }
824 else
825 fputs(ppd->jcl_end, fp);
826
827 return (0);
828}
829
830
831/*
832 * 'ppd_handle_media()' - Handle media selection...
833 */
834
835static void
836ppd_handle_media(ppd_file_t *ppd)
837{
838 ppd_choice_t *manual_feed, /* ManualFeed choice, if any */
839 *input_slot, /* InputSlot choice, if any */
840 *page; /* PageSize/PageRegion */
841 ppd_size_t *size; /* Current media size */
842 ppd_attr_t *rpr; /* RequiresPageRegion value */
843
844
845 /*
846 * This function determines if the user has selected a media source
847 * via the InputSlot or ManualFeed options; if so, it marks the
848 * PageRegion option corresponding to the current media size.
849 * Otherwise it marks the PageSize option.
850 */
851
852 if ((size = ppdPageSize(ppd, NULL)) == NULL)
853 return;
854
855 manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed");
856 input_slot = ppdFindMarkedChoice(ppd, "InputSlot");
857
858 if (input_slot != NULL)
859 rpr = ppdFindAttr(ppd, "RequiresPageRegion", input_slot->choice);
860 else
861 rpr = NULL;
862
863 if (!rpr)
864 rpr = ppdFindAttr(ppd, "RequiresPageRegion", "All");
865
fa73b229 866 if (!strcasecmp(size->name, "Custom") || (!manual_feed && !input_slot) ||
867 !((manual_feed && !strcasecmp(manual_feed->choice, "True")) ||
868 (input_slot && input_slot->code && input_slot->code[0])))
ef416fc2 869 {
870 /*
871 * Manual feed was not selected and/or the input slot selection does
872 * not contain any PostScript code. Use the PageSize option...
873 */
874
875 ppdMarkOption(ppd, "PageSize", size->name);
876 }
877 else
878 {
879 /*
880 * Manual feed was selected and/or the input slot selection contains
881 * PostScript code. Use the PageRegion option...
882 */
883
884 ppdMarkOption(ppd, "PageRegion", size->name);
885
886 /*
887 * RequiresPageRegion does not apply to manual feed so we need to
888 * check that we are not doing manual feed before unmarking PageRegion.
889 */
890
891 if (!(manual_feed && !strcasecmp(manual_feed->choice, "True")) &&
892 ((rpr && rpr->value && !strcmp(rpr->value, "False")) ||
893 (!rpr && !ppd->num_filters)))
894 {
895 /*
896 * Either the PPD file specifies no PageRegion code or the PPD file
897 * not for a CUPS raster driver and thus defaults to no PageRegion
898 * code... Unmark the PageRegion choice so that we don't output the
899 * code...
900 */
901
902 page = ppdFindMarkedChoice(ppd, "PageRegion");
903
904 if (page)
905 page->marked = 0;
906 }
907 }
908}
909
910
911/*
912 * 'ppd_sort()' - Sort options by ordering numbers...
913 */
914
915static int /* O - -1 if c1 < c2, 0 if equal, 1 otherwise */
916ppd_sort(ppd_choice_t **c1, /* I - First choice */
917 ppd_choice_t **c2) /* I - Second choice */
918{
fa73b229 919 if ((*c1)->option->order < (*c2)->option->order)
ef416fc2 920 return (-1);
fa73b229 921 else if ((*c1)->option->order > (*c2)->option->order)
ef416fc2 922 return (1);
923 else
924 return (0);
925}
926
927
928/*
fa73b229 929 * End of "$Id: emit.c 4980 2006-01-25 19:57:45Z mike $".
ef416fc2 930 */