]>
Commit | Line | Data |
---|---|---|
ea930040 | 1 | /* |
b2e10895 | 2 | * "$Id$" |
ea930040 | 3 | * |
3a193f5e | 4 | * PPD code emission routines for the Common UNIX Printing System (CUPS). |
ea930040 | 5 | * |
b2e10895 | 6 | * Copyright 1997-2005 by Easy Software Products, all rights reserved. |
ea930040 | 7 | * |
3a193f5e | 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 | |
ea930040 | 16 | * Easy Software Products |
58ec2a95 | 17 | * 44141 Airport View Drive, Suite 204 |
b2e10895 | 18 | * Hollywood, Maryland 20636 USA |
ea930040 | 19 | * |
c4dcf3cc | 20 | * Voice: (301) 373-9600 |
ea930040 | 21 | * EMail: cups-info@cups.org |
22 | * WWW: http://www.cups.org | |
23 | * | |
2b85e375 | 24 | * PostScript is a trademark of Adobe Systems, Inc. |
25 | * | |
dab1a4d8 | 26 | * This file is subject to the Apple OS-Developed Software exception. |
27 | * | |
ea930040 | 28 | * Contents: |
29 | * | |
ed6078a4 | 30 | * ppdCollect() - Collect all marked options that reside in the |
31 | * specified section. | |
32 | * ppdEmit() - Emit code for marked options to a file. | |
33 | * ppdEmitFd() - Emit code for marked options to a file. | |
34 | * ppdEmitJCL() - Emit code for JCL options to a file. | |
35 | * ppd_handle_media() - Handle media selection... | |
36 | * ppd_sort() - Sort options by ordering numbers... | |
ea930040 | 37 | */ |
38 | ||
39 | /* | |
2b85e375 | 40 | * Include necessary headers... |
41 | */ | |
42 | ||
43 | #include "ppd.h" | |
3b960317 | 44 | #include <stdlib.h> |
aaa5608c | 45 | #include "string.h" |
3b960317 | 46 | |
47 | #if defined(WIN32) || defined(__EMX__) | |
2456b740 | 48 | # include <io.h> |
49 | #else | |
50 | # include <unistd.h> | |
3b960317 | 51 | #endif /* WIN32 || __EMX__ */ |
2b85e375 | 52 | |
53 | ||
8c1333e2 | 54 | /* |
55 | * Local functions... | |
56 | */ | |
57 | ||
ed6078a4 | 58 | static void ppd_handle_media(ppd_file_t *ppd); |
8c1333e2 | 59 | static int ppd_sort(ppd_choice_t **c1, ppd_choice_t **c2); |
cbcf8057 | 60 | |
61 | ||
ed6078a4 | 62 | /* |
63 | * Local globals... | |
64 | */ | |
65 | ||
66 | static const char *ppd_custom_code = | |
67 | "pop pop pop\n" | |
68 | "<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n"; | |
69 | ||
70 | ||
cbcf8057 | 71 | /* |
72 | * 'ppdCollect()' - Collect all marked options that reside in the specified | |
73 | * section. | |
74 | */ | |
75 | ||
76 | int /* O - Number of options marked */ | |
77 | ppdCollect(ppd_file_t *ppd, /* I - PPD file data */ | |
78 | ppd_section_t section, /* I - Section to collect */ | |
79 | ppd_choice_t ***choices) /* O - Pointers to choices */ | |
80 | { | |
81 | int i, j, k, m; /* Looping vars */ | |
82 | ppd_group_t *g, /* Current group */ | |
83 | *sg; /* Current sub-group */ | |
84 | ppd_option_t *o; /* Current option */ | |
85 | ppd_choice_t *c; /* Current choice */ | |
86 | int count; /* Number of choices collected */ | |
87 | ppd_choice_t **collect; /* Collected choices */ | |
88 | ||
89 | ||
90 | if (ppd == NULL) | |
91 | return (0); | |
92 | ||
93 | /* | |
94 | * Allocate memory for up to 1000 selected choices... | |
95 | */ | |
96 | ||
97 | count = 0; | |
98 | collect = calloc(sizeof(ppd_choice_t *), 1000); | |
99 | ||
100 | /* | |
101 | * Loop through all options and add choices as needed... | |
102 | */ | |
103 | ||
104 | for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++) | |
105 | { | |
106 | for (j = g->num_options, o = g->options; j > 0; j --, o ++) | |
107 | if (o->section == section) | |
108 | for (k = o->num_choices, c = o->choices; k > 0; k --, c ++) | |
109 | if (c->marked && count < 1000) | |
110 | { | |
111 | collect[count] = c; | |
112 | count ++; | |
113 | } | |
114 | ||
115 | for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++) | |
116 | for (k = sg->num_options, o = sg->options; k > 0; k --, o ++) | |
117 | if (o->section == section) | |
118 | for (m = o->num_choices, c = o->choices; m > 0; m --, c ++) | |
119 | if (c->marked && count < 1000) | |
120 | { | |
121 | collect[count] = c; | |
122 | count ++; | |
123 | } | |
124 | } | |
125 | ||
126 | /* | |
127 | * If we have more than 1 marked choice, sort them... | |
128 | */ | |
129 | ||
130 | if (count > 1) | |
131 | qsort(collect, count, sizeof(ppd_choice_t *), | |
132 | (int (*)(const void *, const void *))ppd_sort); | |
133 | ||
134 | /* | |
135 | * Return the array and number of choices; if 0, free the array since | |
136 | * it isn't needed. | |
137 | */ | |
138 | ||
139 | if (count > 0) | |
140 | { | |
141 | *choices = collect; | |
142 | return (count); | |
143 | } | |
144 | else | |
145 | { | |
146 | *choices = NULL; | |
147 | free(collect); | |
148 | return (0); | |
149 | } | |
150 | } | |
8c1333e2 | 151 | |
152 | ||
2b85e375 | 153 | /* |
154 | * 'ppdEmit()' - Emit code for marked options to a file. | |
155 | */ | |
156 | ||
157 | int /* O - 0 on success, -1 on failure */ | |
158 | ppdEmit(ppd_file_t *ppd, /* I - PPD file record */ | |
159 | FILE *fp, /* I - File to write to */ | |
160 | ppd_section_t section) /* I - Section to write */ | |
161 | { | |
8c1333e2 | 162 | int i, /* Looping var */ |
163 | count; /* Number of choices */ | |
164 | ppd_choice_t **choices; /* Choices */ | |
6fdf969a | 165 | ppd_size_t *size; /* Custom page size */ |
8c1333e2 | 166 | |
167 | ||
ed6078a4 | 168 | /* |
169 | * Use PageSize or PageRegion as required... | |
170 | */ | |
171 | ||
172 | ppd_handle_media(ppd); | |
173 | ||
174 | /* | |
175 | * Collect the options we need to emit and emit them! | |
176 | */ | |
177 | ||
cbcf8057 | 178 | if ((count = ppdCollect(ppd, section, &choices)) == 0) |
8c1333e2 | 179 | return (0); |
180 | ||
181 | for (i = 0; i < count; i ++) | |
182 | if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) | |
183 | { | |
96831d7f | 184 | /* |
185 | * Send wrapper commands to prevent printer errors for unsupported | |
186 | * options... | |
187 | */ | |
188 | ||
189 | if (fputs("[{\n", fp) < 0) | |
190 | { | |
191 | free(choices); | |
192 | return (-1); | |
193 | } | |
194 | ||
8c1333e2 | 195 | /* |
196 | * Send DSC comments with option... | |
197 | */ | |
198 | ||
ed6078a4 | 199 | if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 || |
200 | strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) && | |
a7b3e92e | 201 | strcasecmp(choices[i]->choice, "Custom") == 0) |
6fdf969a | 202 | { |
203 | /* | |
8c5f90ff | 204 | * Variable size; write out standard size options, using the |
205 | * parameter positions defined in the PPD file... | |
6fdf969a | 206 | */ |
207 | ||
8c5f90ff | 208 | ppd_attr_t *attr; /* PPD attribute */ |
209 | int pos, /* Position of custom value */ | |
ae90e335 | 210 | values[5], /* Values for custom command */ |
211 | orientation; /* Orientation to use */ | |
8c5f90ff | 212 | |
213 | ||
214 | fputs("%%BeginFeature: *CustomPageSize True\n", fp); | |
215 | ||
6fdf969a | 216 | size = ppdPageSize(ppd, "Custom"); |
8c5f90ff | 217 | |
218 | memset(values, 0, sizeof(values)); | |
219 | ||
220 | if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL) | |
221 | { | |
222 | pos = atoi(attr->value) - 1; | |
223 | ||
224 | if (pos < 0 || pos > 4) | |
225 | pos = 0; | |
226 | } | |
227 | else | |
228 | pos = 0; | |
229 | ||
230 | values[pos] = (int)size->width; | |
231 | ||
232 | if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL) | |
233 | { | |
234 | pos = atoi(attr->value) - 1; | |
235 | ||
236 | if (pos < 0 || pos > 4) | |
237 | pos = 1; | |
238 | } | |
239 | else | |
240 | pos = 1; | |
241 | ||
242 | values[pos] = (int)size->length; | |
243 | ||
7161ef54 | 244 | /* |
245 | * According to the Adobe PPD specification, an orientation of 1 | |
246 | * will produce a print that comes out upside-down with the X | |
247 | * axis perpendicular to the direction of feed, which is exactly | |
248 | * what we want to be consistent with non-PS printers. | |
249 | * | |
250 | * We could also use an orientation of 3 to produce output that | |
251 | * comes out rightside-up (this is the default for many large format | |
252 | * printer PPDs), however for consistency we will stick with the | |
253 | * value 1. | |
254 | * | |
255 | * If we wanted to get fancy, we could use orientations of 0 or | |
256 | * 2 and swap the width and length, however we don't want to get | |
257 | * fancy, we just want it to work consistently. | |
258 | * | |
259 | * The orientation value is range limited by the Orientation | |
260 | * parameter definition, so certain non-PS printer drivers that | |
261 | * only support an Orientation of 0 will get the value 0 as | |
262 | * expected. | |
263 | */ | |
264 | ||
265 | orientation = 1; | |
ae90e335 | 266 | |
267 | if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", | |
268 | "Orientation")) != NULL) | |
269 | { | |
270 | int min_orient, max_orient; /* Minimum and maximum orientations */ | |
271 | ||
272 | ||
273 | if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient, | |
274 | &max_orient) != 3) | |
275 | pos = 4; | |
276 | else | |
277 | { | |
5edf6841 | 278 | pos --; |
279 | ||
ae90e335 | 280 | if (pos < 0 || pos > 4) |
281 | pos = 4; | |
282 | ||
283 | if (orientation > max_orient) | |
284 | orientation = max_orient; | |
285 | else if (orientation < min_orient) | |
286 | orientation = min_orient; | |
287 | } | |
288 | } | |
289 | else | |
290 | pos = 4; | |
291 | ||
292 | values[pos] = orientation; | |
293 | ||
8c5f90ff | 294 | fprintf(fp, "%d %d %d %d %d\n", values[0], values[1], |
295 | values[2], values[3], values[4]); | |
6fdf969a | 296 | |
297 | if (choices[i]->code == NULL) | |
298 | { | |
299 | /* | |
300 | * This can happen with certain buggy PPD files that don't include | |
301 | * a CustomPageSize command sequence... We just use a generic | |
302 | * Level 2 command sequence... | |
303 | */ | |
304 | ||
ed6078a4 | 305 | fputs(ppd_custom_code, fp); |
6fdf969a | 306 | } |
307 | } | |
8c5f90ff | 308 | else if (fprintf(fp, "%%%%BeginFeature: *%s %s\n", |
309 | ((ppd_option_t *)choices[i]->option)->keyword, | |
310 | choices[i]->choice) < 0) | |
311 | { | |
312 | free(choices); | |
313 | return (-1); | |
314 | } | |
6fdf969a | 315 | |
316 | if (choices[i]->code != NULL && choices[i]->code[0] != '\0') | |
8c1333e2 | 317 | { |
d23a857a | 318 | if (fputs(choices[i]->code, fp) < 0) |
58ec2a95 | 319 | { |
320 | free(choices); | |
321 | return (-1); | |
322 | } | |
323 | ||
d23a857a | 324 | if (choices[i]->code[strlen(choices[i]->code) - 1] != '\n') |
58ec2a95 | 325 | putc('\n', fp); |
8c1333e2 | 326 | } |
327 | ||
58ec2a95 | 328 | if (fputs("%%EndFeature\n", fp) < 0) |
8c1333e2 | 329 | { |
330 | free(choices); | |
331 | return (-1); | |
332 | } | |
96831d7f | 333 | |
334 | if (fputs("} stopped cleartomark\n", fp) < 0) | |
335 | { | |
336 | free(choices); | |
337 | return (-1); | |
338 | } | |
8c1333e2 | 339 | } |
d23a857a | 340 | else if (fputs(choices[i]->code, fp) < 0) |
8c1333e2 | 341 | { |
342 | free(choices); | |
343 | return (-1); | |
344 | } | |
345 | ||
346 | free(choices); | |
2b85e375 | 347 | return (0); |
348 | } | |
349 | ||
350 | ||
351 | /* | |
352 | * 'ppdEmitFd()' - Emit code for marked options to a file. | |
ea930040 | 353 | */ |
354 | ||
2b85e375 | 355 | int /* O - 0 on success, -1 on failure */ |
356 | ppdEmitFd(ppd_file_t *ppd, /* I - PPD file record */ | |
357 | int fd, /* I - File to write to */ | |
358 | ppd_section_t section) /* I - Section to write */ | |
359 | { | |
8c1333e2 | 360 | int i, /* Looping var */ |
8c5f90ff | 361 | count, /* Number of choices */ |
362 | custom_size; /* Non-zero if this option is a custom size */ | |
8c1333e2 | 363 | ppd_choice_t **choices; /* Choices */ |
ed6078a4 | 364 | ppd_size_t *size; /* Custom page size */ |
8c1333e2 | 365 | char buf[1024]; /* Output buffer for feature */ |
366 | ||
367 | ||
ed6078a4 | 368 | /* |
369 | * Use PageSize or PageRegion as required... | |
370 | */ | |
371 | ||
372 | ppd_handle_media(ppd); | |
373 | ||
374 | /* | |
375 | * Collect the options we need to emit and emit them! | |
376 | */ | |
377 | ||
cbcf8057 | 378 | if ((count = ppdCollect(ppd, section, &choices)) == 0) |
8c1333e2 | 379 | return (0); |
380 | ||
381 | for (i = 0; i < count; i ++) | |
382 | if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) | |
383 | { | |
96831d7f | 384 | /* |
385 | * Send wrapper commands to prevent printer errors for unsupported | |
386 | * options... | |
387 | */ | |
388 | ||
389 | if (write(fd, "[{\n", 3) < 1) | |
390 | { | |
391 | free(choices); | |
392 | return (-1); | |
393 | } | |
394 | ||
8c1333e2 | 395 | /* |
396 | * Send DSC comments with option... | |
397 | */ | |
398 | ||
8c5f90ff | 399 | if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 || |
400 | strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) && | |
401 | strcasecmp(choices[i]->choice, "Custom") == 0) | |
402 | { | |
403 | custom_size = 1; | |
404 | ||
405 | strcpy(buf, "%%BeginFeature: *CustomPageSize True\n"); | |
406 | } | |
407 | else | |
408 | { | |
409 | custom_size = 0; | |
410 | ||
411 | snprintf(buf, sizeof(buf), "%%%%BeginFeature: *%s %s\n", | |
412 | ((ppd_option_t *)choices[i]->option)->keyword, | |
413 | choices[i]->choice); | |
414 | } | |
8c1333e2 | 415 | |
416 | if (write(fd, buf, strlen(buf)) < 1) | |
417 | { | |
418 | free(choices); | |
419 | return (-1); | |
420 | } | |
421 | ||
8c5f90ff | 422 | if (custom_size) |
8c1333e2 | 423 | { |
ed6078a4 | 424 | /* |
8c5f90ff | 425 | * Variable size; write out standard size options, using the |
426 | * parameter positions defined in the PPD file... | |
ed6078a4 | 427 | */ |
428 | ||
8c5f90ff | 429 | ppd_attr_t *attr; /* PPD attribute */ |
430 | int pos, /* Position of custom value */ | |
ae90e335 | 431 | values[5], /* Values for custom command */ |
432 | orientation; /* Orientation to use */ | |
8c5f90ff | 433 | |
434 | ||
ed6078a4 | 435 | size = ppdPageSize(ppd, "Custom"); |
8c5f90ff | 436 | |
437 | memset(values, 0, sizeof(values)); | |
438 | ||
439 | if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL) | |
440 | { | |
441 | pos = atoi(attr->value) - 1; | |
442 | ||
443 | if (pos < 0 || pos > 4) | |
444 | pos = 0; | |
445 | } | |
446 | else | |
447 | pos = 0; | |
448 | ||
449 | values[pos] = (int)size->width; | |
450 | ||
451 | if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL) | |
452 | { | |
453 | pos = atoi(attr->value) - 1; | |
454 | ||
455 | if (pos < 0 || pos > 4) | |
456 | pos = 1; | |
457 | } | |
458 | else | |
459 | pos = 1; | |
460 | ||
461 | values[pos] = (int)size->length; | |
462 | ||
ae90e335 | 463 | if (size->width < size->length) |
464 | orientation = 1; | |
465 | else | |
466 | orientation = 0; | |
467 | ||
468 | if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", | |
469 | "Orientation")) != NULL) | |
470 | { | |
471 | int min_orient, max_orient; /* Minimum and maximum orientations */ | |
472 | ||
473 | ||
474 | if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient, | |
475 | &max_orient) != 3) | |
476 | pos = 4; | |
477 | else | |
478 | { | |
5edf6841 | 479 | pos --; |
480 | ||
ae90e335 | 481 | if (pos < 0 || pos > 4) |
482 | pos = 4; | |
483 | ||
484 | if (orientation > max_orient) | |
485 | orientation = max_orient; | |
486 | else if (orientation < min_orient) | |
487 | orientation = min_orient; | |
488 | } | |
489 | } | |
490 | else | |
491 | pos = 4; | |
492 | ||
493 | values[pos] = orientation; | |
494 | ||
8c5f90ff | 495 | snprintf(buf, sizeof(buf), "%d %d %d %d %d\n", values[0], values[1], |
496 | values[2], values[3], values[4]); | |
ed6078a4 | 497 | |
498 | if (write(fd, buf, strlen(buf)) < 1) | |
499 | { | |
500 | free(choices); | |
501 | return (-1); | |
502 | } | |
503 | ||
504 | if (choices[i]->code == NULL) | |
505 | { | |
506 | /* | |
507 | * This can happen with certain buggy PPD files that don't include | |
508 | * a CustomPageSize command sequence... We just use a generic | |
509 | * Level 2 command sequence... | |
510 | */ | |
511 | ||
512 | if (write(fd, ppd_custom_code, strlen(ppd_custom_code)) < 1) | |
513 | { | |
514 | free(choices); | |
515 | return (-1); | |
516 | } | |
517 | } | |
518 | } | |
519 | ||
520 | if (choices[i]->code != NULL && choices[i]->code[0] != '\0') | |
521 | { | |
522 | if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1) | |
523 | { | |
524 | free(choices); | |
525 | return (-1); | |
526 | } | |
8c1333e2 | 527 | } |
528 | ||
529 | if (write(fd, "%%EndFeature\n", 13) < 1) | |
530 | { | |
531 | free(choices); | |
532 | return (-1); | |
533 | } | |
96831d7f | 534 | |
535 | if (write(fd, "} stopped cleartomark\n", 22) < 1) | |
536 | { | |
537 | free(choices); | |
538 | return (-1); | |
539 | } | |
8c1333e2 | 540 | } |
d23a857a | 541 | else if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1) |
8c1333e2 | 542 | { |
543 | free(choices); | |
544 | return (-1); | |
545 | } | |
546 | ||
547 | free(choices); | |
2b85e375 | 548 | return (0); |
549 | } | |
ea930040 | 550 | |
551 | ||
ee6a18b5 | 552 | /* |
553 | * 'ppdEmitJCL()' - Emit code for JCL options to a file. | |
554 | */ | |
555 | ||
556 | int /* O - 0 on success, -1 on failure */ | |
557 | ppdEmitJCL(ppd_file_t *ppd, /* I - PPD file record */ | |
558 | FILE *fp, /* I - File to write to */ | |
559 | int job_id, /* I - Job ID */ | |
560 | const char *user, /* I - Username */ | |
561 | const char *title) /* I - Title */ | |
562 | { | |
33b8a82d | 563 | char *ptr; /* Pointer into JCL string */ |
ae90e335 | 564 | char temp[81]; /* Local title string */ |
ee6a18b5 | 565 | |
566 | ||
b2e10895 | 567 | /* |
568 | * Range check the input... | |
569 | */ | |
570 | ||
ee6a18b5 | 571 | if (ppd == NULL || ppd->jcl_begin == NULL || ppd->jcl_ps == NULL) |
572 | return (0); | |
573 | ||
b2e10895 | 574 | /* |
575 | * See if the printer supports HP PJL... | |
576 | */ | |
577 | ||
ee6a18b5 | 578 | if (strncmp(ppd->jcl_begin, "\033%-12345X@", 10) == 0) |
579 | { | |
580 | /* | |
581 | * This printer uses HP PJL commands for output; filter the output | |
582 | * so that we only have a single "@PJL JOB" command in the header... | |
ae90e335 | 583 | * |
584 | * To avoid bugs in the PJL implementation of certain vendors' products | |
585 | * (Xerox in particular), we add a dummy "@PJL" command at the beginning | |
586 | * of the PJL commands to initialize PJL processing. | |
ee6a18b5 | 587 | */ |
588 | ||
ae90e335 | 589 | fputs("\033%-12345X@PJL\n", fp); |
ee6a18b5 | 590 | for (ptr = ppd->jcl_begin + 9; *ptr;) |
591 | if (strncmp(ptr, "@PJL JOB", 8) == 0) | |
592 | { | |
593 | /* | |
594 | * Skip job command... | |
595 | */ | |
596 | ||
597 | for (;*ptr; ptr ++) | |
598 | if (*ptr == '\n') | |
599 | break; | |
600 | ||
601 | if (*ptr) | |
602 | ptr ++; | |
603 | } | |
604 | else | |
605 | { | |
606 | /* | |
607 | * Copy line... | |
608 | */ | |
609 | ||
610 | for (;*ptr; ptr ++) | |
611 | { | |
612 | putc(*ptr, fp); | |
613 | if (*ptr == '\n') | |
614 | break; | |
615 | } | |
616 | ||
617 | if (*ptr) | |
618 | ptr ++; | |
619 | } | |
620 | ||
b2e10895 | 621 | /* |
622 | * Eliminate any path info from the job title... | |
623 | */ | |
624 | ||
625 | if ((ptr = strrchr(title, '/')) != NULL) | |
626 | title = ptr + 1; | |
627 | ||
ae90e335 | 628 | /* |
629 | * Replace double quotes with single quotes so that the title | |
630 | * does not cause a PJL syntax error. | |
631 | */ | |
632 | ||
633 | strlcpy(temp, title, sizeof(temp)); | |
634 | ||
635 | for (ptr = temp; *ptr; ptr ++) | |
636 | if (*ptr == '\"') | |
637 | *ptr = '\''; | |
638 | ||
ee6a18b5 | 639 | /* |
640 | * Send PJL JOB command before we enter PostScript mode... | |
641 | */ | |
642 | ||
ae90e335 | 643 | fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%d %s %s\"\n", temp, |
644 | job_id, user, temp); | |
ee6a18b5 | 645 | } |
646 | else | |
af50faa7 | 647 | fputs(ppd->jcl_begin, fp); |
ee6a18b5 | 648 | |
af50faa7 | 649 | ppdEmit(ppd, fp, PPD_ORDER_JCL); |
650 | fputs(ppd->jcl_ps, fp); | |
37ac5c5e | 651 | |
652 | return (0); | |
ee6a18b5 | 653 | } |
654 | ||
655 | ||
ed6078a4 | 656 | /* |
657 | * 'ppd_handle_media()' - Handle media selection... | |
658 | */ | |
659 | ||
660 | static void | |
661 | ppd_handle_media(ppd_file_t *ppd) | |
662 | { | |
663 | ppd_choice_t *manual_feed, /* ManualFeed choice, if any */ | |
b3291c5a | 664 | *input_slot, /* InputSlot choice, if any */ |
665 | *page; /* PageSize/PageRegion */ | |
ed6078a4 | 666 | ppd_size_t *size; /* Current media size */ |
1b98ab76 | 667 | ppd_attr_t *rpr; /* RequiresPageRegion value */ |
ed6078a4 | 668 | |
669 | ||
670 | /* | |
671 | * This function determines if the user has selected a media source | |
672 | * via the InputSlot or ManualFeed options; if so, it marks the | |
673 | * PageRegion option corresponding to the current media size. | |
674 | * Otherwise it marks the PageSize option. | |
675 | */ | |
676 | ||
677 | if ((size = ppdPageSize(ppd, NULL)) == NULL) | |
678 | return; | |
679 | ||
680 | manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed"); | |
681 | input_slot = ppdFindMarkedChoice(ppd, "InputSlot"); | |
682 | ||
b3291c5a | 683 | if (input_slot != NULL) |
684 | rpr = ppdFindAttr(ppd, "RequiresPageRegion", input_slot->choice); | |
685 | else | |
686 | rpr = NULL; | |
687 | ||
688 | if (!rpr) | |
689 | rpr = ppdFindAttr(ppd, "RequiresPageRegion", "All"); | |
690 | ||
ed6078a4 | 691 | if (strcasecmp(size->name, "Custom") == 0 || |
692 | (manual_feed == NULL && input_slot == NULL) || | |
693 | (manual_feed != NULL && strcasecmp(manual_feed->choice, "False") == 0) || | |
694 | (input_slot != NULL && (input_slot->code == NULL || !input_slot->code[0]))) | |
695 | { | |
696 | /* | |
697 | * Manual feed was not selected and/or the input slot selection does | |
698 | * not contain any PostScript code. Use the PageSize option... | |
699 | */ | |
700 | ||
701 | ppdMarkOption(ppd, "PageSize", size->name); | |
702 | } | |
703 | else | |
704 | { | |
705 | /* | |
706 | * Manual feed was selected and/or the input slot selection contains | |
707 | * PostScript code. Use the PageRegion option... | |
708 | */ | |
709 | ||
710 | ppdMarkOption(ppd, "PageRegion", size->name); | |
b3291c5a | 711 | |
6f83172d | 712 | /* |
713 | * RequiresPageRegion does not apply to manual feed so we need to | |
714 | * check that we are not doing manual feed before unmarking PageRegion. | |
715 | */ | |
716 | ||
717 | if (!(manual_feed && !strcasecmp(manual_feed->choice, "True")) && | |
718 | ((rpr && rpr->value && !strcmp(rpr->value, "False")) || | |
719 | (!rpr && !ppd->num_filters))) | |
b3291c5a | 720 | { |
721 | /* | |
722 | * Either the PPD file specifies no PageRegion code or the PPD file | |
723 | * not for a CUPS raster driver and thus defaults to no PageRegion | |
724 | * code... Unmark the PageRegion choice so that we don't output the | |
725 | * code... | |
726 | */ | |
727 | ||
728 | page = ppdFindMarkedChoice(ppd, "PageRegion"); | |
729 | ||
730 | if (page) | |
731 | page->marked = 0; | |
732 | } | |
ed6078a4 | 733 | } |
734 | } | |
735 | ||
736 | ||
ea930040 | 737 | /* |
8c1333e2 | 738 | * 'ppd_sort()' - Sort options by ordering numbers... |
739 | */ | |
740 | ||
741 | static int /* O - -1 if c1 < c2, 0 if equal, 1 otherwise */ | |
742 | ppd_sort(ppd_choice_t **c1, /* I - First choice */ | |
743 | ppd_choice_t **c2) /* I - Second choice */ | |
744 | { | |
745 | if (((ppd_option_t *)(*c1)->option)->order < ((ppd_option_t *)(*c2)->option)->order) | |
746 | return (-1); | |
747 | else if (((ppd_option_t *)(*c1)->option)->order > ((ppd_option_t *)(*c2)->option)->order) | |
748 | return (1); | |
749 | else | |
750 | return (0); | |
751 | } | |
752 | ||
753 | ||
754 | /* | |
b2e10895 | 755 | * End of "$Id$". |
ea930040 | 756 | */ |