xref: /aosp_15_r20/external/libcups/cups/ppd-emit.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * PPD code emission routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  *
10*5e7646d2SAndroid Build Coastguard Worker  * PostScript is a trademark of Adobe Systems, Inc.
11*5e7646d2SAndroid Build Coastguard Worker  */
12*5e7646d2SAndroid Build Coastguard Worker 
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
15*5e7646d2SAndroid Build Coastguard Worker  */
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
18*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
19*5e7646d2SAndroid Build Coastguard Worker #include "ppd.h"
20*5e7646d2SAndroid Build Coastguard Worker #if defined(_WIN32) || defined(__EMX__)
21*5e7646d2SAndroid Build Coastguard Worker #  include <io.h>
22*5e7646d2SAndroid Build Coastguard Worker #else
23*5e7646d2SAndroid Build Coastguard Worker #  include <unistd.h>
24*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 || __EMX__ */
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker 
27*5e7646d2SAndroid Build Coastguard Worker /*
28*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
29*5e7646d2SAndroid Build Coastguard Worker  */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker static int	ppd_compare_cparams(ppd_cparam_t *a, ppd_cparam_t *b);
32*5e7646d2SAndroid Build Coastguard Worker static void	ppd_handle_media(ppd_file_t *ppd);
33*5e7646d2SAndroid Build Coastguard Worker 
34*5e7646d2SAndroid Build Coastguard Worker 
35*5e7646d2SAndroid Build Coastguard Worker /*
36*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
37*5e7646d2SAndroid Build Coastguard Worker  */
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker static const char ppd_custom_code[] =
40*5e7646d2SAndroid Build Coastguard Worker 		"pop pop pop\n"
41*5e7646d2SAndroid Build Coastguard Worker 		"<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n";
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker 
44*5e7646d2SAndroid Build Coastguard Worker /*
45*5e7646d2SAndroid Build Coastguard Worker  * 'ppdCollect()' - Collect all marked options that reside in the specified
46*5e7646d2SAndroid Build Coastguard Worker  *                  section.
47*5e7646d2SAndroid Build Coastguard Worker  *
48*5e7646d2SAndroid Build Coastguard Worker  * The choices array should be freed using @code free@ when you are
49*5e7646d2SAndroid Build Coastguard Worker  * finished with it.
50*5e7646d2SAndroid Build Coastguard Worker  */
51*5e7646d2SAndroid Build Coastguard Worker 
52*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of options marked */
ppdCollect(ppd_file_t * ppd,ppd_section_t section,ppd_choice_t *** choices)53*5e7646d2SAndroid Build Coastguard Worker ppdCollect(ppd_file_t    *ppd,		/* I - PPD file data */
54*5e7646d2SAndroid Build Coastguard Worker            ppd_section_t section,	/* I - Section to collect */
55*5e7646d2SAndroid Build Coastguard Worker            ppd_choice_t  ***choices)	/* O - Pointers to choices */
56*5e7646d2SAndroid Build Coastguard Worker {
57*5e7646d2SAndroid Build Coastguard Worker   return (ppdCollect2(ppd, section, 0.0, choices));
58*5e7646d2SAndroid Build Coastguard Worker }
59*5e7646d2SAndroid Build Coastguard Worker 
60*5e7646d2SAndroid Build Coastguard Worker 
61*5e7646d2SAndroid Build Coastguard Worker /*
62*5e7646d2SAndroid Build Coastguard Worker  * 'ppdCollect2()' - Collect all marked options that reside in the
63*5e7646d2SAndroid Build Coastguard Worker  *                   specified section and minimum order.
64*5e7646d2SAndroid Build Coastguard Worker  *
65*5e7646d2SAndroid Build Coastguard Worker  * The choices array should be freed using @code free@ when you are
66*5e7646d2SAndroid Build Coastguard Worker  * finished with it.
67*5e7646d2SAndroid Build Coastguard Worker  *
68*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
69*5e7646d2SAndroid Build Coastguard Worker  */
70*5e7646d2SAndroid Build Coastguard Worker 
71*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of options marked */
ppdCollect2(ppd_file_t * ppd,ppd_section_t section,float min_order,ppd_choice_t *** choices)72*5e7646d2SAndroid Build Coastguard Worker ppdCollect2(ppd_file_t    *ppd,		/* I - PPD file data */
73*5e7646d2SAndroid Build Coastguard Worker             ppd_section_t section,	/* I - Section to collect */
74*5e7646d2SAndroid Build Coastguard Worker 	    float         min_order,	/* I - Minimum OrderDependency value */
75*5e7646d2SAndroid Build Coastguard Worker             ppd_choice_t  ***choices)	/* O - Pointers to choices */
76*5e7646d2SAndroid Build Coastguard Worker {
77*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*c;			/* Current choice */
78*5e7646d2SAndroid Build Coastguard Worker   ppd_section_t	csection;		/* Current section */
79*5e7646d2SAndroid Build Coastguard Worker   float		corder;			/* Current OrderDependency value */
80*5e7646d2SAndroid Build Coastguard Worker   int		count;			/* Number of choices collected */
81*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	**collect;		/* Collected choices */
82*5e7646d2SAndroid Build Coastguard Worker   float		*orders;		/* Collected order values */
83*5e7646d2SAndroid Build Coastguard Worker 
84*5e7646d2SAndroid Build Coastguard Worker 
85*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ppdCollect2(ppd=%p, section=%d, min_order=%f, choices=%p)",
86*5e7646d2SAndroid Build Coastguard Worker                 ppd, section, min_order, choices));
87*5e7646d2SAndroid Build Coastguard Worker 
88*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !choices)
89*5e7646d2SAndroid Build Coastguard Worker   {
90*5e7646d2SAndroid Build Coastguard Worker     if (choices)
91*5e7646d2SAndroid Build Coastguard Worker       *choices = NULL;
92*5e7646d2SAndroid Build Coastguard Worker 
93*5e7646d2SAndroid Build Coastguard Worker     return (0);
94*5e7646d2SAndroid Build Coastguard Worker   }
95*5e7646d2SAndroid Build Coastguard Worker 
96*5e7646d2SAndroid Build Coastguard Worker  /*
97*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory for up to N selected choices...
98*5e7646d2SAndroid Build Coastguard Worker   */
99*5e7646d2SAndroid Build Coastguard Worker 
100*5e7646d2SAndroid Build Coastguard Worker   count = 0;
101*5e7646d2SAndroid Build Coastguard Worker   if ((collect = calloc(sizeof(ppd_choice_t *),
102*5e7646d2SAndroid Build Coastguard Worker                         (size_t)cupsArrayCount(ppd->marked))) == NULL)
103*5e7646d2SAndroid Build Coastguard Worker   {
104*5e7646d2SAndroid Build Coastguard Worker     *choices = NULL;
105*5e7646d2SAndroid Build Coastguard Worker     return (0);
106*5e7646d2SAndroid Build Coastguard Worker   }
107*5e7646d2SAndroid Build Coastguard Worker 
108*5e7646d2SAndroid Build Coastguard Worker   if ((orders = calloc(sizeof(float), (size_t)cupsArrayCount(ppd->marked))) == NULL)
109*5e7646d2SAndroid Build Coastguard Worker   {
110*5e7646d2SAndroid Build Coastguard Worker     *choices = NULL;
111*5e7646d2SAndroid Build Coastguard Worker     free(collect);
112*5e7646d2SAndroid Build Coastguard Worker     return (0);
113*5e7646d2SAndroid Build Coastguard Worker   }
114*5e7646d2SAndroid Build Coastguard Worker 
115*5e7646d2SAndroid Build Coastguard Worker  /*
116*5e7646d2SAndroid Build Coastguard Worker   * Loop through all options and add choices as needed...
117*5e7646d2SAndroid Build Coastguard Worker   */
118*5e7646d2SAndroid Build Coastguard Worker 
119*5e7646d2SAndroid Build Coastguard Worker   for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked);
120*5e7646d2SAndroid Build Coastguard Worker        c;
121*5e7646d2SAndroid Build Coastguard Worker        c = (ppd_choice_t *)cupsArrayNext(ppd->marked))
122*5e7646d2SAndroid Build Coastguard Worker   {
123*5e7646d2SAndroid Build Coastguard Worker     csection = c->option->section;
124*5e7646d2SAndroid Build Coastguard Worker     corder   = c->option->order;
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(c->choice, "Custom"))
127*5e7646d2SAndroid Build Coastguard Worker     {
128*5e7646d2SAndroid Build Coastguard Worker       ppd_attr_t	*attr;		/* NonUIOrderDependency value */
129*5e7646d2SAndroid Build Coastguard Worker       float		aorder;		/* Order value */
130*5e7646d2SAndroid Build Coastguard Worker       char		asection[17],	/* Section name */
131*5e7646d2SAndroid Build Coastguard Worker 			amain[PPD_MAX_NAME + 1],
132*5e7646d2SAndroid Build Coastguard Worker 			aoption[PPD_MAX_NAME];
133*5e7646d2SAndroid Build Coastguard Worker 					/* *CustomFoo and True */
134*5e7646d2SAndroid Build Coastguard Worker 
135*5e7646d2SAndroid Build Coastguard Worker 
136*5e7646d2SAndroid Build Coastguard Worker       for (attr = ppdFindAttr(ppd, "NonUIOrderDependency", NULL);
137*5e7646d2SAndroid Build Coastguard Worker            attr;
138*5e7646d2SAndroid Build Coastguard Worker 	   attr = ppdFindNextAttr(ppd, "NonUIOrderDependency", NULL))
139*5e7646d2SAndroid Build Coastguard Worker         if (attr->value &&
140*5e7646d2SAndroid Build Coastguard Worker 	    sscanf(attr->value, "%f%16s%41s%40s", &aorder, asection, amain,
141*5e7646d2SAndroid Build Coastguard Worker 	           aoption) == 4 &&
142*5e7646d2SAndroid Build Coastguard Worker 	    !strncmp(amain, "*Custom", 7) &&
143*5e7646d2SAndroid Build Coastguard Worker 	    !strcmp(amain + 7, c->option->keyword) && !strcmp(aoption, "True"))
144*5e7646d2SAndroid Build Coastguard Worker 	{
145*5e7646d2SAndroid Build Coastguard Worker 	 /*
146*5e7646d2SAndroid Build Coastguard Worker 	  * Use this NonUIOrderDependency...
147*5e7646d2SAndroid Build Coastguard Worker 	  */
148*5e7646d2SAndroid Build Coastguard Worker 
149*5e7646d2SAndroid Build Coastguard Worker           corder = aorder;
150*5e7646d2SAndroid Build Coastguard Worker 
151*5e7646d2SAndroid Build Coastguard Worker 	  if (!strcmp(asection, "DocumentSetup"))
152*5e7646d2SAndroid Build Coastguard Worker 	    csection = PPD_ORDER_DOCUMENT;
153*5e7646d2SAndroid Build Coastguard Worker 	  else if (!strcmp(asection, "ExitServer"))
154*5e7646d2SAndroid Build Coastguard Worker 	    csection = PPD_ORDER_EXIT;
155*5e7646d2SAndroid Build Coastguard Worker 	  else if (!strcmp(asection, "JCLSetup"))
156*5e7646d2SAndroid Build Coastguard Worker 	    csection = PPD_ORDER_JCL;
157*5e7646d2SAndroid Build Coastguard Worker 	  else if (!strcmp(asection, "PageSetup"))
158*5e7646d2SAndroid Build Coastguard Worker 	    csection = PPD_ORDER_PAGE;
159*5e7646d2SAndroid Build Coastguard Worker 	  else if (!strcmp(asection, "Prolog"))
160*5e7646d2SAndroid Build Coastguard Worker 	    csection = PPD_ORDER_PROLOG;
161*5e7646d2SAndroid Build Coastguard Worker 	  else
162*5e7646d2SAndroid Build Coastguard Worker 	    csection = PPD_ORDER_ANY;
163*5e7646d2SAndroid Build Coastguard Worker 
164*5e7646d2SAndroid Build Coastguard Worker 	  break;
165*5e7646d2SAndroid Build Coastguard Worker 	}
166*5e7646d2SAndroid Build Coastguard Worker     }
167*5e7646d2SAndroid Build Coastguard Worker 
168*5e7646d2SAndroid Build Coastguard Worker     if (csection == section && corder >= min_order)
169*5e7646d2SAndroid Build Coastguard Worker     {
170*5e7646d2SAndroid Build Coastguard Worker       collect[count] = c;
171*5e7646d2SAndroid Build Coastguard Worker       orders[count]  = corder;
172*5e7646d2SAndroid Build Coastguard Worker       count ++;
173*5e7646d2SAndroid Build Coastguard Worker     }
174*5e7646d2SAndroid Build Coastguard Worker   }
175*5e7646d2SAndroid Build Coastguard Worker 
176*5e7646d2SAndroid Build Coastguard Worker  /*
177*5e7646d2SAndroid Build Coastguard Worker   * If we have more than 1 marked choice, sort them...
178*5e7646d2SAndroid Build Coastguard Worker   */
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker   if (count > 1)
181*5e7646d2SAndroid Build Coastguard Worker   {
182*5e7646d2SAndroid Build Coastguard Worker     int i, j;				/* Looping vars */
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < (count - 1); i ++)
185*5e7646d2SAndroid Build Coastguard Worker       for (j = i + 1; j < count; j ++)
186*5e7646d2SAndroid Build Coastguard Worker         if (orders[i] > orders[j])
187*5e7646d2SAndroid Build Coastguard Worker 	{
188*5e7646d2SAndroid Build Coastguard Worker 	  c          = collect[i];
189*5e7646d2SAndroid Build Coastguard Worker 	  corder     = orders[i];
190*5e7646d2SAndroid Build Coastguard Worker 	  collect[i] = collect[j];
191*5e7646d2SAndroid Build Coastguard Worker 	  orders[i]  = orders[j];
192*5e7646d2SAndroid Build Coastguard Worker 	  collect[j] = c;
193*5e7646d2SAndroid Build Coastguard Worker 	  orders[j]  = corder;
194*5e7646d2SAndroid Build Coastguard Worker 	}
195*5e7646d2SAndroid Build Coastguard Worker   }
196*5e7646d2SAndroid Build Coastguard Worker 
197*5e7646d2SAndroid Build Coastguard Worker   free(orders);
198*5e7646d2SAndroid Build Coastguard Worker 
199*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ppdCollect2: %d marked choices...", count));
200*5e7646d2SAndroid Build Coastguard Worker 
201*5e7646d2SAndroid Build Coastguard Worker  /*
202*5e7646d2SAndroid Build Coastguard Worker   * Return the array and number of choices; if 0, free the array since
203*5e7646d2SAndroid Build Coastguard Worker   * it isn't needed.
204*5e7646d2SAndroid Build Coastguard Worker   */
205*5e7646d2SAndroid Build Coastguard Worker 
206*5e7646d2SAndroid Build Coastguard Worker   if (count > 0)
207*5e7646d2SAndroid Build Coastguard Worker   {
208*5e7646d2SAndroid Build Coastguard Worker     *choices = collect;
209*5e7646d2SAndroid Build Coastguard Worker     return (count);
210*5e7646d2SAndroid Build Coastguard Worker   }
211*5e7646d2SAndroid Build Coastguard Worker   else
212*5e7646d2SAndroid Build Coastguard Worker   {
213*5e7646d2SAndroid Build Coastguard Worker     *choices = NULL;
214*5e7646d2SAndroid Build Coastguard Worker     free(collect);
215*5e7646d2SAndroid Build Coastguard Worker     return (0);
216*5e7646d2SAndroid Build Coastguard Worker   }
217*5e7646d2SAndroid Build Coastguard Worker }
218*5e7646d2SAndroid Build Coastguard Worker 
219*5e7646d2SAndroid Build Coastguard Worker 
220*5e7646d2SAndroid Build Coastguard Worker /*
221*5e7646d2SAndroid Build Coastguard Worker  * 'ppdEmit()' - Emit code for marked options to a file.
222*5e7646d2SAndroid Build Coastguard Worker  */
223*5e7646d2SAndroid Build Coastguard Worker 
224*5e7646d2SAndroid Build Coastguard Worker int					/* O - 0 on success, -1 on failure */
ppdEmit(ppd_file_t * ppd,FILE * fp,ppd_section_t section)225*5e7646d2SAndroid Build Coastguard Worker ppdEmit(ppd_file_t    *ppd,		/* I - PPD file record */
226*5e7646d2SAndroid Build Coastguard Worker         FILE          *fp,		/* I - File to write to */
227*5e7646d2SAndroid Build Coastguard Worker         ppd_section_t section)		/* I - Section to write */
228*5e7646d2SAndroid Build Coastguard Worker {
229*5e7646d2SAndroid Build Coastguard Worker   return (ppdEmitAfterOrder(ppd, fp, section, 0, 0.0));
230*5e7646d2SAndroid Build Coastguard Worker }
231*5e7646d2SAndroid Build Coastguard Worker 
232*5e7646d2SAndroid Build Coastguard Worker 
233*5e7646d2SAndroid Build Coastguard Worker /*
234*5e7646d2SAndroid Build Coastguard Worker  * 'ppdEmitAfterOrder()' - Emit a subset of the code for marked options to a file.
235*5e7646d2SAndroid Build Coastguard Worker  *
236*5e7646d2SAndroid Build Coastguard Worker  * When "limit" is non-zero, this function only emits options whose
237*5e7646d2SAndroid Build Coastguard Worker  * OrderDependency value is greater than or equal to "min_order".
238*5e7646d2SAndroid Build Coastguard Worker  *
239*5e7646d2SAndroid Build Coastguard Worker  * When "limit" is zero, this function is identical to ppdEmit().
240*5e7646d2SAndroid Build Coastguard Worker  *
241*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
242*5e7646d2SAndroid Build Coastguard Worker  */
243*5e7646d2SAndroid Build Coastguard Worker 
244*5e7646d2SAndroid Build Coastguard Worker int					/* O - 0 on success, -1 on failure */
ppdEmitAfterOrder(ppd_file_t * ppd,FILE * fp,ppd_section_t section,int limit,float min_order)245*5e7646d2SAndroid Build Coastguard Worker ppdEmitAfterOrder(
246*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t    *ppd,			/* I - PPD file record */
247*5e7646d2SAndroid Build Coastguard Worker     FILE          *fp,			/* I - File to write to */
248*5e7646d2SAndroid Build Coastguard Worker     ppd_section_t section,		/* I - Section to write */
249*5e7646d2SAndroid Build Coastguard Worker     int		  limit,		/* I - Non-zero to use min_order */
250*5e7646d2SAndroid Build Coastguard Worker     float         min_order)		/* I - Lowest OrderDependency */
251*5e7646d2SAndroid Build Coastguard Worker {
252*5e7646d2SAndroid Build Coastguard Worker   char	*buffer;			/* Option code */
253*5e7646d2SAndroid Build Coastguard Worker   int	status;				/* Return status */
254*5e7646d2SAndroid Build Coastguard Worker 
255*5e7646d2SAndroid Build Coastguard Worker 
256*5e7646d2SAndroid Build Coastguard Worker  /*
257*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
258*5e7646d2SAndroid Build Coastguard Worker   */
259*5e7646d2SAndroid Build Coastguard Worker 
260*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !fp)
261*5e7646d2SAndroid Build Coastguard Worker     return (-1);
262*5e7646d2SAndroid Build Coastguard Worker 
263*5e7646d2SAndroid Build Coastguard Worker  /*
264*5e7646d2SAndroid Build Coastguard Worker   * Get the string...
265*5e7646d2SAndroid Build Coastguard Worker   */
266*5e7646d2SAndroid Build Coastguard Worker 
267*5e7646d2SAndroid Build Coastguard Worker   buffer = ppdEmitString(ppd, section, limit ? min_order : 0.0f);
268*5e7646d2SAndroid Build Coastguard Worker 
269*5e7646d2SAndroid Build Coastguard Worker  /*
270*5e7646d2SAndroid Build Coastguard Worker   * Write it as needed and return...
271*5e7646d2SAndroid Build Coastguard Worker   */
272*5e7646d2SAndroid Build Coastguard Worker 
273*5e7646d2SAndroid Build Coastguard Worker   if (buffer)
274*5e7646d2SAndroid Build Coastguard Worker   {
275*5e7646d2SAndroid Build Coastguard Worker     status = fputs(buffer, fp) < 0 ? -1 : 0;
276*5e7646d2SAndroid Build Coastguard Worker 
277*5e7646d2SAndroid Build Coastguard Worker     free(buffer);
278*5e7646d2SAndroid Build Coastguard Worker   }
279*5e7646d2SAndroid Build Coastguard Worker   else
280*5e7646d2SAndroid Build Coastguard Worker     status = 0;
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker   return (status);
283*5e7646d2SAndroid Build Coastguard Worker }
284*5e7646d2SAndroid Build Coastguard Worker 
285*5e7646d2SAndroid Build Coastguard Worker 
286*5e7646d2SAndroid Build Coastguard Worker /*
287*5e7646d2SAndroid Build Coastguard Worker  * 'ppdEmitFd()' - Emit code for marked options to a file.
288*5e7646d2SAndroid Build Coastguard Worker  */
289*5e7646d2SAndroid Build Coastguard Worker 
290*5e7646d2SAndroid Build Coastguard Worker int					/* O - 0 on success, -1 on failure */
ppdEmitFd(ppd_file_t * ppd,int fd,ppd_section_t section)291*5e7646d2SAndroid Build Coastguard Worker ppdEmitFd(ppd_file_t    *ppd,		/* I - PPD file record */
292*5e7646d2SAndroid Build Coastguard Worker           int           fd,		/* I - File to write to */
293*5e7646d2SAndroid Build Coastguard Worker           ppd_section_t section)	/* I - Section to write */
294*5e7646d2SAndroid Build Coastguard Worker {
295*5e7646d2SAndroid Build Coastguard Worker   char		*buffer,		/* Option code */
296*5e7646d2SAndroid Build Coastguard Worker 		*bufptr;		/* Pointer into code */
297*5e7646d2SAndroid Build Coastguard Worker   size_t	buflength;		/* Length of option code */
298*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes;			/* Bytes written */
299*5e7646d2SAndroid Build Coastguard Worker   int		status;			/* Return status */
300*5e7646d2SAndroid Build Coastguard Worker 
301*5e7646d2SAndroid Build Coastguard Worker 
302*5e7646d2SAndroid Build Coastguard Worker  /*
303*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
304*5e7646d2SAndroid Build Coastguard Worker   */
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || fd < 0)
307*5e7646d2SAndroid Build Coastguard Worker     return (-1);
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker  /*
310*5e7646d2SAndroid Build Coastguard Worker   * Get the string...
311*5e7646d2SAndroid Build Coastguard Worker   */
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker   buffer = ppdEmitString(ppd, section, 0.0);
314*5e7646d2SAndroid Build Coastguard Worker 
315*5e7646d2SAndroid Build Coastguard Worker  /*
316*5e7646d2SAndroid Build Coastguard Worker   * Write it as needed and return...
317*5e7646d2SAndroid Build Coastguard Worker   */
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker   if (buffer)
320*5e7646d2SAndroid Build Coastguard Worker   {
321*5e7646d2SAndroid Build Coastguard Worker     buflength = strlen(buffer);
322*5e7646d2SAndroid Build Coastguard Worker     bufptr    = buffer;
323*5e7646d2SAndroid Build Coastguard Worker     bytes     = 0;
324*5e7646d2SAndroid Build Coastguard Worker 
325*5e7646d2SAndroid Build Coastguard Worker     while (buflength > 0)
326*5e7646d2SAndroid Build Coastguard Worker     {
327*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
328*5e7646d2SAndroid Build Coastguard Worker       if ((bytes = (ssize_t)write(fd, bufptr, (unsigned)buflength)) < 0)
329*5e7646d2SAndroid Build Coastguard Worker #else
330*5e7646d2SAndroid Build Coastguard Worker       if ((bytes = write(fd, bufptr, buflength)) < 0)
331*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
332*5e7646d2SAndroid Build Coastguard Worker       {
333*5e7646d2SAndroid Build Coastguard Worker         if (errno == EAGAIN || errno == EINTR)
334*5e7646d2SAndroid Build Coastguard Worker 	  continue;
335*5e7646d2SAndroid Build Coastguard Worker 
336*5e7646d2SAndroid Build Coastguard Worker 	break;
337*5e7646d2SAndroid Build Coastguard Worker       }
338*5e7646d2SAndroid Build Coastguard Worker 
339*5e7646d2SAndroid Build Coastguard Worker       buflength -= (size_t)bytes;
340*5e7646d2SAndroid Build Coastguard Worker       bufptr    += bytes;
341*5e7646d2SAndroid Build Coastguard Worker     }
342*5e7646d2SAndroid Build Coastguard Worker 
343*5e7646d2SAndroid Build Coastguard Worker     status = bytes < 0 ? -1 : 0;
344*5e7646d2SAndroid Build Coastguard Worker 
345*5e7646d2SAndroid Build Coastguard Worker     free(buffer);
346*5e7646d2SAndroid Build Coastguard Worker   }
347*5e7646d2SAndroid Build Coastguard Worker   else
348*5e7646d2SAndroid Build Coastguard Worker     status = 0;
349*5e7646d2SAndroid Build Coastguard Worker 
350*5e7646d2SAndroid Build Coastguard Worker   return (status);
351*5e7646d2SAndroid Build Coastguard Worker }
352*5e7646d2SAndroid Build Coastguard Worker 
353*5e7646d2SAndroid Build Coastguard Worker 
354*5e7646d2SAndroid Build Coastguard Worker /*
355*5e7646d2SAndroid Build Coastguard Worker  * 'ppdEmitJCL()' - Emit code for JCL options to a file.
356*5e7646d2SAndroid Build Coastguard Worker  */
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker int					/* O - 0 on success, -1 on failure */
ppdEmitJCL(ppd_file_t * ppd,FILE * fp,int job_id,const char * user,const char * title)359*5e7646d2SAndroid Build Coastguard Worker ppdEmitJCL(ppd_file_t *ppd,		/* I - PPD file record */
360*5e7646d2SAndroid Build Coastguard Worker            FILE       *fp,		/* I - File to write to */
361*5e7646d2SAndroid Build Coastguard Worker            int        job_id,		/* I - Job ID */
362*5e7646d2SAndroid Build Coastguard Worker 	   const char *user,		/* I - Username */
363*5e7646d2SAndroid Build Coastguard Worker 	   const char *title)		/* I - Title */
364*5e7646d2SAndroid Build Coastguard Worker {
365*5e7646d2SAndroid Build Coastguard Worker   char		*ptr;			/* Pointer into JCL string */
366*5e7646d2SAndroid Build Coastguard Worker   char		temp[65],		/* Local title string */
367*5e7646d2SAndroid Build Coastguard Worker 		displaymsg[33];		/* Local display string */
368*5e7646d2SAndroid Build Coastguard Worker 
369*5e7646d2SAndroid Build Coastguard Worker 
370*5e7646d2SAndroid Build Coastguard Worker  /*
371*5e7646d2SAndroid Build Coastguard Worker   * Range check the input...
372*5e7646d2SAndroid Build Coastguard Worker   */
373*5e7646d2SAndroid Build Coastguard Worker 
374*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !ppd->jcl_begin || !ppd->jcl_ps)
375*5e7646d2SAndroid Build Coastguard Worker     return (0);
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker  /*
378*5e7646d2SAndroid Build Coastguard Worker   * See if the printer supports HP PJL...
379*5e7646d2SAndroid Build Coastguard Worker   */
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker   if (!strncmp(ppd->jcl_begin, "\033%-12345X@", 10))
382*5e7646d2SAndroid Build Coastguard Worker   {
383*5e7646d2SAndroid Build Coastguard Worker    /*
384*5e7646d2SAndroid Build Coastguard Worker     * This printer uses HP PJL commands for output; filter the output
385*5e7646d2SAndroid Build Coastguard Worker     * so that we only have a single "@PJL JOB" command in the header...
386*5e7646d2SAndroid Build Coastguard Worker     *
387*5e7646d2SAndroid Build Coastguard Worker     * To avoid bugs in the PJL implementation of certain vendors' products
388*5e7646d2SAndroid Build Coastguard Worker     * (Xerox in particular), we add a dummy "@PJL" command at the beginning
389*5e7646d2SAndroid Build Coastguard Worker     * of the PJL commands to initialize PJL processing.
390*5e7646d2SAndroid Build Coastguard Worker     */
391*5e7646d2SAndroid Build Coastguard Worker 
392*5e7646d2SAndroid Build Coastguard Worker     ppd_attr_t	*charset;		/* PJL charset */
393*5e7646d2SAndroid Build Coastguard Worker     ppd_attr_t	*display;		/* PJL display command */
394*5e7646d2SAndroid Build Coastguard Worker 
395*5e7646d2SAndroid Build Coastguard Worker 
396*5e7646d2SAndroid Build Coastguard Worker     if ((charset = ppdFindAttr(ppd, "cupsPJLCharset", NULL)) != NULL)
397*5e7646d2SAndroid Build Coastguard Worker     {
398*5e7646d2SAndroid Build Coastguard Worker       if (!charset->value || _cups_strcasecmp(charset->value, "UTF-8"))
399*5e7646d2SAndroid Build Coastguard Worker         charset = NULL;
400*5e7646d2SAndroid Build Coastguard Worker     }
401*5e7646d2SAndroid Build Coastguard Worker 
402*5e7646d2SAndroid Build Coastguard Worker     if ((display = ppdFindAttr(ppd, "cupsPJLDisplay", NULL)) != NULL)
403*5e7646d2SAndroid Build Coastguard Worker     {
404*5e7646d2SAndroid Build Coastguard Worker       if (!display->value)
405*5e7646d2SAndroid Build Coastguard Worker         display = NULL;
406*5e7646d2SAndroid Build Coastguard Worker     }
407*5e7646d2SAndroid Build Coastguard Worker 
408*5e7646d2SAndroid Build Coastguard Worker     fputs("\033%-12345X@PJL\n", fp);
409*5e7646d2SAndroid Build Coastguard Worker     for (ptr = ppd->jcl_begin + 9; *ptr;)
410*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(ptr, "@PJL JOB", 8))
411*5e7646d2SAndroid Build Coastguard Worker       {
412*5e7646d2SAndroid Build Coastguard Worker        /*
413*5e7646d2SAndroid Build Coastguard Worker         * Skip job command...
414*5e7646d2SAndroid Build Coastguard Worker 	*/
415*5e7646d2SAndroid Build Coastguard Worker 
416*5e7646d2SAndroid Build Coastguard Worker         for (;*ptr; ptr ++)
417*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr == '\n')
418*5e7646d2SAndroid Build Coastguard Worker 	    break;
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker 	if (*ptr)
421*5e7646d2SAndroid Build Coastguard Worker 	  ptr ++;
422*5e7646d2SAndroid Build Coastguard Worker       }
423*5e7646d2SAndroid Build Coastguard Worker       else
424*5e7646d2SAndroid Build Coastguard Worker       {
425*5e7646d2SAndroid Build Coastguard Worker        /*
426*5e7646d2SAndroid Build Coastguard Worker         * Copy line...
427*5e7646d2SAndroid Build Coastguard Worker 	*/
428*5e7646d2SAndroid Build Coastguard Worker 
429*5e7646d2SAndroid Build Coastguard Worker         for (;*ptr; ptr ++)
430*5e7646d2SAndroid Build Coastguard Worker 	{
431*5e7646d2SAndroid Build Coastguard Worker 	  putc(*ptr, fp);
432*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr == '\n')
433*5e7646d2SAndroid Build Coastguard Worker 	    break;
434*5e7646d2SAndroid Build Coastguard Worker 	}
435*5e7646d2SAndroid Build Coastguard Worker 
436*5e7646d2SAndroid Build Coastguard Worker 	if (*ptr)
437*5e7646d2SAndroid Build Coastguard Worker 	  ptr ++;
438*5e7646d2SAndroid Build Coastguard Worker       }
439*5e7646d2SAndroid Build Coastguard Worker 
440*5e7646d2SAndroid Build Coastguard Worker    /*
441*5e7646d2SAndroid Build Coastguard Worker     * Clean up the job title...
442*5e7646d2SAndroid Build Coastguard Worker     */
443*5e7646d2SAndroid Build Coastguard Worker 
444*5e7646d2SAndroid Build Coastguard Worker     if (!title)
445*5e7646d2SAndroid Build Coastguard Worker       title = "Unknown";
446*5e7646d2SAndroid Build Coastguard Worker 
447*5e7646d2SAndroid Build Coastguard Worker     if ((ptr = strrchr(title, '/')) != NULL)
448*5e7646d2SAndroid Build Coastguard Worker     {
449*5e7646d2SAndroid Build Coastguard Worker      /*
450*5e7646d2SAndroid Build Coastguard Worker       * Only show basename of file path...
451*5e7646d2SAndroid Build Coastguard Worker       */
452*5e7646d2SAndroid Build Coastguard Worker 
453*5e7646d2SAndroid Build Coastguard Worker       title = ptr + 1;
454*5e7646d2SAndroid Build Coastguard Worker     }
455*5e7646d2SAndroid Build Coastguard Worker 
456*5e7646d2SAndroid Build Coastguard Worker     if (!strncmp(title, "smbprn.", 7))
457*5e7646d2SAndroid Build Coastguard Worker     {
458*5e7646d2SAndroid Build Coastguard Worker      /*
459*5e7646d2SAndroid Build Coastguard Worker       * Skip leading smbprn.######## from Samba jobs...
460*5e7646d2SAndroid Build Coastguard Worker       */
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker       for (title += 7; *title && isdigit(*title & 255); title ++);
463*5e7646d2SAndroid Build Coastguard Worker       while (_cups_isspace(*title))
464*5e7646d2SAndroid Build Coastguard Worker         title ++;
465*5e7646d2SAndroid Build Coastguard Worker 
466*5e7646d2SAndroid Build Coastguard Worker       if ((ptr = strstr(title, " - ")) != NULL)
467*5e7646d2SAndroid Build Coastguard Worker       {
468*5e7646d2SAndroid Build Coastguard Worker        /*
469*5e7646d2SAndroid Build Coastguard Worker 	* Skip application name in "Some Application - Title of job"...
470*5e7646d2SAndroid Build Coastguard Worker 	*/
471*5e7646d2SAndroid Build Coastguard Worker 
472*5e7646d2SAndroid Build Coastguard Worker 	title = ptr + 3;
473*5e7646d2SAndroid Build Coastguard Worker       }
474*5e7646d2SAndroid Build Coastguard Worker     }
475*5e7646d2SAndroid Build Coastguard Worker 
476*5e7646d2SAndroid Build Coastguard Worker    /*
477*5e7646d2SAndroid Build Coastguard Worker     * Replace double quotes with single quotes and UTF-8 characters with
478*5e7646d2SAndroid Build Coastguard Worker     * question marks so that the title does not cause a PJL syntax error.
479*5e7646d2SAndroid Build Coastguard Worker     */
480*5e7646d2SAndroid Build Coastguard Worker 
481*5e7646d2SAndroid Build Coastguard Worker     strlcpy(temp, title, sizeof(temp));
482*5e7646d2SAndroid Build Coastguard Worker 
483*5e7646d2SAndroid Build Coastguard Worker     for (ptr = temp; *ptr; ptr ++)
484*5e7646d2SAndroid Build Coastguard Worker       if (*ptr == '\"')
485*5e7646d2SAndroid Build Coastguard Worker         *ptr = '\'';
486*5e7646d2SAndroid Build Coastguard Worker       else if (!charset && (*ptr & 128))
487*5e7646d2SAndroid Build Coastguard Worker         *ptr = '?';
488*5e7646d2SAndroid Build Coastguard Worker 
489*5e7646d2SAndroid Build Coastguard Worker    /*
490*5e7646d2SAndroid Build Coastguard Worker     * CUPS STR #3125: Long PJL JOB NAME causes problems with some printers
491*5e7646d2SAndroid Build Coastguard Worker     *
492*5e7646d2SAndroid Build Coastguard Worker     * Generate the display message, truncating at 32 characters + nul to avoid
493*5e7646d2SAndroid Build Coastguard Worker     * issues with some printer's PJL implementations...
494*5e7646d2SAndroid Build Coastguard Worker     */
495*5e7646d2SAndroid Build Coastguard Worker 
496*5e7646d2SAndroid Build Coastguard Worker     if (!user)
497*5e7646d2SAndroid Build Coastguard Worker       user = "anonymous";
498*5e7646d2SAndroid Build Coastguard Worker 
499*5e7646d2SAndroid Build Coastguard Worker     snprintf(displaymsg, sizeof(displaymsg), "%d %s %s", job_id, user, temp);
500*5e7646d2SAndroid Build Coastguard Worker 
501*5e7646d2SAndroid Build Coastguard Worker    /*
502*5e7646d2SAndroid Build Coastguard Worker     * Send PJL JOB and PJL RDYMSG commands before we enter PostScript mode...
503*5e7646d2SAndroid Build Coastguard Worker     */
504*5e7646d2SAndroid Build Coastguard Worker 
505*5e7646d2SAndroid Build Coastguard Worker     if (display && strcmp(display->value, "job"))
506*5e7646d2SAndroid Build Coastguard Worker       fprintf(fp, "@PJL JOB NAME = \"%s\"\n", temp);
507*5e7646d2SAndroid Build Coastguard Worker     else if (display && !strcmp(display->value, "rdymsg"))
508*5e7646d2SAndroid Build Coastguard Worker       fprintf(fp, "@PJL RDYMSG DISPLAY = \"%s\"\n", displaymsg);
509*5e7646d2SAndroid Build Coastguard Worker     else
510*5e7646d2SAndroid Build Coastguard Worker       fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%s\"\n", temp,
511*5e7646d2SAndroid Build Coastguard Worker 	      displaymsg);
512*5e7646d2SAndroid Build Coastguard Worker 
513*5e7646d2SAndroid Build Coastguard Worker    /*
514*5e7646d2SAndroid Build Coastguard Worker     * Replace double quotes with single quotes and UTF-8 characters with
515*5e7646d2SAndroid Build Coastguard Worker     * question marks so that the user does not cause a PJL syntax error.
516*5e7646d2SAndroid Build Coastguard Worker     */
517*5e7646d2SAndroid Build Coastguard Worker 
518*5e7646d2SAndroid Build Coastguard Worker     strlcpy(temp, user, sizeof(temp));
519*5e7646d2SAndroid Build Coastguard Worker 
520*5e7646d2SAndroid Build Coastguard Worker     for (ptr = temp; *ptr; ptr ++)
521*5e7646d2SAndroid Build Coastguard Worker       if (*ptr == '\"')
522*5e7646d2SAndroid Build Coastguard Worker         *ptr = '\'';
523*5e7646d2SAndroid Build Coastguard Worker       else if (!charset && (*ptr & 128))
524*5e7646d2SAndroid Build Coastguard Worker         *ptr = '?';
525*5e7646d2SAndroid Build Coastguard Worker 
526*5e7646d2SAndroid Build Coastguard Worker     fprintf(fp, "@PJL SET USERNAME = \"%s\"\n", temp);
527*5e7646d2SAndroid Build Coastguard Worker   }
528*5e7646d2SAndroid Build Coastguard Worker   else
529*5e7646d2SAndroid Build Coastguard Worker     fputs(ppd->jcl_begin, fp);
530*5e7646d2SAndroid Build Coastguard Worker 
531*5e7646d2SAndroid Build Coastguard Worker   ppdEmit(ppd, fp, PPD_ORDER_JCL);
532*5e7646d2SAndroid Build Coastguard Worker   fputs(ppd->jcl_ps, fp);
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker   return (0);
535*5e7646d2SAndroid Build Coastguard Worker }
536*5e7646d2SAndroid Build Coastguard Worker 
537*5e7646d2SAndroid Build Coastguard Worker 
538*5e7646d2SAndroid Build Coastguard Worker /*
539*5e7646d2SAndroid Build Coastguard Worker  * 'ppdEmitJCLEnd()' - Emit JCLEnd code to a file.
540*5e7646d2SAndroid Build Coastguard Worker  *
541*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
542*5e7646d2SAndroid Build Coastguard Worker  */
543*5e7646d2SAndroid Build Coastguard Worker 
544*5e7646d2SAndroid Build Coastguard Worker int					/* O - 0 on success, -1 on failure */
ppdEmitJCLEnd(ppd_file_t * ppd,FILE * fp)545*5e7646d2SAndroid Build Coastguard Worker ppdEmitJCLEnd(ppd_file_t *ppd,		/* I - PPD file record */
546*5e7646d2SAndroid Build Coastguard Worker               FILE       *fp)		/* I - File to write to */
547*5e7646d2SAndroid Build Coastguard Worker {
548*5e7646d2SAndroid Build Coastguard Worker  /*
549*5e7646d2SAndroid Build Coastguard Worker   * Range check the input...
550*5e7646d2SAndroid Build Coastguard Worker   */
551*5e7646d2SAndroid Build Coastguard Worker 
552*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
553*5e7646d2SAndroid Build Coastguard Worker     return (0);
554*5e7646d2SAndroid Build Coastguard Worker 
555*5e7646d2SAndroid Build Coastguard Worker   if (!ppd->jcl_end)
556*5e7646d2SAndroid Build Coastguard Worker   {
557*5e7646d2SAndroid Build Coastguard Worker     if (ppd->num_filters == 0)
558*5e7646d2SAndroid Build Coastguard Worker       putc(0x04, fp);
559*5e7646d2SAndroid Build Coastguard Worker 
560*5e7646d2SAndroid Build Coastguard Worker     return (0);
561*5e7646d2SAndroid Build Coastguard Worker   }
562*5e7646d2SAndroid Build Coastguard Worker 
563*5e7646d2SAndroid Build Coastguard Worker  /*
564*5e7646d2SAndroid Build Coastguard Worker   * See if the printer supports HP PJL...
565*5e7646d2SAndroid Build Coastguard Worker   */
566*5e7646d2SAndroid Build Coastguard Worker 
567*5e7646d2SAndroid Build Coastguard Worker   if (!strncmp(ppd->jcl_end, "\033%-12345X@", 10))
568*5e7646d2SAndroid Build Coastguard Worker   {
569*5e7646d2SAndroid Build Coastguard Worker    /*
570*5e7646d2SAndroid Build Coastguard Worker     * This printer uses HP PJL commands for output; filter the output
571*5e7646d2SAndroid Build Coastguard Worker     * so that we only have a single "@PJL JOB" command in the header...
572*5e7646d2SAndroid Build Coastguard Worker     *
573*5e7646d2SAndroid Build Coastguard Worker     * To avoid bugs in the PJL implementation of certain vendors' products
574*5e7646d2SAndroid Build Coastguard Worker     * (Xerox in particular), we add a dummy "@PJL" command at the beginning
575*5e7646d2SAndroid Build Coastguard Worker     * of the PJL commands to initialize PJL processing.
576*5e7646d2SAndroid Build Coastguard Worker     */
577*5e7646d2SAndroid Build Coastguard Worker 
578*5e7646d2SAndroid Build Coastguard Worker     fputs("\033%-12345X@PJL\n", fp);
579*5e7646d2SAndroid Build Coastguard Worker     fputs("@PJL RDYMSG DISPLAY = \"\"\n", fp);
580*5e7646d2SAndroid Build Coastguard Worker     fputs(ppd->jcl_end + 9, fp);
581*5e7646d2SAndroid Build Coastguard Worker   }
582*5e7646d2SAndroid Build Coastguard Worker   else
583*5e7646d2SAndroid Build Coastguard Worker     fputs(ppd->jcl_end, fp);
584*5e7646d2SAndroid Build Coastguard Worker 
585*5e7646d2SAndroid Build Coastguard Worker   return (0);
586*5e7646d2SAndroid Build Coastguard Worker }
587*5e7646d2SAndroid Build Coastguard Worker 
588*5e7646d2SAndroid Build Coastguard Worker 
589*5e7646d2SAndroid Build Coastguard Worker /*
590*5e7646d2SAndroid Build Coastguard Worker  * 'ppdEmitString()' - Get a string containing the code for marked options.
591*5e7646d2SAndroid Build Coastguard Worker  *
592*5e7646d2SAndroid Build Coastguard Worker  * When "min_order" is greater than zero, this function only includes options
593*5e7646d2SAndroid Build Coastguard Worker  * whose OrderDependency value is greater than or equal to "min_order".
594*5e7646d2SAndroid Build Coastguard Worker  * Otherwise, all options in the specified section are included in the
595*5e7646d2SAndroid Build Coastguard Worker  * returned string.
596*5e7646d2SAndroid Build Coastguard Worker  *
597*5e7646d2SAndroid Build Coastguard Worker  * The return string is allocated on the heap and should be freed using
598*5e7646d2SAndroid Build Coastguard Worker  * @code free@ when you are done with it.
599*5e7646d2SAndroid Build Coastguard Worker  *
600*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.2/macOS 10.5@
601*5e7646d2SAndroid Build Coastguard Worker  */
602*5e7646d2SAndroid Build Coastguard Worker 
603*5e7646d2SAndroid Build Coastguard Worker char *					/* O - String containing option code or @code NULL@ if there is no option code */
ppdEmitString(ppd_file_t * ppd,ppd_section_t section,float min_order)604*5e7646d2SAndroid Build Coastguard Worker ppdEmitString(ppd_file_t    *ppd,	/* I - PPD file record */
605*5e7646d2SAndroid Build Coastguard Worker               ppd_section_t section,	/* I - Section to write */
606*5e7646d2SAndroid Build Coastguard Worker 	      float         min_order)	/* I - Lowest OrderDependency */
607*5e7646d2SAndroid Build Coastguard Worker {
608*5e7646d2SAndroid Build Coastguard Worker   int		i, j,			/* Looping vars */
609*5e7646d2SAndroid Build Coastguard Worker 		count;			/* Number of choices */
610*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	**choices;		/* Choices */
611*5e7646d2SAndroid Build Coastguard Worker   ppd_size_t	*size;			/* Custom page size */
612*5e7646d2SAndroid Build Coastguard Worker   ppd_coption_t	*coption;		/* Custom option */
613*5e7646d2SAndroid Build Coastguard Worker   ppd_cparam_t	*cparam;		/* Custom parameter */
614*5e7646d2SAndroid Build Coastguard Worker   size_t	bufsize;		/* Size of string buffer needed */
615*5e7646d2SAndroid Build Coastguard Worker   char		*buffer,		/* String buffer */
616*5e7646d2SAndroid Build Coastguard Worker 		*bufptr,		/* Pointer into buffer */
617*5e7646d2SAndroid Build Coastguard Worker 		*bufend;		/* End of buffer */
618*5e7646d2SAndroid Build Coastguard Worker   struct lconv	*loc;			/* Locale data */
619*5e7646d2SAndroid Build Coastguard Worker 
620*5e7646d2SAndroid Build Coastguard Worker 
621*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("ppdEmitString(ppd=%p, section=%d, min_order=%f)",
622*5e7646d2SAndroid Build Coastguard Worker                 ppd, section, min_order));
623*5e7646d2SAndroid Build Coastguard Worker 
624*5e7646d2SAndroid Build Coastguard Worker  /*
625*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
626*5e7646d2SAndroid Build Coastguard Worker   */
627*5e7646d2SAndroid Build Coastguard Worker 
628*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
629*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
630*5e7646d2SAndroid Build Coastguard Worker 
631*5e7646d2SAndroid Build Coastguard Worker  /*
632*5e7646d2SAndroid Build Coastguard Worker   * Use PageSize or PageRegion as required...
633*5e7646d2SAndroid Build Coastguard Worker   */
634*5e7646d2SAndroid Build Coastguard Worker 
635*5e7646d2SAndroid Build Coastguard Worker   ppd_handle_media(ppd);
636*5e7646d2SAndroid Build Coastguard Worker 
637*5e7646d2SAndroid Build Coastguard Worker  /*
638*5e7646d2SAndroid Build Coastguard Worker   * Collect the options we need to emit...
639*5e7646d2SAndroid Build Coastguard Worker   */
640*5e7646d2SAndroid Build Coastguard Worker 
641*5e7646d2SAndroid Build Coastguard Worker   if ((count = ppdCollect2(ppd, section, min_order, &choices)) == 0)
642*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
643*5e7646d2SAndroid Build Coastguard Worker 
644*5e7646d2SAndroid Build Coastguard Worker  /*
645*5e7646d2SAndroid Build Coastguard Worker   * Count the number of bytes that are required to hold all of the
646*5e7646d2SAndroid Build Coastguard Worker   * option code...
647*5e7646d2SAndroid Build Coastguard Worker   */
648*5e7646d2SAndroid Build Coastguard Worker 
649*5e7646d2SAndroid Build Coastguard Worker   for (i = 0, bufsize = 1; i < count; i ++)
650*5e7646d2SAndroid Build Coastguard Worker   {
651*5e7646d2SAndroid Build Coastguard Worker     if (section == PPD_ORDER_JCL)
652*5e7646d2SAndroid Build Coastguard Worker     {
653*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
654*5e7646d2SAndroid Build Coastguard Worker 	  (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
655*5e7646d2SAndroid Build Coastguard Worker 	      != NULL)
656*5e7646d2SAndroid Build Coastguard Worker       {
657*5e7646d2SAndroid Build Coastguard Worker        /*
658*5e7646d2SAndroid Build Coastguard Worker         * Add space to account for custom parameter substitution...
659*5e7646d2SAndroid Build Coastguard Worker 	*/
660*5e7646d2SAndroid Build Coastguard Worker 
661*5e7646d2SAndroid Build Coastguard Worker         for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
662*5e7646d2SAndroid Build Coastguard Worker 	     cparam;
663*5e7646d2SAndroid Build Coastguard Worker 	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
664*5e7646d2SAndroid Build Coastguard Worker 	{
665*5e7646d2SAndroid Build Coastguard Worker           switch (cparam->type)
666*5e7646d2SAndroid Build Coastguard Worker 	  {
667*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_UNKNOWN :
668*5e7646d2SAndroid Build Coastguard Worker 	        break;
669*5e7646d2SAndroid Build Coastguard Worker 
670*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_CURVE :
671*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_INVCURVE :
672*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_POINTS :
673*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_REAL :
674*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_INT :
675*5e7646d2SAndroid Build Coastguard Worker 	        bufsize += 10;
676*5e7646d2SAndroid Build Coastguard Worker 	        break;
677*5e7646d2SAndroid Build Coastguard Worker 
678*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_PASSCODE :
679*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_PASSWORD :
680*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_STRING :
681*5e7646d2SAndroid Build Coastguard Worker 	        if (cparam->current.custom_string)
682*5e7646d2SAndroid Build Coastguard Worker 		  bufsize += strlen(cparam->current.custom_string);
683*5e7646d2SAndroid Build Coastguard Worker 	        break;
684*5e7646d2SAndroid Build Coastguard Worker           }
685*5e7646d2SAndroid Build Coastguard Worker 	}
686*5e7646d2SAndroid Build Coastguard Worker       }
687*5e7646d2SAndroid Build Coastguard Worker     }
688*5e7646d2SAndroid Build Coastguard Worker     else if (section != PPD_ORDER_EXIT)
689*5e7646d2SAndroid Build Coastguard Worker     {
690*5e7646d2SAndroid Build Coastguard Worker       bufsize += 3;			/* [{\n */
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker       if ((!_cups_strcasecmp(choices[i]->option->keyword, "PageSize") ||
693*5e7646d2SAndroid Build Coastguard Worker            !_cups_strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
694*5e7646d2SAndroid Build Coastguard Worker           !_cups_strcasecmp(choices[i]->choice, "Custom"))
695*5e7646d2SAndroid Build Coastguard Worker       {
696*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("2ppdEmitString: Custom size set!");
697*5e7646d2SAndroid Build Coastguard Worker 
698*5e7646d2SAndroid Build Coastguard Worker         bufsize += 37;			/* %%BeginFeature: *CustomPageSize True\n */
699*5e7646d2SAndroid Build Coastguard Worker         bufsize += 50;			/* Five 9-digit numbers + newline */
700*5e7646d2SAndroid Build Coastguard Worker       }
701*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
702*5e7646d2SAndroid Build Coastguard Worker                (coption = ppdFindCustomOption(ppd,
703*5e7646d2SAndroid Build Coastguard Worker 	                                      choices[i]->option->keyword))
704*5e7646d2SAndroid Build Coastguard Worker 	           != NULL)
705*5e7646d2SAndroid Build Coastguard Worker       {
706*5e7646d2SAndroid Build Coastguard Worker         bufsize += 23 + strlen(choices[i]->option->keyword) + 6;
707*5e7646d2SAndroid Build Coastguard Worker 					/* %%BeginFeature: *Customkeyword True\n */
708*5e7646d2SAndroid Build Coastguard Worker 
709*5e7646d2SAndroid Build Coastguard Worker 
710*5e7646d2SAndroid Build Coastguard Worker         for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
711*5e7646d2SAndroid Build Coastguard Worker 	     cparam;
712*5e7646d2SAndroid Build Coastguard Worker 	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
713*5e7646d2SAndroid Build Coastguard Worker 	{
714*5e7646d2SAndroid Build Coastguard Worker           switch (cparam->type)
715*5e7646d2SAndroid Build Coastguard Worker 	  {
716*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_UNKNOWN :
717*5e7646d2SAndroid Build Coastguard Worker 	        break;
718*5e7646d2SAndroid Build Coastguard Worker 
719*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_CURVE :
720*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_INVCURVE :
721*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_POINTS :
722*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_REAL :
723*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_INT :
724*5e7646d2SAndroid Build Coastguard Worker 	        bufsize += 10;
725*5e7646d2SAndroid Build Coastguard Worker 	        break;
726*5e7646d2SAndroid Build Coastguard Worker 
727*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_PASSCODE :
728*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_PASSWORD :
729*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_STRING :
730*5e7646d2SAndroid Build Coastguard Worker 		bufsize += 3;
731*5e7646d2SAndroid Build Coastguard Worker 	        if (cparam->current.custom_string)
732*5e7646d2SAndroid Build Coastguard Worker 		  bufsize += 4 * strlen(cparam->current.custom_string);
733*5e7646d2SAndroid Build Coastguard Worker 	        break;
734*5e7646d2SAndroid Build Coastguard Worker           }
735*5e7646d2SAndroid Build Coastguard Worker 	}
736*5e7646d2SAndroid Build Coastguard Worker       }
737*5e7646d2SAndroid Build Coastguard Worker       else
738*5e7646d2SAndroid Build Coastguard Worker         bufsize += 17 + strlen(choices[i]->option->keyword) + 1 +
739*5e7646d2SAndroid Build Coastguard Worker 	           strlen(choices[i]->choice) + 1;
740*5e7646d2SAndroid Build Coastguard Worker 					/* %%BeginFeature: *keyword choice\n */
741*5e7646d2SAndroid Build Coastguard Worker 
742*5e7646d2SAndroid Build Coastguard Worker       bufsize += 13;			/* %%EndFeature\n */
743*5e7646d2SAndroid Build Coastguard Worker       bufsize += 22;			/* } stopped cleartomark\n */
744*5e7646d2SAndroid Build Coastguard Worker     }
745*5e7646d2SAndroid Build Coastguard Worker 
746*5e7646d2SAndroid Build Coastguard Worker     if (choices[i]->code)
747*5e7646d2SAndroid Build Coastguard Worker       bufsize += strlen(choices[i]->code) + 1;
748*5e7646d2SAndroid Build Coastguard Worker     else
749*5e7646d2SAndroid Build Coastguard Worker       bufsize += strlen(ppd_custom_code);
750*5e7646d2SAndroid Build Coastguard Worker   }
751*5e7646d2SAndroid Build Coastguard Worker 
752*5e7646d2SAndroid Build Coastguard Worker  /*
753*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory...
754*5e7646d2SAndroid Build Coastguard Worker   */
755*5e7646d2SAndroid Build Coastguard Worker 
756*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("2ppdEmitString: Allocating %d bytes for string...",
757*5e7646d2SAndroid Build Coastguard Worker                 (int)bufsize));
758*5e7646d2SAndroid Build Coastguard Worker 
759*5e7646d2SAndroid Build Coastguard Worker   if ((buffer = calloc(1, bufsize)) == NULL)
760*5e7646d2SAndroid Build Coastguard Worker   {
761*5e7646d2SAndroid Build Coastguard Worker     free(choices);
762*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
763*5e7646d2SAndroid Build Coastguard Worker   }
764*5e7646d2SAndroid Build Coastguard Worker 
765*5e7646d2SAndroid Build Coastguard Worker   bufend = buffer + bufsize - 1;
766*5e7646d2SAndroid Build Coastguard Worker   loc    = localeconv();
767*5e7646d2SAndroid Build Coastguard Worker 
768*5e7646d2SAndroid Build Coastguard Worker  /*
769*5e7646d2SAndroid Build Coastguard Worker   * Copy the option code to the buffer...
770*5e7646d2SAndroid Build Coastguard Worker   */
771*5e7646d2SAndroid Build Coastguard Worker 
772*5e7646d2SAndroid Build Coastguard Worker   for (i = 0, bufptr = buffer; i < count; i ++, bufptr += strlen(bufptr))
773*5e7646d2SAndroid Build Coastguard Worker     if (section == PPD_ORDER_JCL)
774*5e7646d2SAndroid Build Coastguard Worker     {
775*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
776*5e7646d2SAndroid Build Coastguard Worker 	  choices[i]->code &&
777*5e7646d2SAndroid Build Coastguard Worker           (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
778*5e7646d2SAndroid Build Coastguard Worker 	      != NULL)
779*5e7646d2SAndroid Build Coastguard Worker       {
780*5e7646d2SAndroid Build Coastguard Worker        /*
781*5e7646d2SAndroid Build Coastguard Worker         * Handle substitutions in custom JCL options...
782*5e7646d2SAndroid Build Coastguard Worker 	*/
783*5e7646d2SAndroid Build Coastguard Worker 
784*5e7646d2SAndroid Build Coastguard Worker 	char	*cptr;			/* Pointer into code */
785*5e7646d2SAndroid Build Coastguard Worker 	int	pnum;			/* Parameter number */
786*5e7646d2SAndroid Build Coastguard Worker 
787*5e7646d2SAndroid Build Coastguard Worker 
788*5e7646d2SAndroid Build Coastguard Worker         for (cptr = choices[i]->code; *cptr && bufptr < bufend;)
789*5e7646d2SAndroid Build Coastguard Worker 	{
790*5e7646d2SAndroid Build Coastguard Worker 	  if (*cptr == '\\')
791*5e7646d2SAndroid Build Coastguard Worker 	  {
792*5e7646d2SAndroid Build Coastguard Worker 	    cptr ++;
793*5e7646d2SAndroid Build Coastguard Worker 
794*5e7646d2SAndroid Build Coastguard Worker 	    if (isdigit(*cptr & 255))
795*5e7646d2SAndroid Build Coastguard Worker 	    {
796*5e7646d2SAndroid Build Coastguard Worker 	     /*
797*5e7646d2SAndroid Build Coastguard Worker 	      * Substitute parameter...
798*5e7646d2SAndroid Build Coastguard Worker 	      */
799*5e7646d2SAndroid Build Coastguard Worker 
800*5e7646d2SAndroid Build Coastguard Worker               pnum = *cptr++ - '0';
801*5e7646d2SAndroid Build Coastguard Worker 	      while (isdigit(*cptr & 255))
802*5e7646d2SAndroid Build Coastguard Worker 	        pnum = pnum * 10 + *cptr++ - '0';
803*5e7646d2SAndroid Build Coastguard Worker 
804*5e7646d2SAndroid Build Coastguard Worker               for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
805*5e7646d2SAndroid Build Coastguard Worker 	           cparam;
806*5e7646d2SAndroid Build Coastguard Worker 		   cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
807*5e7646d2SAndroid Build Coastguard Worker 		if (cparam->order == pnum)
808*5e7646d2SAndroid Build Coastguard Worker 		  break;
809*5e7646d2SAndroid Build Coastguard Worker 
810*5e7646d2SAndroid Build Coastguard Worker               if (cparam)
811*5e7646d2SAndroid Build Coastguard Worker 	      {
812*5e7646d2SAndroid Build Coastguard Worker 	        switch (cparam->type)
813*5e7646d2SAndroid Build Coastguard Worker 		{
814*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_UNKNOWN :
815*5e7646d2SAndroid Build Coastguard Worker 		      break;
816*5e7646d2SAndroid Build Coastguard Worker 
817*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_CURVE :
818*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_INVCURVE :
819*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_POINTS :
820*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_REAL :
821*5e7646d2SAndroid Build Coastguard Worker 		      bufptr = _cupsStrFormatd(bufptr, bufend,
822*5e7646d2SAndroid Build Coastguard Worker 					       cparam->current.custom_real,
823*5e7646d2SAndroid Build Coastguard Worker 					       loc);
824*5e7646d2SAndroid Build Coastguard Worker 		      break;
825*5e7646d2SAndroid Build Coastguard Worker 
826*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_INT :
827*5e7646d2SAndroid Build Coastguard Worker 		      snprintf(bufptr, (size_t)(bufend - bufptr), "%d", cparam->current.custom_int);
828*5e7646d2SAndroid Build Coastguard Worker 		      bufptr += strlen(bufptr);
829*5e7646d2SAndroid Build Coastguard Worker 		      break;
830*5e7646d2SAndroid Build Coastguard Worker 
831*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_PASSCODE :
832*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_PASSWORD :
833*5e7646d2SAndroid Build Coastguard Worker 		  case PPD_CUSTOM_STRING :
834*5e7646d2SAndroid Build Coastguard Worker 		      if (cparam->current.custom_string)
835*5e7646d2SAndroid Build Coastguard Worker 		      {
836*5e7646d2SAndroid Build Coastguard Worker 			strlcpy(bufptr, cparam->current.custom_string, (size_t)(bufend - bufptr));
837*5e7646d2SAndroid Build Coastguard Worker 			bufptr += strlen(bufptr);
838*5e7646d2SAndroid Build Coastguard Worker 		      }
839*5e7646d2SAndroid Build Coastguard Worker 		      break;
840*5e7646d2SAndroid Build Coastguard Worker 		}
841*5e7646d2SAndroid Build Coastguard Worker 	      }
842*5e7646d2SAndroid Build Coastguard Worker 	    }
843*5e7646d2SAndroid Build Coastguard Worker 	    else if (*cptr)
844*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = *cptr++;
845*5e7646d2SAndroid Build Coastguard Worker 	  }
846*5e7646d2SAndroid Build Coastguard Worker 	  else
847*5e7646d2SAndroid Build Coastguard Worker 	    *bufptr++ = *cptr++;
848*5e7646d2SAndroid Build Coastguard Worker 	}
849*5e7646d2SAndroid Build Coastguard Worker       }
850*5e7646d2SAndroid Build Coastguard Worker       else if (choices[i]->code)
851*5e7646d2SAndroid Build Coastguard Worker       {
852*5e7646d2SAndroid Build Coastguard Worker        /*
853*5e7646d2SAndroid Build Coastguard Worker         * Otherwise just copy the option code directly...
854*5e7646d2SAndroid Build Coastguard Worker 	*/
855*5e7646d2SAndroid Build Coastguard Worker 
856*5e7646d2SAndroid Build Coastguard Worker         strlcpy(bufptr, choices[i]->code, (size_t)(bufend - bufptr + 1));
857*5e7646d2SAndroid Build Coastguard Worker         bufptr += strlen(bufptr);
858*5e7646d2SAndroid Build Coastguard Worker       }
859*5e7646d2SAndroid Build Coastguard Worker     }
860*5e7646d2SAndroid Build Coastguard Worker     else if (section != PPD_ORDER_EXIT)
861*5e7646d2SAndroid Build Coastguard Worker     {
862*5e7646d2SAndroid Build Coastguard Worker      /*
863*5e7646d2SAndroid Build Coastguard Worker       * Add wrapper commands to prevent printer errors for unsupported
864*5e7646d2SAndroid Build Coastguard Worker       * options...
865*5e7646d2SAndroid Build Coastguard Worker       */
866*5e7646d2SAndroid Build Coastguard Worker 
867*5e7646d2SAndroid Build Coastguard Worker       strlcpy(bufptr, "[{\n", (size_t)(bufend - bufptr + 1));
868*5e7646d2SAndroid Build Coastguard Worker       bufptr += 3;
869*5e7646d2SAndroid Build Coastguard Worker 
870*5e7646d2SAndroid Build Coastguard Worker      /*
871*5e7646d2SAndroid Build Coastguard Worker       * Send DSC comments with option...
872*5e7646d2SAndroid Build Coastguard Worker       */
873*5e7646d2SAndroid Build Coastguard Worker 
874*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("2ppdEmitString: Adding code for %s=%s...",
875*5e7646d2SAndroid Build Coastguard Worker 		    choices[i]->option->keyword, choices[i]->choice));
876*5e7646d2SAndroid Build Coastguard Worker 
877*5e7646d2SAndroid Build Coastguard Worker       if ((!_cups_strcasecmp(choices[i]->option->keyword, "PageSize") ||
878*5e7646d2SAndroid Build Coastguard Worker            !_cups_strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
879*5e7646d2SAndroid Build Coastguard Worker           !_cups_strcasecmp(choices[i]->choice, "Custom"))
880*5e7646d2SAndroid Build Coastguard Worker       {
881*5e7646d2SAndroid Build Coastguard Worker        /*
882*5e7646d2SAndroid Build Coastguard Worker         * Variable size; write out standard size options, using the
883*5e7646d2SAndroid Build Coastguard Worker 	* parameter positions defined in the PPD file...
884*5e7646d2SAndroid Build Coastguard Worker 	*/
885*5e7646d2SAndroid Build Coastguard Worker 
886*5e7646d2SAndroid Build Coastguard Worker         ppd_attr_t	*attr;		/* PPD attribute */
887*5e7646d2SAndroid Build Coastguard Worker 	int		pos,		/* Position of custom value */
888*5e7646d2SAndroid Build Coastguard Worker 			orientation;	/* Orientation to use */
889*5e7646d2SAndroid Build Coastguard Worker 	float		values[5];	/* Values for custom command */
890*5e7646d2SAndroid Build Coastguard Worker 
891*5e7646d2SAndroid Build Coastguard Worker 
892*5e7646d2SAndroid Build Coastguard Worker         strlcpy(bufptr, "%%BeginFeature: *CustomPageSize True\n", (size_t)(bufend - bufptr + 1));
893*5e7646d2SAndroid Build Coastguard Worker         bufptr += 37;
894*5e7646d2SAndroid Build Coastguard Worker 
895*5e7646d2SAndroid Build Coastguard Worker         size = ppdPageSize(ppd, "Custom");
896*5e7646d2SAndroid Build Coastguard Worker 
897*5e7646d2SAndroid Build Coastguard Worker         memset(values, 0, sizeof(values));
898*5e7646d2SAndroid Build Coastguard Worker 
899*5e7646d2SAndroid Build Coastguard Worker 	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
900*5e7646d2SAndroid Build Coastguard Worker 	{
901*5e7646d2SAndroid Build Coastguard Worker 	  pos = atoi(attr->value) - 1;
902*5e7646d2SAndroid Build Coastguard Worker 
903*5e7646d2SAndroid Build Coastguard Worker           if (pos < 0 || pos > 4)
904*5e7646d2SAndroid Build Coastguard Worker 	    pos = 0;
905*5e7646d2SAndroid Build Coastguard Worker 	}
906*5e7646d2SAndroid Build Coastguard Worker 	else
907*5e7646d2SAndroid Build Coastguard Worker 	  pos = 0;
908*5e7646d2SAndroid Build Coastguard Worker 
909*5e7646d2SAndroid Build Coastguard Worker 	values[pos] = size->width;
910*5e7646d2SAndroid Build Coastguard Worker 
911*5e7646d2SAndroid Build Coastguard Worker 	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
912*5e7646d2SAndroid Build Coastguard Worker 	{
913*5e7646d2SAndroid Build Coastguard Worker 	  pos = atoi(attr->value) - 1;
914*5e7646d2SAndroid Build Coastguard Worker 
915*5e7646d2SAndroid Build Coastguard Worker           if (pos < 0 || pos > 4)
916*5e7646d2SAndroid Build Coastguard Worker 	    pos = 1;
917*5e7646d2SAndroid Build Coastguard Worker 	}
918*5e7646d2SAndroid Build Coastguard Worker 	else
919*5e7646d2SAndroid Build Coastguard Worker 	  pos = 1;
920*5e7646d2SAndroid Build Coastguard Worker 
921*5e7646d2SAndroid Build Coastguard Worker 	values[pos] = size->length;
922*5e7646d2SAndroid Build Coastguard Worker 
923*5e7646d2SAndroid Build Coastguard Worker        /*
924*5e7646d2SAndroid Build Coastguard Worker         * According to the Adobe PPD specification, an orientation of 1
925*5e7646d2SAndroid Build Coastguard Worker 	* will produce a print that comes out upside-down with the X
926*5e7646d2SAndroid Build Coastguard Worker 	* axis perpendicular to the direction of feed, which is exactly
927*5e7646d2SAndroid Build Coastguard Worker 	* what we want to be consistent with non-PS printers.
928*5e7646d2SAndroid Build Coastguard Worker 	*
929*5e7646d2SAndroid Build Coastguard Worker 	* We could also use an orientation of 3 to produce output that
930*5e7646d2SAndroid Build Coastguard Worker 	* comes out rightside-up (this is the default for many large format
931*5e7646d2SAndroid Build Coastguard Worker 	* printer PPDs), however for consistency we will stick with the
932*5e7646d2SAndroid Build Coastguard Worker 	* value 1.
933*5e7646d2SAndroid Build Coastguard Worker 	*
934*5e7646d2SAndroid Build Coastguard Worker 	* If we wanted to get fancy, we could use orientations of 0 or
935*5e7646d2SAndroid Build Coastguard Worker 	* 2 and swap the width and length, however we don't want to get
936*5e7646d2SAndroid Build Coastguard Worker 	* fancy, we just want it to work consistently.
937*5e7646d2SAndroid Build Coastguard Worker 	*
938*5e7646d2SAndroid Build Coastguard Worker 	* The orientation value is range limited by the Orientation
939*5e7646d2SAndroid Build Coastguard Worker 	* parameter definition, so certain non-PS printer drivers that
940*5e7646d2SAndroid Build Coastguard Worker 	* only support an Orientation of 0 will get the value 0 as
941*5e7646d2SAndroid Build Coastguard Worker 	* expected.
942*5e7646d2SAndroid Build Coastguard Worker 	*/
943*5e7646d2SAndroid Build Coastguard Worker 
944*5e7646d2SAndroid Build Coastguard Worker         orientation = 1;
945*5e7646d2SAndroid Build Coastguard Worker 
946*5e7646d2SAndroid Build Coastguard Worker 	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
947*5e7646d2SAndroid Build Coastguard Worker 	                        "Orientation")) != NULL)
948*5e7646d2SAndroid Build Coastguard Worker 	{
949*5e7646d2SAndroid Build Coastguard Worker 	  int min_orient, max_orient;	/* Minimum and maximum orientations */
950*5e7646d2SAndroid Build Coastguard Worker 
951*5e7646d2SAndroid Build Coastguard Worker 
952*5e7646d2SAndroid Build Coastguard Worker           if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
953*5e7646d2SAndroid Build Coastguard Worker 	             &max_orient) != 3)
954*5e7646d2SAndroid Build Coastguard Worker 	    pos = 4;
955*5e7646d2SAndroid Build Coastguard Worker 	  else
956*5e7646d2SAndroid Build Coastguard Worker 	  {
957*5e7646d2SAndroid Build Coastguard Worker 	    pos --;
958*5e7646d2SAndroid Build Coastguard Worker 
959*5e7646d2SAndroid Build Coastguard Worker             if (pos < 0 || pos > 4)
960*5e7646d2SAndroid Build Coastguard Worker 	      pos = 4;
961*5e7646d2SAndroid Build Coastguard Worker 
962*5e7646d2SAndroid Build Coastguard Worker             if (orientation > max_orient)
963*5e7646d2SAndroid Build Coastguard Worker 	      orientation = max_orient;
964*5e7646d2SAndroid Build Coastguard Worker 	    else if (orientation < min_orient)
965*5e7646d2SAndroid Build Coastguard Worker 	      orientation = min_orient;
966*5e7646d2SAndroid Build Coastguard Worker 	  }
967*5e7646d2SAndroid Build Coastguard Worker 	}
968*5e7646d2SAndroid Build Coastguard Worker 	else
969*5e7646d2SAndroid Build Coastguard Worker 	  pos = 4;
970*5e7646d2SAndroid Build Coastguard Worker 
971*5e7646d2SAndroid Build Coastguard Worker 	values[pos] = (float)orientation;
972*5e7646d2SAndroid Build Coastguard Worker 
973*5e7646d2SAndroid Build Coastguard Worker         for (pos = 0; pos < 5; pos ++)
974*5e7646d2SAndroid Build Coastguard Worker 	{
975*5e7646d2SAndroid Build Coastguard Worker 	  bufptr    = _cupsStrFormatd(bufptr, bufend, values[pos], loc);
976*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = '\n';
977*5e7646d2SAndroid Build Coastguard Worker         }
978*5e7646d2SAndroid Build Coastguard Worker 
979*5e7646d2SAndroid Build Coastguard Worker 	if (!choices[i]->code)
980*5e7646d2SAndroid Build Coastguard Worker 	{
981*5e7646d2SAndroid Build Coastguard Worker 	 /*
982*5e7646d2SAndroid Build Coastguard Worker 	  * This can happen with certain buggy PPD files that don't include
983*5e7646d2SAndroid Build Coastguard Worker 	  * a CustomPageSize command sequence...  We just use a generic
984*5e7646d2SAndroid Build Coastguard Worker 	  * Level 2 command sequence...
985*5e7646d2SAndroid Build Coastguard Worker 	  */
986*5e7646d2SAndroid Build Coastguard Worker 
987*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(bufptr, ppd_custom_code, (size_t)(bufend - bufptr + 1));
988*5e7646d2SAndroid Build Coastguard Worker           bufptr += strlen(bufptr);
989*5e7646d2SAndroid Build Coastguard Worker 	}
990*5e7646d2SAndroid Build Coastguard Worker       }
991*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
992*5e7646d2SAndroid Build Coastguard Worker                (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
993*5e7646d2SAndroid Build Coastguard Worker 	           != NULL)
994*5e7646d2SAndroid Build Coastguard Worker       {
995*5e7646d2SAndroid Build Coastguard Worker        /*
996*5e7646d2SAndroid Build Coastguard Worker         * Custom option...
997*5e7646d2SAndroid Build Coastguard Worker 	*/
998*5e7646d2SAndroid Build Coastguard Worker 
999*5e7646d2SAndroid Build Coastguard Worker         const char	*s;		/* Pointer into string value */
1000*5e7646d2SAndroid Build Coastguard Worker         cups_array_t	*params;	/* Parameters in the correct output order */
1001*5e7646d2SAndroid Build Coastguard Worker 
1002*5e7646d2SAndroid Build Coastguard Worker 
1003*5e7646d2SAndroid Build Coastguard Worker         params = cupsArrayNew((cups_array_func_t)ppd_compare_cparams, NULL);
1004*5e7646d2SAndroid Build Coastguard Worker 
1005*5e7646d2SAndroid Build Coastguard Worker         for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
1006*5e7646d2SAndroid Build Coastguard Worker 	     cparam;
1007*5e7646d2SAndroid Build Coastguard Worker 	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
1008*5e7646d2SAndroid Build Coastguard Worker           cupsArrayAdd(params, cparam);
1009*5e7646d2SAndroid Build Coastguard Worker 
1010*5e7646d2SAndroid Build Coastguard Worker         snprintf(bufptr, (size_t)(bufend - bufptr + 1), "%%%%BeginFeature: *Custom%s True\n", coption->keyword);
1011*5e7646d2SAndroid Build Coastguard Worker         bufptr += strlen(bufptr);
1012*5e7646d2SAndroid Build Coastguard Worker 
1013*5e7646d2SAndroid Build Coastguard Worker         for (cparam = (ppd_cparam_t *)cupsArrayFirst(params);
1014*5e7646d2SAndroid Build Coastguard Worker 	     cparam;
1015*5e7646d2SAndroid Build Coastguard Worker 	     cparam = (ppd_cparam_t *)cupsArrayNext(params))
1016*5e7646d2SAndroid Build Coastguard Worker 	{
1017*5e7646d2SAndroid Build Coastguard Worker           switch (cparam->type)
1018*5e7646d2SAndroid Build Coastguard Worker 	  {
1019*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_UNKNOWN :
1020*5e7646d2SAndroid Build Coastguard Worker 	        break;
1021*5e7646d2SAndroid Build Coastguard Worker 
1022*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_CURVE :
1023*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_INVCURVE :
1024*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_POINTS :
1025*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_REAL :
1026*5e7646d2SAndroid Build Coastguard Worker 	        bufptr    = _cupsStrFormatd(bufptr, bufend,
1027*5e7646d2SAndroid Build Coastguard Worker 		                            cparam->current.custom_real, loc);
1028*5e7646d2SAndroid Build Coastguard Worker                 *bufptr++ = '\n';
1029*5e7646d2SAndroid Build Coastguard Worker 	        break;
1030*5e7646d2SAndroid Build Coastguard Worker 
1031*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_INT :
1032*5e7646d2SAndroid Build Coastguard Worker 	        snprintf(bufptr, (size_t)(bufend - bufptr + 1), "%d\n", cparam->current.custom_int);
1033*5e7646d2SAndroid Build Coastguard Worker 		bufptr += strlen(bufptr);
1034*5e7646d2SAndroid Build Coastguard Worker 	        break;
1035*5e7646d2SAndroid Build Coastguard Worker 
1036*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_PASSCODE :
1037*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_PASSWORD :
1038*5e7646d2SAndroid Build Coastguard Worker 	    case PPD_CUSTOM_STRING :
1039*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '(';
1040*5e7646d2SAndroid Build Coastguard Worker 
1041*5e7646d2SAndroid Build Coastguard Worker 		if (cparam->current.custom_string)
1042*5e7646d2SAndroid Build Coastguard Worker 		{
1043*5e7646d2SAndroid Build Coastguard Worker 		  for (s = cparam->current.custom_string; *s; s ++)
1044*5e7646d2SAndroid Build Coastguard Worker 		  {
1045*5e7646d2SAndroid Build Coastguard Worker 		    if (*s < ' ' || *s == '(' || *s == ')' || *s >= 127)
1046*5e7646d2SAndroid Build Coastguard Worker 		    {
1047*5e7646d2SAndroid Build Coastguard Worker 		      snprintf(bufptr, (size_t)(bufend - bufptr + 1), "\\%03o", *s & 255);
1048*5e7646d2SAndroid Build Coastguard Worker 		      bufptr += strlen(bufptr);
1049*5e7646d2SAndroid Build Coastguard Worker 		    }
1050*5e7646d2SAndroid Build Coastguard Worker 		    else
1051*5e7646d2SAndroid Build Coastguard Worker 		      *bufptr++ = *s;
1052*5e7646d2SAndroid Build Coastguard Worker 		  }
1053*5e7646d2SAndroid Build Coastguard Worker 		}
1054*5e7646d2SAndroid Build Coastguard Worker 
1055*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = ')';
1056*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = '\n';
1057*5e7646d2SAndroid Build Coastguard Worker 	        break;
1058*5e7646d2SAndroid Build Coastguard Worker           }
1059*5e7646d2SAndroid Build Coastguard Worker 	}
1060*5e7646d2SAndroid Build Coastguard Worker 
1061*5e7646d2SAndroid Build Coastguard Worker 	cupsArrayDelete(params);
1062*5e7646d2SAndroid Build Coastguard Worker       }
1063*5e7646d2SAndroid Build Coastguard Worker       else
1064*5e7646d2SAndroid Build Coastguard Worker       {
1065*5e7646d2SAndroid Build Coastguard Worker         snprintf(bufptr, (size_t)(bufend - bufptr + 1), "%%%%BeginFeature: *%s %s\n", choices[i]->option->keyword, choices[i]->choice);
1066*5e7646d2SAndroid Build Coastguard Worker 	bufptr += strlen(bufptr);
1067*5e7646d2SAndroid Build Coastguard Worker       }
1068*5e7646d2SAndroid Build Coastguard Worker 
1069*5e7646d2SAndroid Build Coastguard Worker       if (choices[i]->code && choices[i]->code[0])
1070*5e7646d2SAndroid Build Coastguard Worker       {
1071*5e7646d2SAndroid Build Coastguard Worker         j = (int)strlen(choices[i]->code);
1072*5e7646d2SAndroid Build Coastguard Worker 	memcpy(bufptr, choices[i]->code, (size_t)j);
1073*5e7646d2SAndroid Build Coastguard Worker 	bufptr += j;
1074*5e7646d2SAndroid Build Coastguard Worker 
1075*5e7646d2SAndroid Build Coastguard Worker 	if (choices[i]->code[j - 1] != '\n')
1076*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = '\n';
1077*5e7646d2SAndroid Build Coastguard Worker       }
1078*5e7646d2SAndroid Build Coastguard Worker 
1079*5e7646d2SAndroid Build Coastguard Worker       strlcpy(bufptr, "%%EndFeature\n"
1080*5e7646d2SAndroid Build Coastguard Worker 		      "} stopped cleartomark\n", (size_t)(bufend - bufptr + 1));
1081*5e7646d2SAndroid Build Coastguard Worker       bufptr += strlen(bufptr);
1082*5e7646d2SAndroid Build Coastguard Worker 
1083*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("2ppdEmitString: Offset in string is %d...",
1084*5e7646d2SAndroid Build Coastguard Worker                     (int)(bufptr - buffer)));
1085*5e7646d2SAndroid Build Coastguard Worker     }
1086*5e7646d2SAndroid Build Coastguard Worker     else if (choices[i]->code)
1087*5e7646d2SAndroid Build Coastguard Worker     {
1088*5e7646d2SAndroid Build Coastguard Worker       strlcpy(bufptr, choices[i]->code, (size_t)(bufend - bufptr + 1));
1089*5e7646d2SAndroid Build Coastguard Worker       bufptr += strlen(bufptr);
1090*5e7646d2SAndroid Build Coastguard Worker     }
1091*5e7646d2SAndroid Build Coastguard Worker 
1092*5e7646d2SAndroid Build Coastguard Worker  /*
1093*5e7646d2SAndroid Build Coastguard Worker   * Nul-terminate, free, and return...
1094*5e7646d2SAndroid Build Coastguard Worker   */
1095*5e7646d2SAndroid Build Coastguard Worker 
1096*5e7646d2SAndroid Build Coastguard Worker   *bufptr = '\0';
1097*5e7646d2SAndroid Build Coastguard Worker 
1098*5e7646d2SAndroid Build Coastguard Worker   free(choices);
1099*5e7646d2SAndroid Build Coastguard Worker 
1100*5e7646d2SAndroid Build Coastguard Worker   return (buffer);
1101*5e7646d2SAndroid Build Coastguard Worker }
1102*5e7646d2SAndroid Build Coastguard Worker 
1103*5e7646d2SAndroid Build Coastguard Worker 
1104*5e7646d2SAndroid Build Coastguard Worker /*
1105*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_compare_cparams()' - Compare the order of two custom parameters.
1106*5e7646d2SAndroid Build Coastguard Worker  */
1107*5e7646d2SAndroid Build Coastguard Worker 
1108*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
ppd_compare_cparams(ppd_cparam_t * a,ppd_cparam_t * b)1109*5e7646d2SAndroid Build Coastguard Worker ppd_compare_cparams(ppd_cparam_t *a,	/* I - First parameter */
1110*5e7646d2SAndroid Build Coastguard Worker                     ppd_cparam_t *b)	/* I - Second parameter */
1111*5e7646d2SAndroid Build Coastguard Worker {
1112*5e7646d2SAndroid Build Coastguard Worker   return (a->order - b->order);
1113*5e7646d2SAndroid Build Coastguard Worker }
1114*5e7646d2SAndroid Build Coastguard Worker 
1115*5e7646d2SAndroid Build Coastguard Worker 
1116*5e7646d2SAndroid Build Coastguard Worker /*
1117*5e7646d2SAndroid Build Coastguard Worker  * 'ppd_handle_media()' - Handle media selection...
1118*5e7646d2SAndroid Build Coastguard Worker  */
1119*5e7646d2SAndroid Build Coastguard Worker 
1120*5e7646d2SAndroid Build Coastguard Worker static void
ppd_handle_media(ppd_file_t * ppd)1121*5e7646d2SAndroid Build Coastguard Worker ppd_handle_media(ppd_file_t *ppd)	/* I - PPD file */
1122*5e7646d2SAndroid Build Coastguard Worker {
1123*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*manual_feed,		/* ManualFeed choice, if any */
1124*5e7646d2SAndroid Build Coastguard Worker 		*input_slot;		/* InputSlot choice, if any */
1125*5e7646d2SAndroid Build Coastguard Worker   ppd_size_t	*size;			/* Current media size */
1126*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t	*rpr;			/* RequiresPageRegion value */
1127*5e7646d2SAndroid Build Coastguard Worker 
1128*5e7646d2SAndroid Build Coastguard Worker 
1129*5e7646d2SAndroid Build Coastguard Worker  /*
1130*5e7646d2SAndroid Build Coastguard Worker   * This function determines what page size code to use, if any, for the
1131*5e7646d2SAndroid Build Coastguard Worker   * current media size, InputSlot, and ManualFeed selections.
1132*5e7646d2SAndroid Build Coastguard Worker   *
1133*5e7646d2SAndroid Build Coastguard Worker   * We use the PageSize code if:
1134*5e7646d2SAndroid Build Coastguard Worker   *
1135*5e7646d2SAndroid Build Coastguard Worker   * 1. A custom media size is selected.
1136*5e7646d2SAndroid Build Coastguard Worker   * 2. ManualFeed and InputSlot are not selected (or do not exist).
1137*5e7646d2SAndroid Build Coastguard Worker   * 3. ManualFeed is selected but is False and InputSlot is not selected or
1138*5e7646d2SAndroid Build Coastguard Worker   *    the selection has no code - the latter check done to support "auto" or
1139*5e7646d2SAndroid Build Coastguard Worker   *    "printer default" InputSlot options.
1140*5e7646d2SAndroid Build Coastguard Worker   *
1141*5e7646d2SAndroid Build Coastguard Worker   * We use the PageRegion code if:
1142*5e7646d2SAndroid Build Coastguard Worker   *
1143*5e7646d2SAndroid Build Coastguard Worker   * 4. RequiresPageRegion does not exist and the PPD contains cupsFilter
1144*5e7646d2SAndroid Build Coastguard Worker   *    keywords, indicating this is a CUPS-based driver.
1145*5e7646d2SAndroid Build Coastguard Worker   * 5. RequiresPageRegion exists for the selected InputSlot (or "All" for any
1146*5e7646d2SAndroid Build Coastguard Worker   *    InputSlot or ManualFeed selection) and is True.
1147*5e7646d2SAndroid Build Coastguard Worker   *
1148*5e7646d2SAndroid Build Coastguard Worker   * If none of the 5 conditions are true, no page size code is used and we
1149*5e7646d2SAndroid Build Coastguard Worker   * unmark any existing PageSize or PageRegion choices.
1150*5e7646d2SAndroid Build Coastguard Worker   */
1151*5e7646d2SAndroid Build Coastguard Worker 
1152*5e7646d2SAndroid Build Coastguard Worker   if ((size = ppdPageSize(ppd, NULL)) == NULL)
1153*5e7646d2SAndroid Build Coastguard Worker     return;
1154*5e7646d2SAndroid Build Coastguard Worker 
1155*5e7646d2SAndroid Build Coastguard Worker   manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed");
1156*5e7646d2SAndroid Build Coastguard Worker   input_slot  = ppdFindMarkedChoice(ppd, "InputSlot");
1157*5e7646d2SAndroid Build Coastguard Worker 
1158*5e7646d2SAndroid Build Coastguard Worker   if (input_slot != NULL)
1159*5e7646d2SAndroid Build Coastguard Worker     rpr = ppdFindAttr(ppd, "RequiresPageRegion", input_slot->choice);
1160*5e7646d2SAndroid Build Coastguard Worker   else
1161*5e7646d2SAndroid Build Coastguard Worker     rpr = NULL;
1162*5e7646d2SAndroid Build Coastguard Worker 
1163*5e7646d2SAndroid Build Coastguard Worker   if (!rpr)
1164*5e7646d2SAndroid Build Coastguard Worker     rpr = ppdFindAttr(ppd, "RequiresPageRegion", "All");
1165*5e7646d2SAndroid Build Coastguard Worker 
1166*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(size->name, "Custom") ||
1167*5e7646d2SAndroid Build Coastguard Worker       (!manual_feed && !input_slot) ||
1168*5e7646d2SAndroid Build Coastguard Worker       (manual_feed && !_cups_strcasecmp(manual_feed->choice, "False") &&
1169*5e7646d2SAndroid Build Coastguard Worker        (!input_slot || (input_slot->code && !input_slot->code[0]))) ||
1170*5e7646d2SAndroid Build Coastguard Worker       (!rpr && ppd->num_filters > 0))
1171*5e7646d2SAndroid Build Coastguard Worker   {
1172*5e7646d2SAndroid Build Coastguard Worker    /*
1173*5e7646d2SAndroid Build Coastguard Worker     * Use PageSize code...
1174*5e7646d2SAndroid Build Coastguard Worker     */
1175*5e7646d2SAndroid Build Coastguard Worker 
1176*5e7646d2SAndroid Build Coastguard Worker     ppdMarkOption(ppd, "PageSize", size->name);
1177*5e7646d2SAndroid Build Coastguard Worker   }
1178*5e7646d2SAndroid Build Coastguard Worker   else if (rpr && rpr->value && !_cups_strcasecmp(rpr->value, "True"))
1179*5e7646d2SAndroid Build Coastguard Worker   {
1180*5e7646d2SAndroid Build Coastguard Worker    /*
1181*5e7646d2SAndroid Build Coastguard Worker     * Use PageRegion code...
1182*5e7646d2SAndroid Build Coastguard Worker     */
1183*5e7646d2SAndroid Build Coastguard Worker 
1184*5e7646d2SAndroid Build Coastguard Worker     ppdMarkOption(ppd, "PageRegion", size->name);
1185*5e7646d2SAndroid Build Coastguard Worker   }
1186*5e7646d2SAndroid Build Coastguard Worker   else
1187*5e7646d2SAndroid Build Coastguard Worker   {
1188*5e7646d2SAndroid Build Coastguard Worker    /*
1189*5e7646d2SAndroid Build Coastguard Worker     * Do not use PageSize or PageRegion code...
1190*5e7646d2SAndroid Build Coastguard Worker     */
1191*5e7646d2SAndroid Build Coastguard Worker 
1192*5e7646d2SAndroid Build Coastguard Worker     ppd_choice_t	*page;		/* PageSize/Region choice, if any */
1193*5e7646d2SAndroid Build Coastguard Worker 
1194*5e7646d2SAndroid Build Coastguard Worker     if ((page = ppdFindMarkedChoice(ppd, "PageSize")) != NULL)
1195*5e7646d2SAndroid Build Coastguard Worker     {
1196*5e7646d2SAndroid Build Coastguard Worker      /*
1197*5e7646d2SAndroid Build Coastguard Worker       * Unmark PageSize...
1198*5e7646d2SAndroid Build Coastguard Worker       */
1199*5e7646d2SAndroid Build Coastguard Worker 
1200*5e7646d2SAndroid Build Coastguard Worker       page->marked = 0;
1201*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRemove(ppd->marked, page);
1202*5e7646d2SAndroid Build Coastguard Worker     }
1203*5e7646d2SAndroid Build Coastguard Worker 
1204*5e7646d2SAndroid Build Coastguard Worker     if ((page = ppdFindMarkedChoice(ppd, "PageRegion")) != NULL)
1205*5e7646d2SAndroid Build Coastguard Worker     {
1206*5e7646d2SAndroid Build Coastguard Worker      /*
1207*5e7646d2SAndroid Build Coastguard Worker       * Unmark PageRegion...
1208*5e7646d2SAndroid Build Coastguard Worker       */
1209*5e7646d2SAndroid Build Coastguard Worker 
1210*5e7646d2SAndroid Build Coastguard Worker       page->marked = 0;
1211*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRemove(ppd->marked, page);
1212*5e7646d2SAndroid Build Coastguard Worker     }
1213*5e7646d2SAndroid Build Coastguard Worker   }
1214*5e7646d2SAndroid Build Coastguard Worker }
1215