]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/emit.c
Copyright update...
[thirdparty/cups.git] / cups / emit.c
1 /*
2 * "$Id: emit.c,v 1.25 2002/01/02 17:58:38 mike Exp $"
3 *
4 * PPD code emission routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2002 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-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * PostScript is a trademark of Adobe Systems, Inc.
25 *
26 * Contents:
27 *
28 * ppdCollect() - Collect all marked options that reside in the specified
29 * ppdEmit() - Emit code for marked options to a file.
30 * ppdEmitFd() - Emit code for marked options to a file.
31 * ppdEmitJCL() - Emit code for JCL options to a file.
32 * ppd_sort() - Sort options by ordering numbers...
33 */
34
35 /*
36 * Include necessary headers...
37 */
38
39 #include "ppd.h"
40 #include <stdlib.h>
41 #include "string.h"
42
43 #if defined(WIN32) || defined(__EMX__)
44 # include <io.h>
45 #else
46 # include <unistd.h>
47 #endif /* WIN32 || __EMX__ */
48
49
50 /*
51 * Local functions...
52 */
53
54 static int ppd_sort(ppd_choice_t **c1, ppd_choice_t **c2);
55
56
57 /*
58 * 'ppdCollect()' - Collect all marked options that reside in the specified
59 * section.
60 */
61
62 int /* O - Number of options marked */
63 ppdCollect(ppd_file_t *ppd, /* I - PPD file data */
64 ppd_section_t section, /* I - Section to collect */
65 ppd_choice_t ***choices) /* O - Pointers to choices */
66 {
67 int i, j, k, m; /* Looping vars */
68 ppd_group_t *g, /* Current group */
69 *sg; /* Current sub-group */
70 ppd_option_t *o; /* Current option */
71 ppd_choice_t *c; /* Current choice */
72 int count; /* Number of choices collected */
73 ppd_choice_t **collect; /* Collected choices */
74
75
76 if (ppd == NULL)
77 return (0);
78
79 /*
80 * Allocate memory for up to 1000 selected choices...
81 */
82
83 count = 0;
84 collect = calloc(sizeof(ppd_choice_t *), 1000);
85
86 /*
87 * Loop through all options and add choices as needed...
88 */
89
90 for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
91 {
92 for (j = g->num_options, o = g->options; j > 0; j --, o ++)
93 if (o->section == section)
94 for (k = o->num_choices, c = o->choices; k > 0; k --, c ++)
95 if (c->marked && count < 1000)
96 {
97 collect[count] = c;
98 count ++;
99 }
100
101 for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
102 for (k = sg->num_options, o = sg->options; k > 0; k --, o ++)
103 if (o->section == section)
104 for (m = o->num_choices, c = o->choices; m > 0; m --, c ++)
105 if (c->marked && count < 1000)
106 {
107 collect[count] = c;
108 count ++;
109 }
110 }
111
112 /*
113 * If we have more than 1 marked choice, sort them...
114 */
115
116 if (count > 1)
117 qsort(collect, count, sizeof(ppd_choice_t *),
118 (int (*)(const void *, const void *))ppd_sort);
119
120 /*
121 * Return the array and number of choices; if 0, free the array since
122 * it isn't needed.
123 */
124
125 if (count > 0)
126 {
127 *choices = collect;
128 return (count);
129 }
130 else
131 {
132 *choices = NULL;
133 free(collect);
134 return (0);
135 }
136 }
137
138
139 /*
140 * 'ppdEmit()' - Emit code for marked options to a file.
141 */
142
143 int /* O - 0 on success, -1 on failure */
144 ppdEmit(ppd_file_t *ppd, /* I - PPD file record */
145 FILE *fp, /* I - File to write to */
146 ppd_section_t section) /* I - Section to write */
147 {
148 int i, /* Looping var */
149 count; /* Number of choices */
150 ppd_choice_t **choices; /* Choices */
151 ppd_size_t *size; /* Custom page size */
152
153
154 if ((count = ppdCollect(ppd, section, &choices)) == 0)
155 return (0);
156
157 for (i = 0; i < count; i ++)
158 if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
159 {
160 /*
161 * Send wrapper commands to prevent printer errors for unsupported
162 * options...
163 */
164
165 if (fputs("[{\n", fp) < 0)
166 {
167 free(choices);
168 return (-1);
169 }
170
171 /*
172 * Send DSC comments with option...
173 */
174
175 if (fprintf(fp, "%%%%BeginFeature: %s %s\n",
176 ((ppd_option_t *)choices[i]->option)->keyword,
177 choices[i]->choice) < 0)
178 {
179 free(choices);
180 return (-1);
181 }
182
183 if (strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 &&
184 strcasecmp(choices[i]->choice, "Custom") == 0)
185 {
186 /*
187 * Variable size; write out standard size options (this should
188 * eventually be changed to use the parameter positions defined
189 * in the PPD file...)
190 */
191
192 size = ppdPageSize(ppd, "Custom");
193 fprintf(fp, "%.0f %.0f 0 0 0\n", size->width, size->length);
194
195 if (choices[i]->code == NULL)
196 {
197 /*
198 * This can happen with certain buggy PPD files that don't include
199 * a CustomPageSize command sequence... We just use a generic
200 * Level 2 command sequence...
201 */
202
203 fputs("pop pop pop\n", fp);
204 fputs("<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n", fp);
205 }
206 }
207
208 if (choices[i]->code != NULL && choices[i]->code[0] != '\0')
209 {
210 if (fputs(choices[i]->code, fp) < 0)
211 {
212 free(choices);
213 return (-1);
214 }
215
216 if (choices[i]->code[strlen(choices[i]->code) - 1] != '\n')
217 putc('\n', fp);
218 }
219
220 if (fputs("%%EndFeature\n", fp) < 0)
221 {
222 free(choices);
223 return (-1);
224 }
225
226 if (fputs("} stopped cleartomark\n", fp) < 0)
227 {
228 free(choices);
229 return (-1);
230 }
231 }
232 else if (fputs(choices[i]->code, fp) < 0)
233 {
234 free(choices);
235 return (-1);
236 }
237
238 free(choices);
239 return (0);
240 }
241
242
243 /*
244 * 'ppdEmitFd()' - Emit code for marked options to a file.
245 */
246
247 int /* O - 0 on success, -1 on failure */
248 ppdEmitFd(ppd_file_t *ppd, /* I - PPD file record */
249 int fd, /* I - File to write to */
250 ppd_section_t section) /* I - Section to write */
251 {
252 int i, /* Looping var */
253 count; /* Number of choices */
254 ppd_choice_t **choices; /* Choices */
255 char buf[1024]; /* Output buffer for feature */
256
257
258 if ((count = ppdCollect(ppd, section, &choices)) == 0)
259 return (0);
260
261 for (i = 0; i < count; i ++)
262 if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
263 {
264 /*
265 * Send wrapper commands to prevent printer errors for unsupported
266 * options...
267 */
268
269 if (write(fd, "[{\n", 3) < 1)
270 {
271 free(choices);
272 return (-1);
273 }
274
275 /*
276 * Send DSC comments with option...
277 */
278
279 snprintf(buf, sizeof(buf), "%%%%BeginFeature: %s %s\n",
280 ((ppd_option_t *)choices[i]->option)->keyword,
281 choices[i]->choice);
282
283 if (write(fd, buf, strlen(buf)) < 1)
284 {
285 free(choices);
286 return (-1);
287 }
288
289 if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
290 {
291 free(choices);
292 return (-1);
293 }
294
295 if (write(fd, "%%EndFeature\n", 13) < 1)
296 {
297 free(choices);
298 return (-1);
299 }
300
301 if (write(fd, "} stopped cleartomark\n", 22) < 1)
302 {
303 free(choices);
304 return (-1);
305 }
306 }
307 else if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
308 {
309 free(choices);
310 return (-1);
311 }
312
313 free(choices);
314 return (0);
315 }
316
317
318 /*
319 * 'ppdEmitJCL()' - Emit code for JCL options to a file.
320 */
321
322 int /* O - 0 on success, -1 on failure */
323 ppdEmitJCL(ppd_file_t *ppd, /* I - PPD file record */
324 FILE *fp, /* I - File to write to */
325 int job_id, /* I - Job ID */
326 const char *user, /* I - Username */
327 const char *title) /* I - Title */
328 {
329 const char *ptr; /* Pointer into JCL string */
330
331
332 /*
333 * Range check the input...
334 */
335
336 if (ppd == NULL || ppd->jcl_begin == NULL || ppd->jcl_ps == NULL)
337 return (0);
338
339 /*
340 * See if the printer supports HP PJL...
341 */
342
343 if (strncmp(ppd->jcl_begin, "\033%-12345X@", 10) == 0)
344 {
345 /*
346 * This printer uses HP PJL commands for output; filter the output
347 * so that we only have a single "@PJL JOB" command in the header...
348 */
349
350 fputs("\033%-12345X", fp);
351 for (ptr = ppd->jcl_begin + 9; *ptr;)
352 if (strncmp(ptr, "@PJL JOB", 8) == 0)
353 {
354 /*
355 * Skip job command...
356 */
357
358 for (;*ptr; ptr ++)
359 if (*ptr == '\n')
360 break;
361
362 if (*ptr)
363 ptr ++;
364 }
365 else
366 {
367 /*
368 * Copy line...
369 */
370
371 for (;*ptr; ptr ++)
372 {
373 putc(*ptr, fp);
374 if (*ptr == '\n')
375 break;
376 }
377
378 if (*ptr)
379 ptr ++;
380 }
381
382 /*
383 * Eliminate any path info from the job title...
384 */
385
386 if ((ptr = strrchr(title, '/')) != NULL)
387 title = ptr + 1;
388
389 /*
390 * Send PJL JOB command before we enter PostScript mode...
391 */
392
393 fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%d %s %s\"\n", title,
394 job_id, user, title);
395 }
396 else
397 fputs(ppd->jcl_begin, stdout);
398
399 ppdEmit(ppd, stdout, PPD_ORDER_JCL);
400 fputs(ppd->jcl_ps, stdout);
401
402 return (0);
403 }
404
405
406 /*
407 * 'ppd_sort()' - Sort options by ordering numbers...
408 */
409
410 static int /* O - -1 if c1 < c2, 0 if equal, 1 otherwise */
411 ppd_sort(ppd_choice_t **c1, /* I - First choice */
412 ppd_choice_t **c2) /* I - Second choice */
413 {
414 if (((ppd_option_t *)(*c1)->option)->order < ((ppd_option_t *)(*c2)->option)->order)
415 return (-1);
416 else if (((ppd_option_t *)(*c1)->option)->order > ((ppd_option_t *)(*c2)->option)->order)
417 return (1);
418 else
419 return (0);
420 }
421
422
423 /*
424 * End of "$Id: emit.c,v 1.25 2002/01/02 17:58:38 mike Exp $".
425 */