xref: /aosp_15_r20/external/libcups/cups/ppd-cache.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * PPD cache implementation for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2010-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  *
6*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
7*5e7646d2SAndroid Build Coastguard Worker  * information.
8*5e7646d2SAndroid Build Coastguard Worker  */
9*5e7646d2SAndroid Build Coastguard Worker 
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker  */
13*5e7646d2SAndroid Build Coastguard Worker 
14*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
15*5e7646d2SAndroid Build Coastguard Worker #include "ppd-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
17*5e7646d2SAndroid Build Coastguard Worker #include <math.h>
18*5e7646d2SAndroid Build Coastguard Worker 
19*5e7646d2SAndroid Build Coastguard Worker 
20*5e7646d2SAndroid Build Coastguard Worker /*
21*5e7646d2SAndroid Build Coastguard Worker  * Macro to test for two almost-equal PWG measurements.
22*5e7646d2SAndroid Build Coastguard Worker  */
23*5e7646d2SAndroid Build Coastguard Worker 
24*5e7646d2SAndroid Build Coastguard Worker #define _PWG_EQUIVALENT(x, y)	(abs((x)-(y)) < 2)
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	cups_get_url(http_t **http, const char *url, char *name, size_t namesize);
32*5e7646d2SAndroid Build Coastguard Worker static void	pwg_add_finishing(cups_array_t *finishings, ipp_finishings_t template, const char *name, const char *value);
33*5e7646d2SAndroid Build Coastguard Worker static void	pwg_add_message(cups_array_t *a, const char *msg, const char *str);
34*5e7646d2SAndroid Build Coastguard Worker static int	pwg_compare_finishings(_pwg_finishings_t *a, _pwg_finishings_t *b);
35*5e7646d2SAndroid Build Coastguard Worker static int	pwg_compare_sizes(cups_size_t *a, cups_size_t *b);
36*5e7646d2SAndroid Build Coastguard Worker static cups_size_t *pwg_copy_size(cups_size_t *size);
37*5e7646d2SAndroid Build Coastguard Worker static void	pwg_free_finishings(_pwg_finishings_t *f);
38*5e7646d2SAndroid Build Coastguard Worker static void	pwg_ppdize_name(const char *ipp, char *name, size_t namesize);
39*5e7646d2SAndroid Build Coastguard Worker static void	pwg_ppdize_resolution(ipp_attribute_t *attr, int element, int *xres, int *yres, char *name, size_t namesize);
40*5e7646d2SAndroid Build Coastguard Worker static void	pwg_unppdize_name(const char *ppd, char *name, size_t namesize,
41*5e7646d2SAndroid Build Coastguard Worker 		                  const char *dashchars);
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker 
44*5e7646d2SAndroid Build Coastguard Worker /*
45*5e7646d2SAndroid Build Coastguard Worker  * '_cupsConvertOptions()' - Convert printer options to standard IPP attributes.
46*5e7646d2SAndroid Build Coastguard Worker  *
47*5e7646d2SAndroid Build Coastguard Worker  * This functions converts PPD and CUPS-specific options to their standard IPP
48*5e7646d2SAndroid Build Coastguard Worker  * attributes and values and adds them to the specified IPP request.
49*5e7646d2SAndroid Build Coastguard Worker  */
50*5e7646d2SAndroid Build Coastguard Worker 
51*5e7646d2SAndroid Build Coastguard Worker int					/* O - New number of copies */
_cupsConvertOptions(ipp_t * request,ppd_file_t * ppd,_ppd_cache_t * pc,ipp_attribute_t * media_col_sup,ipp_attribute_t * doc_handling_sup,ipp_attribute_t * print_color_mode_sup,const char * user,const char * format,int copies,int num_options,cups_option_t * options)52*5e7646d2SAndroid Build Coastguard Worker _cupsConvertOptions(
53*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *request,		/* I - IPP request */
54*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t      *ppd,		/* I - PPD file */
55*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t    *pc,		/* I - PPD cache info */
56*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *media_col_sup,	/* I - media-col-supported values */
57*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *doc_handling_sup,	/* I - multiple-document-handling-supported values */
58*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *print_color_mode_sup,
59*5e7646d2SAndroid Build Coastguard Worker                                 	/* I - Printer supports print-color-mode */
60*5e7646d2SAndroid Build Coastguard Worker     const char    *user,		/* I - User info */
61*5e7646d2SAndroid Build Coastguard Worker     const char    *format,		/* I - document-format value */
62*5e7646d2SAndroid Build Coastguard Worker     int           copies,		/* I - Number of copies */
63*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of options */
64*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options)		/* I - Options */
65*5e7646d2SAndroid Build Coastguard Worker {
66*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
67*5e7646d2SAndroid Build Coastguard Worker   const char	*keyword,		/* PWG keyword */
68*5e7646d2SAndroid Build Coastguard Worker 		*password;		/* Password string */
69*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t	*size;			/* PWG media size */
70*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*media_col,		/* media-col value */
71*5e7646d2SAndroid Build Coastguard Worker 		*media_size;		/* media-size value */
72*5e7646d2SAndroid Build Coastguard Worker   const char	*media_source,		/* media-source value */
73*5e7646d2SAndroid Build Coastguard Worker 		*media_type,		/* media-type value */
74*5e7646d2SAndroid Build Coastguard Worker 		*collate_str,		/* multiple-document-handling value */
75*5e7646d2SAndroid Build Coastguard Worker 		*color_attr_name,	/* Supported color attribute */
76*5e7646d2SAndroid Build Coastguard Worker 		*mandatory,		/* Mandatory attributes */
77*5e7646d2SAndroid Build Coastguard Worker 		*finishing_template;	/* Finishing template */
78*5e7646d2SAndroid Build Coastguard Worker   int		num_finishings = 0,	/* Number of finishing values */
79*5e7646d2SAndroid Build Coastguard Worker 		finishings[10];		/* Finishing enum values */
80*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t	*choice;		/* Marked choice */
81*5e7646d2SAndroid Build Coastguard Worker   int           finishings_copies = copies,
82*5e7646d2SAndroid Build Coastguard Worker                                         /* Number of copies for finishings */
83*5e7646d2SAndroid Build Coastguard Worker                 job_pages = 0,		/* job-pages value */
84*5e7646d2SAndroid Build Coastguard Worker 		number_up = 1;		/* number-up value */
85*5e7646d2SAndroid Build Coastguard Worker   const char	*value;			/* Option value */
86*5e7646d2SAndroid Build Coastguard Worker 
87*5e7646d2SAndroid Build Coastguard Worker 
88*5e7646d2SAndroid Build Coastguard Worker  /*
89*5e7646d2SAndroid Build Coastguard Worker   * Send standard IPP attributes...
90*5e7646d2SAndroid Build Coastguard Worker   */
91*5e7646d2SAndroid Build Coastguard Worker 
92*5e7646d2SAndroid Build Coastguard Worker   if (pc->password && (password = cupsGetOption("job-password", num_options, options)) != NULL && ippGetOperation(request) != IPP_OP_VALIDATE_JOB)
93*5e7646d2SAndroid Build Coastguard Worker   {
94*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t	*attr = NULL;	/* job-password attribute */
95*5e7646d2SAndroid Build Coastguard Worker 
96*5e7646d2SAndroid Build Coastguard Worker     if ((keyword = cupsGetOption("job-password-encryption", num_options, options)) == NULL)
97*5e7646d2SAndroid Build Coastguard Worker       keyword = "none";
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(keyword, "none"))
100*5e7646d2SAndroid Build Coastguard Worker     {
101*5e7646d2SAndroid Build Coastguard Worker      /*
102*5e7646d2SAndroid Build Coastguard Worker       * Add plain-text job-password...
103*5e7646d2SAndroid Build Coastguard Worker       */
104*5e7646d2SAndroid Build Coastguard Worker 
105*5e7646d2SAndroid Build Coastguard Worker       attr = ippAddOctetString(request, IPP_TAG_OPERATION, "job-password", password, (int)strlen(password));
106*5e7646d2SAndroid Build Coastguard Worker     }
107*5e7646d2SAndroid Build Coastguard Worker     else
108*5e7646d2SAndroid Build Coastguard Worker     {
109*5e7646d2SAndroid Build Coastguard Worker      /*
110*5e7646d2SAndroid Build Coastguard Worker       * Add hashed job-password...
111*5e7646d2SAndroid Build Coastguard Worker       */
112*5e7646d2SAndroid Build Coastguard Worker 
113*5e7646d2SAndroid Build Coastguard Worker       unsigned char	hash[64];	/* Hash of password */
114*5e7646d2SAndroid Build Coastguard Worker       ssize_t		hashlen;	/* Length of hash */
115*5e7646d2SAndroid Build Coastguard Worker 
116*5e7646d2SAndroid Build Coastguard Worker       if ((hashlen = cupsHashData(keyword, password, strlen(password), hash, sizeof(hash))) > 0)
117*5e7646d2SAndroid Build Coastguard Worker         attr = ippAddOctetString(request, IPP_TAG_OPERATION, "job-password", hash, (int)hashlen);
118*5e7646d2SAndroid Build Coastguard Worker     }
119*5e7646d2SAndroid Build Coastguard Worker 
120*5e7646d2SAndroid Build Coastguard Worker     if (attr)
121*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "job-password-encryption", NULL, keyword);
122*5e7646d2SAndroid Build Coastguard Worker   }
123*5e7646d2SAndroid Build Coastguard Worker 
124*5e7646d2SAndroid Build Coastguard Worker   if (pc->account_id)
125*5e7646d2SAndroid Build Coastguard Worker   {
126*5e7646d2SAndroid Build Coastguard Worker     if ((keyword = cupsGetOption("job-account-id", num_options, options)) == NULL)
127*5e7646d2SAndroid Build Coastguard Worker       keyword = cupsGetOption("job-billing", num_options, options);
128*5e7646d2SAndroid Build Coastguard Worker 
129*5e7646d2SAndroid Build Coastguard Worker     if (keyword)
130*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-account-id", NULL, keyword);
131*5e7646d2SAndroid Build Coastguard Worker   }
132*5e7646d2SAndroid Build Coastguard Worker 
133*5e7646d2SAndroid Build Coastguard Worker   if (pc->accounting_user_id)
134*5e7646d2SAndroid Build Coastguard Worker   {
135*5e7646d2SAndroid Build Coastguard Worker     if ((keyword = cupsGetOption("job-accounting-user-id", num_options, options)) == NULL)
136*5e7646d2SAndroid Build Coastguard Worker       keyword = user;
137*5e7646d2SAndroid Build Coastguard Worker 
138*5e7646d2SAndroid Build Coastguard Worker     if (keyword)
139*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-accounting-user-id", NULL, keyword);
140*5e7646d2SAndroid Build Coastguard Worker   }
141*5e7646d2SAndroid Build Coastguard Worker 
142*5e7646d2SAndroid Build Coastguard Worker   for (mandatory = (const char *)cupsArrayFirst(pc->mandatory); mandatory; mandatory = (const char *)cupsArrayNext(pc->mandatory))
143*5e7646d2SAndroid Build Coastguard Worker   {
144*5e7646d2SAndroid Build Coastguard Worker     if (strcmp(mandatory, "copies") &&
145*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "destination-uris") &&
146*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "finishings") &&
147*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "finishings-col") &&
148*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "finishing-template") &&
149*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "job-account-id") &&
150*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "job-accounting-user-id") &&
151*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "job-password") &&
152*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "job-password-encryption") &&
153*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "media") &&
154*5e7646d2SAndroid Build Coastguard Worker 	strncmp(mandatory, "media-col", 9) &&
155*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "multiple-document-handling") &&
156*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "output-bin") &&
157*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "print-color-mode") &&
158*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "print-quality") &&
159*5e7646d2SAndroid Build Coastguard Worker 	strcmp(mandatory, "sides") &&
160*5e7646d2SAndroid Build Coastguard Worker 	(keyword = cupsGetOption(mandatory, num_options, options)) != NULL)
161*5e7646d2SAndroid Build Coastguard Worker     {
162*5e7646d2SAndroid Build Coastguard Worker       _ipp_option_t *opt = _ippFindOption(mandatory);
163*5e7646d2SAndroid Build Coastguard Worker 				    /* Option type */
164*5e7646d2SAndroid Build Coastguard Worker       ipp_tag_t	value_tag = opt ? opt->value_tag : IPP_TAG_NAME;
165*5e7646d2SAndroid Build Coastguard Worker 				    /* Value type */
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker       switch (value_tag)
168*5e7646d2SAndroid Build Coastguard Worker       {
169*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_INTEGER :
170*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_ENUM :
171*5e7646d2SAndroid Build Coastguard Worker 	    ippAddInteger(request, IPP_TAG_JOB, value_tag, mandatory, atoi(keyword));
172*5e7646d2SAndroid Build Coastguard Worker 	    break;
173*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_BOOLEAN :
174*5e7646d2SAndroid Build Coastguard Worker 	    ippAddBoolean(request, IPP_TAG_JOB, mandatory, !_cups_strcasecmp(keyword, "true"));
175*5e7646d2SAndroid Build Coastguard Worker 	    break;
176*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_RANGE :
177*5e7646d2SAndroid Build Coastguard Worker 	    {
178*5e7646d2SAndroid Build Coastguard Worker 	      int lower, upper;	/* Range */
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker 	      if (sscanf(keyword, "%d-%d", &lower, &upper) != 2)
181*5e7646d2SAndroid Build Coastguard Worker 		lower = upper = atoi(keyword);
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker 	      ippAddRange(request, IPP_TAG_JOB, mandatory, lower, upper);
184*5e7646d2SAndroid Build Coastguard Worker 	    }
185*5e7646d2SAndroid Build Coastguard Worker 	    break;
186*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_STRING :
187*5e7646d2SAndroid Build Coastguard Worker 	    ippAddOctetString(request, IPP_TAG_JOB, mandatory, keyword, (int)strlen(keyword));
188*5e7646d2SAndroid Build Coastguard Worker 	    break;
189*5e7646d2SAndroid Build Coastguard Worker 	default :
190*5e7646d2SAndroid Build Coastguard Worker 	    if (!strcmp(mandatory, "print-color-mode") && !strcmp(keyword, "monochrome"))
191*5e7646d2SAndroid Build Coastguard Worker 	    {
192*5e7646d2SAndroid Build Coastguard Worker 	      if (ippContainsString(print_color_mode_sup, "auto-monochrome"))
193*5e7646d2SAndroid Build Coastguard Worker 		keyword = "auto-monochrome";
194*5e7646d2SAndroid Build Coastguard Worker 	      else if (ippContainsString(print_color_mode_sup, "process-monochrome") && !ippContainsString(print_color_mode_sup, "monochrome"))
195*5e7646d2SAndroid Build Coastguard Worker 		keyword = "process-monochrome";
196*5e7646d2SAndroid Build Coastguard Worker 	    }
197*5e7646d2SAndroid Build Coastguard Worker 
198*5e7646d2SAndroid Build Coastguard Worker 	    ippAddString(request, IPP_TAG_JOB, value_tag, mandatory, NULL, keyword);
199*5e7646d2SAndroid Build Coastguard Worker 	    break;
200*5e7646d2SAndroid Build Coastguard Worker       }
201*5e7646d2SAndroid Build Coastguard Worker     }
202*5e7646d2SAndroid Build Coastguard Worker   }
203*5e7646d2SAndroid Build Coastguard Worker 
204*5e7646d2SAndroid Build Coastguard Worker   if ((keyword = cupsGetOption("PageSize", num_options, options)) == NULL)
205*5e7646d2SAndroid Build Coastguard Worker     keyword = cupsGetOption("media", num_options, options);
206*5e7646d2SAndroid Build Coastguard Worker 
207*5e7646d2SAndroid Build Coastguard Worker   media_source = _ppdCacheGetSource(pc, cupsGetOption("InputSlot", num_options, options));
208*5e7646d2SAndroid Build Coastguard Worker   media_type   = _ppdCacheGetType(pc, cupsGetOption("MediaType", num_options, options));
209*5e7646d2SAndroid Build Coastguard Worker   size         = _ppdCacheGetSize(pc, keyword);
210*5e7646d2SAndroid Build Coastguard Worker 
211*5e7646d2SAndroid Build Coastguard Worker   if (size || media_source || media_type)
212*5e7646d2SAndroid Build Coastguard Worker   {
213*5e7646d2SAndroid Build Coastguard Worker    /*
214*5e7646d2SAndroid Build Coastguard Worker     * Add a media-col value...
215*5e7646d2SAndroid Build Coastguard Worker     */
216*5e7646d2SAndroid Build Coastguard Worker 
217*5e7646d2SAndroid Build Coastguard Worker     media_col = ippNew();
218*5e7646d2SAndroid Build Coastguard Worker 
219*5e7646d2SAndroid Build Coastguard Worker     if (size)
220*5e7646d2SAndroid Build Coastguard Worker     {
221*5e7646d2SAndroid Build Coastguard Worker       media_size = ippNew();
222*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER,
223*5e7646d2SAndroid Build Coastguard Worker                     "x-dimension", size->width);
224*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(media_size, IPP_TAG_ZERO, IPP_TAG_INTEGER,
225*5e7646d2SAndroid Build Coastguard Worker                     "y-dimension", size->length);
226*5e7646d2SAndroid Build Coastguard Worker 
227*5e7646d2SAndroid Build Coastguard Worker       ippAddCollection(media_col, IPP_TAG_ZERO, "media-size", media_size);
228*5e7646d2SAndroid Build Coastguard Worker     }
229*5e7646d2SAndroid Build Coastguard Worker 
230*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < media_col_sup->num_values; i ++)
231*5e7646d2SAndroid Build Coastguard Worker     {
232*5e7646d2SAndroid Build Coastguard Worker       if (size && !strcmp(media_col_sup->values[i].string.text, "media-left-margin"))
233*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-left-margin", size->left);
234*5e7646d2SAndroid Build Coastguard Worker       else if (size && !strcmp(media_col_sup->values[i].string.text, "media-bottom-margin"))
235*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-bottom-margin", size->bottom);
236*5e7646d2SAndroid Build Coastguard Worker       else if (size && !strcmp(media_col_sup->values[i].string.text, "media-right-margin"))
237*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-right-margin", size->right);
238*5e7646d2SAndroid Build Coastguard Worker       else if (size && !strcmp(media_col_sup->values[i].string.text, "media-top-margin"))
239*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(media_col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-top-margin", size->top);
240*5e7646d2SAndroid Build Coastguard Worker       else if (media_source && !strcmp(media_col_sup->values[i].string.text, "media-source"))
241*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-source", NULL, media_source);
242*5e7646d2SAndroid Build Coastguard Worker       else if (media_type && !strcmp(media_col_sup->values[i].string.text, "media-type"))
243*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(media_col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-type", NULL, media_type);
244*5e7646d2SAndroid Build Coastguard Worker     }
245*5e7646d2SAndroid Build Coastguard Worker 
246*5e7646d2SAndroid Build Coastguard Worker     ippAddCollection(request, IPP_TAG_JOB, "media-col", media_col);
247*5e7646d2SAndroid Build Coastguard Worker   }
248*5e7646d2SAndroid Build Coastguard Worker 
249*5e7646d2SAndroid Build Coastguard Worker   if ((keyword = cupsGetOption("output-bin", num_options, options)) == NULL)
250*5e7646d2SAndroid Build Coastguard Worker   {
251*5e7646d2SAndroid Build Coastguard Worker     if ((choice = ppdFindMarkedChoice(ppd, "OutputBin")) != NULL)
252*5e7646d2SAndroid Build Coastguard Worker       keyword = _ppdCacheGetBin(pc, choice->choice);
253*5e7646d2SAndroid Build Coastguard Worker   }
254*5e7646d2SAndroid Build Coastguard Worker 
255*5e7646d2SAndroid Build Coastguard Worker   if (keyword)
256*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-bin", NULL, keyword);
257*5e7646d2SAndroid Build Coastguard Worker 
258*5e7646d2SAndroid Build Coastguard Worker   color_attr_name = print_color_mode_sup ? "print-color-mode" : "output-mode";
259*5e7646d2SAndroid Build Coastguard Worker 
260*5e7646d2SAndroid Build Coastguard Worker   if ((keyword = cupsGetOption("print-color-mode", num_options, options)) == NULL)
261*5e7646d2SAndroid Build Coastguard Worker   {
262*5e7646d2SAndroid Build Coastguard Worker     if ((choice = ppdFindMarkedChoice(ppd, "ColorModel")) != NULL)
263*5e7646d2SAndroid Build Coastguard Worker     {
264*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(choice->choice, "Gray"))
265*5e7646d2SAndroid Build Coastguard Worker 	keyword = "monochrome";
266*5e7646d2SAndroid Build Coastguard Worker       else
267*5e7646d2SAndroid Build Coastguard Worker 	keyword = "color";
268*5e7646d2SAndroid Build Coastguard Worker     }
269*5e7646d2SAndroid Build Coastguard Worker   }
270*5e7646d2SAndroid Build Coastguard Worker 
271*5e7646d2SAndroid Build Coastguard Worker   if (keyword && !strcmp(keyword, "monochrome"))
272*5e7646d2SAndroid Build Coastguard Worker   {
273*5e7646d2SAndroid Build Coastguard Worker     if (ippContainsString(print_color_mode_sup, "auto-monochrome"))
274*5e7646d2SAndroid Build Coastguard Worker       keyword = "auto-monochrome";
275*5e7646d2SAndroid Build Coastguard Worker     else if (ippContainsString(print_color_mode_sup, "process-monochrome") && !ippContainsString(print_color_mode_sup, "monochrome"))
276*5e7646d2SAndroid Build Coastguard Worker       keyword = "process-monochrome";
277*5e7646d2SAndroid Build Coastguard Worker   }
278*5e7646d2SAndroid Build Coastguard Worker 
279*5e7646d2SAndroid Build Coastguard Worker   if (keyword)
280*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, color_attr_name, NULL, keyword);
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker   if ((keyword = cupsGetOption("print-quality", num_options, options)) != NULL)
283*5e7646d2SAndroid Build Coastguard Worker     ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality", atoi(keyword));
284*5e7646d2SAndroid Build Coastguard Worker   else if ((choice = ppdFindMarkedChoice(ppd, "cupsPrintQuality")) != NULL)
285*5e7646d2SAndroid Build Coastguard Worker   {
286*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(choice->choice, "draft"))
287*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality", IPP_QUALITY_DRAFT);
288*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(choice->choice, "normal"))
289*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality", IPP_QUALITY_NORMAL);
290*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(choice->choice, "high"))
291*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality", IPP_QUALITY_HIGH);
292*5e7646d2SAndroid Build Coastguard Worker   }
293*5e7646d2SAndroid Build Coastguard Worker 
294*5e7646d2SAndroid Build Coastguard Worker   if ((keyword = cupsGetOption("sides", num_options, options)) != NULL)
295*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, keyword);
296*5e7646d2SAndroid Build Coastguard Worker   else if (pc->sides_option && (choice = ppdFindMarkedChoice(ppd, pc->sides_option)) != NULL)
297*5e7646d2SAndroid Build Coastguard Worker   {
298*5e7646d2SAndroid Build Coastguard Worker     if (pc->sides_1sided && !_cups_strcasecmp(choice->choice, pc->sides_1sided))
299*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "one-sided");
300*5e7646d2SAndroid Build Coastguard Worker     else if (pc->sides_2sided_long && !_cups_strcasecmp(choice->choice, pc->sides_2sided_long))
301*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-long-edge");
302*5e7646d2SAndroid Build Coastguard Worker     else if (pc->sides_2sided_short && !_cups_strcasecmp(choice->choice, pc->sides_2sided_short))
303*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-short-edge");
304*5e7646d2SAndroid Build Coastguard Worker   }
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker  /*
307*5e7646d2SAndroid Build Coastguard Worker   * Copies...
308*5e7646d2SAndroid Build Coastguard Worker   */
309*5e7646d2SAndroid Build Coastguard Worker 
310*5e7646d2SAndroid Build Coastguard Worker   if ((keyword = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
311*5e7646d2SAndroid Build Coastguard Worker   {
312*5e7646d2SAndroid Build Coastguard Worker     if (strstr(keyword, "uncollated"))
313*5e7646d2SAndroid Build Coastguard Worker       keyword = "false";
314*5e7646d2SAndroid Build Coastguard Worker     else
315*5e7646d2SAndroid Build Coastguard Worker       keyword = "true";
316*5e7646d2SAndroid Build Coastguard Worker   }
317*5e7646d2SAndroid Build Coastguard Worker   else if ((keyword = cupsGetOption("collate", num_options, options)) == NULL)
318*5e7646d2SAndroid Build Coastguard Worker     keyword = "true";
319*5e7646d2SAndroid Build Coastguard Worker 
320*5e7646d2SAndroid Build Coastguard Worker   if (format)
321*5e7646d2SAndroid Build Coastguard Worker   {
322*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(format, "image/gif") ||
323*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(format, "image/jp2") ||
324*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(format, "image/jpeg") ||
325*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(format, "image/png") ||
326*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strcasecmp(format, "image/tiff") ||
327*5e7646d2SAndroid Build Coastguard Worker 	!_cups_strncasecmp(format, "image/x-", 8))
328*5e7646d2SAndroid Build Coastguard Worker     {
329*5e7646d2SAndroid Build Coastguard Worker      /*
330*5e7646d2SAndroid Build Coastguard Worker       * Collation makes no sense for single page image formats...
331*5e7646d2SAndroid Build Coastguard Worker       */
332*5e7646d2SAndroid Build Coastguard Worker 
333*5e7646d2SAndroid Build Coastguard Worker       keyword = "false";
334*5e7646d2SAndroid Build Coastguard Worker     }
335*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strncasecmp(format, "image/", 6) ||
336*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(format, "application/vnd.cups-raster"))
337*5e7646d2SAndroid Build Coastguard Worker     {
338*5e7646d2SAndroid Build Coastguard Worker      /*
339*5e7646d2SAndroid Build Coastguard Worker       * Multi-page image formats will have copies applied by the upstream
340*5e7646d2SAndroid Build Coastguard Worker       * filters...
341*5e7646d2SAndroid Build Coastguard Worker       */
342*5e7646d2SAndroid Build Coastguard Worker 
343*5e7646d2SAndroid Build Coastguard Worker       copies = 1;
344*5e7646d2SAndroid Build Coastguard Worker     }
345*5e7646d2SAndroid Build Coastguard Worker   }
346*5e7646d2SAndroid Build Coastguard Worker 
347*5e7646d2SAndroid Build Coastguard Worker   if (doc_handling_sup)
348*5e7646d2SAndroid Build Coastguard Worker   {
349*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(keyword, "true"))
350*5e7646d2SAndroid Build Coastguard Worker       collate_str = "separate-documents-collated-copies";
351*5e7646d2SAndroid Build Coastguard Worker     else
352*5e7646d2SAndroid Build Coastguard Worker       collate_str = "separate-documents-uncollated-copies";
353*5e7646d2SAndroid Build Coastguard Worker 
354*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < doc_handling_sup->num_values; i ++)
355*5e7646d2SAndroid Build Coastguard Worker     {
356*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(doc_handling_sup->values[i].string.text, collate_str))
357*5e7646d2SAndroid Build Coastguard Worker       {
358*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "multiple-document-handling", NULL, collate_str);
359*5e7646d2SAndroid Build Coastguard Worker 	break;
360*5e7646d2SAndroid Build Coastguard Worker       }
361*5e7646d2SAndroid Build Coastguard Worker     }
362*5e7646d2SAndroid Build Coastguard Worker 
363*5e7646d2SAndroid Build Coastguard Worker     if (i >= doc_handling_sup->num_values)
364*5e7646d2SAndroid Build Coastguard Worker       copies = 1;
365*5e7646d2SAndroid Build Coastguard Worker   }
366*5e7646d2SAndroid Build Coastguard Worker 
367*5e7646d2SAndroid Build Coastguard Worker  /*
368*5e7646d2SAndroid Build Coastguard Worker   * Map finishing options...
369*5e7646d2SAndroid Build Coastguard Worker   */
370*5e7646d2SAndroid Build Coastguard Worker 
371*5e7646d2SAndroid Build Coastguard Worker   if (copies != finishings_copies)
372*5e7646d2SAndroid Build Coastguard Worker   {
373*5e7646d2SAndroid Build Coastguard Worker     // Figure out the proper job-pages-per-set value...
374*5e7646d2SAndroid Build Coastguard Worker     if ((value = cupsGetOption("job-pages", num_options, options)) == NULL)
375*5e7646d2SAndroid Build Coastguard Worker       value = cupsGetOption("com.apple.print.PrintSettings.PMTotalBeginPages..n.", num_options, options);
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker     if (value)
378*5e7646d2SAndroid Build Coastguard Worker       job_pages = atoi(value);
379*5e7646d2SAndroid Build Coastguard Worker 
380*5e7646d2SAndroid Build Coastguard Worker     // Adjust for number-up
381*5e7646d2SAndroid Build Coastguard Worker     if ((value = cupsGetOption("number-up", num_options, options)) != NULL)
382*5e7646d2SAndroid Build Coastguard Worker       number_up = atoi(value);
383*5e7646d2SAndroid Build Coastguard Worker 
384*5e7646d2SAndroid Build Coastguard Worker     job_pages = (job_pages + number_up - 1) / number_up;
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker     // When duplex printing, raster data will include an extra (blank) page to
387*5e7646d2SAndroid Build Coastguard Worker     // make the total number of pages even.  Make sure this is reflected in the
388*5e7646d2SAndroid Build Coastguard Worker     // page count...
389*5e7646d2SAndroid Build Coastguard Worker     if ((job_pages & 1) && (keyword = cupsGetOption("sides", num_options, options)) != NULL && strcmp(keyword, "one-sided"))
390*5e7646d2SAndroid Build Coastguard Worker       job_pages ++;
391*5e7646d2SAndroid Build Coastguard Worker   }
392*5e7646d2SAndroid Build Coastguard Worker 
393*5e7646d2SAndroid Build Coastguard Worker   if ((finishing_template = cupsGetOption("cupsFinishingTemplate", num_options, options)) == NULL)
394*5e7646d2SAndroid Build Coastguard Worker     finishing_template = cupsGetOption("finishing-template", num_options, options);
395*5e7646d2SAndroid Build Coastguard Worker 
396*5e7646d2SAndroid Build Coastguard Worker   if (finishing_template && strcmp(finishing_template, "none"))
397*5e7646d2SAndroid Build Coastguard Worker   {
398*5e7646d2SAndroid Build Coastguard Worker     ipp_t *fin_col = ippNew();		/* finishings-col value */
399*5e7646d2SAndroid Build Coastguard Worker 
400*5e7646d2SAndroid Build Coastguard Worker     ippAddString(fin_col, IPP_TAG_JOB, IPP_TAG_KEYWORD, "finishing-template", NULL, finishing_template);
401*5e7646d2SAndroid Build Coastguard Worker     ippAddCollection(request, IPP_TAG_JOB, "finishings-col", fin_col);
402*5e7646d2SAndroid Build Coastguard Worker     ippDelete(fin_col);
403*5e7646d2SAndroid Build Coastguard Worker 
404*5e7646d2SAndroid Build Coastguard Worker     if (copies != finishings_copies && job_pages > 0)
405*5e7646d2SAndroid Build Coastguard Worker     {
406*5e7646d2SAndroid Build Coastguard Worker      /*
407*5e7646d2SAndroid Build Coastguard Worker       * Send job-pages-per-set attribute to apply finishings correctly...
408*5e7646d2SAndroid Build Coastguard Worker       */
409*5e7646d2SAndroid Build Coastguard Worker 
410*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", job_pages);
411*5e7646d2SAndroid Build Coastguard Worker     }
412*5e7646d2SAndroid Build Coastguard Worker   }
413*5e7646d2SAndroid Build Coastguard Worker   else
414*5e7646d2SAndroid Build Coastguard Worker   {
415*5e7646d2SAndroid Build Coastguard Worker     num_finishings = _ppdCacheGetFinishingValues(ppd, pc, (int)(sizeof(finishings) / sizeof(finishings[0])), finishings);
416*5e7646d2SAndroid Build Coastguard Worker     if (num_finishings > 0)
417*5e7646d2SAndroid Build Coastguard Worker     {
418*5e7646d2SAndroid Build Coastguard Worker       ippAddIntegers(request, IPP_TAG_JOB, IPP_TAG_ENUM, "finishings", num_finishings, finishings);
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker       if (copies != finishings_copies && job_pages > 0)
421*5e7646d2SAndroid Build Coastguard Worker       {
422*5e7646d2SAndroid Build Coastguard Worker        /*
423*5e7646d2SAndroid Build Coastguard Worker 	* Send job-pages-per-set attribute to apply finishings correctly...
424*5e7646d2SAndroid Build Coastguard Worker 	*/
425*5e7646d2SAndroid Build Coastguard Worker 
426*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", job_pages);
427*5e7646d2SAndroid Build Coastguard Worker       }
428*5e7646d2SAndroid Build Coastguard Worker     }
429*5e7646d2SAndroid Build Coastguard Worker   }
430*5e7646d2SAndroid Build Coastguard Worker 
431*5e7646d2SAndroid Build Coastguard Worker   return (copies);
432*5e7646d2SAndroid Build Coastguard Worker }
433*5e7646d2SAndroid Build Coastguard Worker 
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker /*
436*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheCreateWithFile()' - Create PPD cache and mapping data from a
437*5e7646d2SAndroid Build Coastguard Worker  *                               written file.
438*5e7646d2SAndroid Build Coastguard Worker  *
439*5e7646d2SAndroid Build Coastguard Worker  * Use the @link _ppdCacheWriteFile@ function to write PWG mapping data to a
440*5e7646d2SAndroid Build Coastguard Worker  * file.
441*5e7646d2SAndroid Build Coastguard Worker  */
442*5e7646d2SAndroid Build Coastguard Worker 
443*5e7646d2SAndroid Build Coastguard Worker _ppd_cache_t *				/* O  - PPD cache and mapping data */
_ppdCacheCreateWithFile(const char * filename,ipp_t ** attrs)444*5e7646d2SAndroid Build Coastguard Worker _ppdCacheCreateWithFile(
445*5e7646d2SAndroid Build Coastguard Worker     const char *filename,		/* I  - File to read */
446*5e7646d2SAndroid Build Coastguard Worker     ipp_t      **attrs)			/* IO - IPP attributes, if any */
447*5e7646d2SAndroid Build Coastguard Worker {
448*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* File */
449*5e7646d2SAndroid Build Coastguard Worker   _ppd_cache_t	*pc;			/* PWG mapping data */
450*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t	*size;			/* Current size */
451*5e7646d2SAndroid Build Coastguard Worker   pwg_map_t	*map;			/* Current map */
452*5e7646d2SAndroid Build Coastguard Worker   _pwg_finishings_t *finishings;	/* Current finishings option */
453*5e7646d2SAndroid Build Coastguard Worker   int		linenum,		/* Current line number */
454*5e7646d2SAndroid Build Coastguard Worker 		num_bins,		/* Number of bins in file */
455*5e7646d2SAndroid Build Coastguard Worker 		num_sizes,		/* Number of sizes in file */
456*5e7646d2SAndroid Build Coastguard Worker 		num_sources,		/* Number of sources in file */
457*5e7646d2SAndroid Build Coastguard Worker 		num_types;		/* Number of types in file */
458*5e7646d2SAndroid Build Coastguard Worker   char		line[2048],		/* Current line */
459*5e7646d2SAndroid Build Coastguard Worker 		*value,			/* Pointer to value in line */
460*5e7646d2SAndroid Build Coastguard Worker 		*valueptr,		/* Pointer into value */
461*5e7646d2SAndroid Build Coastguard Worker 		pwg_keyword[128],	/* PWG keyword */
462*5e7646d2SAndroid Build Coastguard Worker 		ppd_keyword[PPD_MAX_NAME];
463*5e7646d2SAndroid Build Coastguard Worker 					/* PPD keyword */
464*5e7646d2SAndroid Build Coastguard Worker   _pwg_print_color_mode_t print_color_mode;
465*5e7646d2SAndroid Build Coastguard Worker 					/* Print color mode for preset */
466*5e7646d2SAndroid Build Coastguard Worker   _pwg_print_quality_t print_quality;	/* Print quality for preset */
467*5e7646d2SAndroid Build Coastguard Worker 
468*5e7646d2SAndroid Build Coastguard Worker 
469*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_ppdCacheCreateWithFile(filename=\"%s\")", filename));
470*5e7646d2SAndroid Build Coastguard Worker 
471*5e7646d2SAndroid Build Coastguard Worker  /*
472*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
473*5e7646d2SAndroid Build Coastguard Worker   */
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker   if (attrs)
476*5e7646d2SAndroid Build Coastguard Worker     *attrs = NULL;
477*5e7646d2SAndroid Build Coastguard Worker 
478*5e7646d2SAndroid Build Coastguard Worker   if (!filename)
479*5e7646d2SAndroid Build Coastguard Worker   {
480*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
481*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
482*5e7646d2SAndroid Build Coastguard Worker   }
483*5e7646d2SAndroid Build Coastguard Worker 
484*5e7646d2SAndroid Build Coastguard Worker  /*
485*5e7646d2SAndroid Build Coastguard Worker   * Open the file...
486*5e7646d2SAndroid Build Coastguard Worker   */
487*5e7646d2SAndroid Build Coastguard Worker 
488*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(filename, "r")) == NULL)
489*5e7646d2SAndroid Build Coastguard Worker   {
490*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
491*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
492*5e7646d2SAndroid Build Coastguard Worker   }
493*5e7646d2SAndroid Build Coastguard Worker 
494*5e7646d2SAndroid Build Coastguard Worker  /*
495*5e7646d2SAndroid Build Coastguard Worker   * Read the first line and make sure it has "#CUPS-PPD-CACHE-version" in it...
496*5e7646d2SAndroid Build Coastguard Worker   */
497*5e7646d2SAndroid Build Coastguard Worker 
498*5e7646d2SAndroid Build Coastguard Worker   if (!cupsFileGets(fp, line, sizeof(line)))
499*5e7646d2SAndroid Build Coastguard Worker   {
500*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
501*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("_ppdCacheCreateWithFile: Unable to read first line.");
502*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
503*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
504*5e7646d2SAndroid Build Coastguard Worker   }
505*5e7646d2SAndroid Build Coastguard Worker 
506*5e7646d2SAndroid Build Coastguard Worker   if (strncmp(line, "#CUPS-PPD-CACHE-", 16))
507*5e7646d2SAndroid Build Coastguard Worker   {
508*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
509*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("_ppdCacheCreateWithFile: Wrong first line \"%s\".", line));
510*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
511*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
512*5e7646d2SAndroid Build Coastguard Worker   }
513*5e7646d2SAndroid Build Coastguard Worker 
514*5e7646d2SAndroid Build Coastguard Worker   if (atoi(line + 16) != _PPD_CACHE_VERSION)
515*5e7646d2SAndroid Build Coastguard Worker   {
516*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Out of date PPD cache file."), 1);
517*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("_ppdCacheCreateWithFile: Cache file has version %s, "
518*5e7646d2SAndroid Build Coastguard Worker                   "expected %d.", line + 16, _PPD_CACHE_VERSION));
519*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
520*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
521*5e7646d2SAndroid Build Coastguard Worker   }
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker  /*
524*5e7646d2SAndroid Build Coastguard Worker   * Allocate the mapping data structure...
525*5e7646d2SAndroid Build Coastguard Worker   */
526*5e7646d2SAndroid Build Coastguard Worker 
527*5e7646d2SAndroid Build Coastguard Worker   if ((pc = calloc(1, sizeof(_ppd_cache_t))) == NULL)
528*5e7646d2SAndroid Build Coastguard Worker   {
529*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
530*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("_ppdCacheCreateWithFile: Unable to allocate _ppd_cache_t.");
531*5e7646d2SAndroid Build Coastguard Worker     goto create_error;
532*5e7646d2SAndroid Build Coastguard Worker   }
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker   pc->max_copies = 9999;
535*5e7646d2SAndroid Build Coastguard Worker 
536*5e7646d2SAndroid Build Coastguard Worker  /*
537*5e7646d2SAndroid Build Coastguard Worker   * Read the file...
538*5e7646d2SAndroid Build Coastguard Worker   */
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker   linenum     = 0;
541*5e7646d2SAndroid Build Coastguard Worker   num_bins    = 0;
542*5e7646d2SAndroid Build Coastguard Worker   num_sizes   = 0;
543*5e7646d2SAndroid Build Coastguard Worker   num_sources = 0;
544*5e7646d2SAndroid Build Coastguard Worker   num_types   = 0;
545*5e7646d2SAndroid Build Coastguard Worker 
546*5e7646d2SAndroid Build Coastguard Worker   while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
547*5e7646d2SAndroid Build Coastguard Worker   {
548*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("_ppdCacheCreateWithFile: line=\"%s\", value=\"%s\", "
549*5e7646d2SAndroid Build Coastguard Worker                   "linenum=%d", line, value, linenum));
550*5e7646d2SAndroid Build Coastguard Worker 
551*5e7646d2SAndroid Build Coastguard Worker     if (!value)
552*5e7646d2SAndroid Build Coastguard Worker     {
553*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheCreateWithFile: Missing value on line %d.",
554*5e7646d2SAndroid Build Coastguard Worker                     linenum));
555*5e7646d2SAndroid Build Coastguard Worker       _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
556*5e7646d2SAndroid Build Coastguard Worker       goto create_error;
557*5e7646d2SAndroid Build Coastguard Worker     }
558*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Filter"))
559*5e7646d2SAndroid Build Coastguard Worker     {
560*5e7646d2SAndroid Build Coastguard Worker       if (!pc->filters)
561*5e7646d2SAndroid Build Coastguard Worker         pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
562*5e7646d2SAndroid Build Coastguard Worker 
563*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->filters, value);
564*5e7646d2SAndroid Build Coastguard Worker     }
565*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "PreFilter"))
566*5e7646d2SAndroid Build Coastguard Worker     {
567*5e7646d2SAndroid Build Coastguard Worker       if (!pc->prefilters)
568*5e7646d2SAndroid Build Coastguard Worker         pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
569*5e7646d2SAndroid Build Coastguard Worker 
570*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->prefilters, value);
571*5e7646d2SAndroid Build Coastguard Worker     }
572*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Product"))
573*5e7646d2SAndroid Build Coastguard Worker     {
574*5e7646d2SAndroid Build Coastguard Worker       pc->product = strdup(value);
575*5e7646d2SAndroid Build Coastguard Worker     }
576*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "SingleFile"))
577*5e7646d2SAndroid Build Coastguard Worker     {
578*5e7646d2SAndroid Build Coastguard Worker       pc->single_file = !_cups_strcasecmp(value, "true");
579*5e7646d2SAndroid Build Coastguard Worker     }
580*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "IPP"))
581*5e7646d2SAndroid Build Coastguard Worker     {
582*5e7646d2SAndroid Build Coastguard Worker       off_t	pos = cupsFileTell(fp),	/* Position in file */
583*5e7646d2SAndroid Build Coastguard Worker 		length = strtol(value, NULL, 10);
584*5e7646d2SAndroid Build Coastguard Worker 					/* Length of IPP attributes */
585*5e7646d2SAndroid Build Coastguard Worker 
586*5e7646d2SAndroid Build Coastguard Worker       if (attrs && *attrs)
587*5e7646d2SAndroid Build Coastguard Worker       {
588*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheCreateWithFile: IPP listed multiple times.");
589*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
590*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
591*5e7646d2SAndroid Build Coastguard Worker       }
592*5e7646d2SAndroid Build Coastguard Worker       else if (length <= 0)
593*5e7646d2SAndroid Build Coastguard Worker       {
594*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP length.");
595*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
596*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
597*5e7646d2SAndroid Build Coastguard Worker       }
598*5e7646d2SAndroid Build Coastguard Worker 
599*5e7646d2SAndroid Build Coastguard Worker       if (attrs)
600*5e7646d2SAndroid Build Coastguard Worker       {
601*5e7646d2SAndroid Build Coastguard Worker        /*
602*5e7646d2SAndroid Build Coastguard Worker         * Read IPP attributes into the provided variable...
603*5e7646d2SAndroid Build Coastguard Worker 	*/
604*5e7646d2SAndroid Build Coastguard Worker 
605*5e7646d2SAndroid Build Coastguard Worker         *attrs = ippNew();
606*5e7646d2SAndroid Build Coastguard Worker 
607*5e7646d2SAndroid Build Coastguard Worker         if (ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL,
608*5e7646d2SAndroid Build Coastguard Worker 		      *attrs) != IPP_STATE_DATA)
609*5e7646d2SAndroid Build Coastguard Worker 	{
610*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data.");
611*5e7646d2SAndroid Build Coastguard Worker 	  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
612*5e7646d2SAndroid Build Coastguard Worker 	  goto create_error;
613*5e7646d2SAndroid Build Coastguard Worker 	}
614*5e7646d2SAndroid Build Coastguard Worker       }
615*5e7646d2SAndroid Build Coastguard Worker       else
616*5e7646d2SAndroid Build Coastguard Worker       {
617*5e7646d2SAndroid Build Coastguard Worker        /*
618*5e7646d2SAndroid Build Coastguard Worker         * Skip the IPP data entirely...
619*5e7646d2SAndroid Build Coastguard Worker 	*/
620*5e7646d2SAndroid Build Coastguard Worker 
621*5e7646d2SAndroid Build Coastguard Worker         cupsFileSeek(fp, pos + length);
622*5e7646d2SAndroid Build Coastguard Worker       }
623*5e7646d2SAndroid Build Coastguard Worker 
624*5e7646d2SAndroid Build Coastguard Worker       if (cupsFileTell(fp) != (pos + length))
625*5e7646d2SAndroid Build Coastguard Worker       {
626*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data.");
627*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
628*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
629*5e7646d2SAndroid Build Coastguard Worker       }
630*5e7646d2SAndroid Build Coastguard Worker     }
631*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "NumBins"))
632*5e7646d2SAndroid Build Coastguard Worker     {
633*5e7646d2SAndroid Build Coastguard Worker       if (num_bins > 0)
634*5e7646d2SAndroid Build Coastguard Worker       {
635*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheCreateWithFile: NumBins listed multiple times.");
636*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
637*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
638*5e7646d2SAndroid Build Coastguard Worker       }
639*5e7646d2SAndroid Build Coastguard Worker 
640*5e7646d2SAndroid Build Coastguard Worker       if ((num_bins = atoi(value)) <= 0 || num_bins > 65536)
641*5e7646d2SAndroid Build Coastguard Worker       {
642*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumBins value %d on line "
643*5e7646d2SAndroid Build Coastguard Worker 		      "%d.", num_sizes, linenum));
644*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
645*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
646*5e7646d2SAndroid Build Coastguard Worker       }
647*5e7646d2SAndroid Build Coastguard Worker 
648*5e7646d2SAndroid Build Coastguard Worker       if ((pc->bins = calloc((size_t)num_bins, sizeof(pwg_map_t))) == NULL)
649*5e7646d2SAndroid Build Coastguard Worker       {
650*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d bins.",
651*5e7646d2SAndroid Build Coastguard Worker 	              num_sizes));
652*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
653*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
654*5e7646d2SAndroid Build Coastguard Worker       }
655*5e7646d2SAndroid Build Coastguard Worker     }
656*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Bin"))
657*5e7646d2SAndroid Build Coastguard Worker     {
658*5e7646d2SAndroid Build Coastguard Worker       if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
659*5e7646d2SAndroid Build Coastguard Worker       {
660*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad Bin on line %d.", linenum));
661*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
662*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
663*5e7646d2SAndroid Build Coastguard Worker       }
664*5e7646d2SAndroid Build Coastguard Worker 
665*5e7646d2SAndroid Build Coastguard Worker       if (pc->num_bins >= num_bins)
666*5e7646d2SAndroid Build Coastguard Worker       {
667*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Too many Bin's on line %d.",
668*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
669*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
670*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
671*5e7646d2SAndroid Build Coastguard Worker       }
672*5e7646d2SAndroid Build Coastguard Worker 
673*5e7646d2SAndroid Build Coastguard Worker       map      = pc->bins + pc->num_bins;
674*5e7646d2SAndroid Build Coastguard Worker       map->pwg = strdup(pwg_keyword);
675*5e7646d2SAndroid Build Coastguard Worker       map->ppd = strdup(ppd_keyword);
676*5e7646d2SAndroid Build Coastguard Worker 
677*5e7646d2SAndroid Build Coastguard Worker       pc->num_bins ++;
678*5e7646d2SAndroid Build Coastguard Worker     }
679*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "NumSizes"))
680*5e7646d2SAndroid Build Coastguard Worker     {
681*5e7646d2SAndroid Build Coastguard Worker       if (num_sizes > 0)
682*5e7646d2SAndroid Build Coastguard Worker       {
683*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheCreateWithFile: NumSizes listed multiple times.");
684*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
685*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
686*5e7646d2SAndroid Build Coastguard Worker       }
687*5e7646d2SAndroid Build Coastguard Worker 
688*5e7646d2SAndroid Build Coastguard Worker       if ((num_sizes = atoi(value)) < 0 || num_sizes > 65536)
689*5e7646d2SAndroid Build Coastguard Worker       {
690*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSizes value %d on line "
691*5e7646d2SAndroid Build Coastguard Worker 	              "%d.", num_sizes, linenum));
692*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
693*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
694*5e7646d2SAndroid Build Coastguard Worker       }
695*5e7646d2SAndroid Build Coastguard Worker 
696*5e7646d2SAndroid Build Coastguard Worker       if (num_sizes > 0)
697*5e7646d2SAndroid Build Coastguard Worker       {
698*5e7646d2SAndroid Build Coastguard Worker 	if ((pc->sizes = calloc((size_t)num_sizes, sizeof(pwg_size_t))) == NULL)
699*5e7646d2SAndroid Build Coastguard Worker 	{
700*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sizes.",
701*5e7646d2SAndroid Build Coastguard Worker 			num_sizes));
702*5e7646d2SAndroid Build Coastguard Worker 	  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
703*5e7646d2SAndroid Build Coastguard Worker 	  goto create_error;
704*5e7646d2SAndroid Build Coastguard Worker 	}
705*5e7646d2SAndroid Build Coastguard Worker       }
706*5e7646d2SAndroid Build Coastguard Worker     }
707*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Size"))
708*5e7646d2SAndroid Build Coastguard Worker     {
709*5e7646d2SAndroid Build Coastguard Worker       if (pc->num_sizes >= num_sizes)
710*5e7646d2SAndroid Build Coastguard Worker       {
711*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Too many Size's on line %d.",
712*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
713*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
714*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
715*5e7646d2SAndroid Build Coastguard Worker       }
716*5e7646d2SAndroid Build Coastguard Worker 
717*5e7646d2SAndroid Build Coastguard Worker       size = pc->sizes + pc->num_sizes;
718*5e7646d2SAndroid Build Coastguard Worker 
719*5e7646d2SAndroid Build Coastguard Worker       if (sscanf(value, "%127s%40s%d%d%d%d%d%d", pwg_keyword, ppd_keyword,
720*5e7646d2SAndroid Build Coastguard Worker 		 &(size->width), &(size->length), &(size->left),
721*5e7646d2SAndroid Build Coastguard Worker 		 &(size->bottom), &(size->right), &(size->top)) != 8)
722*5e7646d2SAndroid Build Coastguard Worker       {
723*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad Size on line %d.",
724*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
725*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
726*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
727*5e7646d2SAndroid Build Coastguard Worker       }
728*5e7646d2SAndroid Build Coastguard Worker 
729*5e7646d2SAndroid Build Coastguard Worker       size->map.pwg = strdup(pwg_keyword);
730*5e7646d2SAndroid Build Coastguard Worker       size->map.ppd = strdup(ppd_keyword);
731*5e7646d2SAndroid Build Coastguard Worker 
732*5e7646d2SAndroid Build Coastguard Worker       pc->num_sizes ++;
733*5e7646d2SAndroid Build Coastguard Worker     }
734*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "CustomSize"))
735*5e7646d2SAndroid Build Coastguard Worker     {
736*5e7646d2SAndroid Build Coastguard Worker       if (pc->custom_max_width > 0)
737*5e7646d2SAndroid Build Coastguard Worker       {
738*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Too many CustomSize's on line "
739*5e7646d2SAndroid Build Coastguard Worker 	              "%d.", linenum));
740*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
741*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
742*5e7646d2SAndroid Build Coastguard Worker       }
743*5e7646d2SAndroid Build Coastguard Worker 
744*5e7646d2SAndroid Build Coastguard Worker       if (sscanf(value, "%d%d%d%d%d%d%d%d", &(pc->custom_max_width),
745*5e7646d2SAndroid Build Coastguard Worker                  &(pc->custom_max_length), &(pc->custom_min_width),
746*5e7646d2SAndroid Build Coastguard Worker 		 &(pc->custom_min_length), &(pc->custom_size.left),
747*5e7646d2SAndroid Build Coastguard Worker 		 &(pc->custom_size.bottom), &(pc->custom_size.right),
748*5e7646d2SAndroid Build Coastguard Worker 		 &(pc->custom_size.top)) != 8)
749*5e7646d2SAndroid Build Coastguard Worker       {
750*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad CustomSize on line %d.",
751*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
752*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
753*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
754*5e7646d2SAndroid Build Coastguard Worker       }
755*5e7646d2SAndroid Build Coastguard Worker 
756*5e7646d2SAndroid Build Coastguard Worker       pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
757*5e7646d2SAndroid Build Coastguard Worker 		        pc->custom_max_width, pc->custom_max_length, NULL);
758*5e7646d2SAndroid Build Coastguard Worker       pc->custom_max_keyword = strdup(pwg_keyword);
759*5e7646d2SAndroid Build Coastguard Worker 
760*5e7646d2SAndroid Build Coastguard Worker       pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
761*5e7646d2SAndroid Build Coastguard Worker 		        pc->custom_min_width, pc->custom_min_length, NULL);
762*5e7646d2SAndroid Build Coastguard Worker       pc->custom_min_keyword = strdup(pwg_keyword);
763*5e7646d2SAndroid Build Coastguard Worker     }
764*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "SourceOption"))
765*5e7646d2SAndroid Build Coastguard Worker     {
766*5e7646d2SAndroid Build Coastguard Worker       pc->source_option = strdup(value);
767*5e7646d2SAndroid Build Coastguard Worker     }
768*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "NumSources"))
769*5e7646d2SAndroid Build Coastguard Worker     {
770*5e7646d2SAndroid Build Coastguard Worker       if (num_sources > 0)
771*5e7646d2SAndroid Build Coastguard Worker       {
772*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheCreateWithFile: NumSources listed multiple "
773*5e7646d2SAndroid Build Coastguard Worker 	           "times.");
774*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
775*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
776*5e7646d2SAndroid Build Coastguard Worker       }
777*5e7646d2SAndroid Build Coastguard Worker 
778*5e7646d2SAndroid Build Coastguard Worker       if ((num_sources = atoi(value)) <= 0 || num_sources > 65536)
779*5e7646d2SAndroid Build Coastguard Worker       {
780*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSources value %d on "
781*5e7646d2SAndroid Build Coastguard Worker 	              "line %d.", num_sources, linenum));
782*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
783*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
784*5e7646d2SAndroid Build Coastguard Worker       }
785*5e7646d2SAndroid Build Coastguard Worker 
786*5e7646d2SAndroid Build Coastguard Worker       if ((pc->sources = calloc((size_t)num_sources, sizeof(pwg_map_t))) == NULL)
787*5e7646d2SAndroid Build Coastguard Worker       {
788*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sources.",
789*5e7646d2SAndroid Build Coastguard Worker 	              num_sources));
790*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
791*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
792*5e7646d2SAndroid Build Coastguard Worker       }
793*5e7646d2SAndroid Build Coastguard Worker     }
794*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Source"))
795*5e7646d2SAndroid Build Coastguard Worker     {
796*5e7646d2SAndroid Build Coastguard Worker       if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
797*5e7646d2SAndroid Build Coastguard Worker       {
798*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad Source on line %d.",
799*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
800*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
801*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
802*5e7646d2SAndroid Build Coastguard Worker       }
803*5e7646d2SAndroid Build Coastguard Worker 
804*5e7646d2SAndroid Build Coastguard Worker       if (pc->num_sources >= num_sources)
805*5e7646d2SAndroid Build Coastguard Worker       {
806*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Too many Source's on line %d.",
807*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
808*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
809*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
810*5e7646d2SAndroid Build Coastguard Worker       }
811*5e7646d2SAndroid Build Coastguard Worker 
812*5e7646d2SAndroid Build Coastguard Worker       map      = pc->sources + pc->num_sources;
813*5e7646d2SAndroid Build Coastguard Worker       map->pwg = strdup(pwg_keyword);
814*5e7646d2SAndroid Build Coastguard Worker       map->ppd = strdup(ppd_keyword);
815*5e7646d2SAndroid Build Coastguard Worker 
816*5e7646d2SAndroid Build Coastguard Worker       pc->num_sources ++;
817*5e7646d2SAndroid Build Coastguard Worker     }
818*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "NumTypes"))
819*5e7646d2SAndroid Build Coastguard Worker     {
820*5e7646d2SAndroid Build Coastguard Worker       if (num_types > 0)
821*5e7646d2SAndroid Build Coastguard Worker       {
822*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheCreateWithFile: NumTypes listed multiple times.");
823*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
824*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
825*5e7646d2SAndroid Build Coastguard Worker       }
826*5e7646d2SAndroid Build Coastguard Worker 
827*5e7646d2SAndroid Build Coastguard Worker       if ((num_types = atoi(value)) <= 0 || num_types > 65536)
828*5e7646d2SAndroid Build Coastguard Worker       {
829*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumTypes value %d on "
830*5e7646d2SAndroid Build Coastguard Worker 	              "line %d.", num_types, linenum));
831*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
832*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
833*5e7646d2SAndroid Build Coastguard Worker       }
834*5e7646d2SAndroid Build Coastguard Worker 
835*5e7646d2SAndroid Build Coastguard Worker       if ((pc->types = calloc((size_t)num_types, sizeof(pwg_map_t))) == NULL)
836*5e7646d2SAndroid Build Coastguard Worker       {
837*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d types.",
838*5e7646d2SAndroid Build Coastguard Worker 	              num_types));
839*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
840*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
841*5e7646d2SAndroid Build Coastguard Worker       }
842*5e7646d2SAndroid Build Coastguard Worker     }
843*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Type"))
844*5e7646d2SAndroid Build Coastguard Worker     {
845*5e7646d2SAndroid Build Coastguard Worker       if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
846*5e7646d2SAndroid Build Coastguard Worker       {
847*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad Type on line %d.",
848*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
849*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
850*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
851*5e7646d2SAndroid Build Coastguard Worker       }
852*5e7646d2SAndroid Build Coastguard Worker 
853*5e7646d2SAndroid Build Coastguard Worker       if (pc->num_types >= num_types)
854*5e7646d2SAndroid Build Coastguard Worker       {
855*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Too many Type's on line %d.",
856*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
857*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
858*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
859*5e7646d2SAndroid Build Coastguard Worker       }
860*5e7646d2SAndroid Build Coastguard Worker 
861*5e7646d2SAndroid Build Coastguard Worker       map      = pc->types + pc->num_types;
862*5e7646d2SAndroid Build Coastguard Worker       map->pwg = strdup(pwg_keyword);
863*5e7646d2SAndroid Build Coastguard Worker       map->ppd = strdup(ppd_keyword);
864*5e7646d2SAndroid Build Coastguard Worker 
865*5e7646d2SAndroid Build Coastguard Worker       pc->num_types ++;
866*5e7646d2SAndroid Build Coastguard Worker     }
867*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Preset"))
868*5e7646d2SAndroid Build Coastguard Worker     {
869*5e7646d2SAndroid Build Coastguard Worker      /*
870*5e7646d2SAndroid Build Coastguard Worker       * Preset output-mode print-quality name=value ...
871*5e7646d2SAndroid Build Coastguard Worker       */
872*5e7646d2SAndroid Build Coastguard Worker 
873*5e7646d2SAndroid Build Coastguard Worker       print_color_mode = (_pwg_print_color_mode_t)strtol(value, &valueptr, 10);
874*5e7646d2SAndroid Build Coastguard Worker       print_quality    = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10);
875*5e7646d2SAndroid Build Coastguard Worker 
876*5e7646d2SAndroid Build Coastguard Worker       if (print_color_mode < _PWG_PRINT_COLOR_MODE_MONOCHROME ||
877*5e7646d2SAndroid Build Coastguard Worker           print_color_mode >= _PWG_PRINT_COLOR_MODE_MAX ||
878*5e7646d2SAndroid Build Coastguard Worker 	  print_quality < _PWG_PRINT_QUALITY_DRAFT ||
879*5e7646d2SAndroid Build Coastguard Worker 	  print_quality >= _PWG_PRINT_QUALITY_MAX ||
880*5e7646d2SAndroid Build Coastguard Worker 	  valueptr == value || !*valueptr)
881*5e7646d2SAndroid Build Coastguard Worker       {
882*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("_ppdCacheCreateWithFile: Bad Preset on line %d.",
883*5e7646d2SAndroid Build Coastguard Worker 	              linenum));
884*5e7646d2SAndroid Build Coastguard Worker 	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
885*5e7646d2SAndroid Build Coastguard Worker 	goto create_error;
886*5e7646d2SAndroid Build Coastguard Worker       }
887*5e7646d2SAndroid Build Coastguard Worker 
888*5e7646d2SAndroid Build Coastguard Worker       pc->num_presets[print_color_mode][print_quality] =
889*5e7646d2SAndroid Build Coastguard Worker           cupsParseOptions(valueptr, 0,
890*5e7646d2SAndroid Build Coastguard Worker 	                   pc->presets[print_color_mode] + print_quality);
891*5e7646d2SAndroid Build Coastguard Worker     }
892*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "SidesOption"))
893*5e7646d2SAndroid Build Coastguard Worker       pc->sides_option = strdup(value);
894*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Sides1Sided"))
895*5e7646d2SAndroid Build Coastguard Worker       pc->sides_1sided = strdup(value);
896*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Sides2SidedLong"))
897*5e7646d2SAndroid Build Coastguard Worker       pc->sides_2sided_long = strdup(value);
898*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Sides2SidedShort"))
899*5e7646d2SAndroid Build Coastguard Worker       pc->sides_2sided_short = strdup(value);
900*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Finishings"))
901*5e7646d2SAndroid Build Coastguard Worker     {
902*5e7646d2SAndroid Build Coastguard Worker       if (!pc->finishings)
903*5e7646d2SAndroid Build Coastguard Worker 	pc->finishings =
904*5e7646d2SAndroid Build Coastguard Worker 	    cupsArrayNew3((cups_array_func_t)pwg_compare_finishings,
905*5e7646d2SAndroid Build Coastguard Worker 			  NULL, NULL, 0, NULL,
906*5e7646d2SAndroid Build Coastguard Worker 			  (cups_afree_func_t)pwg_free_finishings);
907*5e7646d2SAndroid Build Coastguard Worker 
908*5e7646d2SAndroid Build Coastguard Worker       if ((finishings = calloc(1, sizeof(_pwg_finishings_t))) == NULL)
909*5e7646d2SAndroid Build Coastguard Worker         goto create_error;
910*5e7646d2SAndroid Build Coastguard Worker 
911*5e7646d2SAndroid Build Coastguard Worker       finishings->value       = (ipp_finishings_t)strtol(value, &valueptr, 10);
912*5e7646d2SAndroid Build Coastguard Worker       finishings->num_options = cupsParseOptions(valueptr, 0,
913*5e7646d2SAndroid Build Coastguard Worker                                                  &(finishings->options));
914*5e7646d2SAndroid Build Coastguard Worker 
915*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->finishings, finishings);
916*5e7646d2SAndroid Build Coastguard Worker     }
917*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "FinishingTemplate"))
918*5e7646d2SAndroid Build Coastguard Worker     {
919*5e7646d2SAndroid Build Coastguard Worker       if (!pc->templates)
920*5e7646d2SAndroid Build Coastguard Worker         pc->templates = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
921*5e7646d2SAndroid Build Coastguard Worker 
922*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->templates, value);
923*5e7646d2SAndroid Build Coastguard Worker     }
924*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "MaxCopies"))
925*5e7646d2SAndroid Build Coastguard Worker       pc->max_copies = atoi(value);
926*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "ChargeInfoURI"))
927*5e7646d2SAndroid Build Coastguard Worker       pc->charge_info_uri = strdup(value);
928*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "JobAccountId"))
929*5e7646d2SAndroid Build Coastguard Worker       pc->account_id = !_cups_strcasecmp(value, "true");
930*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "JobAccountingUserId"))
931*5e7646d2SAndroid Build Coastguard Worker       pc->accounting_user_id = !_cups_strcasecmp(value, "true");
932*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "JobPassword"))
933*5e7646d2SAndroid Build Coastguard Worker       pc->password = strdup(value);
934*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Mandatory"))
935*5e7646d2SAndroid Build Coastguard Worker     {
936*5e7646d2SAndroid Build Coastguard Worker       if (pc->mandatory)
937*5e7646d2SAndroid Build Coastguard Worker         _cupsArrayAddStrings(pc->mandatory, value, ' ');
938*5e7646d2SAndroid Build Coastguard Worker       else
939*5e7646d2SAndroid Build Coastguard Worker         pc->mandatory = _cupsArrayNewStrings(value, ' ');
940*5e7646d2SAndroid Build Coastguard Worker     }
941*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "SupportFile"))
942*5e7646d2SAndroid Build Coastguard Worker     {
943*5e7646d2SAndroid Build Coastguard Worker       if (!pc->support_files)
944*5e7646d2SAndroid Build Coastguard Worker         pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
945*5e7646d2SAndroid Build Coastguard Worker 
946*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->support_files, value);
947*5e7646d2SAndroid Build Coastguard Worker     }
948*5e7646d2SAndroid Build Coastguard Worker     else
949*5e7646d2SAndroid Build Coastguard Worker     {
950*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheCreateWithFile: Unknown %s on line %d.", line,
951*5e7646d2SAndroid Build Coastguard Worker 		    linenum));
952*5e7646d2SAndroid Build Coastguard Worker     }
953*5e7646d2SAndroid Build Coastguard Worker   }
954*5e7646d2SAndroid Build Coastguard Worker 
955*5e7646d2SAndroid Build Coastguard Worker   if (pc->num_sizes < num_sizes)
956*5e7646d2SAndroid Build Coastguard Worker   {
957*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sizes (%d < %d).",
958*5e7646d2SAndroid Build Coastguard Worker                   pc->num_sizes, num_sizes));
959*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
960*5e7646d2SAndroid Build Coastguard Worker     goto create_error;
961*5e7646d2SAndroid Build Coastguard Worker   }
962*5e7646d2SAndroid Build Coastguard Worker 
963*5e7646d2SAndroid Build Coastguard Worker   if (pc->num_sources < num_sources)
964*5e7646d2SAndroid Build Coastguard Worker   {
965*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sources (%d < %d).",
966*5e7646d2SAndroid Build Coastguard Worker                   pc->num_sources, num_sources));
967*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
968*5e7646d2SAndroid Build Coastguard Worker     goto create_error;
969*5e7646d2SAndroid Build Coastguard Worker   }
970*5e7646d2SAndroid Build Coastguard Worker 
971*5e7646d2SAndroid Build Coastguard Worker   if (pc->num_types < num_types)
972*5e7646d2SAndroid Build Coastguard Worker   {
973*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("_ppdCacheCreateWithFile: Not enough types (%d < %d).",
974*5e7646d2SAndroid Build Coastguard Worker                   pc->num_types, num_types));
975*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad PPD cache file."), 1);
976*5e7646d2SAndroid Build Coastguard Worker     goto create_error;
977*5e7646d2SAndroid Build Coastguard Worker   }
978*5e7646d2SAndroid Build Coastguard Worker 
979*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(fp);
980*5e7646d2SAndroid Build Coastguard Worker 
981*5e7646d2SAndroid Build Coastguard Worker   return (pc);
982*5e7646d2SAndroid Build Coastguard Worker 
983*5e7646d2SAndroid Build Coastguard Worker  /*
984*5e7646d2SAndroid Build Coastguard Worker   * If we get here the file was bad - free any data and return...
985*5e7646d2SAndroid Build Coastguard Worker   */
986*5e7646d2SAndroid Build Coastguard Worker 
987*5e7646d2SAndroid Build Coastguard Worker   create_error:
988*5e7646d2SAndroid Build Coastguard Worker 
989*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(fp);
990*5e7646d2SAndroid Build Coastguard Worker   _ppdCacheDestroy(pc);
991*5e7646d2SAndroid Build Coastguard Worker 
992*5e7646d2SAndroid Build Coastguard Worker   if (attrs)
993*5e7646d2SAndroid Build Coastguard Worker   {
994*5e7646d2SAndroid Build Coastguard Worker     ippDelete(*attrs);
995*5e7646d2SAndroid Build Coastguard Worker     *attrs = NULL;
996*5e7646d2SAndroid Build Coastguard Worker   }
997*5e7646d2SAndroid Build Coastguard Worker 
998*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
999*5e7646d2SAndroid Build Coastguard Worker }
1000*5e7646d2SAndroid Build Coastguard Worker 
1001*5e7646d2SAndroid Build Coastguard Worker 
1002*5e7646d2SAndroid Build Coastguard Worker /*
1003*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheCreateWithPPD()' - Create PWG mapping data from a PPD file.
1004*5e7646d2SAndroid Build Coastguard Worker  */
1005*5e7646d2SAndroid Build Coastguard Worker 
1006*5e7646d2SAndroid Build Coastguard Worker _ppd_cache_t *				/* O - PPD cache and mapping data */
_ppdCacheCreateWithPPD(ppd_file_t * ppd)1007*5e7646d2SAndroid Build Coastguard Worker _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
1008*5e7646d2SAndroid Build Coastguard Worker {
1009*5e7646d2SAndroid Build Coastguard Worker   int			i, j, k;	/* Looping vars */
1010*5e7646d2SAndroid Build Coastguard Worker   _ppd_cache_t		*pc;		/* PWG mapping data */
1011*5e7646d2SAndroid Build Coastguard Worker   ppd_option_t		*input_slot,	/* InputSlot option */
1012*5e7646d2SAndroid Build Coastguard Worker 			*media_type,	/* MediaType option */
1013*5e7646d2SAndroid Build Coastguard Worker 			*output_bin,	/* OutputBin option */
1014*5e7646d2SAndroid Build Coastguard Worker 			*color_model,	/* ColorModel option */
1015*5e7646d2SAndroid Build Coastguard Worker 			*duplex,	/* Duplex option */
1016*5e7646d2SAndroid Build Coastguard Worker 			*ppd_option;	/* Other PPD option */
1017*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t		*choice;	/* Current InputSlot/MediaType */
1018*5e7646d2SAndroid Build Coastguard Worker   pwg_map_t		*map;		/* Current source/type map */
1019*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t		*ppd_attr;	/* Current PPD preset attribute */
1020*5e7646d2SAndroid Build Coastguard Worker   int			num_options;	/* Number of preset options and props */
1021*5e7646d2SAndroid Build Coastguard Worker   cups_option_t		*options;	/* Preset options and properties */
1022*5e7646d2SAndroid Build Coastguard Worker   ppd_size_t		*ppd_size;	/* Current PPD size */
1023*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t		*pwg_size;	/* Current PWG size */
1024*5e7646d2SAndroid Build Coastguard Worker   char			pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3],
1025*5e7646d2SAndroid Build Coastguard Worker 					/* PWG keyword string */
1026*5e7646d2SAndroid Build Coastguard Worker 			ppd_name[PPD_MAX_NAME];
1027*5e7646d2SAndroid Build Coastguard Worker 					/* Normalized PPD name */
1028*5e7646d2SAndroid Build Coastguard Worker   const char		*pwg_name;	/* Standard PWG media name */
1029*5e7646d2SAndroid Build Coastguard Worker   pwg_media_t		*pwg_media;	/* PWG media data */
1030*5e7646d2SAndroid Build Coastguard Worker   _pwg_print_color_mode_t pwg_print_color_mode;
1031*5e7646d2SAndroid Build Coastguard Worker 					/* print-color-mode index */
1032*5e7646d2SAndroid Build Coastguard Worker   _pwg_print_quality_t	pwg_print_quality;
1033*5e7646d2SAndroid Build Coastguard Worker 					/* print-quality index */
1034*5e7646d2SAndroid Build Coastguard Worker   int			similar;	/* Are the old and new size similar? */
1035*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t		*old_size;	/* Current old size */
1036*5e7646d2SAndroid Build Coastguard Worker   int			old_imageable,	/* Old imageable length in 2540ths */
1037*5e7646d2SAndroid Build Coastguard Worker 			old_borderless,	/* Old borderless state */
1038*5e7646d2SAndroid Build Coastguard Worker 			old_known_pwg;	/* Old PWG name is well-known */
1039*5e7646d2SAndroid Build Coastguard Worker   int			new_width,	/* New width in 2540ths */
1040*5e7646d2SAndroid Build Coastguard Worker 			new_length,	/* New length in 2540ths */
1041*5e7646d2SAndroid Build Coastguard Worker 			new_left,	/* New left margin in 2540ths */
1042*5e7646d2SAndroid Build Coastguard Worker 			new_bottom,	/* New bottom margin in 2540ths */
1043*5e7646d2SAndroid Build Coastguard Worker 			new_right,	/* New right margin in 2540ths */
1044*5e7646d2SAndroid Build Coastguard Worker 			new_top,	/* New top margin in 2540ths */
1045*5e7646d2SAndroid Build Coastguard Worker 			new_imageable,	/* New imageable length in 2540ths */
1046*5e7646d2SAndroid Build Coastguard Worker 			new_borderless,	/* New borderless state */
1047*5e7646d2SAndroid Build Coastguard Worker 			new_known_pwg;	/* New PWG name is well-known */
1048*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t		*new_size;	/* New size to add, if any */
1049*5e7646d2SAndroid Build Coastguard Worker   const char		*filter;	/* Current filter */
1050*5e7646d2SAndroid Build Coastguard Worker   _pwg_finishings_t	*finishings;	/* Current finishings value */
1051*5e7646d2SAndroid Build Coastguard Worker   char			msg_id[256];	/* Message identifier */
1052*5e7646d2SAndroid Build Coastguard Worker 
1053*5e7646d2SAndroid Build Coastguard Worker 
1054*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_ppdCacheCreateWithPPD(ppd=%p)", ppd));
1055*5e7646d2SAndroid Build Coastguard Worker 
1056*5e7646d2SAndroid Build Coastguard Worker  /*
1057*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1058*5e7646d2SAndroid Build Coastguard Worker   */
1059*5e7646d2SAndroid Build Coastguard Worker 
1060*5e7646d2SAndroid Build Coastguard Worker   if (!ppd)
1061*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1062*5e7646d2SAndroid Build Coastguard Worker 
1063*5e7646d2SAndroid Build Coastguard Worker  /*
1064*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory...
1065*5e7646d2SAndroid Build Coastguard Worker   */
1066*5e7646d2SAndroid Build Coastguard Worker 
1067*5e7646d2SAndroid Build Coastguard Worker   if ((pc = calloc(1, sizeof(_ppd_cache_t))) == NULL)
1068*5e7646d2SAndroid Build Coastguard Worker   {
1069*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("_ppdCacheCreateWithPPD: Unable to allocate _ppd_cache_t.");
1070*5e7646d2SAndroid Build Coastguard Worker     goto create_error;
1071*5e7646d2SAndroid Build Coastguard Worker   }
1072*5e7646d2SAndroid Build Coastguard Worker 
1073*5e7646d2SAndroid Build Coastguard Worker   pc->strings = _cupsMessageNew(NULL);
1074*5e7646d2SAndroid Build Coastguard Worker 
1075*5e7646d2SAndroid Build Coastguard Worker  /*
1076*5e7646d2SAndroid Build Coastguard Worker   * Copy and convert size data...
1077*5e7646d2SAndroid Build Coastguard Worker   */
1078*5e7646d2SAndroid Build Coastguard Worker 
1079*5e7646d2SAndroid Build Coastguard Worker   if (ppd->num_sizes > 0)
1080*5e7646d2SAndroid Build Coastguard Worker   {
1081*5e7646d2SAndroid Build Coastguard Worker     if ((pc->sizes = calloc((size_t)ppd->num_sizes, sizeof(pwg_size_t))) == NULL)
1082*5e7646d2SAndroid Build Coastguard Worker     {
1083*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
1084*5e7646d2SAndroid Build Coastguard Worker 		    "pwg_size_t's.", ppd->num_sizes));
1085*5e7646d2SAndroid Build Coastguard Worker       goto create_error;
1086*5e7646d2SAndroid Build Coastguard Worker     }
1087*5e7646d2SAndroid Build Coastguard Worker 
1088*5e7646d2SAndroid Build Coastguard Worker     for (i = ppd->num_sizes, pwg_size = pc->sizes, ppd_size = ppd->sizes;
1089*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
1090*5e7646d2SAndroid Build Coastguard Worker 	 i --, ppd_size ++)
1091*5e7646d2SAndroid Build Coastguard Worker     {
1092*5e7646d2SAndroid Build Coastguard Worker      /*
1093*5e7646d2SAndroid Build Coastguard Worker       * Don't copy over custom size...
1094*5e7646d2SAndroid Build Coastguard Worker       */
1095*5e7646d2SAndroid Build Coastguard Worker 
1096*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(ppd_size->name, "Custom"))
1097*5e7646d2SAndroid Build Coastguard Worker 	continue;
1098*5e7646d2SAndroid Build Coastguard Worker 
1099*5e7646d2SAndroid Build Coastguard Worker      /*
1100*5e7646d2SAndroid Build Coastguard Worker       * Convert the PPD size name to the corresponding PWG keyword name.
1101*5e7646d2SAndroid Build Coastguard Worker       */
1102*5e7646d2SAndroid Build Coastguard Worker 
1103*5e7646d2SAndroid Build Coastguard Worker       if ((pwg_media = pwgMediaForSize(PWG_FROM_POINTS(ppd_size->width), PWG_FROM_POINTS(ppd_size->length))) != NULL)
1104*5e7646d2SAndroid Build Coastguard Worker       {
1105*5e7646d2SAndroid Build Coastguard Worker        /*
1106*5e7646d2SAndroid Build Coastguard Worker 	* Standard name, do we have conflicts?
1107*5e7646d2SAndroid Build Coastguard Worker 	*/
1108*5e7646d2SAndroid Build Coastguard Worker 
1109*5e7646d2SAndroid Build Coastguard Worker 	for (j = 0; j < pc->num_sizes; j ++)
1110*5e7646d2SAndroid Build Coastguard Worker 	  if (!strcmp(pc->sizes[j].map.pwg, pwg_media->pwg))
1111*5e7646d2SAndroid Build Coastguard Worker 	  {
1112*5e7646d2SAndroid Build Coastguard Worker 	    pwg_media = NULL;
1113*5e7646d2SAndroid Build Coastguard Worker 	    break;
1114*5e7646d2SAndroid Build Coastguard Worker 	  }
1115*5e7646d2SAndroid Build Coastguard Worker       }
1116*5e7646d2SAndroid Build Coastguard Worker 
1117*5e7646d2SAndroid Build Coastguard Worker       if (pwg_media)
1118*5e7646d2SAndroid Build Coastguard Worker       {
1119*5e7646d2SAndroid Build Coastguard Worker        /*
1120*5e7646d2SAndroid Build Coastguard Worker 	* Standard name and no conflicts, use it!
1121*5e7646d2SAndroid Build Coastguard Worker 	*/
1122*5e7646d2SAndroid Build Coastguard Worker 
1123*5e7646d2SAndroid Build Coastguard Worker 	pwg_name      = pwg_media->pwg;
1124*5e7646d2SAndroid Build Coastguard Worker 	new_known_pwg = 1;
1125*5e7646d2SAndroid Build Coastguard Worker       }
1126*5e7646d2SAndroid Build Coastguard Worker       else
1127*5e7646d2SAndroid Build Coastguard Worker       {
1128*5e7646d2SAndroid Build Coastguard Worker        /*
1129*5e7646d2SAndroid Build Coastguard Worker 	* Not a standard name; convert it to a PWG vendor name of the form:
1130*5e7646d2SAndroid Build Coastguard Worker 	*
1131*5e7646d2SAndroid Build Coastguard Worker 	*     pp_lowerppd_WIDTHxHEIGHTuu
1132*5e7646d2SAndroid Build Coastguard Worker 	*/
1133*5e7646d2SAndroid Build Coastguard Worker 
1134*5e7646d2SAndroid Build Coastguard Worker 	pwg_name      = pwg_keyword;
1135*5e7646d2SAndroid Build Coastguard Worker 	new_known_pwg = 0;
1136*5e7646d2SAndroid Build Coastguard Worker 
1137*5e7646d2SAndroid Build Coastguard Worker 	pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name), "_.");
1138*5e7646d2SAndroid Build Coastguard Worker 	pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name,
1139*5e7646d2SAndroid Build Coastguard Worker 			  PWG_FROM_POINTS(ppd_size->width),
1140*5e7646d2SAndroid Build Coastguard Worker 			  PWG_FROM_POINTS(ppd_size->length), NULL);
1141*5e7646d2SAndroid Build Coastguard Worker       }
1142*5e7646d2SAndroid Build Coastguard Worker 
1143*5e7646d2SAndroid Build Coastguard Worker      /*
1144*5e7646d2SAndroid Build Coastguard Worker       * If we have a similar paper with non-zero margins then we only want to
1145*5e7646d2SAndroid Build Coastguard Worker       * keep it if it has a larger imageable area length.  The NULL check is for
1146*5e7646d2SAndroid Build Coastguard Worker       * dimensions that are <= 0...
1147*5e7646d2SAndroid Build Coastguard Worker       */
1148*5e7646d2SAndroid Build Coastguard Worker 
1149*5e7646d2SAndroid Build Coastguard Worker       if ((pwg_media = _pwgMediaNearSize(PWG_FROM_POINTS(ppd_size->width),
1150*5e7646d2SAndroid Build Coastguard Worker 					PWG_FROM_POINTS(ppd_size->length),
1151*5e7646d2SAndroid Build Coastguard Worker 					0)) == NULL)
1152*5e7646d2SAndroid Build Coastguard Worker 	continue;
1153*5e7646d2SAndroid Build Coastguard Worker 
1154*5e7646d2SAndroid Build Coastguard Worker       new_width      = pwg_media->width;
1155*5e7646d2SAndroid Build Coastguard Worker       new_length     = pwg_media->length;
1156*5e7646d2SAndroid Build Coastguard Worker       new_left       = PWG_FROM_POINTS(ppd_size->left);
1157*5e7646d2SAndroid Build Coastguard Worker       new_bottom     = PWG_FROM_POINTS(ppd_size->bottom);
1158*5e7646d2SAndroid Build Coastguard Worker       new_right      = PWG_FROM_POINTS(ppd_size->width - ppd_size->right);
1159*5e7646d2SAndroid Build Coastguard Worker       new_top        = PWG_FROM_POINTS(ppd_size->length - ppd_size->top);
1160*5e7646d2SAndroid Build Coastguard Worker       new_imageable  = new_length - new_top - new_bottom;
1161*5e7646d2SAndroid Build Coastguard Worker       new_borderless = new_bottom == 0 && new_top == 0 &&
1162*5e7646d2SAndroid Build Coastguard Worker 		       new_left == 0 && new_right == 0;
1163*5e7646d2SAndroid Build Coastguard Worker 
1164*5e7646d2SAndroid Build Coastguard Worker       for (k = pc->num_sizes, similar = 0, old_size = pc->sizes, new_size = NULL;
1165*5e7646d2SAndroid Build Coastguard Worker 	   k > 0 && !similar;
1166*5e7646d2SAndroid Build Coastguard Worker 	   k --, old_size ++)
1167*5e7646d2SAndroid Build Coastguard Worker       {
1168*5e7646d2SAndroid Build Coastguard Worker 	old_imageable  = old_size->length - old_size->top - old_size->bottom;
1169*5e7646d2SAndroid Build Coastguard Worker 	old_borderless = old_size->left == 0 && old_size->bottom == 0 &&
1170*5e7646d2SAndroid Build Coastguard Worker 			 old_size->right == 0 && old_size->top == 0;
1171*5e7646d2SAndroid Build Coastguard Worker 	old_known_pwg  = strncmp(old_size->map.pwg, "oe_", 3) &&
1172*5e7646d2SAndroid Build Coastguard Worker 			 strncmp(old_size->map.pwg, "om_", 3);
1173*5e7646d2SAndroid Build Coastguard Worker 
1174*5e7646d2SAndroid Build Coastguard Worker 	similar = old_borderless == new_borderless &&
1175*5e7646d2SAndroid Build Coastguard Worker 		  _PWG_EQUIVALENT(old_size->width, new_width) &&
1176*5e7646d2SAndroid Build Coastguard Worker 		  _PWG_EQUIVALENT(old_size->length, new_length);
1177*5e7646d2SAndroid Build Coastguard Worker 
1178*5e7646d2SAndroid Build Coastguard Worker 	if (similar &&
1179*5e7646d2SAndroid Build Coastguard Worker 	    (new_known_pwg || (!old_known_pwg && new_imageable > old_imageable)))
1180*5e7646d2SAndroid Build Coastguard Worker 	{
1181*5e7646d2SAndroid Build Coastguard Worker 	 /*
1182*5e7646d2SAndroid Build Coastguard Worker 	  * The new paper has a larger imageable area so it could replace
1183*5e7646d2SAndroid Build Coastguard Worker 	  * the older paper.  Regardless of the imageable area, we always
1184*5e7646d2SAndroid Build Coastguard Worker 	  * prefer the size with a well-known PWG name.
1185*5e7646d2SAndroid Build Coastguard Worker 	  */
1186*5e7646d2SAndroid Build Coastguard Worker 
1187*5e7646d2SAndroid Build Coastguard Worker 	  new_size = old_size;
1188*5e7646d2SAndroid Build Coastguard Worker 	  free(old_size->map.ppd);
1189*5e7646d2SAndroid Build Coastguard Worker 	  free(old_size->map.pwg);
1190*5e7646d2SAndroid Build Coastguard Worker 	}
1191*5e7646d2SAndroid Build Coastguard Worker       }
1192*5e7646d2SAndroid Build Coastguard Worker 
1193*5e7646d2SAndroid Build Coastguard Worker       if (!similar)
1194*5e7646d2SAndroid Build Coastguard Worker       {
1195*5e7646d2SAndroid Build Coastguard Worker        /*
1196*5e7646d2SAndroid Build Coastguard Worker 	* The paper was unique enough to deserve its own entry so add it to the
1197*5e7646d2SAndroid Build Coastguard Worker 	* end.
1198*5e7646d2SAndroid Build Coastguard Worker 	*/
1199*5e7646d2SAndroid Build Coastguard Worker 
1200*5e7646d2SAndroid Build Coastguard Worker 	new_size = pwg_size ++;
1201*5e7646d2SAndroid Build Coastguard Worker 	pc->num_sizes ++;
1202*5e7646d2SAndroid Build Coastguard Worker       }
1203*5e7646d2SAndroid Build Coastguard Worker 
1204*5e7646d2SAndroid Build Coastguard Worker       if (new_size)
1205*5e7646d2SAndroid Build Coastguard Worker       {
1206*5e7646d2SAndroid Build Coastguard Worker        /*
1207*5e7646d2SAndroid Build Coastguard Worker 	* Save this size...
1208*5e7646d2SAndroid Build Coastguard Worker 	*/
1209*5e7646d2SAndroid Build Coastguard Worker 
1210*5e7646d2SAndroid Build Coastguard Worker 	new_size->map.ppd = strdup(ppd_size->name);
1211*5e7646d2SAndroid Build Coastguard Worker 	new_size->map.pwg = strdup(pwg_name);
1212*5e7646d2SAndroid Build Coastguard Worker 	new_size->width   = new_width;
1213*5e7646d2SAndroid Build Coastguard Worker 	new_size->length  = new_length;
1214*5e7646d2SAndroid Build Coastguard Worker 	new_size->left    = new_left;
1215*5e7646d2SAndroid Build Coastguard Worker 	new_size->bottom  = new_bottom;
1216*5e7646d2SAndroid Build Coastguard Worker 	new_size->right   = new_right;
1217*5e7646d2SAndroid Build Coastguard Worker 	new_size->top     = new_top;
1218*5e7646d2SAndroid Build Coastguard Worker       }
1219*5e7646d2SAndroid Build Coastguard Worker     }
1220*5e7646d2SAndroid Build Coastguard Worker   }
1221*5e7646d2SAndroid Build Coastguard Worker 
1222*5e7646d2SAndroid Build Coastguard Worker   if (ppd->variable_sizes)
1223*5e7646d2SAndroid Build Coastguard Worker   {
1224*5e7646d2SAndroid Build Coastguard Worker    /*
1225*5e7646d2SAndroid Build Coastguard Worker     * Generate custom size data...
1226*5e7646d2SAndroid Build Coastguard Worker     */
1227*5e7646d2SAndroid Build Coastguard Worker 
1228*5e7646d2SAndroid Build Coastguard Worker     pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
1229*5e7646d2SAndroid Build Coastguard Worker 		      PWG_FROM_POINTS(ppd->custom_max[0]),
1230*5e7646d2SAndroid Build Coastguard Worker 		      PWG_FROM_POINTS(ppd->custom_max[1]), NULL);
1231*5e7646d2SAndroid Build Coastguard Worker     pc->custom_max_keyword = strdup(pwg_keyword);
1232*5e7646d2SAndroid Build Coastguard Worker     pc->custom_max_width   = PWG_FROM_POINTS(ppd->custom_max[0]);
1233*5e7646d2SAndroid Build Coastguard Worker     pc->custom_max_length  = PWG_FROM_POINTS(ppd->custom_max[1]);
1234*5e7646d2SAndroid Build Coastguard Worker 
1235*5e7646d2SAndroid Build Coastguard Worker     pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
1236*5e7646d2SAndroid Build Coastguard Worker 		      PWG_FROM_POINTS(ppd->custom_min[0]),
1237*5e7646d2SAndroid Build Coastguard Worker 		      PWG_FROM_POINTS(ppd->custom_min[1]), NULL);
1238*5e7646d2SAndroid Build Coastguard Worker     pc->custom_min_keyword = strdup(pwg_keyword);
1239*5e7646d2SAndroid Build Coastguard Worker     pc->custom_min_width   = PWG_FROM_POINTS(ppd->custom_min[0]);
1240*5e7646d2SAndroid Build Coastguard Worker     pc->custom_min_length  = PWG_FROM_POINTS(ppd->custom_min[1]);
1241*5e7646d2SAndroid Build Coastguard Worker 
1242*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.left   = PWG_FROM_POINTS(ppd->custom_margins[0]);
1243*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.bottom = PWG_FROM_POINTS(ppd->custom_margins[1]);
1244*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.right  = PWG_FROM_POINTS(ppd->custom_margins[2]);
1245*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.top    = PWG_FROM_POINTS(ppd->custom_margins[3]);
1246*5e7646d2SAndroid Build Coastguard Worker   }
1247*5e7646d2SAndroid Build Coastguard Worker 
1248*5e7646d2SAndroid Build Coastguard Worker  /*
1249*5e7646d2SAndroid Build Coastguard Worker   * Copy and convert InputSlot data...
1250*5e7646d2SAndroid Build Coastguard Worker   */
1251*5e7646d2SAndroid Build Coastguard Worker 
1252*5e7646d2SAndroid Build Coastguard Worker   if ((input_slot = ppdFindOption(ppd, "InputSlot")) == NULL)
1253*5e7646d2SAndroid Build Coastguard Worker     input_slot = ppdFindOption(ppd, "HPPaperSource");
1254*5e7646d2SAndroid Build Coastguard Worker 
1255*5e7646d2SAndroid Build Coastguard Worker   if (input_slot)
1256*5e7646d2SAndroid Build Coastguard Worker   {
1257*5e7646d2SAndroid Build Coastguard Worker     pc->source_option = strdup(input_slot->keyword);
1258*5e7646d2SAndroid Build Coastguard Worker 
1259*5e7646d2SAndroid Build Coastguard Worker     if ((pc->sources = calloc((size_t)input_slot->num_choices, sizeof(pwg_map_t))) == NULL)
1260*5e7646d2SAndroid Build Coastguard Worker     {
1261*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
1262*5e7646d2SAndroid Build Coastguard Worker                     "pwg_map_t's for InputSlot.", input_slot->num_choices));
1263*5e7646d2SAndroid Build Coastguard Worker       goto create_error;
1264*5e7646d2SAndroid Build Coastguard Worker     }
1265*5e7646d2SAndroid Build Coastguard Worker 
1266*5e7646d2SAndroid Build Coastguard Worker     pc->num_sources = input_slot->num_choices;
1267*5e7646d2SAndroid Build Coastguard Worker 
1268*5e7646d2SAndroid Build Coastguard Worker     for (i = input_slot->num_choices, choice = input_slot->choices,
1269*5e7646d2SAndroid Build Coastguard Worker              map = pc->sources;
1270*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
1271*5e7646d2SAndroid Build Coastguard Worker 	 i --, choice ++, map ++)
1272*5e7646d2SAndroid Build Coastguard Worker     {
1273*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strncasecmp(choice->choice, "Auto", 4) ||
1274*5e7646d2SAndroid Build Coastguard Worker           !_cups_strcasecmp(choice->choice, "Default"))
1275*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "auto";
1276*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "Cassette"))
1277*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "main";
1278*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "PhotoTray"))
1279*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "photo";
1280*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "CDTray"))
1281*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "disc";
1282*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Multipurpose", 12) ||
1283*5e7646d2SAndroid Build Coastguard Worker                !_cups_strcasecmp(choice->choice, "MP") ||
1284*5e7646d2SAndroid Build Coastguard Worker                !_cups_strcasecmp(choice->choice, "MPTray"))
1285*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "by-pass-tray";
1286*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "LargeCapacity"))
1287*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "large-capacity";
1288*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Lower", 5))
1289*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "bottom";
1290*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Middle", 6))
1291*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "middle";
1292*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Upper", 5))
1293*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "top";
1294*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Side", 4))
1295*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "side";
1296*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "Roll"))
1297*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "main-roll";
1298*5e7646d2SAndroid Build Coastguard Worker       else
1299*5e7646d2SAndroid Build Coastguard Worker       {
1300*5e7646d2SAndroid Build Coastguard Worker        /*
1301*5e7646d2SAndroid Build Coastguard Worker         * Convert PPD name to lowercase...
1302*5e7646d2SAndroid Build Coastguard Worker 	*/
1303*5e7646d2SAndroid Build Coastguard Worker 
1304*5e7646d2SAndroid Build Coastguard Worker         pwg_name = pwg_keyword;
1305*5e7646d2SAndroid Build Coastguard Worker 	pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword),
1306*5e7646d2SAndroid Build Coastguard Worker 	                  "_");
1307*5e7646d2SAndroid Build Coastguard Worker       }
1308*5e7646d2SAndroid Build Coastguard Worker 
1309*5e7646d2SAndroid Build Coastguard Worker       map->pwg = strdup(pwg_name);
1310*5e7646d2SAndroid Build Coastguard Worker       map->ppd = strdup(choice->choice);
1311*5e7646d2SAndroid Build Coastguard Worker 
1312*5e7646d2SAndroid Build Coastguard Worker      /*
1313*5e7646d2SAndroid Build Coastguard Worker       * Add localized text for PWG keyword to message catalog...
1314*5e7646d2SAndroid Build Coastguard Worker       */
1315*5e7646d2SAndroid Build Coastguard Worker 
1316*5e7646d2SAndroid Build Coastguard Worker       snprintf(msg_id, sizeof(msg_id), "media-source.%s", pwg_name);
1317*5e7646d2SAndroid Build Coastguard Worker       pwg_add_message(pc->strings, msg_id, choice->text);
1318*5e7646d2SAndroid Build Coastguard Worker     }
1319*5e7646d2SAndroid Build Coastguard Worker   }
1320*5e7646d2SAndroid Build Coastguard Worker 
1321*5e7646d2SAndroid Build Coastguard Worker  /*
1322*5e7646d2SAndroid Build Coastguard Worker   * Copy and convert MediaType data...
1323*5e7646d2SAndroid Build Coastguard Worker   */
1324*5e7646d2SAndroid Build Coastguard Worker 
1325*5e7646d2SAndroid Build Coastguard Worker   if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL)
1326*5e7646d2SAndroid Build Coastguard Worker   {
1327*5e7646d2SAndroid Build Coastguard Worker     if ((pc->types = calloc((size_t)media_type->num_choices, sizeof(pwg_map_t))) == NULL)
1328*5e7646d2SAndroid Build Coastguard Worker     {
1329*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
1330*5e7646d2SAndroid Build Coastguard Worker                     "pwg_map_t's for MediaType.", media_type->num_choices));
1331*5e7646d2SAndroid Build Coastguard Worker       goto create_error;
1332*5e7646d2SAndroid Build Coastguard Worker     }
1333*5e7646d2SAndroid Build Coastguard Worker 
1334*5e7646d2SAndroid Build Coastguard Worker     pc->num_types = media_type->num_choices;
1335*5e7646d2SAndroid Build Coastguard Worker 
1336*5e7646d2SAndroid Build Coastguard Worker     for (i = media_type->num_choices, choice = media_type->choices,
1337*5e7646d2SAndroid Build Coastguard Worker              map = pc->types;
1338*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
1339*5e7646d2SAndroid Build Coastguard Worker 	 i --, choice ++, map ++)
1340*5e7646d2SAndroid Build Coastguard Worker     {
1341*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strncasecmp(choice->choice, "Auto", 4) ||
1342*5e7646d2SAndroid Build Coastguard Worker           !_cups_strcasecmp(choice->choice, "Any") ||
1343*5e7646d2SAndroid Build Coastguard Worker           !_cups_strcasecmp(choice->choice, "Default"))
1344*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "auto";
1345*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Card", 4))
1346*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "cardstock";
1347*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Env", 3))
1348*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "envelope";
1349*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Gloss", 5))
1350*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "photographic-glossy";
1351*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "HighGloss"))
1352*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "photographic-high-gloss";
1353*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "Matte"))
1354*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "photographic-matte";
1355*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Plain", 5))
1356*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "stationery";
1357*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Coated", 6))
1358*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "stationery-coated";
1359*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "Inkjet"))
1360*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "stationery-inkjet";
1361*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "Letterhead"))
1362*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "stationery-letterhead";
1363*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Preprint", 8))
1364*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "stationery-preprinted";
1365*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(choice->choice, "Recycled"))
1366*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "stationery-recycled";
1367*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strncasecmp(choice->choice, "Transparen", 10))
1368*5e7646d2SAndroid Build Coastguard Worker         pwg_name = "transparency";
1369*5e7646d2SAndroid Build Coastguard Worker       else
1370*5e7646d2SAndroid Build Coastguard Worker       {
1371*5e7646d2SAndroid Build Coastguard Worker        /*
1372*5e7646d2SAndroid Build Coastguard Worker         * Convert PPD name to lowercase...
1373*5e7646d2SAndroid Build Coastguard Worker 	*/
1374*5e7646d2SAndroid Build Coastguard Worker 
1375*5e7646d2SAndroid Build Coastguard Worker         pwg_name = pwg_keyword;
1376*5e7646d2SAndroid Build Coastguard Worker 	pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword),
1377*5e7646d2SAndroid Build Coastguard Worker 	                  "_");
1378*5e7646d2SAndroid Build Coastguard Worker       }
1379*5e7646d2SAndroid Build Coastguard Worker 
1380*5e7646d2SAndroid Build Coastguard Worker       map->pwg = strdup(pwg_name);
1381*5e7646d2SAndroid Build Coastguard Worker       map->ppd = strdup(choice->choice);
1382*5e7646d2SAndroid Build Coastguard Worker 
1383*5e7646d2SAndroid Build Coastguard Worker      /*
1384*5e7646d2SAndroid Build Coastguard Worker       * Add localized text for PWG keyword to message catalog...
1385*5e7646d2SAndroid Build Coastguard Worker       */
1386*5e7646d2SAndroid Build Coastguard Worker 
1387*5e7646d2SAndroid Build Coastguard Worker       snprintf(msg_id, sizeof(msg_id), "media-type.%s", pwg_name);
1388*5e7646d2SAndroid Build Coastguard Worker       pwg_add_message(pc->strings, msg_id, choice->text);
1389*5e7646d2SAndroid Build Coastguard Worker     }
1390*5e7646d2SAndroid Build Coastguard Worker   }
1391*5e7646d2SAndroid Build Coastguard Worker 
1392*5e7646d2SAndroid Build Coastguard Worker  /*
1393*5e7646d2SAndroid Build Coastguard Worker   * Copy and convert OutputBin data...
1394*5e7646d2SAndroid Build Coastguard Worker   */
1395*5e7646d2SAndroid Build Coastguard Worker 
1396*5e7646d2SAndroid Build Coastguard Worker   if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL)
1397*5e7646d2SAndroid Build Coastguard Worker   {
1398*5e7646d2SAndroid Build Coastguard Worker     if ((pc->bins = calloc((size_t)output_bin->num_choices, sizeof(pwg_map_t))) == NULL)
1399*5e7646d2SAndroid Build Coastguard Worker     {
1400*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d "
1401*5e7646d2SAndroid Build Coastguard Worker                     "pwg_map_t's for OutputBin.", output_bin->num_choices));
1402*5e7646d2SAndroid Build Coastguard Worker       goto create_error;
1403*5e7646d2SAndroid Build Coastguard Worker     }
1404*5e7646d2SAndroid Build Coastguard Worker 
1405*5e7646d2SAndroid Build Coastguard Worker     pc->num_bins = output_bin->num_choices;
1406*5e7646d2SAndroid Build Coastguard Worker 
1407*5e7646d2SAndroid Build Coastguard Worker     for (i = output_bin->num_choices, choice = output_bin->choices,
1408*5e7646d2SAndroid Build Coastguard Worker              map = pc->bins;
1409*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
1410*5e7646d2SAndroid Build Coastguard Worker 	 i --, choice ++, map ++)
1411*5e7646d2SAndroid Build Coastguard Worker     {
1412*5e7646d2SAndroid Build Coastguard Worker       pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword), "_");
1413*5e7646d2SAndroid Build Coastguard Worker 
1414*5e7646d2SAndroid Build Coastguard Worker       map->pwg = strdup(pwg_keyword);
1415*5e7646d2SAndroid Build Coastguard Worker       map->ppd = strdup(choice->choice);
1416*5e7646d2SAndroid Build Coastguard Worker 
1417*5e7646d2SAndroid Build Coastguard Worker      /*
1418*5e7646d2SAndroid Build Coastguard Worker       * Add localized text for PWG keyword to message catalog...
1419*5e7646d2SAndroid Build Coastguard Worker       */
1420*5e7646d2SAndroid Build Coastguard Worker 
1421*5e7646d2SAndroid Build Coastguard Worker       snprintf(msg_id, sizeof(msg_id), "output-bin.%s", pwg_keyword);
1422*5e7646d2SAndroid Build Coastguard Worker       pwg_add_message(pc->strings, msg_id, choice->text);
1423*5e7646d2SAndroid Build Coastguard Worker     }
1424*5e7646d2SAndroid Build Coastguard Worker   }
1425*5e7646d2SAndroid Build Coastguard Worker 
1426*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL)
1427*5e7646d2SAndroid Build Coastguard Worker   {
1428*5e7646d2SAndroid Build Coastguard Worker    /*
1429*5e7646d2SAndroid Build Coastguard Worker     * Copy and convert APPrinterPreset (output-mode + print-quality) data...
1430*5e7646d2SAndroid Build Coastguard Worker     */
1431*5e7646d2SAndroid Build Coastguard Worker 
1432*5e7646d2SAndroid Build Coastguard Worker     const char	*quality,		/* com.apple.print.preset.quality value */
1433*5e7646d2SAndroid Build Coastguard Worker 		*output_mode,		/* com.apple.print.preset.output-mode value */
1434*5e7646d2SAndroid Build Coastguard Worker 		*color_model_val,	/* ColorModel choice */
1435*5e7646d2SAndroid Build Coastguard Worker 		*graphicsType,		/* com.apple.print.preset.graphicsType value */
1436*5e7646d2SAndroid Build Coastguard Worker 		*media_front_coating;	/* com.apple.print.preset.media-front-coating value */
1437*5e7646d2SAndroid Build Coastguard Worker 
1438*5e7646d2SAndroid Build Coastguard Worker     do
1439*5e7646d2SAndroid Build Coastguard Worker     {
1440*5e7646d2SAndroid Build Coastguard Worker      /*
1441*5e7646d2SAndroid Build Coastguard Worker       * Add localized text for PWG keyword to message catalog...
1442*5e7646d2SAndroid Build Coastguard Worker       */
1443*5e7646d2SAndroid Build Coastguard Worker 
1444*5e7646d2SAndroid Build Coastguard Worker       snprintf(msg_id, sizeof(msg_id), "preset-name.%s", ppd_attr->spec);
1445*5e7646d2SAndroid Build Coastguard Worker       pwg_add_message(pc->strings, msg_id, ppd_attr->text);
1446*5e7646d2SAndroid Build Coastguard Worker 
1447*5e7646d2SAndroid Build Coastguard Worker      /*
1448*5e7646d2SAndroid Build Coastguard Worker       * Get the options for this preset...
1449*5e7646d2SAndroid Build Coastguard Worker       */
1450*5e7646d2SAndroid Build Coastguard Worker 
1451*5e7646d2SAndroid Build Coastguard Worker       num_options = _ppdParseOptions(ppd_attr->value, 0, &options,
1452*5e7646d2SAndroid Build Coastguard Worker                                      _PPD_PARSE_ALL);
1453*5e7646d2SAndroid Build Coastguard Worker 
1454*5e7646d2SAndroid Build Coastguard Worker       if ((quality = cupsGetOption("com.apple.print.preset.quality",
1455*5e7646d2SAndroid Build Coastguard Worker                                    num_options, options)) != NULL)
1456*5e7646d2SAndroid Build Coastguard Worker       {
1457*5e7646d2SAndroid Build Coastguard Worker        /*
1458*5e7646d2SAndroid Build Coastguard Worker         * Get the print-quality for this preset...
1459*5e7646d2SAndroid Build Coastguard Worker 	*/
1460*5e7646d2SAndroid Build Coastguard Worker 
1461*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(quality, "low"))
1462*5e7646d2SAndroid Build Coastguard Worker 	  pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
1463*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(quality, "high"))
1464*5e7646d2SAndroid Build Coastguard Worker 	  pwg_print_quality = _PWG_PRINT_QUALITY_HIGH;
1465*5e7646d2SAndroid Build Coastguard Worker 	else
1466*5e7646d2SAndroid Build Coastguard Worker 	  pwg_print_quality = _PWG_PRINT_QUALITY_NORMAL;
1467*5e7646d2SAndroid Build Coastguard Worker 
1468*5e7646d2SAndroid Build Coastguard Worker        /*
1469*5e7646d2SAndroid Build Coastguard Worker 	* Ignore graphicsType "Photo" presets that are not high quality.
1470*5e7646d2SAndroid Build Coastguard Worker 	*/
1471*5e7646d2SAndroid Build Coastguard Worker 
1472*5e7646d2SAndroid Build Coastguard Worker 	graphicsType = cupsGetOption("com.apple.print.preset.graphicsType",
1473*5e7646d2SAndroid Build Coastguard Worker 				      num_options, options);
1474*5e7646d2SAndroid Build Coastguard Worker 
1475*5e7646d2SAndroid Build Coastguard Worker 	if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && graphicsType &&
1476*5e7646d2SAndroid Build Coastguard Worker 	    !strcmp(graphicsType, "Photo"))
1477*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1478*5e7646d2SAndroid Build Coastguard Worker 
1479*5e7646d2SAndroid Build Coastguard Worker        /*
1480*5e7646d2SAndroid Build Coastguard Worker 	* Ignore presets for normal and draft quality where the coating
1481*5e7646d2SAndroid Build Coastguard Worker 	* isn't "none" or "autodetect".
1482*5e7646d2SAndroid Build Coastguard Worker 	*/
1483*5e7646d2SAndroid Build Coastguard Worker 
1484*5e7646d2SAndroid Build Coastguard Worker 	media_front_coating = cupsGetOption(
1485*5e7646d2SAndroid Build Coastguard Worker 	                          "com.apple.print.preset.media-front-coating",
1486*5e7646d2SAndroid Build Coastguard Worker 			          num_options, options);
1487*5e7646d2SAndroid Build Coastguard Worker 
1488*5e7646d2SAndroid Build Coastguard Worker         if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH &&
1489*5e7646d2SAndroid Build Coastguard Worker 	    media_front_coating &&
1490*5e7646d2SAndroid Build Coastguard Worker 	    strcmp(media_front_coating, "none") &&
1491*5e7646d2SAndroid Build Coastguard Worker 	    strcmp(media_front_coating, "autodetect"))
1492*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1493*5e7646d2SAndroid Build Coastguard Worker 
1494*5e7646d2SAndroid Build Coastguard Worker        /*
1495*5e7646d2SAndroid Build Coastguard Worker         * Get the output mode for this preset...
1496*5e7646d2SAndroid Build Coastguard Worker 	*/
1497*5e7646d2SAndroid Build Coastguard Worker 
1498*5e7646d2SAndroid Build Coastguard Worker         output_mode     = cupsGetOption("com.apple.print.preset.output-mode",
1499*5e7646d2SAndroid Build Coastguard Worker 	                                num_options, options);
1500*5e7646d2SAndroid Build Coastguard Worker         color_model_val = cupsGetOption("ColorModel", num_options, options);
1501*5e7646d2SAndroid Build Coastguard Worker 
1502*5e7646d2SAndroid Build Coastguard Worker         if (output_mode)
1503*5e7646d2SAndroid Build Coastguard Worker 	{
1504*5e7646d2SAndroid Build Coastguard Worker 	  if (!strcmp(output_mode, "monochrome"))
1505*5e7646d2SAndroid Build Coastguard Worker 	    pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME;
1506*5e7646d2SAndroid Build Coastguard Worker 	  else
1507*5e7646d2SAndroid Build Coastguard Worker 	    pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
1508*5e7646d2SAndroid Build Coastguard Worker 	}
1509*5e7646d2SAndroid Build Coastguard Worker 	else if (color_model_val)
1510*5e7646d2SAndroid Build Coastguard Worker 	{
1511*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strcasecmp(color_model_val, "Gray"))
1512*5e7646d2SAndroid Build Coastguard Worker 	    pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME;
1513*5e7646d2SAndroid Build Coastguard Worker 	  else
1514*5e7646d2SAndroid Build Coastguard Worker 	    pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
1515*5e7646d2SAndroid Build Coastguard Worker 	}
1516*5e7646d2SAndroid Build Coastguard Worker 	else
1517*5e7646d2SAndroid Build Coastguard Worker 	  pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
1518*5e7646d2SAndroid Build Coastguard Worker 
1519*5e7646d2SAndroid Build Coastguard Worker        /*
1520*5e7646d2SAndroid Build Coastguard Worker         * Save the options for this combination as needed...
1521*5e7646d2SAndroid Build Coastguard Worker 	*/
1522*5e7646d2SAndroid Build Coastguard Worker 
1523*5e7646d2SAndroid Build Coastguard Worker         if (!pc->num_presets[pwg_print_color_mode][pwg_print_quality])
1524*5e7646d2SAndroid Build Coastguard Worker 	  pc->num_presets[pwg_print_color_mode][pwg_print_quality] =
1525*5e7646d2SAndroid Build Coastguard Worker 	      _ppdParseOptions(ppd_attr->value, 0,
1526*5e7646d2SAndroid Build Coastguard Worker 	                       pc->presets[pwg_print_color_mode] +
1527*5e7646d2SAndroid Build Coastguard Worker 			           pwg_print_quality, _PPD_PARSE_OPTIONS);
1528*5e7646d2SAndroid Build Coastguard Worker       }
1529*5e7646d2SAndroid Build Coastguard Worker 
1530*5e7646d2SAndroid Build Coastguard Worker       cupsFreeOptions(num_options, options);
1531*5e7646d2SAndroid Build Coastguard Worker     }
1532*5e7646d2SAndroid Build Coastguard Worker     while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) != NULL);
1533*5e7646d2SAndroid Build Coastguard Worker   }
1534*5e7646d2SAndroid Build Coastguard Worker 
1535*5e7646d2SAndroid Build Coastguard Worker   if (!pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] &&
1536*5e7646d2SAndroid Build Coastguard Worker       !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] &&
1537*5e7646d2SAndroid Build Coastguard Worker       !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH])
1538*5e7646d2SAndroid Build Coastguard Worker   {
1539*5e7646d2SAndroid Build Coastguard Worker    /*
1540*5e7646d2SAndroid Build Coastguard Worker     * Try adding some common color options to create grayscale presets.  These
1541*5e7646d2SAndroid Build Coastguard Worker     * are listed in order of popularity...
1542*5e7646d2SAndroid Build Coastguard Worker     */
1543*5e7646d2SAndroid Build Coastguard Worker 
1544*5e7646d2SAndroid Build Coastguard Worker     const char	*color_option = NULL,	/* Color control option */
1545*5e7646d2SAndroid Build Coastguard Worker 		*gray_choice = NULL;	/* Choice to select grayscale */
1546*5e7646d2SAndroid Build Coastguard Worker 
1547*5e7646d2SAndroid Build Coastguard Worker     if ((color_model = ppdFindOption(ppd, "ColorModel")) != NULL &&
1548*5e7646d2SAndroid Build Coastguard Worker         ppdFindChoice(color_model, "Gray"))
1549*5e7646d2SAndroid Build Coastguard Worker     {
1550*5e7646d2SAndroid Build Coastguard Worker       color_option = "ColorModel";
1551*5e7646d2SAndroid Build Coastguard Worker       gray_choice  = "Gray";
1552*5e7646d2SAndroid Build Coastguard Worker     }
1553*5e7646d2SAndroid Build Coastguard Worker     else if ((color_model = ppdFindOption(ppd, "HPColorMode")) != NULL &&
1554*5e7646d2SAndroid Build Coastguard Worker              ppdFindChoice(color_model, "grayscale"))
1555*5e7646d2SAndroid Build Coastguard Worker     {
1556*5e7646d2SAndroid Build Coastguard Worker       color_option = "HPColorMode";
1557*5e7646d2SAndroid Build Coastguard Worker       gray_choice  = "grayscale";
1558*5e7646d2SAndroid Build Coastguard Worker     }
1559*5e7646d2SAndroid Build Coastguard Worker     else if ((color_model = ppdFindOption(ppd, "BRMonoColor")) != NULL &&
1560*5e7646d2SAndroid Build Coastguard Worker              ppdFindChoice(color_model, "Mono"))
1561*5e7646d2SAndroid Build Coastguard Worker     {
1562*5e7646d2SAndroid Build Coastguard Worker       color_option = "BRMonoColor";
1563*5e7646d2SAndroid Build Coastguard Worker       gray_choice  = "Mono";
1564*5e7646d2SAndroid Build Coastguard Worker     }
1565*5e7646d2SAndroid Build Coastguard Worker     else if ((color_model = ppdFindOption(ppd, "CNIJSGrayScale")) != NULL &&
1566*5e7646d2SAndroid Build Coastguard Worker              ppdFindChoice(color_model, "1"))
1567*5e7646d2SAndroid Build Coastguard Worker     {
1568*5e7646d2SAndroid Build Coastguard Worker       color_option = "CNIJSGrayScale";
1569*5e7646d2SAndroid Build Coastguard Worker       gray_choice  = "1";
1570*5e7646d2SAndroid Build Coastguard Worker     }
1571*5e7646d2SAndroid Build Coastguard Worker     else if ((color_model = ppdFindOption(ppd, "HPColorAsGray")) != NULL &&
1572*5e7646d2SAndroid Build Coastguard Worker              ppdFindChoice(color_model, "True"))
1573*5e7646d2SAndroid Build Coastguard Worker     {
1574*5e7646d2SAndroid Build Coastguard Worker       color_option = "HPColorAsGray";
1575*5e7646d2SAndroid Build Coastguard Worker       gray_choice  = "True";
1576*5e7646d2SAndroid Build Coastguard Worker     }
1577*5e7646d2SAndroid Build Coastguard Worker 
1578*5e7646d2SAndroid Build Coastguard Worker     if (color_option && gray_choice)
1579*5e7646d2SAndroid Build Coastguard Worker     {
1580*5e7646d2SAndroid Build Coastguard Worker      /*
1581*5e7646d2SAndroid Build Coastguard Worker       * Copy and convert ColorModel (output-mode) data...
1582*5e7646d2SAndroid Build Coastguard Worker       */
1583*5e7646d2SAndroid Build Coastguard Worker 
1584*5e7646d2SAndroid Build Coastguard Worker       cups_option_t	*coption,	/* Color option */
1585*5e7646d2SAndroid Build Coastguard Worker 			  *moption;	/* Monochrome option */
1586*5e7646d2SAndroid Build Coastguard Worker 
1587*5e7646d2SAndroid Build Coastguard Worker       for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT;
1588*5e7646d2SAndroid Build Coastguard Worker 	   pwg_print_quality < _PWG_PRINT_QUALITY_MAX;
1589*5e7646d2SAndroid Build Coastguard Worker 	   pwg_print_quality ++)
1590*5e7646d2SAndroid Build Coastguard Worker       {
1591*5e7646d2SAndroid Build Coastguard Worker 	if (pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_print_quality])
1592*5e7646d2SAndroid Build Coastguard Worker 	{
1593*5e7646d2SAndroid Build Coastguard Worker 	 /*
1594*5e7646d2SAndroid Build Coastguard Worker 	  * Copy the color options...
1595*5e7646d2SAndroid Build Coastguard Worker 	  */
1596*5e7646d2SAndroid Build Coastguard Worker 
1597*5e7646d2SAndroid Build Coastguard Worker 	  num_options = pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR]
1598*5e7646d2SAndroid Build Coastguard Worker 					[pwg_print_quality];
1599*5e7646d2SAndroid Build Coastguard Worker 	  options     = calloc(sizeof(cups_option_t), (size_t)num_options);
1600*5e7646d2SAndroid Build Coastguard Worker 
1601*5e7646d2SAndroid Build Coastguard Worker 	  if (options)
1602*5e7646d2SAndroid Build Coastguard Worker 	  {
1603*5e7646d2SAndroid Build Coastguard Worker 	    for (i = num_options, moption = options,
1604*5e7646d2SAndroid Build Coastguard Worker 		     coption = pc->presets[_PWG_PRINT_COLOR_MODE_COLOR]
1605*5e7646d2SAndroid Build Coastguard Worker 					   [pwg_print_quality];
1606*5e7646d2SAndroid Build Coastguard Worker 		 i > 0;
1607*5e7646d2SAndroid Build Coastguard Worker 		 i --, moption ++, coption ++)
1608*5e7646d2SAndroid Build Coastguard Worker 	    {
1609*5e7646d2SAndroid Build Coastguard Worker 	      moption->name  = _cupsStrRetain(coption->name);
1610*5e7646d2SAndroid Build Coastguard Worker 	      moption->value = _cupsStrRetain(coption->value);
1611*5e7646d2SAndroid Build Coastguard Worker 	    }
1612*5e7646d2SAndroid Build Coastguard Worker 
1613*5e7646d2SAndroid Build Coastguard Worker 	    pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
1614*5e7646d2SAndroid Build Coastguard Worker 		num_options;
1615*5e7646d2SAndroid Build Coastguard Worker 	    pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
1616*5e7646d2SAndroid Build Coastguard Worker 		options;
1617*5e7646d2SAndroid Build Coastguard Worker 	  }
1618*5e7646d2SAndroid Build Coastguard Worker 	}
1619*5e7646d2SAndroid Build Coastguard Worker 	else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL)
1620*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1621*5e7646d2SAndroid Build Coastguard Worker 
1622*5e7646d2SAndroid Build Coastguard Worker        /*
1623*5e7646d2SAndroid Build Coastguard Worker 	* Add the grayscale option to the preset...
1624*5e7646d2SAndroid Build Coastguard Worker 	*/
1625*5e7646d2SAndroid Build Coastguard Worker 
1626*5e7646d2SAndroid Build Coastguard Worker 	pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] =
1627*5e7646d2SAndroid Build Coastguard Worker 	    cupsAddOption(color_option, gray_choice,
1628*5e7646d2SAndroid Build Coastguard Worker 			  pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME]
1629*5e7646d2SAndroid Build Coastguard Worker 					  [pwg_print_quality],
1630*5e7646d2SAndroid Build Coastguard Worker 			  pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME] +
1631*5e7646d2SAndroid Build Coastguard Worker 			      pwg_print_quality);
1632*5e7646d2SAndroid Build Coastguard Worker       }
1633*5e7646d2SAndroid Build Coastguard Worker     }
1634*5e7646d2SAndroid Build Coastguard Worker   }
1635*5e7646d2SAndroid Build Coastguard Worker 
1636*5e7646d2SAndroid Build Coastguard Worker  /*
1637*5e7646d2SAndroid Build Coastguard Worker   * Copy and convert Duplex (sides) data...
1638*5e7646d2SAndroid Build Coastguard Worker   */
1639*5e7646d2SAndroid Build Coastguard Worker 
1640*5e7646d2SAndroid Build Coastguard Worker   if ((duplex = ppdFindOption(ppd, "Duplex")) == NULL)
1641*5e7646d2SAndroid Build Coastguard Worker     if ((duplex = ppdFindOption(ppd, "JCLDuplex")) == NULL)
1642*5e7646d2SAndroid Build Coastguard Worker       if ((duplex = ppdFindOption(ppd, "EFDuplex")) == NULL)
1643*5e7646d2SAndroid Build Coastguard Worker         if ((duplex = ppdFindOption(ppd, "EFDuplexing")) == NULL)
1644*5e7646d2SAndroid Build Coastguard Worker 	  duplex = ppdFindOption(ppd, "KD03Duplex");
1645*5e7646d2SAndroid Build Coastguard Worker 
1646*5e7646d2SAndroid Build Coastguard Worker   if (duplex)
1647*5e7646d2SAndroid Build Coastguard Worker   {
1648*5e7646d2SAndroid Build Coastguard Worker     pc->sides_option = strdup(duplex->keyword);
1649*5e7646d2SAndroid Build Coastguard Worker 
1650*5e7646d2SAndroid Build Coastguard Worker     for (i = duplex->num_choices, choice = duplex->choices;
1651*5e7646d2SAndroid Build Coastguard Worker          i > 0;
1652*5e7646d2SAndroid Build Coastguard Worker 	 i --, choice ++)
1653*5e7646d2SAndroid Build Coastguard Worker     {
1654*5e7646d2SAndroid Build Coastguard Worker       if ((!_cups_strcasecmp(choice->choice, "None") ||
1655*5e7646d2SAndroid Build Coastguard Worker 	   !_cups_strcasecmp(choice->choice, "False")) && !pc->sides_1sided)
1656*5e7646d2SAndroid Build Coastguard Worker         pc->sides_1sided = strdup(choice->choice);
1657*5e7646d2SAndroid Build Coastguard Worker       else if ((!_cups_strcasecmp(choice->choice, "DuplexNoTumble") ||
1658*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(choice->choice, "LongEdge") ||
1659*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(choice->choice, "Top")) && !pc->sides_2sided_long)
1660*5e7646d2SAndroid Build Coastguard Worker         pc->sides_2sided_long = strdup(choice->choice);
1661*5e7646d2SAndroid Build Coastguard Worker       else if ((!_cups_strcasecmp(choice->choice, "DuplexTumble") ||
1662*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(choice->choice, "ShortEdge") ||
1663*5e7646d2SAndroid Build Coastguard Worker 	        !_cups_strcasecmp(choice->choice, "Bottom")) &&
1664*5e7646d2SAndroid Build Coastguard Worker 	       !pc->sides_2sided_short)
1665*5e7646d2SAndroid Build Coastguard Worker         pc->sides_2sided_short = strdup(choice->choice);
1666*5e7646d2SAndroid Build Coastguard Worker     }
1667*5e7646d2SAndroid Build Coastguard Worker   }
1668*5e7646d2SAndroid Build Coastguard Worker 
1669*5e7646d2SAndroid Build Coastguard Worker  /*
1670*5e7646d2SAndroid Build Coastguard Worker   * Copy filters and pre-filters...
1671*5e7646d2SAndroid Build Coastguard Worker   */
1672*5e7646d2SAndroid Build Coastguard Worker 
1673*5e7646d2SAndroid Build Coastguard Worker   pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
1674*5e7646d2SAndroid Build Coastguard Worker 
1675*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(pc->filters,
1676*5e7646d2SAndroid Build Coastguard Worker                "application/vnd.cups-raw application/octet-stream 0 -");
1677*5e7646d2SAndroid Build Coastguard Worker 
1678*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) != NULL)
1679*5e7646d2SAndroid Build Coastguard Worker   {
1680*5e7646d2SAndroid Build Coastguard Worker     do
1681*5e7646d2SAndroid Build Coastguard Worker     {
1682*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->filters, ppd_attr->value);
1683*5e7646d2SAndroid Build Coastguard Worker     }
1684*5e7646d2SAndroid Build Coastguard Worker     while ((ppd_attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);
1685*5e7646d2SAndroid Build Coastguard Worker   }
1686*5e7646d2SAndroid Build Coastguard Worker   else if (ppd->num_filters > 0)
1687*5e7646d2SAndroid Build Coastguard Worker   {
1688*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < ppd->num_filters; i ++)
1689*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->filters, ppd->filters[i]);
1690*5e7646d2SAndroid Build Coastguard Worker   }
1691*5e7646d2SAndroid Build Coastguard Worker   else
1692*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(pc->filters, "application/vnd.cups-postscript 0 -");
1693*5e7646d2SAndroid Build Coastguard Worker 
1694*5e7646d2SAndroid Build Coastguard Worker  /*
1695*5e7646d2SAndroid Build Coastguard Worker   * See if we have a command filter...
1696*5e7646d2SAndroid Build Coastguard Worker   */
1697*5e7646d2SAndroid Build Coastguard Worker 
1698*5e7646d2SAndroid Build Coastguard Worker   for (filter = (const char *)cupsArrayFirst(pc->filters);
1699*5e7646d2SAndroid Build Coastguard Worker        filter;
1700*5e7646d2SAndroid Build Coastguard Worker        filter = (const char *)cupsArrayNext(pc->filters))
1701*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strncasecmp(filter, "application/vnd.cups-command", 28) &&
1702*5e7646d2SAndroid Build Coastguard Worker         _cups_isspace(filter[28]))
1703*5e7646d2SAndroid Build Coastguard Worker       break;
1704*5e7646d2SAndroid Build Coastguard Worker 
1705*5e7646d2SAndroid Build Coastguard Worker   if (!filter &&
1706*5e7646d2SAndroid Build Coastguard Worker       ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) == NULL ||
1707*5e7646d2SAndroid Build Coastguard Worker        _cups_strcasecmp(ppd_attr->value, "none")))
1708*5e7646d2SAndroid Build Coastguard Worker   {
1709*5e7646d2SAndroid Build Coastguard Worker    /*
1710*5e7646d2SAndroid Build Coastguard Worker     * No command filter and no cupsCommands keyword telling us not to use one.
1711*5e7646d2SAndroid Build Coastguard Worker     * See if this is a PostScript printer, and if so add a PostScript command
1712*5e7646d2SAndroid Build Coastguard Worker     * filter...
1713*5e7646d2SAndroid Build Coastguard Worker     */
1714*5e7646d2SAndroid Build Coastguard Worker 
1715*5e7646d2SAndroid Build Coastguard Worker     for (filter = (const char *)cupsArrayFirst(pc->filters);
1716*5e7646d2SAndroid Build Coastguard Worker 	 filter;
1717*5e7646d2SAndroid Build Coastguard Worker 	 filter = (const char *)cupsArrayNext(pc->filters))
1718*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strncasecmp(filter, "application/vnd.cups-postscript", 31) &&
1719*5e7646d2SAndroid Build Coastguard Worker 	  _cups_isspace(filter[31]))
1720*5e7646d2SAndroid Build Coastguard Worker 	break;
1721*5e7646d2SAndroid Build Coastguard Worker 
1722*5e7646d2SAndroid Build Coastguard Worker     if (filter)
1723*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->filters,
1724*5e7646d2SAndroid Build Coastguard Worker                    "application/vnd.cups-command application/postscript 100 "
1725*5e7646d2SAndroid Build Coastguard Worker                    "commandtops");
1726*5e7646d2SAndroid Build Coastguard Worker   }
1727*5e7646d2SAndroid Build Coastguard Worker 
1728*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
1729*5e7646d2SAndroid Build Coastguard Worker   {
1730*5e7646d2SAndroid Build Coastguard Worker     pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
1731*5e7646d2SAndroid Build Coastguard Worker 
1732*5e7646d2SAndroid Build Coastguard Worker     do
1733*5e7646d2SAndroid Build Coastguard Worker     {
1734*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->prefilters, ppd_attr->value);
1735*5e7646d2SAndroid Build Coastguard Worker     }
1736*5e7646d2SAndroid Build Coastguard Worker     while ((ppd_attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL)) != NULL);
1737*5e7646d2SAndroid Build Coastguard Worker   }
1738*5e7646d2SAndroid Build Coastguard Worker 
1739*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsSingleFile", NULL)) != NULL)
1740*5e7646d2SAndroid Build Coastguard Worker     pc->single_file = !_cups_strcasecmp(ppd_attr->value, "true");
1741*5e7646d2SAndroid Build Coastguard Worker 
1742*5e7646d2SAndroid Build Coastguard Worker  /*
1743*5e7646d2SAndroid Build Coastguard Worker   * Copy the product string, if any...
1744*5e7646d2SAndroid Build Coastguard Worker   */
1745*5e7646d2SAndroid Build Coastguard Worker 
1746*5e7646d2SAndroid Build Coastguard Worker   if (ppd->product)
1747*5e7646d2SAndroid Build Coastguard Worker     pc->product = strdup(ppd->product);
1748*5e7646d2SAndroid Build Coastguard Worker 
1749*5e7646d2SAndroid Build Coastguard Worker  /*
1750*5e7646d2SAndroid Build Coastguard Worker   * Copy finishings mapping data...
1751*5e7646d2SAndroid Build Coastguard Worker   */
1752*5e7646d2SAndroid Build Coastguard Worker 
1753*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsIPPFinishings", NULL)) != NULL)
1754*5e7646d2SAndroid Build Coastguard Worker   {
1755*5e7646d2SAndroid Build Coastguard Worker    /*
1756*5e7646d2SAndroid Build Coastguard Worker     * Have proper vendor mapping of IPP finishings values to PPD options...
1757*5e7646d2SAndroid Build Coastguard Worker     */
1758*5e7646d2SAndroid Build Coastguard Worker 
1759*5e7646d2SAndroid Build Coastguard Worker     pc->finishings = cupsArrayNew3((cups_array_func_t)pwg_compare_finishings,
1760*5e7646d2SAndroid Build Coastguard Worker                                    NULL, NULL, 0, NULL,
1761*5e7646d2SAndroid Build Coastguard Worker                                    (cups_afree_func_t)pwg_free_finishings);
1762*5e7646d2SAndroid Build Coastguard Worker 
1763*5e7646d2SAndroid Build Coastguard Worker     do
1764*5e7646d2SAndroid Build Coastguard Worker     {
1765*5e7646d2SAndroid Build Coastguard Worker       if ((finishings = calloc(1, sizeof(_pwg_finishings_t))) == NULL)
1766*5e7646d2SAndroid Build Coastguard Worker         goto create_error;
1767*5e7646d2SAndroid Build Coastguard Worker 
1768*5e7646d2SAndroid Build Coastguard Worker       finishings->value       = (ipp_finishings_t)atoi(ppd_attr->spec);
1769*5e7646d2SAndroid Build Coastguard Worker       finishings->num_options = _ppdParseOptions(ppd_attr->value, 0,
1770*5e7646d2SAndroid Build Coastguard Worker                                                  &(finishings->options),
1771*5e7646d2SAndroid Build Coastguard Worker                                                  _PPD_PARSE_OPTIONS);
1772*5e7646d2SAndroid Build Coastguard Worker 
1773*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->finishings, finishings);
1774*5e7646d2SAndroid Build Coastguard Worker     }
1775*5e7646d2SAndroid Build Coastguard Worker     while ((ppd_attr = ppdFindNextAttr(ppd, "cupsIPPFinishings",
1776*5e7646d2SAndroid Build Coastguard Worker                                        NULL)) != NULL);
1777*5e7646d2SAndroid Build Coastguard Worker   }
1778*5e7646d2SAndroid Build Coastguard Worker   else
1779*5e7646d2SAndroid Build Coastguard Worker   {
1780*5e7646d2SAndroid Build Coastguard Worker    /*
1781*5e7646d2SAndroid Build Coastguard Worker     * No IPP mapping data, try to map common/standard PPD keywords...
1782*5e7646d2SAndroid Build Coastguard Worker     */
1783*5e7646d2SAndroid Build Coastguard Worker 
1784*5e7646d2SAndroid Build Coastguard Worker     pc->finishings = cupsArrayNew3((cups_array_func_t)pwg_compare_finishings, NULL, NULL, 0, NULL, (cups_afree_func_t)pwg_free_finishings);
1785*5e7646d2SAndroid Build Coastguard Worker 
1786*5e7646d2SAndroid Build Coastguard Worker     if ((ppd_option = ppdFindOption(ppd, "StapleLocation")) != NULL)
1787*5e7646d2SAndroid Build Coastguard Worker     {
1788*5e7646d2SAndroid Build Coastguard Worker      /*
1789*5e7646d2SAndroid Build Coastguard Worker       * Add staple finishings...
1790*5e7646d2SAndroid Build Coastguard Worker       */
1791*5e7646d2SAndroid Build Coastguard Worker 
1792*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "SinglePortrait"))
1793*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_STAPLE_TOP_LEFT, "StapleLocation", "SinglePortrait");
1794*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "UpperLeft")) /* Ricoh extension */
1795*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_STAPLE_TOP_LEFT, "StapleLocation", "UpperLeft");
1796*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "UpperRight")) /* Ricoh extension */
1797*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_STAPLE_TOP_RIGHT, "StapleLocation", "UpperRight");
1798*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "SingleLandscape"))
1799*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_STAPLE_BOTTOM_LEFT, "StapleLocation", "SingleLandscape");
1800*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "DualLandscape"))
1801*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_STAPLE_DUAL_LEFT, "StapleLocation", "DualLandscape");
1802*5e7646d2SAndroid Build Coastguard Worker     }
1803*5e7646d2SAndroid Build Coastguard Worker 
1804*5e7646d2SAndroid Build Coastguard Worker     if ((ppd_option = ppdFindOption(ppd, "RIPunch")) != NULL)
1805*5e7646d2SAndroid Build Coastguard Worker     {
1806*5e7646d2SAndroid Build Coastguard Worker      /*
1807*5e7646d2SAndroid Build Coastguard Worker       * Add (Ricoh) punch finishings...
1808*5e7646d2SAndroid Build Coastguard Worker       */
1809*5e7646d2SAndroid Build Coastguard Worker 
1810*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Left2"))
1811*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_DUAL_LEFT, "RIPunch", "Left2");
1812*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Left3"))
1813*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_TRIPLE_LEFT, "RIPunch", "Left3");
1814*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Left4"))
1815*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_QUAD_LEFT, "RIPunch", "Left4");
1816*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Right2"))
1817*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_DUAL_RIGHT, "RIPunch", "Right2");
1818*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Right3"))
1819*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_TRIPLE_RIGHT, "RIPunch", "Right3");
1820*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Right4"))
1821*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_QUAD_RIGHT, "RIPunch", "Right4");
1822*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Upper2"))
1823*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_DUAL_TOP, "RIPunch", "Upper2");
1824*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Upper3"))
1825*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_TRIPLE_TOP, "RIPunch", "Upper3");
1826*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Upper4"))
1827*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_PUNCH_QUAD_TOP, "RIPunch", "Upper4");
1828*5e7646d2SAndroid Build Coastguard Worker     }
1829*5e7646d2SAndroid Build Coastguard Worker 
1830*5e7646d2SAndroid Build Coastguard Worker     if ((ppd_option = ppdFindOption(ppd, "BindEdge")) != NULL)
1831*5e7646d2SAndroid Build Coastguard Worker     {
1832*5e7646d2SAndroid Build Coastguard Worker      /*
1833*5e7646d2SAndroid Build Coastguard Worker       * Add bind finishings...
1834*5e7646d2SAndroid Build Coastguard Worker       */
1835*5e7646d2SAndroid Build Coastguard Worker 
1836*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Left"))
1837*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_BIND_LEFT, "BindEdge", "Left");
1838*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Right"))
1839*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_BIND_RIGHT, "BindEdge", "Right");
1840*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Top"))
1841*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_BIND_TOP, "BindEdge", "Top");
1842*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Bottom"))
1843*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_BIND_BOTTOM, "BindEdge", "Bottom");
1844*5e7646d2SAndroid Build Coastguard Worker     }
1845*5e7646d2SAndroid Build Coastguard Worker 
1846*5e7646d2SAndroid Build Coastguard Worker     if ((ppd_option = ppdFindOption(ppd, "FoldType")) != NULL)
1847*5e7646d2SAndroid Build Coastguard Worker     {
1848*5e7646d2SAndroid Build Coastguard Worker      /*
1849*5e7646d2SAndroid Build Coastguard Worker       * Add (Adobe) fold finishings...
1850*5e7646d2SAndroid Build Coastguard Worker       */
1851*5e7646d2SAndroid Build Coastguard Worker 
1852*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "ZFold"))
1853*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_Z, "FoldType", "ZFold");
1854*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Saddle"))
1855*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_HALF, "FoldType", "Saddle");
1856*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "DoubleGate"))
1857*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_DOUBLE_GATE, "FoldType", "DoubleGate");
1858*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "LeftGate"))
1859*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_LEFT_GATE, "FoldType", "LeftGate");
1860*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "RightGate"))
1861*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_RIGHT_GATE, "FoldType", "RightGate");
1862*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "Letter"))
1863*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_LETTER, "FoldType", "Letter");
1864*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "XFold"))
1865*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_POSTER, "FoldType", "XFold");
1866*5e7646d2SAndroid Build Coastguard Worker     }
1867*5e7646d2SAndroid Build Coastguard Worker 
1868*5e7646d2SAndroid Build Coastguard Worker     if ((ppd_option = ppdFindOption(ppd, "RIFoldType")) != NULL)
1869*5e7646d2SAndroid Build Coastguard Worker     {
1870*5e7646d2SAndroid Build Coastguard Worker      /*
1871*5e7646d2SAndroid Build Coastguard Worker       * Add (Ricoh) fold finishings...
1872*5e7646d2SAndroid Build Coastguard Worker       */
1873*5e7646d2SAndroid Build Coastguard Worker 
1874*5e7646d2SAndroid Build Coastguard Worker       if (ppdFindChoice(ppd_option, "OutsideTwoFold"))
1875*5e7646d2SAndroid Build Coastguard Worker         pwg_add_finishing(pc->finishings, IPP_FINISHINGS_FOLD_LETTER, "RIFoldType", "OutsideTwoFold");
1876*5e7646d2SAndroid Build Coastguard Worker     }
1877*5e7646d2SAndroid Build Coastguard Worker 
1878*5e7646d2SAndroid Build Coastguard Worker     if (cupsArrayCount(pc->finishings) == 0)
1879*5e7646d2SAndroid Build Coastguard Worker     {
1880*5e7646d2SAndroid Build Coastguard Worker       cupsArrayDelete(pc->finishings);
1881*5e7646d2SAndroid Build Coastguard Worker       pc->finishings = NULL;
1882*5e7646d2SAndroid Build Coastguard Worker     }
1883*5e7646d2SAndroid Build Coastguard Worker   }
1884*5e7646d2SAndroid Build Coastguard Worker 
1885*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_option = ppdFindOption(ppd, "cupsFinishingTemplate")) != NULL)
1886*5e7646d2SAndroid Build Coastguard Worker   {
1887*5e7646d2SAndroid Build Coastguard Worker     pc->templates = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
1888*5e7646d2SAndroid Build Coastguard Worker 
1889*5e7646d2SAndroid Build Coastguard Worker     for (choice = ppd_option->choices, i = ppd_option->num_choices; i > 0; choice ++, i --)
1890*5e7646d2SAndroid Build Coastguard Worker     {
1891*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pc->templates, (void *)choice->choice);
1892*5e7646d2SAndroid Build Coastguard Worker 
1893*5e7646d2SAndroid Build Coastguard Worker      /*
1894*5e7646d2SAndroid Build Coastguard Worker       * Add localized text for PWG keyword to message catalog...
1895*5e7646d2SAndroid Build Coastguard Worker       */
1896*5e7646d2SAndroid Build Coastguard Worker 
1897*5e7646d2SAndroid Build Coastguard Worker       snprintf(msg_id, sizeof(msg_id), "finishing-template.%s", choice->choice);
1898*5e7646d2SAndroid Build Coastguard Worker       pwg_add_message(pc->strings, msg_id, choice->text);
1899*5e7646d2SAndroid Build Coastguard Worker     }
1900*5e7646d2SAndroid Build Coastguard Worker   }
1901*5e7646d2SAndroid Build Coastguard Worker 
1902*5e7646d2SAndroid Build Coastguard Worker  /*
1903*5e7646d2SAndroid Build Coastguard Worker   * Max copies...
1904*5e7646d2SAndroid Build Coastguard Worker   */
1905*5e7646d2SAndroid Build Coastguard Worker 
1906*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsMaxCopies", NULL)) != NULL)
1907*5e7646d2SAndroid Build Coastguard Worker     pc->max_copies = atoi(ppd_attr->value);
1908*5e7646d2SAndroid Build Coastguard Worker   else if (ppd->manual_copies)
1909*5e7646d2SAndroid Build Coastguard Worker     pc->max_copies = 1;
1910*5e7646d2SAndroid Build Coastguard Worker   else
1911*5e7646d2SAndroid Build Coastguard Worker     pc->max_copies = 9999;
1912*5e7646d2SAndroid Build Coastguard Worker 
1913*5e7646d2SAndroid Build Coastguard Worker  /*
1914*5e7646d2SAndroid Build Coastguard Worker   * cupsChargeInfoURI, cupsJobAccountId, cupsJobAccountingUserId,
1915*5e7646d2SAndroid Build Coastguard Worker   * cupsJobPassword, and cupsMandatory.
1916*5e7646d2SAndroid Build Coastguard Worker   */
1917*5e7646d2SAndroid Build Coastguard Worker 
1918*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsChargeInfoURI", NULL)) != NULL)
1919*5e7646d2SAndroid Build Coastguard Worker     pc->charge_info_uri = strdup(ppd_attr->value);
1920*5e7646d2SAndroid Build Coastguard Worker 
1921*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsJobAccountId", NULL)) != NULL)
1922*5e7646d2SAndroid Build Coastguard Worker     pc->account_id = !_cups_strcasecmp(ppd_attr->value, "true");
1923*5e7646d2SAndroid Build Coastguard Worker 
1924*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsJobAccountingUserId", NULL)) != NULL)
1925*5e7646d2SAndroid Build Coastguard Worker     pc->accounting_user_id = !_cups_strcasecmp(ppd_attr->value, "true");
1926*5e7646d2SAndroid Build Coastguard Worker 
1927*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsJobPassword", NULL)) != NULL)
1928*5e7646d2SAndroid Build Coastguard Worker     pc->password = strdup(ppd_attr->value);
1929*5e7646d2SAndroid Build Coastguard Worker 
1930*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
1931*5e7646d2SAndroid Build Coastguard Worker     pc->mandatory = _cupsArrayNewStrings(ppd_attr->value, ' ');
1932*5e7646d2SAndroid Build Coastguard Worker 
1933*5e7646d2SAndroid Build Coastguard Worker  /*
1934*5e7646d2SAndroid Build Coastguard Worker   * Support files...
1935*5e7646d2SAndroid Build Coastguard Worker   */
1936*5e7646d2SAndroid Build Coastguard Worker 
1937*5e7646d2SAndroid Build Coastguard Worker   pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
1938*5e7646d2SAndroid Build Coastguard Worker 
1939*5e7646d2SAndroid Build Coastguard Worker   for (ppd_attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
1940*5e7646d2SAndroid Build Coastguard Worker        ppd_attr;
1941*5e7646d2SAndroid Build Coastguard Worker        ppd_attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
1942*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(pc->support_files, ppd_attr->value);
1943*5e7646d2SAndroid Build Coastguard Worker 
1944*5e7646d2SAndroid Build Coastguard Worker   if ((ppd_attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL)) != NULL)
1945*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(pc->support_files, ppd_attr->value);
1946*5e7646d2SAndroid Build Coastguard Worker 
1947*5e7646d2SAndroid Build Coastguard Worker  /*
1948*5e7646d2SAndroid Build Coastguard Worker   * Return the cache data...
1949*5e7646d2SAndroid Build Coastguard Worker   */
1950*5e7646d2SAndroid Build Coastguard Worker 
1951*5e7646d2SAndroid Build Coastguard Worker   return (pc);
1952*5e7646d2SAndroid Build Coastguard Worker 
1953*5e7646d2SAndroid Build Coastguard Worker  /*
1954*5e7646d2SAndroid Build Coastguard Worker   * If we get here we need to destroy the PWG mapping data and return NULL...
1955*5e7646d2SAndroid Build Coastguard Worker   */
1956*5e7646d2SAndroid Build Coastguard Worker 
1957*5e7646d2SAndroid Build Coastguard Worker   create_error:
1958*5e7646d2SAndroid Build Coastguard Worker 
1959*5e7646d2SAndroid Build Coastguard Worker   _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Out of memory."), 1);
1960*5e7646d2SAndroid Build Coastguard Worker   _ppdCacheDestroy(pc);
1961*5e7646d2SAndroid Build Coastguard Worker 
1962*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
1963*5e7646d2SAndroid Build Coastguard Worker }
1964*5e7646d2SAndroid Build Coastguard Worker 
1965*5e7646d2SAndroid Build Coastguard Worker 
1966*5e7646d2SAndroid Build Coastguard Worker /*
1967*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheDestroy()' - Free all memory used for PWG mapping data.
1968*5e7646d2SAndroid Build Coastguard Worker  */
1969*5e7646d2SAndroid Build Coastguard Worker 
1970*5e7646d2SAndroid Build Coastguard Worker void
_ppdCacheDestroy(_ppd_cache_t * pc)1971*5e7646d2SAndroid Build Coastguard Worker _ppdCacheDestroy(_ppd_cache_t *pc)	/* I - PPD cache and mapping data */
1972*5e7646d2SAndroid Build Coastguard Worker {
1973*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
1974*5e7646d2SAndroid Build Coastguard Worker   pwg_map_t	*map;			/* Current map */
1975*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t	*size;			/* Current size */
1976*5e7646d2SAndroid Build Coastguard Worker 
1977*5e7646d2SAndroid Build Coastguard Worker 
1978*5e7646d2SAndroid Build Coastguard Worker  /*
1979*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1980*5e7646d2SAndroid Build Coastguard Worker   */
1981*5e7646d2SAndroid Build Coastguard Worker 
1982*5e7646d2SAndroid Build Coastguard Worker   if (!pc)
1983*5e7646d2SAndroid Build Coastguard Worker     return;
1984*5e7646d2SAndroid Build Coastguard Worker 
1985*5e7646d2SAndroid Build Coastguard Worker  /*
1986*5e7646d2SAndroid Build Coastguard Worker   * Free memory as needed...
1987*5e7646d2SAndroid Build Coastguard Worker   */
1988*5e7646d2SAndroid Build Coastguard Worker 
1989*5e7646d2SAndroid Build Coastguard Worker   if (pc->bins)
1990*5e7646d2SAndroid Build Coastguard Worker   {
1991*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++)
1992*5e7646d2SAndroid Build Coastguard Worker     {
1993*5e7646d2SAndroid Build Coastguard Worker       free(map->pwg);
1994*5e7646d2SAndroid Build Coastguard Worker       free(map->ppd);
1995*5e7646d2SAndroid Build Coastguard Worker     }
1996*5e7646d2SAndroid Build Coastguard Worker 
1997*5e7646d2SAndroid Build Coastguard Worker     free(pc->bins);
1998*5e7646d2SAndroid Build Coastguard Worker   }
1999*5e7646d2SAndroid Build Coastguard Worker 
2000*5e7646d2SAndroid Build Coastguard Worker   if (pc->sizes)
2001*5e7646d2SAndroid Build Coastguard Worker   {
2002*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
2003*5e7646d2SAndroid Build Coastguard Worker     {
2004*5e7646d2SAndroid Build Coastguard Worker       free(size->map.pwg);
2005*5e7646d2SAndroid Build Coastguard Worker       free(size->map.ppd);
2006*5e7646d2SAndroid Build Coastguard Worker     }
2007*5e7646d2SAndroid Build Coastguard Worker 
2008*5e7646d2SAndroid Build Coastguard Worker     free(pc->sizes);
2009*5e7646d2SAndroid Build Coastguard Worker   }
2010*5e7646d2SAndroid Build Coastguard Worker 
2011*5e7646d2SAndroid Build Coastguard Worker   free(pc->source_option);
2012*5e7646d2SAndroid Build Coastguard Worker 
2013*5e7646d2SAndroid Build Coastguard Worker   if (pc->sources)
2014*5e7646d2SAndroid Build Coastguard Worker   {
2015*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++)
2016*5e7646d2SAndroid Build Coastguard Worker     {
2017*5e7646d2SAndroid Build Coastguard Worker       free(map->pwg);
2018*5e7646d2SAndroid Build Coastguard Worker       free(map->ppd);
2019*5e7646d2SAndroid Build Coastguard Worker     }
2020*5e7646d2SAndroid Build Coastguard Worker 
2021*5e7646d2SAndroid Build Coastguard Worker     free(pc->sources);
2022*5e7646d2SAndroid Build Coastguard Worker   }
2023*5e7646d2SAndroid Build Coastguard Worker 
2024*5e7646d2SAndroid Build Coastguard Worker   if (pc->types)
2025*5e7646d2SAndroid Build Coastguard Worker   {
2026*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_types, map = pc->types; i > 0; i --, map ++)
2027*5e7646d2SAndroid Build Coastguard Worker     {
2028*5e7646d2SAndroid Build Coastguard Worker       free(map->pwg);
2029*5e7646d2SAndroid Build Coastguard Worker       free(map->ppd);
2030*5e7646d2SAndroid Build Coastguard Worker     }
2031*5e7646d2SAndroid Build Coastguard Worker 
2032*5e7646d2SAndroid Build Coastguard Worker     free(pc->types);
2033*5e7646d2SAndroid Build Coastguard Worker   }
2034*5e7646d2SAndroid Build Coastguard Worker 
2035*5e7646d2SAndroid Build Coastguard Worker   free(pc->custom_max_keyword);
2036*5e7646d2SAndroid Build Coastguard Worker   free(pc->custom_min_keyword);
2037*5e7646d2SAndroid Build Coastguard Worker 
2038*5e7646d2SAndroid Build Coastguard Worker   free(pc->product);
2039*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pc->filters);
2040*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pc->prefilters);
2041*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pc->finishings);
2042*5e7646d2SAndroid Build Coastguard Worker 
2043*5e7646d2SAndroid Build Coastguard Worker   free(pc->charge_info_uri);
2044*5e7646d2SAndroid Build Coastguard Worker   free(pc->password);
2045*5e7646d2SAndroid Build Coastguard Worker 
2046*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pc->mandatory);
2047*5e7646d2SAndroid Build Coastguard Worker 
2048*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pc->support_files);
2049*5e7646d2SAndroid Build Coastguard Worker 
2050*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pc->strings);
2051*5e7646d2SAndroid Build Coastguard Worker 
2052*5e7646d2SAndroid Build Coastguard Worker   free(pc);
2053*5e7646d2SAndroid Build Coastguard Worker }
2054*5e7646d2SAndroid Build Coastguard Worker 
2055*5e7646d2SAndroid Build Coastguard Worker 
2056*5e7646d2SAndroid Build Coastguard Worker /*
2057*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetBin()' - Get the PWG output-bin keyword associated with a PPD
2058*5e7646d2SAndroid Build Coastguard Worker  *                  OutputBin.
2059*5e7646d2SAndroid Build Coastguard Worker  */
2060*5e7646d2SAndroid Build Coastguard Worker 
2061*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - output-bin or NULL */
_ppdCacheGetBin(_ppd_cache_t * pc,const char * output_bin)2062*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetBin(
2063*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2064*5e7646d2SAndroid Build Coastguard Worker     const char   *output_bin)		/* I - PPD OutputBin string */
2065*5e7646d2SAndroid Build Coastguard Worker {
2066*5e7646d2SAndroid Build Coastguard Worker   int	i;				/* Looping var */
2067*5e7646d2SAndroid Build Coastguard Worker 
2068*5e7646d2SAndroid Build Coastguard Worker 
2069*5e7646d2SAndroid Build Coastguard Worker  /*
2070*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2071*5e7646d2SAndroid Build Coastguard Worker   */
2072*5e7646d2SAndroid Build Coastguard Worker 
2073*5e7646d2SAndroid Build Coastguard Worker   if (!pc || !output_bin)
2074*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2075*5e7646d2SAndroid Build Coastguard Worker 
2076*5e7646d2SAndroid Build Coastguard Worker  /*
2077*5e7646d2SAndroid Build Coastguard Worker   * Look up the OutputBin string...
2078*5e7646d2SAndroid Build Coastguard Worker   */
2079*5e7646d2SAndroid Build Coastguard Worker 
2080*5e7646d2SAndroid Build Coastguard Worker 
2081*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < pc->num_bins; i ++)
2082*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(output_bin, pc->bins[i].ppd))
2083*5e7646d2SAndroid Build Coastguard Worker       return (pc->bins[i].pwg);
2084*5e7646d2SAndroid Build Coastguard Worker 
2085*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2086*5e7646d2SAndroid Build Coastguard Worker }
2087*5e7646d2SAndroid Build Coastguard Worker 
2088*5e7646d2SAndroid Build Coastguard Worker 
2089*5e7646d2SAndroid Build Coastguard Worker /*
2090*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetFinishingOptions()' - Get PPD finishing options for the given
2091*5e7646d2SAndroid Build Coastguard Worker  *                                    IPP finishings value(s).
2092*5e7646d2SAndroid Build Coastguard Worker  */
2093*5e7646d2SAndroid Build Coastguard Worker 
2094*5e7646d2SAndroid Build Coastguard Worker int					/* O  - New number of options */
_ppdCacheGetFinishingOptions(_ppd_cache_t * pc,ipp_t * job,ipp_finishings_t value,int num_options,cups_option_t ** options)2095*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetFinishingOptions(
2096*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t     *pc,		/* I  - PPD cache and mapping data */
2097*5e7646d2SAndroid Build Coastguard Worker     ipp_t            *job,		/* I  - Job attributes or NULL */
2098*5e7646d2SAndroid Build Coastguard Worker     ipp_finishings_t value,		/* I  - IPP finishings value of IPP_FINISHINGS_NONE */
2099*5e7646d2SAndroid Build Coastguard Worker     int              num_options,	/* I  - Number of options */
2100*5e7646d2SAndroid Build Coastguard Worker     cups_option_t    **options)		/* IO - Options */
2101*5e7646d2SAndroid Build Coastguard Worker {
2102*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
2103*5e7646d2SAndroid Build Coastguard Worker   _pwg_finishings_t	*f,		/* PWG finishings options */
2104*5e7646d2SAndroid Build Coastguard Worker 			key;		/* Search key */
2105*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Finishings attribute */
2106*5e7646d2SAndroid Build Coastguard Worker   cups_option_t		*option;	/* Current finishings option */
2107*5e7646d2SAndroid Build Coastguard Worker 
2108*5e7646d2SAndroid Build Coastguard Worker 
2109*5e7646d2SAndroid Build Coastguard Worker  /*
2110*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2111*5e7646d2SAndroid Build Coastguard Worker   */
2112*5e7646d2SAndroid Build Coastguard Worker 
2113*5e7646d2SAndroid Build Coastguard Worker   if (!pc || cupsArrayCount(pc->finishings) == 0 || !options ||
2114*5e7646d2SAndroid Build Coastguard Worker       (!job && value == IPP_FINISHINGS_NONE))
2115*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
2116*5e7646d2SAndroid Build Coastguard Worker 
2117*5e7646d2SAndroid Build Coastguard Worker  /*
2118*5e7646d2SAndroid Build Coastguard Worker   * Apply finishing options...
2119*5e7646d2SAndroid Build Coastguard Worker   */
2120*5e7646d2SAndroid Build Coastguard Worker 
2121*5e7646d2SAndroid Build Coastguard Worker   if (job && (attr = ippFindAttribute(job, "finishings", IPP_TAG_ENUM)) != NULL)
2122*5e7646d2SAndroid Build Coastguard Worker   {
2123*5e7646d2SAndroid Build Coastguard Worker     int	num_values = ippGetCount(attr);	/* Number of values */
2124*5e7646d2SAndroid Build Coastguard Worker 
2125*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_values; i ++)
2126*5e7646d2SAndroid Build Coastguard Worker     {
2127*5e7646d2SAndroid Build Coastguard Worker       key.value = (ipp_finishings_t)ippGetInteger(attr, i);
2128*5e7646d2SAndroid Build Coastguard Worker 
2129*5e7646d2SAndroid Build Coastguard Worker       if ((f = cupsArrayFind(pc->finishings, &key)) != NULL)
2130*5e7646d2SAndroid Build Coastguard Worker       {
2131*5e7646d2SAndroid Build Coastguard Worker         int	j;			/* Another looping var */
2132*5e7646d2SAndroid Build Coastguard Worker 
2133*5e7646d2SAndroid Build Coastguard Worker         for (j = f->num_options, option = f->options; j > 0; j --, option ++)
2134*5e7646d2SAndroid Build Coastguard Worker           num_options = cupsAddOption(option->name, option->value,
2135*5e7646d2SAndroid Build Coastguard Worker                                       num_options, options);
2136*5e7646d2SAndroid Build Coastguard Worker       }
2137*5e7646d2SAndroid Build Coastguard Worker     }
2138*5e7646d2SAndroid Build Coastguard Worker   }
2139*5e7646d2SAndroid Build Coastguard Worker   else if (value != IPP_FINISHINGS_NONE)
2140*5e7646d2SAndroid Build Coastguard Worker   {
2141*5e7646d2SAndroid Build Coastguard Worker     key.value = value;
2142*5e7646d2SAndroid Build Coastguard Worker 
2143*5e7646d2SAndroid Build Coastguard Worker     if ((f = cupsArrayFind(pc->finishings, &key)) != NULL)
2144*5e7646d2SAndroid Build Coastguard Worker     {
2145*5e7646d2SAndroid Build Coastguard Worker       int	j;			/* Another looping var */
2146*5e7646d2SAndroid Build Coastguard Worker 
2147*5e7646d2SAndroid Build Coastguard Worker       for (j = f->num_options, option = f->options; j > 0; j --, option ++)
2148*5e7646d2SAndroid Build Coastguard Worker 	num_options = cupsAddOption(option->name, option->value,
2149*5e7646d2SAndroid Build Coastguard Worker 				    num_options, options);
2150*5e7646d2SAndroid Build Coastguard Worker     }
2151*5e7646d2SAndroid Build Coastguard Worker   }
2152*5e7646d2SAndroid Build Coastguard Worker 
2153*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
2154*5e7646d2SAndroid Build Coastguard Worker }
2155*5e7646d2SAndroid Build Coastguard Worker 
2156*5e7646d2SAndroid Build Coastguard Worker 
2157*5e7646d2SAndroid Build Coastguard Worker /*
2158*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetFinishingValues()' - Get IPP finishings value(s) from the given
2159*5e7646d2SAndroid Build Coastguard Worker  *                                   PPD options.
2160*5e7646d2SAndroid Build Coastguard Worker  */
2161*5e7646d2SAndroid Build Coastguard Worker 
2162*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of finishings values */
_ppdCacheGetFinishingValues(ppd_file_t * ppd,_ppd_cache_t * pc,int max_values,int * values)2163*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetFinishingValues(
2164*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t    *ppd,			/* I - Marked PPD file */
2165*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t  *pc,			/* I - PPD cache and mapping data */
2166*5e7646d2SAndroid Build Coastguard Worker     int           max_values,		/* I - Maximum number of finishings values */
2167*5e7646d2SAndroid Build Coastguard Worker     int           *values)		/* O - Finishings values */
2168*5e7646d2SAndroid Build Coastguard Worker {
2169*5e7646d2SAndroid Build Coastguard Worker   int			i,		/* Looping var */
2170*5e7646d2SAndroid Build Coastguard Worker 			num_values = 0;	/* Number of values */
2171*5e7646d2SAndroid Build Coastguard Worker   _pwg_finishings_t	*f;		/* Current finishings option */
2172*5e7646d2SAndroid Build Coastguard Worker   cups_option_t		*option;	/* Current option */
2173*5e7646d2SAndroid Build Coastguard Worker   ppd_choice_t		*choice;	/* Marked PPD choice */
2174*5e7646d2SAndroid Build Coastguard Worker 
2175*5e7646d2SAndroid Build Coastguard Worker 
2176*5e7646d2SAndroid Build Coastguard Worker  /*
2177*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2178*5e7646d2SAndroid Build Coastguard Worker   */
2179*5e7646d2SAndroid Build Coastguard Worker 
2180*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_ppdCacheGetFinishingValues(ppd=%p, pc=%p, max_values=%d, values=%p)", ppd, pc, max_values, values));
2181*5e7646d2SAndroid Build Coastguard Worker 
2182*5e7646d2SAndroid Build Coastguard Worker   if (!ppd || !pc || max_values < 1 || !values)
2183*5e7646d2SAndroid Build Coastguard Worker   {
2184*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("_ppdCacheGetFinishingValues: Bad arguments, returning 0.");
2185*5e7646d2SAndroid Build Coastguard Worker     return (0);
2186*5e7646d2SAndroid Build Coastguard Worker   }
2187*5e7646d2SAndroid Build Coastguard Worker   else if (!pc->finishings)
2188*5e7646d2SAndroid Build Coastguard Worker   {
2189*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("_ppdCacheGetFinishingValues: No finishings support, returning 0.");
2190*5e7646d2SAndroid Build Coastguard Worker     return (0);
2191*5e7646d2SAndroid Build Coastguard Worker   }
2192*5e7646d2SAndroid Build Coastguard Worker 
2193*5e7646d2SAndroid Build Coastguard Worker  /*
2194*5e7646d2SAndroid Build Coastguard Worker   * Go through the finishings options and see what is set...
2195*5e7646d2SAndroid Build Coastguard Worker   */
2196*5e7646d2SAndroid Build Coastguard Worker 
2197*5e7646d2SAndroid Build Coastguard Worker   for (f = (_pwg_finishings_t *)cupsArrayFirst(pc->finishings);
2198*5e7646d2SAndroid Build Coastguard Worker        f;
2199*5e7646d2SAndroid Build Coastguard Worker        f = (_pwg_finishings_t *)cupsArrayNext(pc->finishings))
2200*5e7646d2SAndroid Build Coastguard Worker   {
2201*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("_ppdCacheGetFinishingValues: Checking %d (%s)", (int)f->value, ippEnumString("finishings", (int)f->value)));
2202*5e7646d2SAndroid Build Coastguard Worker 
2203*5e7646d2SAndroid Build Coastguard Worker     for (i = f->num_options, option = f->options; i > 0; i --, option ++)
2204*5e7646d2SAndroid Build Coastguard Worker     {
2205*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheGetFinishingValues: %s=%s?", option->name, option->value));
2206*5e7646d2SAndroid Build Coastguard Worker 
2207*5e7646d2SAndroid Build Coastguard Worker       if ((choice = ppdFindMarkedChoice(ppd, option->name)) == NULL || _cups_strcasecmp(option->value, choice->choice))
2208*5e7646d2SAndroid Build Coastguard Worker       {
2209*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("_ppdCacheGetFinishingValues: NO");
2210*5e7646d2SAndroid Build Coastguard Worker         break;
2211*5e7646d2SAndroid Build Coastguard Worker       }
2212*5e7646d2SAndroid Build Coastguard Worker     }
2213*5e7646d2SAndroid Build Coastguard Worker 
2214*5e7646d2SAndroid Build Coastguard Worker     if (i == 0)
2215*5e7646d2SAndroid Build Coastguard Worker     {
2216*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("_ppdCacheGetFinishingValues: Adding %d (%s)", (int)f->value, ippEnumString("finishings", (int)f->value)));
2217*5e7646d2SAndroid Build Coastguard Worker 
2218*5e7646d2SAndroid Build Coastguard Worker       values[num_values ++] = (int)f->value;
2219*5e7646d2SAndroid Build Coastguard Worker 
2220*5e7646d2SAndroid Build Coastguard Worker       if (num_values >= max_values)
2221*5e7646d2SAndroid Build Coastguard Worker         break;
2222*5e7646d2SAndroid Build Coastguard Worker     }
2223*5e7646d2SAndroid Build Coastguard Worker   }
2224*5e7646d2SAndroid Build Coastguard Worker 
2225*5e7646d2SAndroid Build Coastguard Worker   if (num_values == 0)
2226*5e7646d2SAndroid Build Coastguard Worker   {
2227*5e7646d2SAndroid Build Coastguard Worker    /*
2228*5e7646d2SAndroid Build Coastguard Worker     * Always have at least "finishings" = 'none'...
2229*5e7646d2SAndroid Build Coastguard Worker     */
2230*5e7646d2SAndroid Build Coastguard Worker 
2231*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("_ppdCacheGetFinishingValues: Adding 3 (none).");
2232*5e7646d2SAndroid Build Coastguard Worker     values[0] = IPP_FINISHINGS_NONE;
2233*5e7646d2SAndroid Build Coastguard Worker     num_values ++;
2234*5e7646d2SAndroid Build Coastguard Worker   }
2235*5e7646d2SAndroid Build Coastguard Worker 
2236*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_ppdCacheGetFinishingValues: Returning %d.", num_values));
2237*5e7646d2SAndroid Build Coastguard Worker 
2238*5e7646d2SAndroid Build Coastguard Worker   return (num_values);
2239*5e7646d2SAndroid Build Coastguard Worker }
2240*5e7646d2SAndroid Build Coastguard Worker 
2241*5e7646d2SAndroid Build Coastguard Worker 
2242*5e7646d2SAndroid Build Coastguard Worker /*
2243*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetInputSlot()' - Get the PPD InputSlot associated with the job
2244*5e7646d2SAndroid Build Coastguard Worker  *                        attributes or a keyword string.
2245*5e7646d2SAndroid Build Coastguard Worker  */
2246*5e7646d2SAndroid Build Coastguard Worker 
2247*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - PPD InputSlot or NULL */
_ppdCacheGetInputSlot(_ppd_cache_t * pc,ipp_t * job,const char * keyword)2248*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetInputSlot(
2249*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2250*5e7646d2SAndroid Build Coastguard Worker     ipp_t        *job,			/* I - Job attributes or NULL */
2251*5e7646d2SAndroid Build Coastguard Worker     const char   *keyword)		/* I - Keyword string or NULL */
2252*5e7646d2SAndroid Build Coastguard Worker {
2253*5e7646d2SAndroid Build Coastguard Worker  /*
2254*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2255*5e7646d2SAndroid Build Coastguard Worker   */
2256*5e7646d2SAndroid Build Coastguard Worker 
2257*5e7646d2SAndroid Build Coastguard Worker   if (!pc || pc->num_sources == 0 || (!job && !keyword))
2258*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2259*5e7646d2SAndroid Build Coastguard Worker 
2260*5e7646d2SAndroid Build Coastguard Worker   if (job && !keyword)
2261*5e7646d2SAndroid Build Coastguard Worker   {
2262*5e7646d2SAndroid Build Coastguard Worker    /*
2263*5e7646d2SAndroid Build Coastguard Worker     * Lookup the media-col attribute and any media-source found there...
2264*5e7646d2SAndroid Build Coastguard Worker     */
2265*5e7646d2SAndroid Build Coastguard Worker 
2266*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t	*media_col,	/* media-col attribute */
2267*5e7646d2SAndroid Build Coastguard Worker 			*media_source;	/* media-source attribute */
2268*5e7646d2SAndroid Build Coastguard Worker     pwg_size_t		size;		/* Dimensional size */
2269*5e7646d2SAndroid Build Coastguard Worker     int			margins_set;	/* Were the margins set? */
2270*5e7646d2SAndroid Build Coastguard Worker 
2271*5e7646d2SAndroid Build Coastguard Worker     media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
2272*5e7646d2SAndroid Build Coastguard Worker     if (media_col &&
2273*5e7646d2SAndroid Build Coastguard Worker         (media_source = ippFindAttribute(ippGetCollection(media_col, 0),
2274*5e7646d2SAndroid Build Coastguard Worker                                          "media-source",
2275*5e7646d2SAndroid Build Coastguard Worker 	                                 IPP_TAG_KEYWORD)) != NULL)
2276*5e7646d2SAndroid Build Coastguard Worker     {
2277*5e7646d2SAndroid Build Coastguard Worker      /*
2278*5e7646d2SAndroid Build Coastguard Worker       * Use the media-source value from media-col...
2279*5e7646d2SAndroid Build Coastguard Worker       */
2280*5e7646d2SAndroid Build Coastguard Worker 
2281*5e7646d2SAndroid Build Coastguard Worker       keyword = ippGetString(media_source, 0, NULL);
2282*5e7646d2SAndroid Build Coastguard Worker     }
2283*5e7646d2SAndroid Build Coastguard Worker     else if (pwgInitSize(&size, job, &margins_set))
2284*5e7646d2SAndroid Build Coastguard Worker     {
2285*5e7646d2SAndroid Build Coastguard Worker      /*
2286*5e7646d2SAndroid Build Coastguard Worker       * For media <= 5x7, look for a photo tray...
2287*5e7646d2SAndroid Build Coastguard Worker       */
2288*5e7646d2SAndroid Build Coastguard Worker 
2289*5e7646d2SAndroid Build Coastguard Worker       if (size.width <= (5 * 2540) && size.length <= (7 * 2540))
2290*5e7646d2SAndroid Build Coastguard Worker         keyword = "photo";
2291*5e7646d2SAndroid Build Coastguard Worker     }
2292*5e7646d2SAndroid Build Coastguard Worker   }
2293*5e7646d2SAndroid Build Coastguard Worker 
2294*5e7646d2SAndroid Build Coastguard Worker   if (keyword)
2295*5e7646d2SAndroid Build Coastguard Worker   {
2296*5e7646d2SAndroid Build Coastguard Worker     int	i;				/* Looping var */
2297*5e7646d2SAndroid Build Coastguard Worker 
2298*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < pc->num_sources; i ++)
2299*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(keyword, pc->sources[i].pwg))
2300*5e7646d2SAndroid Build Coastguard Worker         return (pc->sources[i].ppd);
2301*5e7646d2SAndroid Build Coastguard Worker   }
2302*5e7646d2SAndroid Build Coastguard Worker 
2303*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2304*5e7646d2SAndroid Build Coastguard Worker }
2305*5e7646d2SAndroid Build Coastguard Worker 
2306*5e7646d2SAndroid Build Coastguard Worker 
2307*5e7646d2SAndroid Build Coastguard Worker /*
2308*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetMediaType()' - Get the PPD MediaType associated with the job
2309*5e7646d2SAndroid Build Coastguard Worker  *                        attributes or a keyword string.
2310*5e7646d2SAndroid Build Coastguard Worker  */
2311*5e7646d2SAndroid Build Coastguard Worker 
2312*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - PPD MediaType or NULL */
_ppdCacheGetMediaType(_ppd_cache_t * pc,ipp_t * job,const char * keyword)2313*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetMediaType(
2314*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2315*5e7646d2SAndroid Build Coastguard Worker     ipp_t        *job,			/* I - Job attributes or NULL */
2316*5e7646d2SAndroid Build Coastguard Worker     const char   *keyword)		/* I - Keyword string or NULL */
2317*5e7646d2SAndroid Build Coastguard Worker {
2318*5e7646d2SAndroid Build Coastguard Worker  /*
2319*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2320*5e7646d2SAndroid Build Coastguard Worker   */
2321*5e7646d2SAndroid Build Coastguard Worker 
2322*5e7646d2SAndroid Build Coastguard Worker   if (!pc || pc->num_types == 0 || (!job && !keyword))
2323*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2324*5e7646d2SAndroid Build Coastguard Worker 
2325*5e7646d2SAndroid Build Coastguard Worker   if (job && !keyword)
2326*5e7646d2SAndroid Build Coastguard Worker   {
2327*5e7646d2SAndroid Build Coastguard Worker    /*
2328*5e7646d2SAndroid Build Coastguard Worker     * Lookup the media-col attribute and any media-source found there...
2329*5e7646d2SAndroid Build Coastguard Worker     */
2330*5e7646d2SAndroid Build Coastguard Worker 
2331*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t	*media_col,	/* media-col attribute */
2332*5e7646d2SAndroid Build Coastguard Worker 			*media_type;	/* media-type attribute */
2333*5e7646d2SAndroid Build Coastguard Worker 
2334*5e7646d2SAndroid Build Coastguard Worker     media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION);
2335*5e7646d2SAndroid Build Coastguard Worker     if (media_col)
2336*5e7646d2SAndroid Build Coastguard Worker     {
2337*5e7646d2SAndroid Build Coastguard Worker       if ((media_type = ippFindAttribute(media_col->values[0].collection,
2338*5e7646d2SAndroid Build Coastguard Worker                                          "media-type",
2339*5e7646d2SAndroid Build Coastguard Worker 	                                 IPP_TAG_KEYWORD)) == NULL)
2340*5e7646d2SAndroid Build Coastguard Worker 	media_type = ippFindAttribute(media_col->values[0].collection,
2341*5e7646d2SAndroid Build Coastguard Worker 				      "media-type", IPP_TAG_NAME);
2342*5e7646d2SAndroid Build Coastguard Worker 
2343*5e7646d2SAndroid Build Coastguard Worker       if (media_type)
2344*5e7646d2SAndroid Build Coastguard Worker 	keyword = media_type->values[0].string.text;
2345*5e7646d2SAndroid Build Coastguard Worker     }
2346*5e7646d2SAndroid Build Coastguard Worker   }
2347*5e7646d2SAndroid Build Coastguard Worker 
2348*5e7646d2SAndroid Build Coastguard Worker   if (keyword)
2349*5e7646d2SAndroid Build Coastguard Worker   {
2350*5e7646d2SAndroid Build Coastguard Worker     int	i;				/* Looping var */
2351*5e7646d2SAndroid Build Coastguard Worker 
2352*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < pc->num_types; i ++)
2353*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(keyword, pc->types[i].pwg))
2354*5e7646d2SAndroid Build Coastguard Worker         return (pc->types[i].ppd);
2355*5e7646d2SAndroid Build Coastguard Worker   }
2356*5e7646d2SAndroid Build Coastguard Worker 
2357*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2358*5e7646d2SAndroid Build Coastguard Worker }
2359*5e7646d2SAndroid Build Coastguard Worker 
2360*5e7646d2SAndroid Build Coastguard Worker 
2361*5e7646d2SAndroid Build Coastguard Worker /*
2362*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetOutputBin()' - Get the PPD OutputBin associated with the keyword
2363*5e7646d2SAndroid Build Coastguard Worker  *                        string.
2364*5e7646d2SAndroid Build Coastguard Worker  */
2365*5e7646d2SAndroid Build Coastguard Worker 
2366*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - PPD OutputBin or NULL */
_ppdCacheGetOutputBin(_ppd_cache_t * pc,const char * output_bin)2367*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetOutputBin(
2368*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2369*5e7646d2SAndroid Build Coastguard Worker     const char   *output_bin)		/* I - Keyword string */
2370*5e7646d2SAndroid Build Coastguard Worker {
2371*5e7646d2SAndroid Build Coastguard Worker   int	i;				/* Looping var */
2372*5e7646d2SAndroid Build Coastguard Worker 
2373*5e7646d2SAndroid Build Coastguard Worker 
2374*5e7646d2SAndroid Build Coastguard Worker  /*
2375*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2376*5e7646d2SAndroid Build Coastguard Worker   */
2377*5e7646d2SAndroid Build Coastguard Worker 
2378*5e7646d2SAndroid Build Coastguard Worker   if (!pc || !output_bin)
2379*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2380*5e7646d2SAndroid Build Coastguard Worker 
2381*5e7646d2SAndroid Build Coastguard Worker  /*
2382*5e7646d2SAndroid Build Coastguard Worker   * Look up the OutputBin string...
2383*5e7646d2SAndroid Build Coastguard Worker   */
2384*5e7646d2SAndroid Build Coastguard Worker 
2385*5e7646d2SAndroid Build Coastguard Worker 
2386*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < pc->num_bins; i ++)
2387*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(output_bin, pc->bins[i].pwg))
2388*5e7646d2SAndroid Build Coastguard Worker       return (pc->bins[i].ppd);
2389*5e7646d2SAndroid Build Coastguard Worker 
2390*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2391*5e7646d2SAndroid Build Coastguard Worker }
2392*5e7646d2SAndroid Build Coastguard Worker 
2393*5e7646d2SAndroid Build Coastguard Worker 
2394*5e7646d2SAndroid Build Coastguard Worker /*
2395*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetPageSize()' - Get the PPD PageSize associated with the job
2396*5e7646d2SAndroid Build Coastguard Worker  *                       attributes or a keyword string.
2397*5e7646d2SAndroid Build Coastguard Worker  */
2398*5e7646d2SAndroid Build Coastguard Worker 
2399*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - PPD PageSize or NULL */
_ppdCacheGetPageSize(_ppd_cache_t * pc,ipp_t * job,const char * keyword,int * exact)2400*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetPageSize(
2401*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2402*5e7646d2SAndroid Build Coastguard Worker     ipp_t        *job,			/* I - Job attributes or NULL */
2403*5e7646d2SAndroid Build Coastguard Worker     const char   *keyword,		/* I - Keyword string or NULL */
2404*5e7646d2SAndroid Build Coastguard Worker     int          *exact)		/* O - 1 if exact match, 0 otherwise */
2405*5e7646d2SAndroid Build Coastguard Worker {
2406*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2407*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t	*size,			/* Current size */
2408*5e7646d2SAndroid Build Coastguard Worker 		*closest,		/* Closest size */
2409*5e7646d2SAndroid Build Coastguard Worker 		jobsize;		/* Size data from job */
2410*5e7646d2SAndroid Build Coastguard Worker   int		margins_set,		/* Were the margins set? */
2411*5e7646d2SAndroid Build Coastguard Worker 		dwidth,			/* Difference in width */
2412*5e7646d2SAndroid Build Coastguard Worker 		dlength,		/* Difference in length */
2413*5e7646d2SAndroid Build Coastguard Worker 		dleft,			/* Difference in left margins */
2414*5e7646d2SAndroid Build Coastguard Worker 		dright,			/* Difference in right margins */
2415*5e7646d2SAndroid Build Coastguard Worker 		dbottom,		/* Difference in bottom margins */
2416*5e7646d2SAndroid Build Coastguard Worker 		dtop,			/* Difference in top margins */
2417*5e7646d2SAndroid Build Coastguard Worker 		dmin,			/* Minimum difference */
2418*5e7646d2SAndroid Build Coastguard Worker 		dclosest;		/* Closest difference */
2419*5e7646d2SAndroid Build Coastguard Worker   const char	*ppd_name;		/* PPD media name */
2420*5e7646d2SAndroid Build Coastguard Worker 
2421*5e7646d2SAndroid Build Coastguard Worker 
2422*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_ppdCacheGetPageSize(pc=%p, job=%p, keyword=\"%s\", exact=%p)",
2423*5e7646d2SAndroid Build Coastguard Worker 	        pc, job, keyword, exact));
2424*5e7646d2SAndroid Build Coastguard Worker 
2425*5e7646d2SAndroid Build Coastguard Worker  /*
2426*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2427*5e7646d2SAndroid Build Coastguard Worker   */
2428*5e7646d2SAndroid Build Coastguard Worker 
2429*5e7646d2SAndroid Build Coastguard Worker   if (!pc || (!job && !keyword))
2430*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2431*5e7646d2SAndroid Build Coastguard Worker 
2432*5e7646d2SAndroid Build Coastguard Worker   if (exact)
2433*5e7646d2SAndroid Build Coastguard Worker     *exact = 0;
2434*5e7646d2SAndroid Build Coastguard Worker 
2435*5e7646d2SAndroid Build Coastguard Worker   ppd_name = keyword;
2436*5e7646d2SAndroid Build Coastguard Worker 
2437*5e7646d2SAndroid Build Coastguard Worker   if (job)
2438*5e7646d2SAndroid Build Coastguard Worker   {
2439*5e7646d2SAndroid Build Coastguard Worker    /*
2440*5e7646d2SAndroid Build Coastguard Worker     * Try getting the PPD media name from the job attributes...
2441*5e7646d2SAndroid Build Coastguard Worker     */
2442*5e7646d2SAndroid Build Coastguard Worker 
2443*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t	*attr;		/* Job attribute */
2444*5e7646d2SAndroid Build Coastguard Worker 
2445*5e7646d2SAndroid Build Coastguard Worker     if ((attr = ippFindAttribute(job, "PageSize", IPP_TAG_ZERO)) == NULL)
2446*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ippFindAttribute(job, "PageRegion", IPP_TAG_ZERO)) == NULL)
2447*5e7646d2SAndroid Build Coastguard Worker         attr = ippFindAttribute(job, "media", IPP_TAG_ZERO);
2448*5e7646d2SAndroid Build Coastguard Worker 
2449*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
2450*5e7646d2SAndroid Build Coastguard Worker     if (attr)
2451*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("1_ppdCacheGetPageSize: Found attribute %s (%s)",
2452*5e7646d2SAndroid Build Coastguard Worker                     attr->name, ippTagString(attr->value_tag)));
2453*5e7646d2SAndroid Build Coastguard Worker     else
2454*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("1_ppdCacheGetPageSize: Did not find media attribute.");
2455*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
2456*5e7646d2SAndroid Build Coastguard Worker 
2457*5e7646d2SAndroid Build Coastguard Worker     if (attr && (attr->value_tag == IPP_TAG_NAME ||
2458*5e7646d2SAndroid Build Coastguard Worker                  attr->value_tag == IPP_TAG_KEYWORD))
2459*5e7646d2SAndroid Build Coastguard Worker       ppd_name = attr->values[0].string.text;
2460*5e7646d2SAndroid Build Coastguard Worker   }
2461*5e7646d2SAndroid Build Coastguard Worker 
2462*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_ppdCacheGetPageSize: ppd_name=\"%s\"", ppd_name));
2463*5e7646d2SAndroid Build Coastguard Worker 
2464*5e7646d2SAndroid Build Coastguard Worker   if (ppd_name)
2465*5e7646d2SAndroid Build Coastguard Worker   {
2466*5e7646d2SAndroid Build Coastguard Worker    /*
2467*5e7646d2SAndroid Build Coastguard Worker     * Try looking up the named PPD size first...
2468*5e7646d2SAndroid Build Coastguard Worker     */
2469*5e7646d2SAndroid Build Coastguard Worker 
2470*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
2471*5e7646d2SAndroid Build Coastguard Worker     {
2472*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("2_ppdCacheGetPageSize: size[%d]=[\"%s\" \"%s\"]",
2473*5e7646d2SAndroid Build Coastguard Worker                     (int)(size - pc->sizes), size->map.pwg, size->map.ppd));
2474*5e7646d2SAndroid Build Coastguard Worker 
2475*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(ppd_name, size->map.ppd) ||
2476*5e7646d2SAndroid Build Coastguard Worker           !_cups_strcasecmp(ppd_name, size->map.pwg))
2477*5e7646d2SAndroid Build Coastguard Worker       {
2478*5e7646d2SAndroid Build Coastguard Worker 	if (exact)
2479*5e7646d2SAndroid Build Coastguard Worker 	  *exact = 1;
2480*5e7646d2SAndroid Build Coastguard Worker 
2481*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", ppd_name));
2482*5e7646d2SAndroid Build Coastguard Worker 
2483*5e7646d2SAndroid Build Coastguard Worker         return (size->map.ppd);
2484*5e7646d2SAndroid Build Coastguard Worker       }
2485*5e7646d2SAndroid Build Coastguard Worker     }
2486*5e7646d2SAndroid Build Coastguard Worker   }
2487*5e7646d2SAndroid Build Coastguard Worker 
2488*5e7646d2SAndroid Build Coastguard Worker   if (job && !keyword)
2489*5e7646d2SAndroid Build Coastguard Worker   {
2490*5e7646d2SAndroid Build Coastguard Worker    /*
2491*5e7646d2SAndroid Build Coastguard Worker     * Get the size using media-col or media, with the preference being
2492*5e7646d2SAndroid Build Coastguard Worker     * media-col.
2493*5e7646d2SAndroid Build Coastguard Worker     */
2494*5e7646d2SAndroid Build Coastguard Worker 
2495*5e7646d2SAndroid Build Coastguard Worker     if (!pwgInitSize(&jobsize, job, &margins_set))
2496*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
2497*5e7646d2SAndroid Build Coastguard Worker   }
2498*5e7646d2SAndroid Build Coastguard Worker   else
2499*5e7646d2SAndroid Build Coastguard Worker   {
2500*5e7646d2SAndroid Build Coastguard Worker    /*
2501*5e7646d2SAndroid Build Coastguard Worker     * Get the size using a media keyword...
2502*5e7646d2SAndroid Build Coastguard Worker     */
2503*5e7646d2SAndroid Build Coastguard Worker 
2504*5e7646d2SAndroid Build Coastguard Worker     pwg_media_t	*media;		/* Media definition */
2505*5e7646d2SAndroid Build Coastguard Worker 
2506*5e7646d2SAndroid Build Coastguard Worker 
2507*5e7646d2SAndroid Build Coastguard Worker     if ((media = pwgMediaForPWG(keyword)) == NULL)
2508*5e7646d2SAndroid Build Coastguard Worker       if ((media = pwgMediaForLegacy(keyword)) == NULL)
2509*5e7646d2SAndroid Build Coastguard Worker         if ((media = pwgMediaForPPD(keyword)) == NULL)
2510*5e7646d2SAndroid Build Coastguard Worker 	  return (NULL);
2511*5e7646d2SAndroid Build Coastguard Worker 
2512*5e7646d2SAndroid Build Coastguard Worker     jobsize.width  = media->width;
2513*5e7646d2SAndroid Build Coastguard Worker     jobsize.length = media->length;
2514*5e7646d2SAndroid Build Coastguard Worker     margins_set    = 0;
2515*5e7646d2SAndroid Build Coastguard Worker   }
2516*5e7646d2SAndroid Build Coastguard Worker 
2517*5e7646d2SAndroid Build Coastguard Worker  /*
2518*5e7646d2SAndroid Build Coastguard Worker   * Now that we have the dimensions and possibly the margins, look at the
2519*5e7646d2SAndroid Build Coastguard Worker   * available sizes and find the match...
2520*5e7646d2SAndroid Build Coastguard Worker   */
2521*5e7646d2SAndroid Build Coastguard Worker 
2522*5e7646d2SAndroid Build Coastguard Worker   closest  = NULL;
2523*5e7646d2SAndroid Build Coastguard Worker   dclosest = 999999999;
2524*5e7646d2SAndroid Build Coastguard Worker 
2525*5e7646d2SAndroid Build Coastguard Worker   if (!ppd_name || _cups_strncasecmp(ppd_name, "Custom.", 7) ||
2526*5e7646d2SAndroid Build Coastguard Worker       _cups_strncasecmp(ppd_name, "custom_", 7))
2527*5e7646d2SAndroid Build Coastguard Worker   {
2528*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
2529*5e7646d2SAndroid Build Coastguard Worker     {
2530*5e7646d2SAndroid Build Coastguard Worker      /*
2531*5e7646d2SAndroid Build Coastguard Worker       * Adobe uses a size matching algorithm with an epsilon of 5 points, which
2532*5e7646d2SAndroid Build Coastguard Worker       * is just about 176/2540ths...
2533*5e7646d2SAndroid Build Coastguard Worker       */
2534*5e7646d2SAndroid Build Coastguard Worker 
2535*5e7646d2SAndroid Build Coastguard Worker       dwidth  = size->width - jobsize.width;
2536*5e7646d2SAndroid Build Coastguard Worker       dlength = size->length - jobsize.length;
2537*5e7646d2SAndroid Build Coastguard Worker 
2538*5e7646d2SAndroid Build Coastguard Worker       if (dwidth <= -176 || dwidth >= 176 || dlength <= -176 || dlength >= 176)
2539*5e7646d2SAndroid Build Coastguard Worker 	continue;
2540*5e7646d2SAndroid Build Coastguard Worker 
2541*5e7646d2SAndroid Build Coastguard Worker       if (margins_set)
2542*5e7646d2SAndroid Build Coastguard Worker       {
2543*5e7646d2SAndroid Build Coastguard Worker        /*
2544*5e7646d2SAndroid Build Coastguard Worker 	* Use a tighter epsilon of 1 point (35/2540ths) for margins...
2545*5e7646d2SAndroid Build Coastguard Worker 	*/
2546*5e7646d2SAndroid Build Coastguard Worker 
2547*5e7646d2SAndroid Build Coastguard Worker 	dleft   = size->left - jobsize.left;
2548*5e7646d2SAndroid Build Coastguard Worker 	dright  = size->right - jobsize.right;
2549*5e7646d2SAndroid Build Coastguard Worker 	dtop    = size->top - jobsize.top;
2550*5e7646d2SAndroid Build Coastguard Worker 	dbottom = size->bottom - jobsize.bottom;
2551*5e7646d2SAndroid Build Coastguard Worker 
2552*5e7646d2SAndroid Build Coastguard Worker 	if (dleft <= -35 || dleft >= 35 || dright <= -35 || dright >= 35 ||
2553*5e7646d2SAndroid Build Coastguard Worker 	    dtop <= -35 || dtop >= 35 || dbottom <= -35 || dbottom >= 35)
2554*5e7646d2SAndroid Build Coastguard Worker 	{
2555*5e7646d2SAndroid Build Coastguard Worker 	  dleft   = dleft < 0 ? -dleft : dleft;
2556*5e7646d2SAndroid Build Coastguard Worker 	  dright  = dright < 0 ? -dright : dright;
2557*5e7646d2SAndroid Build Coastguard Worker 	  dbottom = dbottom < 0 ? -dbottom : dbottom;
2558*5e7646d2SAndroid Build Coastguard Worker 	  dtop    = dtop < 0 ? -dtop : dtop;
2559*5e7646d2SAndroid Build Coastguard Worker 	  dmin    = dleft + dright + dbottom + dtop;
2560*5e7646d2SAndroid Build Coastguard Worker 
2561*5e7646d2SAndroid Build Coastguard Worker 	  if (dmin < dclosest)
2562*5e7646d2SAndroid Build Coastguard Worker 	  {
2563*5e7646d2SAndroid Build Coastguard Worker 	    dclosest = dmin;
2564*5e7646d2SAndroid Build Coastguard Worker 	    closest  = size;
2565*5e7646d2SAndroid Build Coastguard Worker 	  }
2566*5e7646d2SAndroid Build Coastguard Worker 
2567*5e7646d2SAndroid Build Coastguard Worker 	  continue;
2568*5e7646d2SAndroid Build Coastguard Worker 	}
2569*5e7646d2SAndroid Build Coastguard Worker       }
2570*5e7646d2SAndroid Build Coastguard Worker 
2571*5e7646d2SAndroid Build Coastguard Worker       if (exact)
2572*5e7646d2SAndroid Build Coastguard Worker 	*exact = 1;
2573*5e7646d2SAndroid Build Coastguard Worker 
2574*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", size->map.ppd));
2575*5e7646d2SAndroid Build Coastguard Worker 
2576*5e7646d2SAndroid Build Coastguard Worker       return (size->map.ppd);
2577*5e7646d2SAndroid Build Coastguard Worker     }
2578*5e7646d2SAndroid Build Coastguard Worker   }
2579*5e7646d2SAndroid Build Coastguard Worker 
2580*5e7646d2SAndroid Build Coastguard Worker   if (closest)
2581*5e7646d2SAndroid Build Coastguard Worker   {
2582*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (closest)",
2583*5e7646d2SAndroid Build Coastguard Worker                   closest->map.ppd));
2584*5e7646d2SAndroid Build Coastguard Worker 
2585*5e7646d2SAndroid Build Coastguard Worker     return (closest->map.ppd);
2586*5e7646d2SAndroid Build Coastguard Worker   }
2587*5e7646d2SAndroid Build Coastguard Worker 
2588*5e7646d2SAndroid Build Coastguard Worker  /*
2589*5e7646d2SAndroid Build Coastguard Worker   * If we get here we need to check for custom page size support...
2590*5e7646d2SAndroid Build Coastguard Worker   */
2591*5e7646d2SAndroid Build Coastguard Worker 
2592*5e7646d2SAndroid Build Coastguard Worker   if (jobsize.width >= pc->custom_min_width &&
2593*5e7646d2SAndroid Build Coastguard Worker       jobsize.width <= pc->custom_max_width &&
2594*5e7646d2SAndroid Build Coastguard Worker       jobsize.length >= pc->custom_min_length &&
2595*5e7646d2SAndroid Build Coastguard Worker       jobsize.length <= pc->custom_max_length)
2596*5e7646d2SAndroid Build Coastguard Worker   {
2597*5e7646d2SAndroid Build Coastguard Worker    /*
2598*5e7646d2SAndroid Build Coastguard Worker     * In range, format as Custom.WWWWxLLLL (points).
2599*5e7646d2SAndroid Build Coastguard Worker     */
2600*5e7646d2SAndroid Build Coastguard Worker 
2601*5e7646d2SAndroid Build Coastguard Worker     snprintf(pc->custom_ppd_size, sizeof(pc->custom_ppd_size), "Custom.%dx%d",
2602*5e7646d2SAndroid Build Coastguard Worker              (int)PWG_TO_POINTS(jobsize.width), (int)PWG_TO_POINTS(jobsize.length));
2603*5e7646d2SAndroid Build Coastguard Worker 
2604*5e7646d2SAndroid Build Coastguard Worker     if (margins_set && exact)
2605*5e7646d2SAndroid Build Coastguard Worker     {
2606*5e7646d2SAndroid Build Coastguard Worker       dleft   = pc->custom_size.left - jobsize.left;
2607*5e7646d2SAndroid Build Coastguard Worker       dright  = pc->custom_size.right - jobsize.right;
2608*5e7646d2SAndroid Build Coastguard Worker       dtop    = pc->custom_size.top - jobsize.top;
2609*5e7646d2SAndroid Build Coastguard Worker       dbottom = pc->custom_size.bottom - jobsize.bottom;
2610*5e7646d2SAndroid Build Coastguard Worker 
2611*5e7646d2SAndroid Build Coastguard Worker       if (dleft > -35 && dleft < 35 && dright > -35 && dright < 35 &&
2612*5e7646d2SAndroid Build Coastguard Worker           dtop > -35 && dtop < 35 && dbottom > -35 && dbottom < 35)
2613*5e7646d2SAndroid Build Coastguard Worker 	*exact = 1;
2614*5e7646d2SAndroid Build Coastguard Worker     }
2615*5e7646d2SAndroid Build Coastguard Worker     else if (exact)
2616*5e7646d2SAndroid Build Coastguard Worker       *exact = 1;
2617*5e7646d2SAndroid Build Coastguard Worker 
2618*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (custom)",
2619*5e7646d2SAndroid Build Coastguard Worker                   pc->custom_ppd_size));
2620*5e7646d2SAndroid Build Coastguard Worker 
2621*5e7646d2SAndroid Build Coastguard Worker     return (pc->custom_ppd_size);
2622*5e7646d2SAndroid Build Coastguard Worker   }
2623*5e7646d2SAndroid Build Coastguard Worker 
2624*5e7646d2SAndroid Build Coastguard Worker  /*
2625*5e7646d2SAndroid Build Coastguard Worker   * No custom page size support or the size is out of range - return NULL.
2626*5e7646d2SAndroid Build Coastguard Worker   */
2627*5e7646d2SAndroid Build Coastguard Worker 
2628*5e7646d2SAndroid Build Coastguard Worker   DEBUG_puts("1_ppdCacheGetPageSize: Returning NULL");
2629*5e7646d2SAndroid Build Coastguard Worker 
2630*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2631*5e7646d2SAndroid Build Coastguard Worker }
2632*5e7646d2SAndroid Build Coastguard Worker 
2633*5e7646d2SAndroid Build Coastguard Worker 
2634*5e7646d2SAndroid Build Coastguard Worker /*
2635*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetSize()' - Get the PWG size associated with a PPD PageSize.
2636*5e7646d2SAndroid Build Coastguard Worker  */
2637*5e7646d2SAndroid Build Coastguard Worker 
2638*5e7646d2SAndroid Build Coastguard Worker pwg_size_t *				/* O - PWG size or NULL */
_ppdCacheGetSize(_ppd_cache_t * pc,const char * page_size)2639*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetSize(
2640*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2641*5e7646d2SAndroid Build Coastguard Worker     const char   *page_size)		/* I - PPD PageSize */
2642*5e7646d2SAndroid Build Coastguard Worker {
2643*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2644*5e7646d2SAndroid Build Coastguard Worker   pwg_media_t	*media;			/* Media */
2645*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t	*size;			/* Current size */
2646*5e7646d2SAndroid Build Coastguard Worker 
2647*5e7646d2SAndroid Build Coastguard Worker 
2648*5e7646d2SAndroid Build Coastguard Worker  /*
2649*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2650*5e7646d2SAndroid Build Coastguard Worker   */
2651*5e7646d2SAndroid Build Coastguard Worker 
2652*5e7646d2SAndroid Build Coastguard Worker   if (!pc || !page_size)
2653*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2654*5e7646d2SAndroid Build Coastguard Worker 
2655*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strncasecmp(page_size, "Custom.", 7))
2656*5e7646d2SAndroid Build Coastguard Worker   {
2657*5e7646d2SAndroid Build Coastguard Worker    /*
2658*5e7646d2SAndroid Build Coastguard Worker     * Custom size; size name can be one of the following:
2659*5e7646d2SAndroid Build Coastguard Worker     *
2660*5e7646d2SAndroid Build Coastguard Worker     *    Custom.WIDTHxLENGTHin    - Size in inches
2661*5e7646d2SAndroid Build Coastguard Worker     *    Custom.WIDTHxLENGTHft    - Size in feet
2662*5e7646d2SAndroid Build Coastguard Worker     *    Custom.WIDTHxLENGTHcm    - Size in centimeters
2663*5e7646d2SAndroid Build Coastguard Worker     *    Custom.WIDTHxLENGTHmm    - Size in millimeters
2664*5e7646d2SAndroid Build Coastguard Worker     *    Custom.WIDTHxLENGTHm     - Size in meters
2665*5e7646d2SAndroid Build Coastguard Worker     *    Custom.WIDTHxLENGTH[pt]  - Size in points
2666*5e7646d2SAndroid Build Coastguard Worker     */
2667*5e7646d2SAndroid Build Coastguard Worker 
2668*5e7646d2SAndroid Build Coastguard Worker     double		w, l;		/* Width and length of page */
2669*5e7646d2SAndroid Build Coastguard Worker     char		*ptr;		/* Pointer into PageSize */
2670*5e7646d2SAndroid Build Coastguard Worker     struct lconv	*loc;		/* Locale data */
2671*5e7646d2SAndroid Build Coastguard Worker 
2672*5e7646d2SAndroid Build Coastguard Worker     loc = localeconv();
2673*5e7646d2SAndroid Build Coastguard Worker     w   = (float)_cupsStrScand(page_size + 7, &ptr, loc);
2674*5e7646d2SAndroid Build Coastguard Worker     if (!ptr || *ptr != 'x')
2675*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
2676*5e7646d2SAndroid Build Coastguard Worker 
2677*5e7646d2SAndroid Build Coastguard Worker     l = (float)_cupsStrScand(ptr + 1, &ptr, loc);
2678*5e7646d2SAndroid Build Coastguard Worker     if (!ptr)
2679*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
2680*5e7646d2SAndroid Build Coastguard Worker 
2681*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(ptr, "in"))
2682*5e7646d2SAndroid Build Coastguard Worker     {
2683*5e7646d2SAndroid Build Coastguard Worker       w *= 2540.0;
2684*5e7646d2SAndroid Build Coastguard Worker       l *= 2540.0;
2685*5e7646d2SAndroid Build Coastguard Worker     }
2686*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(ptr, "ft"))
2687*5e7646d2SAndroid Build Coastguard Worker     {
2688*5e7646d2SAndroid Build Coastguard Worker       w *= 12.0 * 2540.0;
2689*5e7646d2SAndroid Build Coastguard Worker       l *= 12.0 * 2540.0;
2690*5e7646d2SAndroid Build Coastguard Worker     }
2691*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(ptr, "mm"))
2692*5e7646d2SAndroid Build Coastguard Worker     {
2693*5e7646d2SAndroid Build Coastguard Worker       w *= 100.0;
2694*5e7646d2SAndroid Build Coastguard Worker       l *= 100.0;
2695*5e7646d2SAndroid Build Coastguard Worker     }
2696*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(ptr, "cm"))
2697*5e7646d2SAndroid Build Coastguard Worker     {
2698*5e7646d2SAndroid Build Coastguard Worker       w *= 1000.0;
2699*5e7646d2SAndroid Build Coastguard Worker       l *= 1000.0;
2700*5e7646d2SAndroid Build Coastguard Worker     }
2701*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(ptr, "m"))
2702*5e7646d2SAndroid Build Coastguard Worker     {
2703*5e7646d2SAndroid Build Coastguard Worker       w *= 100000.0;
2704*5e7646d2SAndroid Build Coastguard Worker       l *= 100000.0;
2705*5e7646d2SAndroid Build Coastguard Worker     }
2706*5e7646d2SAndroid Build Coastguard Worker     else
2707*5e7646d2SAndroid Build Coastguard Worker     {
2708*5e7646d2SAndroid Build Coastguard Worker       w *= 2540.0 / 72.0;
2709*5e7646d2SAndroid Build Coastguard Worker       l *= 2540.0 / 72.0;
2710*5e7646d2SAndroid Build Coastguard Worker     }
2711*5e7646d2SAndroid Build Coastguard Worker 
2712*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.width  = (int)w;
2713*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.length = (int)l;
2714*5e7646d2SAndroid Build Coastguard Worker 
2715*5e7646d2SAndroid Build Coastguard Worker     return (&(pc->custom_size));
2716*5e7646d2SAndroid Build Coastguard Worker   }
2717*5e7646d2SAndroid Build Coastguard Worker 
2718*5e7646d2SAndroid Build Coastguard Worker  /*
2719*5e7646d2SAndroid Build Coastguard Worker   * Not a custom size - look it up...
2720*5e7646d2SAndroid Build Coastguard Worker   */
2721*5e7646d2SAndroid Build Coastguard Worker 
2722*5e7646d2SAndroid Build Coastguard Worker   for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
2723*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(page_size, size->map.ppd) ||
2724*5e7646d2SAndroid Build Coastguard Worker         !_cups_strcasecmp(page_size, size->map.pwg))
2725*5e7646d2SAndroid Build Coastguard Worker       return (size);
2726*5e7646d2SAndroid Build Coastguard Worker 
2727*5e7646d2SAndroid Build Coastguard Worker  /*
2728*5e7646d2SAndroid Build Coastguard Worker   * Look up standard sizes...
2729*5e7646d2SAndroid Build Coastguard Worker   */
2730*5e7646d2SAndroid Build Coastguard Worker 
2731*5e7646d2SAndroid Build Coastguard Worker   if ((media = pwgMediaForPPD(page_size)) == NULL)
2732*5e7646d2SAndroid Build Coastguard Worker     if ((media = pwgMediaForLegacy(page_size)) == NULL)
2733*5e7646d2SAndroid Build Coastguard Worker       media = pwgMediaForPWG(page_size);
2734*5e7646d2SAndroid Build Coastguard Worker 
2735*5e7646d2SAndroid Build Coastguard Worker   if (media)
2736*5e7646d2SAndroid Build Coastguard Worker   {
2737*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.width  = media->width;
2738*5e7646d2SAndroid Build Coastguard Worker     pc->custom_size.length = media->length;
2739*5e7646d2SAndroid Build Coastguard Worker 
2740*5e7646d2SAndroid Build Coastguard Worker     return (&(pc->custom_size));
2741*5e7646d2SAndroid Build Coastguard Worker   }
2742*5e7646d2SAndroid Build Coastguard Worker 
2743*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2744*5e7646d2SAndroid Build Coastguard Worker }
2745*5e7646d2SAndroid Build Coastguard Worker 
2746*5e7646d2SAndroid Build Coastguard Worker 
2747*5e7646d2SAndroid Build Coastguard Worker /*
2748*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetSource()' - Get the PWG media-source associated with a PPD
2749*5e7646d2SAndroid Build Coastguard Worker  *                          InputSlot.
2750*5e7646d2SAndroid Build Coastguard Worker  */
2751*5e7646d2SAndroid Build Coastguard Worker 
2752*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - PWG media-source keyword */
_ppdCacheGetSource(_ppd_cache_t * pc,const char * input_slot)2753*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetSource(
2754*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2755*5e7646d2SAndroid Build Coastguard Worker     const char   *input_slot)		/* I - PPD InputSlot */
2756*5e7646d2SAndroid Build Coastguard Worker {
2757*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2758*5e7646d2SAndroid Build Coastguard Worker   pwg_map_t	*source;		/* Current source */
2759*5e7646d2SAndroid Build Coastguard Worker 
2760*5e7646d2SAndroid Build Coastguard Worker 
2761*5e7646d2SAndroid Build Coastguard Worker  /*
2762*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2763*5e7646d2SAndroid Build Coastguard Worker   */
2764*5e7646d2SAndroid Build Coastguard Worker 
2765*5e7646d2SAndroid Build Coastguard Worker   if (!pc || !input_slot)
2766*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2767*5e7646d2SAndroid Build Coastguard Worker 
2768*5e7646d2SAndroid Build Coastguard Worker   for (i = pc->num_sources, source = pc->sources; i > 0; i --, source ++)
2769*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(input_slot, source->ppd))
2770*5e7646d2SAndroid Build Coastguard Worker       return (source->pwg);
2771*5e7646d2SAndroid Build Coastguard Worker 
2772*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2773*5e7646d2SAndroid Build Coastguard Worker }
2774*5e7646d2SAndroid Build Coastguard Worker 
2775*5e7646d2SAndroid Build Coastguard Worker 
2776*5e7646d2SAndroid Build Coastguard Worker /*
2777*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheGetType()' - Get the PWG media-type associated with a PPD
2778*5e7646d2SAndroid Build Coastguard Worker  *                        MediaType.
2779*5e7646d2SAndroid Build Coastguard Worker  */
2780*5e7646d2SAndroid Build Coastguard Worker 
2781*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - PWG media-type keyword */
_ppdCacheGetType(_ppd_cache_t * pc,const char * media_type)2782*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetType(
2783*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2784*5e7646d2SAndroid Build Coastguard Worker     const char   *media_type)		/* I - PPD MediaType */
2785*5e7646d2SAndroid Build Coastguard Worker {
2786*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
2787*5e7646d2SAndroid Build Coastguard Worker   pwg_map_t	*type;			/* Current type */
2788*5e7646d2SAndroid Build Coastguard Worker 
2789*5e7646d2SAndroid Build Coastguard Worker 
2790*5e7646d2SAndroid Build Coastguard Worker  /*
2791*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2792*5e7646d2SAndroid Build Coastguard Worker   */
2793*5e7646d2SAndroid Build Coastguard Worker 
2794*5e7646d2SAndroid Build Coastguard Worker   if (!pc || !media_type)
2795*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2796*5e7646d2SAndroid Build Coastguard Worker 
2797*5e7646d2SAndroid Build Coastguard Worker   for (i = pc->num_types, type = pc->types; i > 0; i --, type ++)
2798*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(media_type, type->ppd))
2799*5e7646d2SAndroid Build Coastguard Worker       return (type->pwg);
2800*5e7646d2SAndroid Build Coastguard Worker 
2801*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2802*5e7646d2SAndroid Build Coastguard Worker }
2803*5e7646d2SAndroid Build Coastguard Worker 
2804*5e7646d2SAndroid Build Coastguard Worker 
2805*5e7646d2SAndroid Build Coastguard Worker /*
2806*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCacheWriteFile()' - Write PWG mapping data to a file.
2807*5e7646d2SAndroid Build Coastguard Worker  */
2808*5e7646d2SAndroid Build Coastguard Worker 
2809*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
_ppdCacheWriteFile(_ppd_cache_t * pc,const char * filename,ipp_t * attrs)2810*5e7646d2SAndroid Build Coastguard Worker _ppdCacheWriteFile(
2811*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t *pc,			/* I - PPD cache and mapping data */
2812*5e7646d2SAndroid Build Coastguard Worker     const char   *filename,		/* I - File to write */
2813*5e7646d2SAndroid Build Coastguard Worker     ipp_t        *attrs)		/* I - Attributes to write, if any */
2814*5e7646d2SAndroid Build Coastguard Worker {
2815*5e7646d2SAndroid Build Coastguard Worker   int			i, j, k;	/* Looping vars */
2816*5e7646d2SAndroid Build Coastguard Worker   cups_file_t		*fp;		/* Output file */
2817*5e7646d2SAndroid Build Coastguard Worker   pwg_size_t		*size;		/* Current size */
2818*5e7646d2SAndroid Build Coastguard Worker   pwg_map_t		*map;		/* Current map */
2819*5e7646d2SAndroid Build Coastguard Worker   _pwg_finishings_t	*f;		/* Current finishing option */
2820*5e7646d2SAndroid Build Coastguard Worker   cups_option_t		*option;	/* Current option */
2821*5e7646d2SAndroid Build Coastguard Worker   const char		*value;		/* String value */
2822*5e7646d2SAndroid Build Coastguard Worker   char			newfile[1024];	/* New filename */
2823*5e7646d2SAndroid Build Coastguard Worker 
2824*5e7646d2SAndroid Build Coastguard Worker 
2825*5e7646d2SAndroid Build Coastguard Worker  /*
2826*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
2827*5e7646d2SAndroid Build Coastguard Worker   */
2828*5e7646d2SAndroid Build Coastguard Worker 
2829*5e7646d2SAndroid Build Coastguard Worker   if (!pc || !filename)
2830*5e7646d2SAndroid Build Coastguard Worker   {
2831*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
2832*5e7646d2SAndroid Build Coastguard Worker     return (0);
2833*5e7646d2SAndroid Build Coastguard Worker   }
2834*5e7646d2SAndroid Build Coastguard Worker 
2835*5e7646d2SAndroid Build Coastguard Worker  /*
2836*5e7646d2SAndroid Build Coastguard Worker   * Open the file and write with compression...
2837*5e7646d2SAndroid Build Coastguard Worker   */
2838*5e7646d2SAndroid Build Coastguard Worker 
2839*5e7646d2SAndroid Build Coastguard Worker   snprintf(newfile, sizeof(newfile), "%s.N", filename);
2840*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(newfile, "w9")) == NULL)
2841*5e7646d2SAndroid Build Coastguard Worker   {
2842*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
2843*5e7646d2SAndroid Build Coastguard Worker     return (0);
2844*5e7646d2SAndroid Build Coastguard Worker   }
2845*5e7646d2SAndroid Build Coastguard Worker 
2846*5e7646d2SAndroid Build Coastguard Worker  /*
2847*5e7646d2SAndroid Build Coastguard Worker   * Standard header...
2848*5e7646d2SAndroid Build Coastguard Worker   */
2849*5e7646d2SAndroid Build Coastguard Worker 
2850*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "#CUPS-PPD-CACHE-%d\n", _PPD_CACHE_VERSION);
2851*5e7646d2SAndroid Build Coastguard Worker 
2852*5e7646d2SAndroid Build Coastguard Worker  /*
2853*5e7646d2SAndroid Build Coastguard Worker   * Output bins...
2854*5e7646d2SAndroid Build Coastguard Worker   */
2855*5e7646d2SAndroid Build Coastguard Worker 
2856*5e7646d2SAndroid Build Coastguard Worker   if (pc->num_bins > 0)
2857*5e7646d2SAndroid Build Coastguard Worker   {
2858*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "NumBins %d\n", pc->num_bins);
2859*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++)
2860*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "Bin %s %s\n", map->pwg, map->ppd);
2861*5e7646d2SAndroid Build Coastguard Worker   }
2862*5e7646d2SAndroid Build Coastguard Worker 
2863*5e7646d2SAndroid Build Coastguard Worker  /*
2864*5e7646d2SAndroid Build Coastguard Worker   * Media sizes...
2865*5e7646d2SAndroid Build Coastguard Worker   */
2866*5e7646d2SAndroid Build Coastguard Worker 
2867*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "NumSizes %d\n", pc->num_sizes);
2868*5e7646d2SAndroid Build Coastguard Worker   for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
2869*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Size %s %s %d %d %d %d %d %d\n", size->map.pwg,
2870*5e7646d2SAndroid Build Coastguard Worker 		   size->map.ppd, size->width, size->length, size->left,
2871*5e7646d2SAndroid Build Coastguard Worker 		   size->bottom, size->right, size->top);
2872*5e7646d2SAndroid Build Coastguard Worker   if (pc->custom_max_width > 0)
2873*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "CustomSize %d %d %d %d %d %d %d %d\n",
2874*5e7646d2SAndroid Build Coastguard Worker                    pc->custom_max_width, pc->custom_max_length,
2875*5e7646d2SAndroid Build Coastguard Worker 		   pc->custom_min_width, pc->custom_min_length,
2876*5e7646d2SAndroid Build Coastguard Worker 		   pc->custom_size.left, pc->custom_size.bottom,
2877*5e7646d2SAndroid Build Coastguard Worker 		   pc->custom_size.right, pc->custom_size.top);
2878*5e7646d2SAndroid Build Coastguard Worker 
2879*5e7646d2SAndroid Build Coastguard Worker  /*
2880*5e7646d2SAndroid Build Coastguard Worker   * Media sources...
2881*5e7646d2SAndroid Build Coastguard Worker   */
2882*5e7646d2SAndroid Build Coastguard Worker 
2883*5e7646d2SAndroid Build Coastguard Worker   if (pc->source_option)
2884*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "SourceOption %s\n", pc->source_option);
2885*5e7646d2SAndroid Build Coastguard Worker 
2886*5e7646d2SAndroid Build Coastguard Worker   if (pc->num_sources > 0)
2887*5e7646d2SAndroid Build Coastguard Worker   {
2888*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "NumSources %d\n", pc->num_sources);
2889*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++)
2890*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "Source %s %s\n", map->pwg, map->ppd);
2891*5e7646d2SAndroid Build Coastguard Worker   }
2892*5e7646d2SAndroid Build Coastguard Worker 
2893*5e7646d2SAndroid Build Coastguard Worker  /*
2894*5e7646d2SAndroid Build Coastguard Worker   * Media types...
2895*5e7646d2SAndroid Build Coastguard Worker   */
2896*5e7646d2SAndroid Build Coastguard Worker 
2897*5e7646d2SAndroid Build Coastguard Worker   if (pc->num_types > 0)
2898*5e7646d2SAndroid Build Coastguard Worker   {
2899*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "NumTypes %d\n", pc->num_types);
2900*5e7646d2SAndroid Build Coastguard Worker     for (i = pc->num_types, map = pc->types; i > 0; i --, map ++)
2901*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "Type %s %s\n", map->pwg, map->ppd);
2902*5e7646d2SAndroid Build Coastguard Worker   }
2903*5e7646d2SAndroid Build Coastguard Worker 
2904*5e7646d2SAndroid Build Coastguard Worker  /*
2905*5e7646d2SAndroid Build Coastguard Worker   * Presets...
2906*5e7646d2SAndroid Build Coastguard Worker   */
2907*5e7646d2SAndroid Build Coastguard Worker 
2908*5e7646d2SAndroid Build Coastguard Worker   for (i = _PWG_PRINT_COLOR_MODE_MONOCHROME; i < _PWG_PRINT_COLOR_MODE_MAX; i ++)
2909*5e7646d2SAndroid Build Coastguard Worker     for (j = _PWG_PRINT_QUALITY_DRAFT; j < _PWG_PRINT_QUALITY_MAX; j ++)
2910*5e7646d2SAndroid Build Coastguard Worker       if (pc->num_presets[i][j])
2911*5e7646d2SAndroid Build Coastguard Worker       {
2912*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "Preset %d %d", i, j);
2913*5e7646d2SAndroid Build Coastguard Worker 	for (k = pc->num_presets[i][j], option = pc->presets[i][j];
2914*5e7646d2SAndroid Build Coastguard Worker 	     k > 0;
2915*5e7646d2SAndroid Build Coastguard Worker 	     k --, option ++)
2916*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(fp, " %s=%s", option->name, option->value);
2917*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePutChar(fp, '\n');
2918*5e7646d2SAndroid Build Coastguard Worker       }
2919*5e7646d2SAndroid Build Coastguard Worker 
2920*5e7646d2SAndroid Build Coastguard Worker  /*
2921*5e7646d2SAndroid Build Coastguard Worker   * Duplex/sides...
2922*5e7646d2SAndroid Build Coastguard Worker   */
2923*5e7646d2SAndroid Build Coastguard Worker 
2924*5e7646d2SAndroid Build Coastguard Worker   if (pc->sides_option)
2925*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "SidesOption %s\n", pc->sides_option);
2926*5e7646d2SAndroid Build Coastguard Worker 
2927*5e7646d2SAndroid Build Coastguard Worker   if (pc->sides_1sided)
2928*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Sides1Sided %s\n", pc->sides_1sided);
2929*5e7646d2SAndroid Build Coastguard Worker 
2930*5e7646d2SAndroid Build Coastguard Worker   if (pc->sides_2sided_long)
2931*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Sides2SidedLong %s\n", pc->sides_2sided_long);
2932*5e7646d2SAndroid Build Coastguard Worker 
2933*5e7646d2SAndroid Build Coastguard Worker   if (pc->sides_2sided_short)
2934*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Sides2SidedShort %s\n", pc->sides_2sided_short);
2935*5e7646d2SAndroid Build Coastguard Worker 
2936*5e7646d2SAndroid Build Coastguard Worker  /*
2937*5e7646d2SAndroid Build Coastguard Worker   * Product, cupsFilter, cupsFilter2, and cupsPreFilter...
2938*5e7646d2SAndroid Build Coastguard Worker   */
2939*5e7646d2SAndroid Build Coastguard Worker 
2940*5e7646d2SAndroid Build Coastguard Worker   if (pc->product)
2941*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "Product", pc->product);
2942*5e7646d2SAndroid Build Coastguard Worker 
2943*5e7646d2SAndroid Build Coastguard Worker   for (value = (const char *)cupsArrayFirst(pc->filters);
2944*5e7646d2SAndroid Build Coastguard Worker        value;
2945*5e7646d2SAndroid Build Coastguard Worker        value = (const char *)cupsArrayNext(pc->filters))
2946*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "Filter", value);
2947*5e7646d2SAndroid Build Coastguard Worker 
2948*5e7646d2SAndroid Build Coastguard Worker   for (value = (const char *)cupsArrayFirst(pc->prefilters);
2949*5e7646d2SAndroid Build Coastguard Worker        value;
2950*5e7646d2SAndroid Build Coastguard Worker        value = (const char *)cupsArrayNext(pc->prefilters))
2951*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "PreFilter", value);
2952*5e7646d2SAndroid Build Coastguard Worker 
2953*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "SingleFile %s\n", pc->single_file ? "true" : "false");
2954*5e7646d2SAndroid Build Coastguard Worker 
2955*5e7646d2SAndroid Build Coastguard Worker  /*
2956*5e7646d2SAndroid Build Coastguard Worker   * Finishing options...
2957*5e7646d2SAndroid Build Coastguard Worker   */
2958*5e7646d2SAndroid Build Coastguard Worker 
2959*5e7646d2SAndroid Build Coastguard Worker   for (f = (_pwg_finishings_t *)cupsArrayFirst(pc->finishings);
2960*5e7646d2SAndroid Build Coastguard Worker        f;
2961*5e7646d2SAndroid Build Coastguard Worker        f = (_pwg_finishings_t *)cupsArrayNext(pc->finishings))
2962*5e7646d2SAndroid Build Coastguard Worker   {
2963*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Finishings %d", f->value);
2964*5e7646d2SAndroid Build Coastguard Worker     for (i = f->num_options, option = f->options; i > 0; i --, option ++)
2965*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, " %s=%s", option->name, option->value);
2966*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutChar(fp, '\n');
2967*5e7646d2SAndroid Build Coastguard Worker   }
2968*5e7646d2SAndroid Build Coastguard Worker 
2969*5e7646d2SAndroid Build Coastguard Worker   for (value = (const char *)cupsArrayFirst(pc->templates); value; value = (const char *)cupsArrayNext(pc->templates))
2970*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "FinishingTemplate", value);
2971*5e7646d2SAndroid Build Coastguard Worker 
2972*5e7646d2SAndroid Build Coastguard Worker  /*
2973*5e7646d2SAndroid Build Coastguard Worker   * Max copies...
2974*5e7646d2SAndroid Build Coastguard Worker   */
2975*5e7646d2SAndroid Build Coastguard Worker 
2976*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "MaxCopies %d\n", pc->max_copies);
2977*5e7646d2SAndroid Build Coastguard Worker 
2978*5e7646d2SAndroid Build Coastguard Worker  /*
2979*5e7646d2SAndroid Build Coastguard Worker   * Accounting/quota/PIN/managed printing values...
2980*5e7646d2SAndroid Build Coastguard Worker   */
2981*5e7646d2SAndroid Build Coastguard Worker 
2982*5e7646d2SAndroid Build Coastguard Worker   if (pc->charge_info_uri)
2983*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "ChargeInfoURI", pc->charge_info_uri);
2984*5e7646d2SAndroid Build Coastguard Worker 
2985*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "JobAccountId %s\n", pc->account_id ? "true" : "false");
2986*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "JobAccountingUserId %s\n",
2987*5e7646d2SAndroid Build Coastguard Worker                  pc->accounting_user_id ? "true" : "false");
2988*5e7646d2SAndroid Build Coastguard Worker 
2989*5e7646d2SAndroid Build Coastguard Worker   if (pc->password)
2990*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "JobPassword", pc->password);
2991*5e7646d2SAndroid Build Coastguard Worker 
2992*5e7646d2SAndroid Build Coastguard Worker   for (value = (char *)cupsArrayFirst(pc->mandatory);
2993*5e7646d2SAndroid Build Coastguard Worker        value;
2994*5e7646d2SAndroid Build Coastguard Worker        value = (char *)cupsArrayNext(pc->mandatory))
2995*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "Mandatory", value);
2996*5e7646d2SAndroid Build Coastguard Worker 
2997*5e7646d2SAndroid Build Coastguard Worker  /*
2998*5e7646d2SAndroid Build Coastguard Worker   * Support files...
2999*5e7646d2SAndroid Build Coastguard Worker   */
3000*5e7646d2SAndroid Build Coastguard Worker 
3001*5e7646d2SAndroid Build Coastguard Worker   for (value = (char *)cupsArrayFirst(pc->support_files);
3002*5e7646d2SAndroid Build Coastguard Worker        value;
3003*5e7646d2SAndroid Build Coastguard Worker        value = (char *)cupsArrayNext(pc->support_files))
3004*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutConf(fp, "SupportFile", value);
3005*5e7646d2SAndroid Build Coastguard Worker 
3006*5e7646d2SAndroid Build Coastguard Worker  /*
3007*5e7646d2SAndroid Build Coastguard Worker   * IPP attributes, if any...
3008*5e7646d2SAndroid Build Coastguard Worker   */
3009*5e7646d2SAndroid Build Coastguard Worker 
3010*5e7646d2SAndroid Build Coastguard Worker   if (attrs)
3011*5e7646d2SAndroid Build Coastguard Worker   {
3012*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "IPP " CUPS_LLFMT "\n", CUPS_LLCAST ippLength(attrs));
3013*5e7646d2SAndroid Build Coastguard Worker 
3014*5e7646d2SAndroid Build Coastguard Worker     attrs->state = IPP_STATE_IDLE;
3015*5e7646d2SAndroid Build Coastguard Worker     ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL, attrs);
3016*5e7646d2SAndroid Build Coastguard Worker   }
3017*5e7646d2SAndroid Build Coastguard Worker 
3018*5e7646d2SAndroid Build Coastguard Worker  /*
3019*5e7646d2SAndroid Build Coastguard Worker   * Close and return...
3020*5e7646d2SAndroid Build Coastguard Worker   */
3021*5e7646d2SAndroid Build Coastguard Worker 
3022*5e7646d2SAndroid Build Coastguard Worker   if (cupsFileClose(fp))
3023*5e7646d2SAndroid Build Coastguard Worker   {
3024*5e7646d2SAndroid Build Coastguard Worker     unlink(newfile);
3025*5e7646d2SAndroid Build Coastguard Worker     return (0);
3026*5e7646d2SAndroid Build Coastguard Worker   }
3027*5e7646d2SAndroid Build Coastguard Worker 
3028*5e7646d2SAndroid Build Coastguard Worker   unlink(filename);
3029*5e7646d2SAndroid Build Coastguard Worker   return (!rename(newfile, filename));
3030*5e7646d2SAndroid Build Coastguard Worker }
3031*5e7646d2SAndroid Build Coastguard Worker 
3032*5e7646d2SAndroid Build Coastguard Worker 
3033*5e7646d2SAndroid Build Coastguard Worker /*
3034*5e7646d2SAndroid Build Coastguard Worker  * '_ppdCreateFromIPP()' - Create a PPD file describing the capabilities
3035*5e7646d2SAndroid Build Coastguard Worker  *                         of an IPP printer.
3036*5e7646d2SAndroid Build Coastguard Worker  */
3037*5e7646d2SAndroid Build Coastguard Worker 
3038*5e7646d2SAndroid Build Coastguard Worker char *					/* O - PPD filename or @code NULL@ on error */
_ppdCreateFromIPP(char * buffer,size_t bufsize,ipp_t * response)3039*5e7646d2SAndroid Build Coastguard Worker _ppdCreateFromIPP(char   *buffer,	/* I - Filename buffer */
3040*5e7646d2SAndroid Build Coastguard Worker                   size_t bufsize,	/* I - Size of filename buffer */
3041*5e7646d2SAndroid Build Coastguard Worker 		  ipp_t  *response)	/* I - Get-Printer-Attributes response */
3042*5e7646d2SAndroid Build Coastguard Worker {
3043*5e7646d2SAndroid Build Coastguard Worker   cups_file_t		*fp;		/* PPD file */
3044*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*sizes;		/* Media sizes supported by printer */
3045*5e7646d2SAndroid Build Coastguard Worker   cups_size_t		*size;		/* Current media size */
3046*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr,		/* xxx-supported */
3047*5e7646d2SAndroid Build Coastguard Worker 			*defattr,	/* xxx-default */
3048*5e7646d2SAndroid Build Coastguard Worker                         *quality,	/* print-quality-supported */
3049*5e7646d2SAndroid Build Coastguard Worker 			*x_dim, *y_dim;	/* Media dimensions */
3050*5e7646d2SAndroid Build Coastguard Worker   ipp_t			*media_col,	/* Media collection */
3051*5e7646d2SAndroid Build Coastguard Worker 			*media_size;	/* Media size collection */
3052*5e7646d2SAndroid Build Coastguard Worker   char			make[256],	/* Make and model */
3053*5e7646d2SAndroid Build Coastguard Worker 			*model,		/* Model name */
3054*5e7646d2SAndroid Build Coastguard Worker 			ppdname[PPD_MAX_NAME];
3055*5e7646d2SAndroid Build Coastguard Worker 		    			/* PPD keyword */
3056*5e7646d2SAndroid Build Coastguard Worker   int			i, j,		/* Looping vars */
3057*5e7646d2SAndroid Build Coastguard Worker 			count,		/* Number of values */
3058*5e7646d2SAndroid Build Coastguard Worker 			bottom,		/* Largest bottom margin */
3059*5e7646d2SAndroid Build Coastguard Worker 			left,		/* Largest left margin */
3060*5e7646d2SAndroid Build Coastguard Worker 			right,		/* Largest right margin */
3061*5e7646d2SAndroid Build Coastguard Worker 			top,		/* Largest top margin */
3062*5e7646d2SAndroid Build Coastguard Worker 			max_length = 0,	/* Maximum custom size */
3063*5e7646d2SAndroid Build Coastguard Worker 			max_width = 0,
3064*5e7646d2SAndroid Build Coastguard Worker 			min_length = INT_MAX,
3065*5e7646d2SAndroid Build Coastguard Worker 					/* Minimum custom size */
3066*5e7646d2SAndroid Build Coastguard Worker 			min_width = INT_MAX,
3067*5e7646d2SAndroid Build Coastguard Worker 			is_apple = 0,	/* Does the printer support Apple raster? */
3068*5e7646d2SAndroid Build Coastguard Worker 			is_pdf = 0,	/* Does the printer support PDF? */
3069*5e7646d2SAndroid Build Coastguard Worker 			is_pwg = 0;	/* Does the printer support PWG Raster? */
3070*5e7646d2SAndroid Build Coastguard Worker   pwg_media_t		*pwg;		/* PWG media size */
3071*5e7646d2SAndroid Build Coastguard Worker   int			xres, yres;	/* Resolution values */
3072*5e7646d2SAndroid Build Coastguard Worker   int                   resolutions[1000];
3073*5e7646d2SAndroid Build Coastguard Worker                                         /* Array of resolution indices */
3074*5e7646d2SAndroid Build Coastguard Worker   char			msgid[256];	/* Message identifier (attr.value) */
3075*5e7646d2SAndroid Build Coastguard Worker   const char		*keyword,	/* Keyword value */
3076*5e7646d2SAndroid Build Coastguard Worker 			*msgstr;	/* Localized string */
3077*5e7646d2SAndroid Build Coastguard Worker   cups_lang_t		*lang = cupsLangDefault();
3078*5e7646d2SAndroid Build Coastguard Worker 					/* Localization info */
3079*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*strings = NULL;/* Printer strings file */
3080*5e7646d2SAndroid Build Coastguard Worker   struct lconv		*loc = localeconv();
3081*5e7646d2SAndroid Build Coastguard Worker 					/* Locale data */
3082*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*fin_options = NULL;
3083*5e7646d2SAndroid Build Coastguard Worker 					/* Finishing options */
3084*5e7646d2SAndroid Build Coastguard Worker 
3085*5e7646d2SAndroid Build Coastguard Worker 
3086*5e7646d2SAndroid Build Coastguard Worker  /*
3087*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
3088*5e7646d2SAndroid Build Coastguard Worker   */
3089*5e7646d2SAndroid Build Coastguard Worker 
3090*5e7646d2SAndroid Build Coastguard Worker   if (buffer)
3091*5e7646d2SAndroid Build Coastguard Worker     *buffer = '\0';
3092*5e7646d2SAndroid Build Coastguard Worker 
3093*5e7646d2SAndroid Build Coastguard Worker   if (!buffer || bufsize < 1)
3094*5e7646d2SAndroid Build Coastguard Worker   {
3095*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
3096*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
3097*5e7646d2SAndroid Build Coastguard Worker   }
3098*5e7646d2SAndroid Build Coastguard Worker 
3099*5e7646d2SAndroid Build Coastguard Worker   if (!response)
3100*5e7646d2SAndroid Build Coastguard Worker   {
3101*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No IPP attributes."), 1);
3102*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
3103*5e7646d2SAndroid Build Coastguard Worker   }
3104*5e7646d2SAndroid Build Coastguard Worker 
3105*5e7646d2SAndroid Build Coastguard Worker  /*
3106*5e7646d2SAndroid Build Coastguard Worker   * Open a temporary file for the PPD...
3107*5e7646d2SAndroid Build Coastguard Worker   */
3108*5e7646d2SAndroid Build Coastguard Worker 
3109*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsTempFile2(buffer, (int)bufsize)) == NULL)
3110*5e7646d2SAndroid Build Coastguard Worker   {
3111*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
3112*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
3113*5e7646d2SAndroid Build Coastguard Worker   }
3114*5e7646d2SAndroid Build Coastguard Worker 
3115*5e7646d2SAndroid Build Coastguard Worker  /*
3116*5e7646d2SAndroid Build Coastguard Worker   * Standard stuff for PPD file...
3117*5e7646d2SAndroid Build Coastguard Worker   */
3118*5e7646d2SAndroid Build Coastguard Worker 
3119*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*PPD-Adobe: \"4.3\"\n");
3120*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*FormatVersion: \"4.3\"\n");
3121*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*FileVersion: \"%d.%d\"\n", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR);
3122*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*LanguageVersion: English\n");
3123*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*LanguageEncoding: ISOLatin1\n");
3124*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*PSVersion: \"(3010.000) 0\"\n");
3125*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*LanguageLevel: \"3\"\n");
3126*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*FileSystem: False\n");
3127*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*PCFileName: \"ippeve.ppd\"\n");
3128*5e7646d2SAndroid Build Coastguard Worker 
3129*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT)) != NULL)
3130*5e7646d2SAndroid Build Coastguard Worker     strlcpy(make, ippGetString(attr, 0, NULL), sizeof(make));
3131*5e7646d2SAndroid Build Coastguard Worker   else
3132*5e7646d2SAndroid Build Coastguard Worker     strlcpy(make, "Unknown Printer", sizeof(make));
3133*5e7646d2SAndroid Build Coastguard Worker 
3134*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strncasecmp(make, "Hewlett Packard ", 16) ||
3135*5e7646d2SAndroid Build Coastguard Worker       !_cups_strncasecmp(make, "Hewlett-Packard ", 16))
3136*5e7646d2SAndroid Build Coastguard Worker   {
3137*5e7646d2SAndroid Build Coastguard Worker     model = make + 16;
3138*5e7646d2SAndroid Build Coastguard Worker     strlcpy(make, "HP", sizeof(make));
3139*5e7646d2SAndroid Build Coastguard Worker   }
3140*5e7646d2SAndroid Build Coastguard Worker   else if ((model = strchr(make, ' ')) != NULL)
3141*5e7646d2SAndroid Build Coastguard Worker     *model++ = '\0';
3142*5e7646d2SAndroid Build Coastguard Worker   else
3143*5e7646d2SAndroid Build Coastguard Worker     model = make;
3144*5e7646d2SAndroid Build Coastguard Worker 
3145*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*Manufacturer: \"%s\"\n", make);
3146*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*ModelName: \"%s\"\n", model);
3147*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*Product: \"(%s)\"\n", model);
3148*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*NickName: \"%s - IPP Everywhere\"\n", model);
3149*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*ShortNickName: \"%s - IPP Everywhere\"\n", model);
3150*5e7646d2SAndroid Build Coastguard Worker 
3151*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "color-supported", IPP_TAG_BOOLEAN)) != NULL && ippGetBoolean(attr, 0))
3152*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*ColorDevice: True\n");
3153*5e7646d2SAndroid Build Coastguard Worker   else
3154*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*ColorDevice: False\n");
3155*5e7646d2SAndroid Build Coastguard Worker 
3156*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*cupsVersion: %d.%d\n", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR);
3157*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "*cupsSNMPSupplies: False\n");
3158*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*cupsLanguages: \"%s\"\n", lang->language);
3159*5e7646d2SAndroid Build Coastguard Worker 
3160*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "printer-more-info", IPP_TAG_URI)) != NULL)
3161*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*APSupplies: \"%s\"\n", ippGetString(attr, 0, NULL));
3162*5e7646d2SAndroid Build Coastguard Worker 
3163*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "printer-charge-info-uri", IPP_TAG_URI)) != NULL)
3164*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*cupsChargeInfoURI: \"%s\"\n", ippGetString(attr, 0, NULL));
3165*5e7646d2SAndroid Build Coastguard Worker 
3166*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "printer-strings-uri", IPP_TAG_URI)) != NULL)
3167*5e7646d2SAndroid Build Coastguard Worker   {
3168*5e7646d2SAndroid Build Coastguard Worker     http_t	*http = NULL;		/* Connection to printer */
3169*5e7646d2SAndroid Build Coastguard Worker     char	stringsfile[1024];	/* Temporary strings file */
3170*5e7646d2SAndroid Build Coastguard Worker 
3171*5e7646d2SAndroid Build Coastguard Worker     if (cups_get_url(&http, ippGetString(attr, 0, NULL), stringsfile, sizeof(stringsfile)))
3172*5e7646d2SAndroid Build Coastguard Worker     {
3173*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsStringsURI: \"%s\"\n", ippGetString(attr, 0, NULL));
3174*5e7646d2SAndroid Build Coastguard Worker 
3175*5e7646d2SAndroid Build Coastguard Worker       strings = _cupsMessageLoad(stringsfile, _CUPS_MESSAGE_STRINGS | _CUPS_MESSAGE_UNQUOTE);
3176*5e7646d2SAndroid Build Coastguard Worker 
3177*5e7646d2SAndroid Build Coastguard Worker       unlink(stringsfile);
3178*5e7646d2SAndroid Build Coastguard Worker     }
3179*5e7646d2SAndroid Build Coastguard Worker 
3180*5e7646d2SAndroid Build Coastguard Worker     if (http)
3181*5e7646d2SAndroid Build Coastguard Worker       httpClose(http);
3182*5e7646d2SAndroid Build Coastguard Worker   }
3183*5e7646d2SAndroid Build Coastguard Worker 
3184*5e7646d2SAndroid Build Coastguard Worker  /*
3185*5e7646d2SAndroid Build Coastguard Worker   * Accounting...
3186*5e7646d2SAndroid Build Coastguard Worker   */
3187*5e7646d2SAndroid Build Coastguard Worker 
3188*5e7646d2SAndroid Build Coastguard Worker   if (ippGetBoolean(ippFindAttribute(response, "job-account-id-supported", IPP_TAG_BOOLEAN), 0))
3189*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*cupsJobAccountId: True\n");
3190*5e7646d2SAndroid Build Coastguard Worker 
3191*5e7646d2SAndroid Build Coastguard Worker   if (ippGetBoolean(ippFindAttribute(response, "job-accounting-user-id-supported", IPP_TAG_BOOLEAN), 0))
3192*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*cupsJobAccountingUserId: True\n");
3193*5e7646d2SAndroid Build Coastguard Worker 
3194*5e7646d2SAndroid Build Coastguard Worker  /*
3195*5e7646d2SAndroid Build Coastguard Worker   * Password/PIN printing...
3196*5e7646d2SAndroid Build Coastguard Worker   */
3197*5e7646d2SAndroid Build Coastguard Worker 
3198*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "job-password-supported", IPP_TAG_INTEGER)) != NULL)
3199*5e7646d2SAndroid Build Coastguard Worker   {
3200*5e7646d2SAndroid Build Coastguard Worker     char	pattern[33];		/* Password pattern */
3201*5e7646d2SAndroid Build Coastguard Worker     int		maxlen = ippGetInteger(attr, 0);
3202*5e7646d2SAndroid Build Coastguard Worker 					/* Maximum length */
3203*5e7646d2SAndroid Build Coastguard Worker     const char	*repertoire = ippGetString(ippFindAttribute(response, "job-password-repertoire-configured", IPP_TAG_KEYWORD), 0, NULL);
3204*5e7646d2SAndroid Build Coastguard Worker 					/* Type of password */
3205*5e7646d2SAndroid Build Coastguard Worker 
3206*5e7646d2SAndroid Build Coastguard Worker     if (maxlen > (int)(sizeof(pattern) - 1))
3207*5e7646d2SAndroid Build Coastguard Worker       maxlen = (int)sizeof(pattern) - 1;
3208*5e7646d2SAndroid Build Coastguard Worker 
3209*5e7646d2SAndroid Build Coastguard Worker     if (!repertoire || !strcmp(repertoire, "iana_us-ascii_digits"))
3210*5e7646d2SAndroid Build Coastguard Worker       memset(pattern, '1', (size_t)maxlen);
3211*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(repertoire, "iana_us-ascii_letters"))
3212*5e7646d2SAndroid Build Coastguard Worker       memset(pattern, 'A', (size_t)maxlen);
3213*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(repertoire, "iana_us-ascii_complex"))
3214*5e7646d2SAndroid Build Coastguard Worker       memset(pattern, 'C', (size_t)maxlen);
3215*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(repertoire, "iana_us-ascii_any"))
3216*5e7646d2SAndroid Build Coastguard Worker       memset(pattern, '.', (size_t)maxlen);
3217*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(repertoire, "iana_utf-8_digits"))
3218*5e7646d2SAndroid Build Coastguard Worker       memset(pattern, 'N', (size_t)maxlen);
3219*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(repertoire, "iana_utf-8_letters"))
3220*5e7646d2SAndroid Build Coastguard Worker       memset(pattern, 'U', (size_t)maxlen);
3221*5e7646d2SAndroid Build Coastguard Worker     else
3222*5e7646d2SAndroid Build Coastguard Worker       memset(pattern, '*', (size_t)maxlen);
3223*5e7646d2SAndroid Build Coastguard Worker 
3224*5e7646d2SAndroid Build Coastguard Worker     pattern[maxlen] = '\0';
3225*5e7646d2SAndroid Build Coastguard Worker 
3226*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*cupsJobPassword: \"%s\"\n", pattern);
3227*5e7646d2SAndroid Build Coastguard Worker   }
3228*5e7646d2SAndroid Build Coastguard Worker 
3229*5e7646d2SAndroid Build Coastguard Worker  /*
3230*5e7646d2SAndroid Build Coastguard Worker   * Filters...
3231*5e7646d2SAndroid Build Coastguard Worker   */
3232*5e7646d2SAndroid Build Coastguard Worker 
3233*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "document-format-supported", IPP_TAG_MIMETYPE)) != NULL)
3234*5e7646d2SAndroid Build Coastguard Worker   {
3235*5e7646d2SAndroid Build Coastguard Worker     is_apple = ippContainsString(attr, "image/urf");
3236*5e7646d2SAndroid Build Coastguard Worker     is_pdf   = ippContainsString(attr, "application/pdf");
3237*5e7646d2SAndroid Build Coastguard Worker     is_pwg   = ippContainsString(attr, "image/pwg-raster") && !is_apple;
3238*5e7646d2SAndroid Build Coastguard Worker 
3239*5e7646d2SAndroid Build Coastguard Worker     if (ippContainsString(attr, "image/jpeg"))
3240*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*cupsFilter2: \"image/jpeg image/jpeg 0 -\"\n");
3241*5e7646d2SAndroid Build Coastguard Worker     if (ippContainsString(attr, "image/png"))
3242*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*cupsFilter2: \"image/png image/png 0 -\"\n");
3243*5e7646d2SAndroid Build Coastguard Worker     if (is_pdf)
3244*5e7646d2SAndroid Build Coastguard Worker     {
3245*5e7646d2SAndroid Build Coastguard Worker      /*
3246*5e7646d2SAndroid Build Coastguard Worker       * Don't locally filter PDF content when printing to a CUPS shared
3247*5e7646d2SAndroid Build Coastguard Worker       * printer, otherwise the options will be applied twice...
3248*5e7646d2SAndroid Build Coastguard Worker       */
3249*5e7646d2SAndroid Build Coastguard Worker 
3250*5e7646d2SAndroid Build Coastguard Worker       if (ippContainsString(attr, "application/vnd.cups-pdf"))
3251*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(fp, "*cupsFilter2: \"application/pdf application/pdf 0 -\"\n");
3252*5e7646d2SAndroid Build Coastguard Worker       else
3253*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(fp, "*cupsFilter2: \"application/vnd.cups-pdf application/pdf 10 -\"\n");
3254*5e7646d2SAndroid Build Coastguard Worker     }
3255*5e7646d2SAndroid Build Coastguard Worker     else
3256*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*cupsManualCopies: True\n");
3257*5e7646d2SAndroid Build Coastguard Worker     if (is_apple)
3258*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*cupsFilter2: \"image/urf image/urf 100 -\"\n");
3259*5e7646d2SAndroid Build Coastguard Worker     if (is_pwg)
3260*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*cupsFilter2: \"image/pwg-raster image/pwg-raster 100 -\"\n");
3261*5e7646d2SAndroid Build Coastguard Worker   }
3262*5e7646d2SAndroid Build Coastguard Worker 
3263*5e7646d2SAndroid Build Coastguard Worker   if (!is_apple && !is_pdf && !is_pwg)
3264*5e7646d2SAndroid Build Coastguard Worker     goto bad_ppd;
3265*5e7646d2SAndroid Build Coastguard Worker 
3266*5e7646d2SAndroid Build Coastguard Worker  /*
3267*5e7646d2SAndroid Build Coastguard Worker   * PageSize/PageRegion/ImageableArea/PaperDimension
3268*5e7646d2SAndroid Build Coastguard Worker   */
3269*5e7646d2SAndroid Build Coastguard Worker 
3270*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "media-bottom-margin-supported", IPP_TAG_INTEGER)) != NULL)
3271*5e7646d2SAndroid Build Coastguard Worker   {
3272*5e7646d2SAndroid Build Coastguard Worker     for (i = 1, bottom = ippGetInteger(attr, 0), count = ippGetCount(attr); i < count; i ++)
3273*5e7646d2SAndroid Build Coastguard Worker       if (ippGetInteger(attr, i) > bottom)
3274*5e7646d2SAndroid Build Coastguard Worker         bottom = ippGetInteger(attr, i);
3275*5e7646d2SAndroid Build Coastguard Worker   }
3276*5e7646d2SAndroid Build Coastguard Worker   else
3277*5e7646d2SAndroid Build Coastguard Worker     bottom = 1270;
3278*5e7646d2SAndroid Build Coastguard Worker 
3279*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "media-left-margin-supported", IPP_TAG_INTEGER)) != NULL)
3280*5e7646d2SAndroid Build Coastguard Worker   {
3281*5e7646d2SAndroid Build Coastguard Worker     for (i = 1, left = ippGetInteger(attr, 0), count = ippGetCount(attr); i < count; i ++)
3282*5e7646d2SAndroid Build Coastguard Worker       if (ippGetInteger(attr, i) > left)
3283*5e7646d2SAndroid Build Coastguard Worker         left = ippGetInteger(attr, i);
3284*5e7646d2SAndroid Build Coastguard Worker   }
3285*5e7646d2SAndroid Build Coastguard Worker   else
3286*5e7646d2SAndroid Build Coastguard Worker     left = 635;
3287*5e7646d2SAndroid Build Coastguard Worker 
3288*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "media-right-margin-supported", IPP_TAG_INTEGER)) != NULL)
3289*5e7646d2SAndroid Build Coastguard Worker   {
3290*5e7646d2SAndroid Build Coastguard Worker     for (i = 1, right = ippGetInteger(attr, 0), count = ippGetCount(attr); i < count; i ++)
3291*5e7646d2SAndroid Build Coastguard Worker       if (ippGetInteger(attr, i) > right)
3292*5e7646d2SAndroid Build Coastguard Worker         right = ippGetInteger(attr, i);
3293*5e7646d2SAndroid Build Coastguard Worker   }
3294*5e7646d2SAndroid Build Coastguard Worker   else
3295*5e7646d2SAndroid Build Coastguard Worker     right = 635;
3296*5e7646d2SAndroid Build Coastguard Worker 
3297*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "media-top-margin-supported", IPP_TAG_INTEGER)) != NULL)
3298*5e7646d2SAndroid Build Coastguard Worker   {
3299*5e7646d2SAndroid Build Coastguard Worker     for (i = 1, top = ippGetInteger(attr, 0), count = ippGetCount(attr); i < count; i ++)
3300*5e7646d2SAndroid Build Coastguard Worker       if (ippGetInteger(attr, i) > top)
3301*5e7646d2SAndroid Build Coastguard Worker         top = ippGetInteger(attr, i);
3302*5e7646d2SAndroid Build Coastguard Worker   }
3303*5e7646d2SAndroid Build Coastguard Worker   else
3304*5e7646d2SAndroid Build Coastguard Worker     top = 1270;
3305*5e7646d2SAndroid Build Coastguard Worker 
3306*5e7646d2SAndroid Build Coastguard Worker   if ((defattr = ippFindAttribute(response, "media-col-default", IPP_TAG_BEGIN_COLLECTION)) != NULL)
3307*5e7646d2SAndroid Build Coastguard Worker   {
3308*5e7646d2SAndroid Build Coastguard Worker     if ((attr = ippFindAttribute(ippGetCollection(defattr, 0), "media-size", IPP_TAG_BEGIN_COLLECTION)) != NULL)
3309*5e7646d2SAndroid Build Coastguard Worker     {
3310*5e7646d2SAndroid Build Coastguard Worker       media_size = ippGetCollection(attr, 0);
3311*5e7646d2SAndroid Build Coastguard Worker       x_dim      = ippFindAttribute(media_size, "x-dimension", IPP_TAG_INTEGER);
3312*5e7646d2SAndroid Build Coastguard Worker       y_dim      = ippFindAttribute(media_size, "y-dimension", IPP_TAG_INTEGER);
3313*5e7646d2SAndroid Build Coastguard Worker 
3314*5e7646d2SAndroid Build Coastguard Worker       if (x_dim && y_dim && (pwg = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0))) != NULL)
3315*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(ppdname, pwg->ppd, sizeof(ppdname));
3316*5e7646d2SAndroid Build Coastguard Worker       else
3317*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(ppdname, "Unknown", sizeof(ppdname));
3318*5e7646d2SAndroid Build Coastguard Worker     }
3319*5e7646d2SAndroid Build Coastguard Worker     else
3320*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ppdname, "Unknown", sizeof(ppdname));
3321*5e7646d2SAndroid Build Coastguard Worker   }
3322*5e7646d2SAndroid Build Coastguard Worker   else if ((pwg = pwgMediaForPWG(ippGetString(ippFindAttribute(response, "media-default", IPP_TAG_ZERO), 0, NULL))) != NULL)
3323*5e7646d2SAndroid Build Coastguard Worker     strlcpy(ppdname, pwg->ppd, sizeof(ppdname));
3324*5e7646d2SAndroid Build Coastguard Worker   else
3325*5e7646d2SAndroid Build Coastguard Worker     strlcpy(ppdname, "Unknown", sizeof(ppdname));
3326*5e7646d2SAndroid Build Coastguard Worker 
3327*5e7646d2SAndroid Build Coastguard Worker   sizes = cupsArrayNew3((cups_array_func_t)pwg_compare_sizes, NULL, NULL, 0, (cups_acopy_func_t)pwg_copy_size, (cups_afree_func_t)free);
3328*5e7646d2SAndroid Build Coastguard Worker 
3329*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "media-col-database", IPP_TAG_BEGIN_COLLECTION)) != NULL)
3330*5e7646d2SAndroid Build Coastguard Worker   {
3331*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, count = ippGetCount(attr); i < count; i ++)
3332*5e7646d2SAndroid Build Coastguard Worker     {
3333*5e7646d2SAndroid Build Coastguard Worker       cups_size_t	temp;		/* Current size */
3334*5e7646d2SAndroid Build Coastguard Worker       ipp_attribute_t	*margin;	/* media-xxx-margin attribute */
3335*5e7646d2SAndroid Build Coastguard Worker 
3336*5e7646d2SAndroid Build Coastguard Worker       media_col   = ippGetCollection(attr, i);
3337*5e7646d2SAndroid Build Coastguard Worker       media_size  = ippGetCollection(ippFindAttribute(media_col, "media-size", IPP_TAG_BEGIN_COLLECTION), 0);
3338*5e7646d2SAndroid Build Coastguard Worker       x_dim       = ippFindAttribute(media_size, "x-dimension", IPP_TAG_ZERO);
3339*5e7646d2SAndroid Build Coastguard Worker       y_dim       = ippFindAttribute(media_size, "y-dimension", IPP_TAG_ZERO);
3340*5e7646d2SAndroid Build Coastguard Worker       pwg         = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0));
3341*5e7646d2SAndroid Build Coastguard Worker 
3342*5e7646d2SAndroid Build Coastguard Worker       if (pwg)
3343*5e7646d2SAndroid Build Coastguard Worker       {
3344*5e7646d2SAndroid Build Coastguard Worker 	temp.width  = pwg->width;
3345*5e7646d2SAndroid Build Coastguard Worker 	temp.length = pwg->length;
3346*5e7646d2SAndroid Build Coastguard Worker 
3347*5e7646d2SAndroid Build Coastguard Worker 	if ((margin = ippFindAttribute(media_col, "media-bottom-margin", IPP_TAG_INTEGER)) != NULL)
3348*5e7646d2SAndroid Build Coastguard Worker 	  temp.bottom = ippGetInteger(margin, 0);
3349*5e7646d2SAndroid Build Coastguard Worker 	else
3350*5e7646d2SAndroid Build Coastguard Worker 	  temp.bottom = bottom;
3351*5e7646d2SAndroid Build Coastguard Worker 
3352*5e7646d2SAndroid Build Coastguard Worker 	if ((margin = ippFindAttribute(media_col, "media-left-margin", IPP_TAG_INTEGER)) != NULL)
3353*5e7646d2SAndroid Build Coastguard Worker 	  temp.left = ippGetInteger(margin, 0);
3354*5e7646d2SAndroid Build Coastguard Worker 	else
3355*5e7646d2SAndroid Build Coastguard Worker 	  temp.left = left;
3356*5e7646d2SAndroid Build Coastguard Worker 
3357*5e7646d2SAndroid Build Coastguard Worker 	if ((margin = ippFindAttribute(media_col, "media-right-margin", IPP_TAG_INTEGER)) != NULL)
3358*5e7646d2SAndroid Build Coastguard Worker 	  temp.right = ippGetInteger(margin, 0);
3359*5e7646d2SAndroid Build Coastguard Worker 	else
3360*5e7646d2SAndroid Build Coastguard Worker 	  temp.right = right;
3361*5e7646d2SAndroid Build Coastguard Worker 
3362*5e7646d2SAndroid Build Coastguard Worker 	if ((margin = ippFindAttribute(media_col, "media-top-margin", IPP_TAG_INTEGER)) != NULL)
3363*5e7646d2SAndroid Build Coastguard Worker 	  temp.top = ippGetInteger(margin, 0);
3364*5e7646d2SAndroid Build Coastguard Worker 	else
3365*5e7646d2SAndroid Build Coastguard Worker 	  temp.top = top;
3366*5e7646d2SAndroid Build Coastguard Worker 
3367*5e7646d2SAndroid Build Coastguard Worker 	if (temp.bottom == 0 && temp.left == 0 && temp.right == 0 && temp.top == 0)
3368*5e7646d2SAndroid Build Coastguard Worker 	  snprintf(temp.media, sizeof(temp.media), "%s.Borderless", pwg->ppd);
3369*5e7646d2SAndroid Build Coastguard Worker 	else
3370*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(temp.media, pwg->ppd, sizeof(temp.media));
3371*5e7646d2SAndroid Build Coastguard Worker 
3372*5e7646d2SAndroid Build Coastguard Worker 	if (!cupsArrayFind(sizes, &temp))
3373*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayAdd(sizes, &temp);
3374*5e7646d2SAndroid Build Coastguard Worker       }
3375*5e7646d2SAndroid Build Coastguard Worker       else if (ippGetValueTag(x_dim) == IPP_TAG_RANGE || ippGetValueTag(y_dim) == IPP_TAG_RANGE)
3376*5e7646d2SAndroid Build Coastguard Worker       {
3377*5e7646d2SAndroid Build Coastguard Worker        /*
3378*5e7646d2SAndroid Build Coastguard Worker 	* Custom size - record the min/max values...
3379*5e7646d2SAndroid Build Coastguard Worker 	*/
3380*5e7646d2SAndroid Build Coastguard Worker 
3381*5e7646d2SAndroid Build Coastguard Worker 	int lower, upper;		/* Range values */
3382*5e7646d2SAndroid Build Coastguard Worker 
3383*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetValueTag(x_dim) == IPP_TAG_RANGE)
3384*5e7646d2SAndroid Build Coastguard Worker 	  lower = ippGetRange(x_dim, 0, &upper);
3385*5e7646d2SAndroid Build Coastguard Worker 	else
3386*5e7646d2SAndroid Build Coastguard Worker 	  lower = upper = ippGetInteger(x_dim, 0);
3387*5e7646d2SAndroid Build Coastguard Worker 
3388*5e7646d2SAndroid Build Coastguard Worker 	if (lower < min_width)
3389*5e7646d2SAndroid Build Coastguard Worker 	  min_width = lower;
3390*5e7646d2SAndroid Build Coastguard Worker 	if (upper > max_width)
3391*5e7646d2SAndroid Build Coastguard Worker 	  max_width = upper;
3392*5e7646d2SAndroid Build Coastguard Worker 
3393*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetValueTag(y_dim) == IPP_TAG_RANGE)
3394*5e7646d2SAndroid Build Coastguard Worker 	  lower = ippGetRange(y_dim, 0, &upper);
3395*5e7646d2SAndroid Build Coastguard Worker 	else
3396*5e7646d2SAndroid Build Coastguard Worker 	  lower = upper = ippGetInteger(y_dim, 0);
3397*5e7646d2SAndroid Build Coastguard Worker 
3398*5e7646d2SAndroid Build Coastguard Worker 	if (lower < min_length)
3399*5e7646d2SAndroid Build Coastguard Worker 	  min_length = lower;
3400*5e7646d2SAndroid Build Coastguard Worker 	if (upper > max_length)
3401*5e7646d2SAndroid Build Coastguard Worker 	  max_length = upper;
3402*5e7646d2SAndroid Build Coastguard Worker       }
3403*5e7646d2SAndroid Build Coastguard Worker     }
3404*5e7646d2SAndroid Build Coastguard Worker 
3405*5e7646d2SAndroid Build Coastguard Worker     if ((max_width == 0 || max_length == 0) && (attr = ippFindAttribute(response, "media-size-supported", IPP_TAG_BEGIN_COLLECTION)) != NULL)
3406*5e7646d2SAndroid Build Coastguard Worker     {
3407*5e7646d2SAndroid Build Coastguard Worker      /*
3408*5e7646d2SAndroid Build Coastguard Worker       * Some printers don't list custom size support in media-col-database...
3409*5e7646d2SAndroid Build Coastguard Worker       */
3410*5e7646d2SAndroid Build Coastguard Worker 
3411*5e7646d2SAndroid Build Coastguard Worker       for (i = 0, count = ippGetCount(attr); i < count; i ++)
3412*5e7646d2SAndroid Build Coastguard Worker       {
3413*5e7646d2SAndroid Build Coastguard Worker 	media_size  = ippGetCollection(attr, i);
3414*5e7646d2SAndroid Build Coastguard Worker 	x_dim       = ippFindAttribute(media_size, "x-dimension", IPP_TAG_ZERO);
3415*5e7646d2SAndroid Build Coastguard Worker 	y_dim       = ippFindAttribute(media_size, "y-dimension", IPP_TAG_ZERO);
3416*5e7646d2SAndroid Build Coastguard Worker 
3417*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetValueTag(x_dim) == IPP_TAG_RANGE || ippGetValueTag(y_dim) == IPP_TAG_RANGE)
3418*5e7646d2SAndroid Build Coastguard Worker 	{
3419*5e7646d2SAndroid Build Coastguard Worker 	 /*
3420*5e7646d2SAndroid Build Coastguard Worker 	  * Custom size - record the min/max values...
3421*5e7646d2SAndroid Build Coastguard Worker 	  */
3422*5e7646d2SAndroid Build Coastguard Worker 
3423*5e7646d2SAndroid Build Coastguard Worker 	  int lower, upper;		/* Range values */
3424*5e7646d2SAndroid Build Coastguard Worker 
3425*5e7646d2SAndroid Build Coastguard Worker 	  if (ippGetValueTag(x_dim) == IPP_TAG_RANGE)
3426*5e7646d2SAndroid Build Coastguard Worker 	    lower = ippGetRange(x_dim, 0, &upper);
3427*5e7646d2SAndroid Build Coastguard Worker 	  else
3428*5e7646d2SAndroid Build Coastguard Worker 	    lower = upper = ippGetInteger(x_dim, 0);
3429*5e7646d2SAndroid Build Coastguard Worker 
3430*5e7646d2SAndroid Build Coastguard Worker 	  if (lower < min_width)
3431*5e7646d2SAndroid Build Coastguard Worker 	    min_width = lower;
3432*5e7646d2SAndroid Build Coastguard Worker 	  if (upper > max_width)
3433*5e7646d2SAndroid Build Coastguard Worker 	    max_width = upper;
3434*5e7646d2SAndroid Build Coastguard Worker 
3435*5e7646d2SAndroid Build Coastguard Worker 	  if (ippGetValueTag(y_dim) == IPP_TAG_RANGE)
3436*5e7646d2SAndroid Build Coastguard Worker 	    lower = ippGetRange(y_dim, 0, &upper);
3437*5e7646d2SAndroid Build Coastguard Worker 	  else
3438*5e7646d2SAndroid Build Coastguard Worker 	    lower = upper = ippGetInteger(y_dim, 0);
3439*5e7646d2SAndroid Build Coastguard Worker 
3440*5e7646d2SAndroid Build Coastguard Worker 	  if (lower < min_length)
3441*5e7646d2SAndroid Build Coastguard Worker 	    min_length = lower;
3442*5e7646d2SAndroid Build Coastguard Worker 	  if (upper > max_length)
3443*5e7646d2SAndroid Build Coastguard Worker 	    max_length = upper;
3444*5e7646d2SAndroid Build Coastguard Worker 	}
3445*5e7646d2SAndroid Build Coastguard Worker       }
3446*5e7646d2SAndroid Build Coastguard Worker     }
3447*5e7646d2SAndroid Build Coastguard Worker   }
3448*5e7646d2SAndroid Build Coastguard Worker   else if ((attr = ippFindAttribute(response, "media-size-supported", IPP_TAG_BEGIN_COLLECTION)) != NULL)
3449*5e7646d2SAndroid Build Coastguard Worker   {
3450*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, count = ippGetCount(attr); i < count; i ++)
3451*5e7646d2SAndroid Build Coastguard Worker     {
3452*5e7646d2SAndroid Build Coastguard Worker       cups_size_t	temp;		/* Current size */
3453*5e7646d2SAndroid Build Coastguard Worker 
3454*5e7646d2SAndroid Build Coastguard Worker       media_size  = ippGetCollection(attr, i);
3455*5e7646d2SAndroid Build Coastguard Worker       x_dim       = ippFindAttribute(media_size, "x-dimension", IPP_TAG_ZERO);
3456*5e7646d2SAndroid Build Coastguard Worker       y_dim       = ippFindAttribute(media_size, "y-dimension", IPP_TAG_ZERO);
3457*5e7646d2SAndroid Build Coastguard Worker       pwg         = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0));
3458*5e7646d2SAndroid Build Coastguard Worker 
3459*5e7646d2SAndroid Build Coastguard Worker       if (pwg)
3460*5e7646d2SAndroid Build Coastguard Worker       {
3461*5e7646d2SAndroid Build Coastguard Worker 	temp.width  = pwg->width;
3462*5e7646d2SAndroid Build Coastguard Worker 	temp.length = pwg->length;
3463*5e7646d2SAndroid Build Coastguard Worker 	temp.bottom = bottom;
3464*5e7646d2SAndroid Build Coastguard Worker 	temp.left   = left;
3465*5e7646d2SAndroid Build Coastguard Worker 	temp.right  = right;
3466*5e7646d2SAndroid Build Coastguard Worker 	temp.top    = top;
3467*5e7646d2SAndroid Build Coastguard Worker 
3468*5e7646d2SAndroid Build Coastguard Worker 	if (temp.bottom == 0 && temp.left == 0 && temp.right == 0 && temp.top == 0)
3469*5e7646d2SAndroid Build Coastguard Worker 	  snprintf(temp.media, sizeof(temp.media), "%s.Borderless", pwg->ppd);
3470*5e7646d2SAndroid Build Coastguard Worker 	else
3471*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(temp.media, pwg->ppd, sizeof(temp.media));
3472*5e7646d2SAndroid Build Coastguard Worker 
3473*5e7646d2SAndroid Build Coastguard Worker 	if (!cupsArrayFind(sizes, &temp))
3474*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayAdd(sizes, &temp);
3475*5e7646d2SAndroid Build Coastguard Worker       }
3476*5e7646d2SAndroid Build Coastguard Worker       else if (ippGetValueTag(x_dim) == IPP_TAG_RANGE || ippGetValueTag(y_dim) == IPP_TAG_RANGE)
3477*5e7646d2SAndroid Build Coastguard Worker       {
3478*5e7646d2SAndroid Build Coastguard Worker        /*
3479*5e7646d2SAndroid Build Coastguard Worker 	* Custom size - record the min/max values...
3480*5e7646d2SAndroid Build Coastguard Worker 	*/
3481*5e7646d2SAndroid Build Coastguard Worker 
3482*5e7646d2SAndroid Build Coastguard Worker 	int lower, upper;		/* Range values */
3483*5e7646d2SAndroid Build Coastguard Worker 
3484*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetValueTag(x_dim) == IPP_TAG_RANGE)
3485*5e7646d2SAndroid Build Coastguard Worker 	  lower = ippGetRange(x_dim, 0, &upper);
3486*5e7646d2SAndroid Build Coastguard Worker 	else
3487*5e7646d2SAndroid Build Coastguard Worker 	  lower = upper = ippGetInteger(x_dim, 0);
3488*5e7646d2SAndroid Build Coastguard Worker 
3489*5e7646d2SAndroid Build Coastguard Worker 	if (lower < min_width)
3490*5e7646d2SAndroid Build Coastguard Worker 	  min_width = lower;
3491*5e7646d2SAndroid Build Coastguard Worker 	if (upper > max_width)
3492*5e7646d2SAndroid Build Coastguard Worker 	  max_width = upper;
3493*5e7646d2SAndroid Build Coastguard Worker 
3494*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetValueTag(y_dim) == IPP_TAG_RANGE)
3495*5e7646d2SAndroid Build Coastguard Worker 	  lower = ippGetRange(y_dim, 0, &upper);
3496*5e7646d2SAndroid Build Coastguard Worker 	else
3497*5e7646d2SAndroid Build Coastguard Worker 	  lower = upper = ippGetInteger(y_dim, 0);
3498*5e7646d2SAndroid Build Coastguard Worker 
3499*5e7646d2SAndroid Build Coastguard Worker 	if (lower < min_length)
3500*5e7646d2SAndroid Build Coastguard Worker 	  min_length = lower;
3501*5e7646d2SAndroid Build Coastguard Worker 	if (upper > max_length)
3502*5e7646d2SAndroid Build Coastguard Worker 	  max_length = upper;
3503*5e7646d2SAndroid Build Coastguard Worker       }
3504*5e7646d2SAndroid Build Coastguard Worker     }
3505*5e7646d2SAndroid Build Coastguard Worker   }
3506*5e7646d2SAndroid Build Coastguard Worker   else if ((attr = ippFindAttribute(response, "media-supported", IPP_TAG_ZERO)) != NULL)
3507*5e7646d2SAndroid Build Coastguard Worker   {
3508*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, count = ippGetCount(attr); i < count; i ++)
3509*5e7646d2SAndroid Build Coastguard Worker     {
3510*5e7646d2SAndroid Build Coastguard Worker       const char	*pwg_size = ippGetString(attr, i, NULL);
3511*5e7646d2SAndroid Build Coastguard Worker     					/* PWG size name */
3512*5e7646d2SAndroid Build Coastguard Worker       cups_size_t	temp;		/* Current size */
3513*5e7646d2SAndroid Build Coastguard Worker 
3514*5e7646d2SAndroid Build Coastguard Worker       if ((pwg = pwgMediaForPWG(pwg_size)) != NULL)
3515*5e7646d2SAndroid Build Coastguard Worker       {
3516*5e7646d2SAndroid Build Coastguard Worker         if (strstr(pwg_size, "_max_") || strstr(pwg_size, "_max."))
3517*5e7646d2SAndroid Build Coastguard Worker         {
3518*5e7646d2SAndroid Build Coastguard Worker           if (pwg->width > max_width)
3519*5e7646d2SAndroid Build Coastguard Worker             max_width = pwg->width;
3520*5e7646d2SAndroid Build Coastguard Worker           if (pwg->length > max_length)
3521*5e7646d2SAndroid Build Coastguard Worker             max_length = pwg->length;
3522*5e7646d2SAndroid Build Coastguard Worker         }
3523*5e7646d2SAndroid Build Coastguard Worker         else if (strstr(pwg_size, "_min_") || strstr(pwg_size, "_min."))
3524*5e7646d2SAndroid Build Coastguard Worker         {
3525*5e7646d2SAndroid Build Coastguard Worker           if (pwg->width < min_width)
3526*5e7646d2SAndroid Build Coastguard Worker             min_width = pwg->width;
3527*5e7646d2SAndroid Build Coastguard Worker           if (pwg->length < min_length)
3528*5e7646d2SAndroid Build Coastguard Worker             min_length = pwg->length;
3529*5e7646d2SAndroid Build Coastguard Worker         }
3530*5e7646d2SAndroid Build Coastguard Worker         else
3531*5e7646d2SAndroid Build Coastguard Worker         {
3532*5e7646d2SAndroid Build Coastguard Worker 	  temp.width  = pwg->width;
3533*5e7646d2SAndroid Build Coastguard Worker 	  temp.length = pwg->length;
3534*5e7646d2SAndroid Build Coastguard Worker 	  temp.bottom = bottom;
3535*5e7646d2SAndroid Build Coastguard Worker 	  temp.left   = left;
3536*5e7646d2SAndroid Build Coastguard Worker 	  temp.right  = right;
3537*5e7646d2SAndroid Build Coastguard Worker 	  temp.top    = top;
3538*5e7646d2SAndroid Build Coastguard Worker 
3539*5e7646d2SAndroid Build Coastguard Worker 	  if (temp.bottom == 0 && temp.left == 0 && temp.right == 0 && temp.top == 0)
3540*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(temp.media, sizeof(temp.media), "%s.Borderless", pwg->ppd);
3541*5e7646d2SAndroid Build Coastguard Worker 	  else
3542*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(temp.media, pwg->ppd, sizeof(temp.media));
3543*5e7646d2SAndroid Build Coastguard Worker 
3544*5e7646d2SAndroid Build Coastguard Worker 	  if (!cupsArrayFind(sizes, &temp))
3545*5e7646d2SAndroid Build Coastguard Worker 	    cupsArrayAdd(sizes, &temp);
3546*5e7646d2SAndroid Build Coastguard Worker 	}
3547*5e7646d2SAndroid Build Coastguard Worker       }
3548*5e7646d2SAndroid Build Coastguard Worker     }
3549*5e7646d2SAndroid Build Coastguard Worker   }
3550*5e7646d2SAndroid Build Coastguard Worker 
3551*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(sizes) > 0)
3552*5e7646d2SAndroid Build Coastguard Worker   {
3553*5e7646d2SAndroid Build Coastguard Worker    /*
3554*5e7646d2SAndroid Build Coastguard Worker     * List all of the standard sizes...
3555*5e7646d2SAndroid Build Coastguard Worker     */
3556*5e7646d2SAndroid Build Coastguard Worker 
3557*5e7646d2SAndroid Build Coastguard Worker     char	tleft[256],		/* Left string */
3558*5e7646d2SAndroid Build Coastguard Worker 		tbottom[256],		/* Bottom string */
3559*5e7646d2SAndroid Build Coastguard Worker 		tright[256],		/* Right string */
3560*5e7646d2SAndroid Build Coastguard Worker 		ttop[256],		/* Top string */
3561*5e7646d2SAndroid Build Coastguard Worker 		twidth[256],		/* Width string */
3562*5e7646d2SAndroid Build Coastguard Worker 		tlength[256];		/* Length string */
3563*5e7646d2SAndroid Build Coastguard Worker 
3564*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*OpenUI *PageSize: PickOne\n"
3565*5e7646d2SAndroid Build Coastguard Worker 		       "*OrderDependency: 10 AnySetup *PageSize\n"
3566*5e7646d2SAndroid Build Coastguard Worker                        "*DefaultPageSize: %s\n", ppdname);
3567*5e7646d2SAndroid Build Coastguard Worker     for (size = (cups_size_t *)cupsArrayFirst(sizes); size; size = (cups_size_t *)cupsArrayNext(sizes))
3568*5e7646d2SAndroid Build Coastguard Worker     {
3569*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(twidth, twidth + sizeof(twidth), size->width * 72.0 / 2540.0, loc);
3570*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tlength, tlength + sizeof(tlength), size->length * 72.0 / 2540.0, loc);
3571*5e7646d2SAndroid Build Coastguard Worker 
3572*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*PageSize %s: \"<</PageSize[%s %s]>>setpagedevice\"\n", size->media, twidth, tlength);
3573*5e7646d2SAndroid Build Coastguard Worker     }
3574*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *PageSize\n");
3575*5e7646d2SAndroid Build Coastguard Worker 
3576*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*OpenUI *PageRegion: PickOne\n"
3577*5e7646d2SAndroid Build Coastguard Worker                        "*OrderDependency: 10 AnySetup *PageRegion\n"
3578*5e7646d2SAndroid Build Coastguard Worker                        "*DefaultPageRegion: %s\n", ppdname);
3579*5e7646d2SAndroid Build Coastguard Worker     for (size = (cups_size_t *)cupsArrayFirst(sizes); size; size = (cups_size_t *)cupsArrayNext(sizes))
3580*5e7646d2SAndroid Build Coastguard Worker     {
3581*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(twidth, twidth + sizeof(twidth), size->width * 72.0 / 2540.0, loc);
3582*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tlength, tlength + sizeof(tlength), size->length * 72.0 / 2540.0, loc);
3583*5e7646d2SAndroid Build Coastguard Worker 
3584*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*PageRegion %s: \"<</PageSize[%s %s]>>setpagedevice\"\n", size->media, twidth, tlength);
3585*5e7646d2SAndroid Build Coastguard Worker     }
3586*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *PageRegion\n");
3587*5e7646d2SAndroid Build Coastguard Worker 
3588*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*DefaultImageableArea: %s\n"
3589*5e7646d2SAndroid Build Coastguard Worker 		       "*DefaultPaperDimension: %s\n", ppdname, ppdname);
3590*5e7646d2SAndroid Build Coastguard Worker 
3591*5e7646d2SAndroid Build Coastguard Worker     for (size = (cups_size_t *)cupsArrayFirst(sizes); size; size = (cups_size_t *)cupsArrayNext(sizes))
3592*5e7646d2SAndroid Build Coastguard Worker     {
3593*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tleft, tleft + sizeof(tleft), size->left * 72.0 / 2540.0, loc);
3594*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tbottom, tbottom + sizeof(tbottom), size->bottom * 72.0 / 2540.0, loc);
3595*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tright, tright + sizeof(tright), (size->width - size->right) * 72.0 / 2540.0, loc);
3596*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(ttop, ttop + sizeof(ttop), (size->length - size->top) * 72.0 / 2540.0, loc);
3597*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(twidth, twidth + sizeof(twidth), size->width * 72.0 / 2540.0, loc);
3598*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tlength, tlength + sizeof(tlength), size->length * 72.0 / 2540.0, loc);
3599*5e7646d2SAndroid Build Coastguard Worker 
3600*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*ImageableArea %s: \"%s %s %s %s\"\n", size->media, tleft, tbottom, tright, ttop);
3601*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*PaperDimension %s: \"%s %s\"\n", size->media, twidth, tlength);
3602*5e7646d2SAndroid Build Coastguard Worker     }
3603*5e7646d2SAndroid Build Coastguard Worker 
3604*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(sizes);
3605*5e7646d2SAndroid Build Coastguard Worker 
3606*5e7646d2SAndroid Build Coastguard Worker    /*
3607*5e7646d2SAndroid Build Coastguard Worker     * Custom size support...
3608*5e7646d2SAndroid Build Coastguard Worker     */
3609*5e7646d2SAndroid Build Coastguard Worker 
3610*5e7646d2SAndroid Build Coastguard Worker     if (max_width > 0 && min_width < INT_MAX && max_length > 0 && min_length < INT_MAX)
3611*5e7646d2SAndroid Build Coastguard Worker     {
3612*5e7646d2SAndroid Build Coastguard Worker       char	tmax[256], tmin[256];	/* Min/max values */
3613*5e7646d2SAndroid Build Coastguard Worker 
3614*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tleft, tleft + sizeof(tleft), left * 72.0 / 2540.0, loc);
3615*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tbottom, tbottom + sizeof(tbottom), bottom * 72.0 / 2540.0, loc);
3616*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tright, tright + sizeof(tright), right * 72.0 / 2540.0, loc);
3617*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(ttop, ttop + sizeof(ttop), top * 72.0 / 2540.0, loc);
3618*5e7646d2SAndroid Build Coastguard Worker 
3619*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*HWMargins: \"%s %s %s %s\"\n", tleft, tbottom, tright, ttop);
3620*5e7646d2SAndroid Build Coastguard Worker 
3621*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tmax, tmax + sizeof(tmax), max_width * 72.0 / 2540.0, loc);
3622*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tmin, tmin + sizeof(tmin), min_width * 72.0 / 2540.0, loc);
3623*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*ParamCustomPageSize Width: 1 points %s %s\n", tmin, tmax);
3624*5e7646d2SAndroid Build Coastguard Worker 
3625*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tmax, tmax + sizeof(tmax), max_length * 72.0 / 2540.0, loc);
3626*5e7646d2SAndroid Build Coastguard Worker       _cupsStrFormatd(tmin, tmin + sizeof(tmin), min_length * 72.0 / 2540.0, loc);
3627*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*ParamCustomPageSize Height: 2 points %s %s\n", tmin, tmax);
3628*5e7646d2SAndroid Build Coastguard Worker 
3629*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*ParamCustomPageSize WidthOffset: 3 points 0 0\n");
3630*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*ParamCustomPageSize HeightOffset: 4 points 0 0\n");
3631*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*ParamCustomPageSize Orientation: 5 int 0 3\n");
3632*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CustomPageSize True: \"pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\"\n");
3633*5e7646d2SAndroid Build Coastguard Worker     }
3634*5e7646d2SAndroid Build Coastguard Worker   }
3635*5e7646d2SAndroid Build Coastguard Worker   else
3636*5e7646d2SAndroid Build Coastguard Worker   {
3637*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(sizes);
3638*5e7646d2SAndroid Build Coastguard Worker     goto bad_ppd;
3639*5e7646d2SAndroid Build Coastguard Worker   }
3640*5e7646d2SAndroid Build Coastguard Worker 
3641*5e7646d2SAndroid Build Coastguard Worker  /*
3642*5e7646d2SAndroid Build Coastguard Worker   * InputSlot...
3643*5e7646d2SAndroid Build Coastguard Worker   */
3644*5e7646d2SAndroid Build Coastguard Worker 
3645*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(ippGetCollection(defattr, 0), "media-source", IPP_TAG_ZERO)) != NULL)
3646*5e7646d2SAndroid Build Coastguard Worker     pwg_ppdize_name(ippGetString(attr, 0, NULL), ppdname, sizeof(ppdname));
3647*5e7646d2SAndroid Build Coastguard Worker   else
3648*5e7646d2SAndroid Build Coastguard Worker     ppdname[0] = '\0';
3649*5e7646d2SAndroid Build Coastguard Worker 
3650*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "media-source-supported", IPP_TAG_ZERO)) != NULL && (count = ippGetCount(attr)) > 1)
3651*5e7646d2SAndroid Build Coastguard Worker   {
3652*5e7646d2SAndroid Build Coastguard Worker     int have_default = ppdname[0] != '\0';
3653*5e7646d2SAndroid Build Coastguard Worker 					/* Do we have a default InputSlot? */
3654*5e7646d2SAndroid Build Coastguard Worker     static const char * const sources[] =
3655*5e7646d2SAndroid Build Coastguard Worker     {					/* Standard "media-source" strings */
3656*5e7646d2SAndroid Build Coastguard Worker       "auto",
3657*5e7646d2SAndroid Build Coastguard Worker       "main",
3658*5e7646d2SAndroid Build Coastguard Worker       "alternate",
3659*5e7646d2SAndroid Build Coastguard Worker       "large-capacity",
3660*5e7646d2SAndroid Build Coastguard Worker       "manual",
3661*5e7646d2SAndroid Build Coastguard Worker       "envelope",
3662*5e7646d2SAndroid Build Coastguard Worker       "disc",
3663*5e7646d2SAndroid Build Coastguard Worker       "photo",
3664*5e7646d2SAndroid Build Coastguard Worker       "hagaki",
3665*5e7646d2SAndroid Build Coastguard Worker       "main-roll",
3666*5e7646d2SAndroid Build Coastguard Worker       "alternate-roll",
3667*5e7646d2SAndroid Build Coastguard Worker       "top",
3668*5e7646d2SAndroid Build Coastguard Worker       "middle",
3669*5e7646d2SAndroid Build Coastguard Worker       "bottom",
3670*5e7646d2SAndroid Build Coastguard Worker       "side",
3671*5e7646d2SAndroid Build Coastguard Worker       "left",
3672*5e7646d2SAndroid Build Coastguard Worker       "right",
3673*5e7646d2SAndroid Build Coastguard Worker       "center",
3674*5e7646d2SAndroid Build Coastguard Worker       "rear",
3675*5e7646d2SAndroid Build Coastguard Worker       "by-pass-tray",
3676*5e7646d2SAndroid Build Coastguard Worker       "tray-1",
3677*5e7646d2SAndroid Build Coastguard Worker       "tray-2",
3678*5e7646d2SAndroid Build Coastguard Worker       "tray-3",
3679*5e7646d2SAndroid Build Coastguard Worker       "tray-4",
3680*5e7646d2SAndroid Build Coastguard Worker       "tray-5",
3681*5e7646d2SAndroid Build Coastguard Worker       "tray-6",
3682*5e7646d2SAndroid Build Coastguard Worker       "tray-7",
3683*5e7646d2SAndroid Build Coastguard Worker       "tray-8",
3684*5e7646d2SAndroid Build Coastguard Worker       "tray-9",
3685*5e7646d2SAndroid Build Coastguard Worker       "tray-10",
3686*5e7646d2SAndroid Build Coastguard Worker       "tray-11",
3687*5e7646d2SAndroid Build Coastguard Worker       "tray-12",
3688*5e7646d2SAndroid Build Coastguard Worker       "tray-13",
3689*5e7646d2SAndroid Build Coastguard Worker       "tray-14",
3690*5e7646d2SAndroid Build Coastguard Worker       "tray-15",
3691*5e7646d2SAndroid Build Coastguard Worker       "tray-16",
3692*5e7646d2SAndroid Build Coastguard Worker       "tray-17",
3693*5e7646d2SAndroid Build Coastguard Worker       "tray-18",
3694*5e7646d2SAndroid Build Coastguard Worker       "tray-19",
3695*5e7646d2SAndroid Build Coastguard Worker       "tray-20",
3696*5e7646d2SAndroid Build Coastguard Worker       "roll-1",
3697*5e7646d2SAndroid Build Coastguard Worker       "roll-2",
3698*5e7646d2SAndroid Build Coastguard Worker       "roll-3",
3699*5e7646d2SAndroid Build Coastguard Worker       "roll-4",
3700*5e7646d2SAndroid Build Coastguard Worker       "roll-5",
3701*5e7646d2SAndroid Build Coastguard Worker       "roll-6",
3702*5e7646d2SAndroid Build Coastguard Worker       "roll-7",
3703*5e7646d2SAndroid Build Coastguard Worker       "roll-8",
3704*5e7646d2SAndroid Build Coastguard Worker       "roll-9",
3705*5e7646d2SAndroid Build Coastguard Worker       "roll-10"
3706*5e7646d2SAndroid Build Coastguard Worker     };
3707*5e7646d2SAndroid Build Coastguard Worker 
3708*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*OpenUI *InputSlot: PickOne\n"
3709*5e7646d2SAndroid Build Coastguard Worker                      "*OrderDependency: 10 AnySetup *InputSlot\n");
3710*5e7646d2SAndroid Build Coastguard Worker     if (have_default)
3711*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*DefaultInputSlot: %s\n", ppdname);
3712*5e7646d2SAndroid Build Coastguard Worker 
3713*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
3714*5e7646d2SAndroid Build Coastguard Worker     {
3715*5e7646d2SAndroid Build Coastguard Worker       keyword = ippGetString(attr, i, NULL);
3716*5e7646d2SAndroid Build Coastguard Worker 
3717*5e7646d2SAndroid Build Coastguard Worker       pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
3718*5e7646d2SAndroid Build Coastguard Worker 
3719*5e7646d2SAndroid Build Coastguard Worker       if (i == 0 && !have_default)
3720*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*DefaultInputSlot: %s\n", ppdname);
3721*5e7646d2SAndroid Build Coastguard Worker 
3722*5e7646d2SAndroid Build Coastguard Worker       for (j = 0; j < (int)(sizeof(sources) / sizeof(sources[0])); j ++)
3723*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(sources[j], keyword))
3724*5e7646d2SAndroid Build Coastguard Worker 	{
3725*5e7646d2SAndroid Build Coastguard Worker 	  snprintf(msgid, sizeof(msgid), "media-source.%s", keyword);
3726*5e7646d2SAndroid Build Coastguard Worker 
3727*5e7646d2SAndroid Build Coastguard Worker 	  if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
3728*5e7646d2SAndroid Build Coastguard Worker 	    if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
3729*5e7646d2SAndroid Build Coastguard Worker 	      msgstr = keyword;
3730*5e7646d2SAndroid Build Coastguard Worker 
3731*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(fp, "*InputSlot %s: \"<</MediaPosition %d>>setpagedevice\"\n", ppdname, j);
3732*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(fp, "*%s.InputSlot %s/%s: \"\"\n", lang->language, ppdname, msgstr);
3733*5e7646d2SAndroid Build Coastguard Worker 	  break;
3734*5e7646d2SAndroid Build Coastguard Worker 	}
3735*5e7646d2SAndroid Build Coastguard Worker     }
3736*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *InputSlot\n");
3737*5e7646d2SAndroid Build Coastguard Worker   }
3738*5e7646d2SAndroid Build Coastguard Worker 
3739*5e7646d2SAndroid Build Coastguard Worker  /*
3740*5e7646d2SAndroid Build Coastguard Worker   * MediaType...
3741*5e7646d2SAndroid Build Coastguard Worker   */
3742*5e7646d2SAndroid Build Coastguard Worker 
3743*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(ippGetCollection(defattr, 0), "media-type", IPP_TAG_ZERO)) != NULL)
3744*5e7646d2SAndroid Build Coastguard Worker     pwg_ppdize_name(ippGetString(attr, 0, NULL), ppdname, sizeof(ppdname));
3745*5e7646d2SAndroid Build Coastguard Worker   else
3746*5e7646d2SAndroid Build Coastguard Worker     strlcpy(ppdname, "Unknown", sizeof(ppdname));
3747*5e7646d2SAndroid Build Coastguard Worker 
3748*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "media-type-supported", IPP_TAG_ZERO)) != NULL && (count = ippGetCount(attr)) > 1)
3749*5e7646d2SAndroid Build Coastguard Worker   {
3750*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*OpenUI *MediaType: PickOne\n"
3751*5e7646d2SAndroid Build Coastguard Worker                        "*OrderDependency: 10 AnySetup *MediaType\n"
3752*5e7646d2SAndroid Build Coastguard Worker                        "*DefaultMediaType: %s\n", ppdname);
3753*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
3754*5e7646d2SAndroid Build Coastguard Worker     {
3755*5e7646d2SAndroid Build Coastguard Worker       keyword = ippGetString(attr, i, NULL);
3756*5e7646d2SAndroid Build Coastguard Worker 
3757*5e7646d2SAndroid Build Coastguard Worker       pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
3758*5e7646d2SAndroid Build Coastguard Worker 
3759*5e7646d2SAndroid Build Coastguard Worker       snprintf(msgid, sizeof(msgid), "media-type.%s", keyword);
3760*5e7646d2SAndroid Build Coastguard Worker       if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
3761*5e7646d2SAndroid Build Coastguard Worker 	if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
3762*5e7646d2SAndroid Build Coastguard Worker 	  msgstr = keyword;
3763*5e7646d2SAndroid Build Coastguard Worker 
3764*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*MediaType %s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, ppdname);
3765*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.MediaType %s/%s: \"\"\n", lang->language, ppdname, msgstr);
3766*5e7646d2SAndroid Build Coastguard Worker     }
3767*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *MediaType\n");
3768*5e7646d2SAndroid Build Coastguard Worker   }
3769*5e7646d2SAndroid Build Coastguard Worker 
3770*5e7646d2SAndroid Build Coastguard Worker  /*
3771*5e7646d2SAndroid Build Coastguard Worker   * ColorModel...
3772*5e7646d2SAndroid Build Coastguard Worker   */
3773*5e7646d2SAndroid Build Coastguard Worker 
3774*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) == NULL)
3775*5e7646d2SAndroid Build Coastguard Worker     if ((attr = ippFindAttribute(response, "pwg-raster-document-type-supported", IPP_TAG_KEYWORD)) == NULL)
3776*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ippFindAttribute(response, "print-color-mode-supported", IPP_TAG_KEYWORD)) == NULL)
3777*5e7646d2SAndroid Build Coastguard Worker         attr = ippFindAttribute(response, "output-mode-supported", IPP_TAG_KEYWORD);
3778*5e7646d2SAndroid Build Coastguard Worker 
3779*5e7646d2SAndroid Build Coastguard Worker   if (attr)
3780*5e7646d2SAndroid Build Coastguard Worker   {
3781*5e7646d2SAndroid Build Coastguard Worker     int wrote_color = 0;
3782*5e7646d2SAndroid Build Coastguard Worker     const char *default_color = NULL;	/* Default */
3783*5e7646d2SAndroid Build Coastguard Worker 
3784*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*%% ColorModel from %s\n", ippGetName(attr));
3785*5e7646d2SAndroid Build Coastguard Worker 
3786*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, count = ippGetCount(attr); i < count; i ++)
3787*5e7646d2SAndroid Build Coastguard Worker     {
3788*5e7646d2SAndroid Build Coastguard Worker       keyword = ippGetString(attr, i, NULL);
3789*5e7646d2SAndroid Build Coastguard Worker 
3790*5e7646d2SAndroid Build Coastguard Worker #define PRINTF_COLORMODEL if (!wrote_color) { cupsFilePrintf(fp, "*OpenUI *ColorModel: PickOne\n*OrderDependency: 10 AnySetup *ColorModel\n*%s.Translation ColorModel/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color Mode"))); wrote_color = 1; }
3791*5e7646d2SAndroid Build Coastguard Worker #define PRINTF_COLOROPTION(name,text,cspace,bpp) { cupsFilePrintf(fp, "*ColorModel %s: \"<</cupsColorSpace %d/cupsBitsPerColor %d/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", name, cspace, bpp); cupsFilePrintf(fp, "*%s.ColorModel %s/%s: \"\"\n", lang->language, name, _cupsLangString(lang, text)); }
3792*5e7646d2SAndroid Build Coastguard Worker 
3793*5e7646d2SAndroid Build Coastguard Worker       if (!strcasecmp(keyword, "black_1") || !strcmp(keyword, "bi-level") || !strcmp(keyword, "process-bi-level"))
3794*5e7646d2SAndroid Build Coastguard Worker       {
3795*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3796*5e7646d2SAndroid Build Coastguard Worker 
3797*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("FastGray", _("Fast Grayscale"), CUPS_CSPACE_K, 1)
3798*5e7646d2SAndroid Build Coastguard Worker 
3799*5e7646d2SAndroid Build Coastguard Worker 	if (!default_color)
3800*5e7646d2SAndroid Build Coastguard Worker 	  default_color = "FastGray";
3801*5e7646d2SAndroid Build Coastguard Worker       }
3802*5e7646d2SAndroid Build Coastguard Worker       else if (!strcasecmp(keyword, "sgray_8") || !strcmp(keyword, "W8") || !strcmp(keyword, "monochrome") || !strcmp(keyword, "process-monochrome"))
3803*5e7646d2SAndroid Build Coastguard Worker       {
3804*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3805*5e7646d2SAndroid Build Coastguard Worker 
3806*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("Gray", _("Grayscale"), CUPS_CSPACE_SW, 8)
3807*5e7646d2SAndroid Build Coastguard Worker 
3808*5e7646d2SAndroid Build Coastguard Worker 	if (!default_color || !strcmp(default_color, "FastGray"))
3809*5e7646d2SAndroid Build Coastguard Worker 	  default_color = "Gray";
3810*5e7646d2SAndroid Build Coastguard Worker       }
3811*5e7646d2SAndroid Build Coastguard Worker       else if (!strcasecmp(keyword, "sgray_16") || !strcmp(keyword, "W8-16"))
3812*5e7646d2SAndroid Build Coastguard Worker       {
3813*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3814*5e7646d2SAndroid Build Coastguard Worker 
3815*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(keyword, "W8-16"))
3816*5e7646d2SAndroid Build Coastguard Worker 	{
3817*5e7646d2SAndroid Build Coastguard Worker 	  PRINTF_COLOROPTION("Gray", _("Grayscale"), CUPS_CSPACE_SW, 8)
3818*5e7646d2SAndroid Build Coastguard Worker 
3819*5e7646d2SAndroid Build Coastguard Worker 	  if (!default_color || !strcmp(default_color, "FastGray"))
3820*5e7646d2SAndroid Build Coastguard Worker 	    default_color = "Gray";
3821*5e7646d2SAndroid Build Coastguard Worker 	}
3822*5e7646d2SAndroid Build Coastguard Worker 
3823*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("Gray16", _("Deep Gray"), CUPS_CSPACE_SW, 16)
3824*5e7646d2SAndroid Build Coastguard Worker       }
3825*5e7646d2SAndroid Build Coastguard Worker       else if (!strcasecmp(keyword, "srgb_8") || !strncmp(keyword, "SRGB24", 7) || !strcmp(keyword, "color"))
3826*5e7646d2SAndroid Build Coastguard Worker       {
3827*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3828*5e7646d2SAndroid Build Coastguard Worker 
3829*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("RGB", _("Color"), CUPS_CSPACE_SRGB, 8)
3830*5e7646d2SAndroid Build Coastguard Worker 
3831*5e7646d2SAndroid Build Coastguard Worker 	default_color = "RGB";
3832*5e7646d2SAndroid Build Coastguard Worker 
3833*5e7646d2SAndroid Build Coastguard Worker         // Apparently some printers only advertise color support, so make sure
3834*5e7646d2SAndroid Build Coastguard Worker         // we also do grayscale for these printers...
3835*5e7646d2SAndroid Build Coastguard Worker 	if (!ippContainsString(attr, "sgray_8") && !ippContainsString(attr, "black_1") && !ippContainsString(attr, "black_8") && !ippContainsString(attr, "W8") && !ippContainsString(attr, "W8-16"))
3836*5e7646d2SAndroid Build Coastguard Worker 	  PRINTF_COLOROPTION("Gray", _("GrayScale"), CUPS_CSPACE_SW, 8)
3837*5e7646d2SAndroid Build Coastguard Worker       }
3838*5e7646d2SAndroid Build Coastguard Worker       else if (!strcasecmp(keyword, "adobe-rgb_16") || !strcmp(keyword, "ADOBERGB48") || !strcmp(keyword, "ADOBERGB24-48"))
3839*5e7646d2SAndroid Build Coastguard Worker       {
3840*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3841*5e7646d2SAndroid Build Coastguard Worker 
3842*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("AdobeRGB", _("Deep Color"), CUPS_CSPACE_ADOBERGB, 16)
3843*5e7646d2SAndroid Build Coastguard Worker 
3844*5e7646d2SAndroid Build Coastguard Worker 	if (!default_color)
3845*5e7646d2SAndroid Build Coastguard Worker 	  default_color = "AdobeRGB";
3846*5e7646d2SAndroid Build Coastguard Worker       }
3847*5e7646d2SAndroid Build Coastguard Worker       else if ((!strcasecmp(keyword, "adobe-rgb_8") && !ippContainsString(attr, "adobe-rgb_16")) || !strcmp(keyword, "ADOBERGB24"))
3848*5e7646d2SAndroid Build Coastguard Worker       {
3849*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3850*5e7646d2SAndroid Build Coastguard Worker 
3851*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("AdobeRGB", _("Deep Color"), CUPS_CSPACE_ADOBERGB, 8)
3852*5e7646d2SAndroid Build Coastguard Worker 
3853*5e7646d2SAndroid Build Coastguard Worker 	if (!default_color)
3854*5e7646d2SAndroid Build Coastguard Worker 	  default_color = "AdobeRGB";
3855*5e7646d2SAndroid Build Coastguard Worker       }
3856*5e7646d2SAndroid Build Coastguard Worker       else if ((!strcasecmp(keyword, "black_8") && !ippContainsString(attr, "black_16")) || !strcmp(keyword, "DEVW8"))
3857*5e7646d2SAndroid Build Coastguard Worker       {
3858*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3859*5e7646d2SAndroid Build Coastguard Worker 
3860*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("DeviceGray", _("Device Gray"), CUPS_CSPACE_W, 8)
3861*5e7646d2SAndroid Build Coastguard Worker       }
3862*5e7646d2SAndroid Build Coastguard Worker       else if (!strcasecmp(keyword, "black_16") || !strcmp(keyword, "DEVW16") || !strcmp(keyword, "DEVW8-16"))
3863*5e7646d2SAndroid Build Coastguard Worker       {
3864*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3865*5e7646d2SAndroid Build Coastguard Worker 
3866*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("DeviceGray", _("Device Gray"), CUPS_CSPACE_W, 16)
3867*5e7646d2SAndroid Build Coastguard Worker       }
3868*5e7646d2SAndroid Build Coastguard Worker       else if ((!strcasecmp(keyword, "cmyk_8") && !ippContainsString(attr, "cmyk_16")) || !strcmp(keyword, "DEVCMYK32"))
3869*5e7646d2SAndroid Build Coastguard Worker       {
3870*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3871*5e7646d2SAndroid Build Coastguard Worker 
3872*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("CMYK", _("Device CMYK"), CUPS_CSPACE_CMYK, 8)
3873*5e7646d2SAndroid Build Coastguard Worker       }
3874*5e7646d2SAndroid Build Coastguard Worker       else if (!strcasecmp(keyword, "cmyk_16") || !strcmp(keyword, "DEVCMYK32-64") || !strcmp(keyword, "DEVCMYK64"))
3875*5e7646d2SAndroid Build Coastguard Worker       {
3876*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3877*5e7646d2SAndroid Build Coastguard Worker 
3878*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("CMYK", _("Device CMYK"), CUPS_CSPACE_CMYK, 16)
3879*5e7646d2SAndroid Build Coastguard Worker       }
3880*5e7646d2SAndroid Build Coastguard Worker       else if ((!strcasecmp(keyword, "rgb_8") && ippContainsString(attr, "rgb_16")) || !strcmp(keyword, "DEVRGB24"))
3881*5e7646d2SAndroid Build Coastguard Worker       {
3882*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3883*5e7646d2SAndroid Build Coastguard Worker 
3884*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("DeviceRGB", _("Device RGB"), CUPS_CSPACE_RGB, 8)
3885*5e7646d2SAndroid Build Coastguard Worker       }
3886*5e7646d2SAndroid Build Coastguard Worker       else if (!strcasecmp(keyword, "rgb_16") || !strcmp(keyword, "DEVRGB24-48") || !strcmp(keyword, "DEVRGB48"))
3887*5e7646d2SAndroid Build Coastguard Worker       {
3888*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLORMODEL
3889*5e7646d2SAndroid Build Coastguard Worker 
3890*5e7646d2SAndroid Build Coastguard Worker 	PRINTF_COLOROPTION("DeviceRGB", _("Device RGB"), CUPS_CSPACE_RGB, 16)
3891*5e7646d2SAndroid Build Coastguard Worker       }
3892*5e7646d2SAndroid Build Coastguard Worker     }
3893*5e7646d2SAndroid Build Coastguard Worker 
3894*5e7646d2SAndroid Build Coastguard Worker     if (default_color)
3895*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*DefaultColorModel: %s\n", default_color);
3896*5e7646d2SAndroid Build Coastguard Worker     if (wrote_color)
3897*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CloseUI: *ColorModel\n");
3898*5e7646d2SAndroid Build Coastguard Worker   }
3899*5e7646d2SAndroid Build Coastguard Worker 
3900*5e7646d2SAndroid Build Coastguard Worker  /*
3901*5e7646d2SAndroid Build Coastguard Worker   * Duplex...
3902*5e7646d2SAndroid Build Coastguard Worker   */
3903*5e7646d2SAndroid Build Coastguard Worker 
3904*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "sides-supported", IPP_TAG_KEYWORD)) != NULL && ippContainsString(attr, "two-sided-long-edge"))
3905*5e7646d2SAndroid Build Coastguard Worker   {
3906*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*OpenUI *Duplex: PickOne\n"
3907*5e7646d2SAndroid Build Coastguard Worker 		       "*OrderDependency: 10 AnySetup *Duplex\n"
3908*5e7646d2SAndroid Build Coastguard Worker 		       "*%s.Translation Duplex/%s: \"\"\n"
3909*5e7646d2SAndroid Build Coastguard Worker 		       "*DefaultDuplex: None\n"
3910*5e7646d2SAndroid Build Coastguard Worker 		       "*Duplex None: \"<</Duplex false>>setpagedevice\"\n"
3911*5e7646d2SAndroid Build Coastguard Worker 		       "*%s.Duplex None/%s: \"\"\n"
3912*5e7646d2SAndroid Build Coastguard Worker 		       "*Duplex DuplexNoTumble: \"<</Duplex true/Tumble false>>setpagedevice\"\n"
3913*5e7646d2SAndroid Build Coastguard Worker 		       "*%s.Duplex DuplexNoTumble/%s: \"\"\n"
3914*5e7646d2SAndroid Build Coastguard Worker 		       "*Duplex DuplexTumble: \"<</Duplex true/Tumble true>>setpagedevice\"\n"
3915*5e7646d2SAndroid Build Coastguard Worker 		       "*%s.Duplex DuplexTumble/%s: \"\"\n"
3916*5e7646d2SAndroid Build Coastguard Worker 		       "*CloseUI: *Duplex\n", lang->language, _cupsLangString(lang, _("2-Sided Printing")), lang->language, _cupsLangString(lang, _("Off (1-Sided)")), lang->language, _cupsLangString(lang, _("Long-Edge (Portrait)")), lang->language, _cupsLangString(lang, _("Short-Edge (Landscape)")));
3917*5e7646d2SAndroid Build Coastguard Worker 
3918*5e7646d2SAndroid Build Coastguard Worker     if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
3919*5e7646d2SAndroid Build Coastguard Worker     {
3920*5e7646d2SAndroid Build Coastguard Worker       for (i = 0, count = ippGetCount(attr); i < count; i ++)
3921*5e7646d2SAndroid Build Coastguard Worker       {
3922*5e7646d2SAndroid Build Coastguard Worker         const char *dm = ippGetString(attr, i, NULL);
3923*5e7646d2SAndroid Build Coastguard Worker                                         /* DM value */
3924*5e7646d2SAndroid Build Coastguard Worker 
3925*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strcasecmp(dm, "DM1"))
3926*5e7646d2SAndroid Build Coastguard Worker         {
3927*5e7646d2SAndroid Build Coastguard Worker           cupsFilePuts(fp, "*cupsBackSide: Normal\n");
3928*5e7646d2SAndroid Build Coastguard Worker           break;
3929*5e7646d2SAndroid Build Coastguard Worker         }
3930*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(dm, "DM2"))
3931*5e7646d2SAndroid Build Coastguard Worker         {
3932*5e7646d2SAndroid Build Coastguard Worker           cupsFilePuts(fp, "*cupsBackSide: Flipped\n");
3933*5e7646d2SAndroid Build Coastguard Worker           break;
3934*5e7646d2SAndroid Build Coastguard Worker         }
3935*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(dm, "DM3"))
3936*5e7646d2SAndroid Build Coastguard Worker         {
3937*5e7646d2SAndroid Build Coastguard Worker           cupsFilePuts(fp, "*cupsBackSide: Rotated\n");
3938*5e7646d2SAndroid Build Coastguard Worker           break;
3939*5e7646d2SAndroid Build Coastguard Worker         }
3940*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(dm, "DM4"))
3941*5e7646d2SAndroid Build Coastguard Worker         {
3942*5e7646d2SAndroid Build Coastguard Worker           cupsFilePuts(fp, "*cupsBackSide: ManualTumble\n");
3943*5e7646d2SAndroid Build Coastguard Worker           break;
3944*5e7646d2SAndroid Build Coastguard Worker         }
3945*5e7646d2SAndroid Build Coastguard Worker       }
3946*5e7646d2SAndroid Build Coastguard Worker     }
3947*5e7646d2SAndroid Build Coastguard Worker     else if ((attr = ippFindAttribute(response, "pwg-raster-document-sheet-back", IPP_TAG_KEYWORD)) != NULL)
3948*5e7646d2SAndroid Build Coastguard Worker     {
3949*5e7646d2SAndroid Build Coastguard Worker       keyword = ippGetString(attr, 0, NULL);
3950*5e7646d2SAndroid Build Coastguard Worker 
3951*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(keyword, "flipped"))
3952*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(fp, "*cupsBackSide: Flipped\n");
3953*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(keyword, "manual-tumble"))
3954*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(fp, "*cupsBackSide: ManualTumble\n");
3955*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(keyword, "normal"))
3956*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(fp, "*cupsBackSide: Normal\n");
3957*5e7646d2SAndroid Build Coastguard Worker       else
3958*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(fp, "*cupsBackSide: Rotated\n");
3959*5e7646d2SAndroid Build Coastguard Worker     }
3960*5e7646d2SAndroid Build Coastguard Worker   }
3961*5e7646d2SAndroid Build Coastguard Worker 
3962*5e7646d2SAndroid Build Coastguard Worker  /*
3963*5e7646d2SAndroid Build Coastguard Worker   * Output bin...
3964*5e7646d2SAndroid Build Coastguard Worker   */
3965*5e7646d2SAndroid Build Coastguard Worker 
3966*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "output-bin-default", IPP_TAG_ZERO)) != NULL)
3967*5e7646d2SAndroid Build Coastguard Worker     pwg_ppdize_name(ippGetString(attr, 0, NULL), ppdname, sizeof(ppdname));
3968*5e7646d2SAndroid Build Coastguard Worker   else
3969*5e7646d2SAndroid Build Coastguard Worker     strlcpy(ppdname, "Unknown", sizeof(ppdname));
3970*5e7646d2SAndroid Build Coastguard Worker 
3971*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "output-bin-supported", IPP_TAG_ZERO)) != NULL && (count = ippGetCount(attr)) > 0)
3972*5e7646d2SAndroid Build Coastguard Worker   {
3973*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t	*trays = ippFindAttribute(response, "printer-output-tray", IPP_TAG_STRING);
3974*5e7646d2SAndroid Build Coastguard Worker 					/* printer-output-tray attribute, if any */
3975*5e7646d2SAndroid Build Coastguard Worker     const char		*tray_ptr;	/* printer-output-tray value */
3976*5e7646d2SAndroid Build Coastguard Worker     int			tray_len;	/* Len of printer-output-tray value */
3977*5e7646d2SAndroid Build Coastguard Worker     char		tray[IPP_MAX_OCTETSTRING];
3978*5e7646d2SAndroid Build Coastguard Worker 					/* printer-output-tray string value */
3979*5e7646d2SAndroid Build Coastguard Worker 
3980*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*OpenUI *OutputBin: PickOne\n"
3981*5e7646d2SAndroid Build Coastguard Worker                        "*OrderDependency: 10 AnySetup *OutputBin\n"
3982*5e7646d2SAndroid Build Coastguard Worker                        "*DefaultOutputBin: %s\n", ppdname);
3983*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(ppdname, "FaceUp"))
3984*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*DefaultOutputOrder: Reverse\n");
3985*5e7646d2SAndroid Build Coastguard Worker     else
3986*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*DefaultOutputOrder: Normal\n");
3987*5e7646d2SAndroid Build Coastguard Worker 
3988*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
3989*5e7646d2SAndroid Build Coastguard Worker     {
3990*5e7646d2SAndroid Build Coastguard Worker       keyword = ippGetString(attr, i, NULL);
3991*5e7646d2SAndroid Build Coastguard Worker 
3992*5e7646d2SAndroid Build Coastguard Worker       pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
3993*5e7646d2SAndroid Build Coastguard Worker 
3994*5e7646d2SAndroid Build Coastguard Worker       snprintf(msgid, sizeof(msgid), "output-bin.%s", keyword);
3995*5e7646d2SAndroid Build Coastguard Worker       if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
3996*5e7646d2SAndroid Build Coastguard Worker 	if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
3997*5e7646d2SAndroid Build Coastguard Worker 	  msgstr = keyword;
3998*5e7646d2SAndroid Build Coastguard Worker 
3999*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*OutputBin %s: \"\"\n", ppdname);
4000*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.OutputBin %s/%s: \"\"\n", lang->language, ppdname, msgstr);
4001*5e7646d2SAndroid Build Coastguard Worker 
4002*5e7646d2SAndroid Build Coastguard Worker       if ((tray_ptr = ippGetOctetString(trays, i, &tray_len)) != NULL)
4003*5e7646d2SAndroid Build Coastguard Worker       {
4004*5e7646d2SAndroid Build Coastguard Worker         if (tray_len >= (int)sizeof(tray))
4005*5e7646d2SAndroid Build Coastguard Worker           tray_len = (int)sizeof(tray) - 1;
4006*5e7646d2SAndroid Build Coastguard Worker 
4007*5e7646d2SAndroid Build Coastguard Worker         memcpy(tray, tray_ptr, (size_t)tray_len);
4008*5e7646d2SAndroid Build Coastguard Worker         tray[tray_len] = '\0';
4009*5e7646d2SAndroid Build Coastguard Worker 
4010*5e7646d2SAndroid Build Coastguard Worker         if (strstr(tray, "stackingorder=lastToFirst;"))
4011*5e7646d2SAndroid Build Coastguard Worker           cupsFilePrintf(fp, "*PageStackOrder %s: Reverse\n", ppdname);
4012*5e7646d2SAndroid Build Coastguard Worker         else
4013*5e7646d2SAndroid Build Coastguard Worker           cupsFilePrintf(fp, "*PageStackOrder %s: Normal\n", ppdname);
4014*5e7646d2SAndroid Build Coastguard Worker       }
4015*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(ppdname, "FaceUp"))
4016*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*PageStackOrder %s: Reverse\n", ppdname);
4017*5e7646d2SAndroid Build Coastguard Worker       else
4018*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*PageStackOrder %s: Normal\n", ppdname);
4019*5e7646d2SAndroid Build Coastguard Worker     }
4020*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *OutputBin\n");
4021*5e7646d2SAndroid Build Coastguard Worker   }
4022*5e7646d2SAndroid Build Coastguard Worker 
4023*5e7646d2SAndroid Build Coastguard Worker  /*
4024*5e7646d2SAndroid Build Coastguard Worker   * Finishing options...
4025*5e7646d2SAndroid Build Coastguard Worker   */
4026*5e7646d2SAndroid Build Coastguard Worker 
4027*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "finishings-supported", IPP_TAG_ENUM)) != NULL)
4028*5e7646d2SAndroid Build Coastguard Worker   {
4029*5e7646d2SAndroid Build Coastguard Worker     int			value;		/* Enum value */
4030*5e7646d2SAndroid Build Coastguard Worker     const char		*ppd_keyword;	/* PPD keyword for enum */
4031*5e7646d2SAndroid Build Coastguard Worker     cups_array_t	*names;		/* Names we've added */
4032*5e7646d2SAndroid Build Coastguard Worker     static const char * const base_keywords[] =
4033*5e7646d2SAndroid Build Coastguard Worker     {					/* Base STD 92 keywords */
4034*5e7646d2SAndroid Build Coastguard Worker       NULL,				/* none */
4035*5e7646d2SAndroid Build Coastguard Worker       "SingleAuto",			/* staple */
4036*5e7646d2SAndroid Build Coastguard Worker       "SingleAuto",			/* punch */
4037*5e7646d2SAndroid Build Coastguard Worker       NULL,				/* cover */
4038*5e7646d2SAndroid Build Coastguard Worker       "BindAuto",			/* bind */
4039*5e7646d2SAndroid Build Coastguard Worker       "SaddleStitch",			/* saddle-stitch */
4040*5e7646d2SAndroid Build Coastguard Worker       "EdgeStitchAuto",			/* edge-stitch */
4041*5e7646d2SAndroid Build Coastguard Worker       "Auto",				/* fold */
4042*5e7646d2SAndroid Build Coastguard Worker       NULL,				/* trim */
4043*5e7646d2SAndroid Build Coastguard Worker       NULL,				/* bale */
4044*5e7646d2SAndroid Build Coastguard Worker       NULL,				/* booklet-maker */
4045*5e7646d2SAndroid Build Coastguard Worker       NULL,				/* jog-offset */
4046*5e7646d2SAndroid Build Coastguard Worker       NULL,				/* coat */
4047*5e7646d2SAndroid Build Coastguard Worker       NULL				/* laminate */
4048*5e7646d2SAndroid Build Coastguard Worker     };
4049*5e7646d2SAndroid Build Coastguard Worker 
4050*5e7646d2SAndroid Build Coastguard Worker     count       = ippGetCount(attr);
4051*5e7646d2SAndroid Build Coastguard Worker     names       = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
4052*5e7646d2SAndroid Build Coastguard Worker     fin_options = cupsArrayNew((cups_array_func_t)strcmp, NULL);
4053*5e7646d2SAndroid Build Coastguard Worker 
4054*5e7646d2SAndroid Build Coastguard Worker    /*
4055*5e7646d2SAndroid Build Coastguard Worker     * Staple/Bind/Stitch
4056*5e7646d2SAndroid Build Coastguard Worker     */
4057*5e7646d2SAndroid Build Coastguard Worker 
4058*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
4059*5e7646d2SAndroid Build Coastguard Worker     {
4060*5e7646d2SAndroid Build Coastguard Worker       value   = ippGetInteger(attr, i);
4061*5e7646d2SAndroid Build Coastguard Worker       keyword = ippEnumString("finishings", value);
4062*5e7646d2SAndroid Build Coastguard Worker 
4063*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(keyword, "staple-", 7) || !strncmp(keyword, "bind-", 5) || !strncmp(keyword, "edge-stitch-", 12) || !strcmp(keyword, "saddle-stitch"))
4064*5e7646d2SAndroid Build Coastguard Worker         break;
4065*5e7646d2SAndroid Build Coastguard Worker     }
4066*5e7646d2SAndroid Build Coastguard Worker 
4067*5e7646d2SAndroid Build Coastguard Worker     if (i < count)
4068*5e7646d2SAndroid Build Coastguard Worker     {
4069*5e7646d2SAndroid Build Coastguard Worker       static const char * const staple_keywords[] =
4070*5e7646d2SAndroid Build Coastguard Worker       {					/* StapleLocation keywords */
4071*5e7646d2SAndroid Build Coastguard Worker 	"SinglePortrait",
4072*5e7646d2SAndroid Build Coastguard Worker 	"SingleRevLandscape",
4073*5e7646d2SAndroid Build Coastguard Worker 	"SingleLandscape",
4074*5e7646d2SAndroid Build Coastguard Worker 	"SingleRevPortrait",
4075*5e7646d2SAndroid Build Coastguard Worker 	"EdgeStitchPortrait",
4076*5e7646d2SAndroid Build Coastguard Worker 	"EdgeStitchLandscape",
4077*5e7646d2SAndroid Build Coastguard Worker 	"EdgeStitchRevPortrait",
4078*5e7646d2SAndroid Build Coastguard Worker 	"EdgeStitchRevLandscape",
4079*5e7646d2SAndroid Build Coastguard Worker 	"DualPortrait",
4080*5e7646d2SAndroid Build Coastguard Worker 	"DualLandscape",
4081*5e7646d2SAndroid Build Coastguard Worker 	"DualRevPortrait",
4082*5e7646d2SAndroid Build Coastguard Worker 	"DualRevLandscape",
4083*5e7646d2SAndroid Build Coastguard Worker 	"TriplePortrait",
4084*5e7646d2SAndroid Build Coastguard Worker 	"TripleLandscape",
4085*5e7646d2SAndroid Build Coastguard Worker 	"TripleRevPortrait",
4086*5e7646d2SAndroid Build Coastguard Worker 	"TripleRevLandscape"
4087*5e7646d2SAndroid Build Coastguard Worker       };
4088*5e7646d2SAndroid Build Coastguard Worker       static const char * const bind_keywords[] =
4089*5e7646d2SAndroid Build Coastguard Worker       {					/* StapleLocation binding keywords */
4090*5e7646d2SAndroid Build Coastguard Worker 	"BindPortrait",
4091*5e7646d2SAndroid Build Coastguard Worker 	"BindLandscape",
4092*5e7646d2SAndroid Build Coastguard Worker 	"BindRevPortrait",
4093*5e7646d2SAndroid Build Coastguard Worker 	"BindRevLandscape"
4094*5e7646d2SAndroid Build Coastguard Worker       };
4095*5e7646d2SAndroid Build Coastguard Worker 
4096*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(fin_options, "*StapleLocation");
4097*5e7646d2SAndroid Build Coastguard Worker 
4098*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OpenUI *StapleLocation: PickOne\n");
4099*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *StapleLocation\n");
4100*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.Translation StapleLocation/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Staple")));
4101*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*DefaultStapleLocation: None\n");
4102*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*StapleLocation None: \"\"\n");
4103*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.StapleLocation None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
4104*5e7646d2SAndroid Build Coastguard Worker 
4105*5e7646d2SAndroid Build Coastguard Worker       for (; i < count; i ++)
4106*5e7646d2SAndroid Build Coastguard Worker       {
4107*5e7646d2SAndroid Build Coastguard Worker         value   = ippGetInteger(attr, i);
4108*5e7646d2SAndroid Build Coastguard Worker         keyword = ippEnumString("finishings", value);
4109*5e7646d2SAndroid Build Coastguard Worker 
4110*5e7646d2SAndroid Build Coastguard Worker         if (strncmp(keyword, "staple-", 7) && strncmp(keyword, "bind-", 5) && strncmp(keyword, "edge-stitch-", 12) && strcmp(keyword, "saddle-stitch"))
4111*5e7646d2SAndroid Build Coastguard Worker           continue;
4112*5e7646d2SAndroid Build Coastguard Worker 
4113*5e7646d2SAndroid Build Coastguard Worker         if (cupsArrayFind(names, (char *)keyword))
4114*5e7646d2SAndroid Build Coastguard Worker           continue;			/* Already did this finishing template */
4115*5e7646d2SAndroid Build Coastguard Worker 
4116*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(names, (char *)keyword);
4117*5e7646d2SAndroid Build Coastguard Worker 
4118*5e7646d2SAndroid Build Coastguard Worker 	snprintf(msgid, sizeof(msgid), "finishings.%d", value);
4119*5e7646d2SAndroid Build Coastguard Worker 	if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
4120*5e7646d2SAndroid Build Coastguard Worker 	  if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
4121*5e7646d2SAndroid Build Coastguard Worker 	    msgstr = keyword;
4122*5e7646d2SAndroid Build Coastguard Worker 
4123*5e7646d2SAndroid Build Coastguard Worker         if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
4124*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
4125*5e7646d2SAndroid Build Coastguard Worker         else if (value >= IPP_FINISHINGS_STAPLE_TOP_LEFT && value <= IPP_FINISHINGS_STAPLE_TRIPLE_BOTTOM)
4126*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = staple_keywords[value - IPP_FINISHINGS_STAPLE_TOP_LEFT];
4127*5e7646d2SAndroid Build Coastguard Worker         else if (value >= IPP_FINISHINGS_BIND_LEFT && value <= IPP_FINISHINGS_BIND_BOTTOM)
4128*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = bind_keywords[value - IPP_FINISHINGS_BIND_LEFT];
4129*5e7646d2SAndroid Build Coastguard Worker         else
4130*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = NULL;
4131*5e7646d2SAndroid Build Coastguard Worker 
4132*5e7646d2SAndroid Build Coastguard Worker         if (!ppd_keyword)
4133*5e7646d2SAndroid Build Coastguard Worker           continue;
4134*5e7646d2SAndroid Build Coastguard Worker 
4135*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*StapleLocation %s: \"\"\n", ppd_keyword);
4136*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*%s.StapleLocation %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
4137*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*StapleLocation %s\"\n", value, keyword, ppd_keyword);
4138*5e7646d2SAndroid Build Coastguard Worker       }
4139*5e7646d2SAndroid Build Coastguard Worker 
4140*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CloseUI: *StapleLocation\n");
4141*5e7646d2SAndroid Build Coastguard Worker     }
4142*5e7646d2SAndroid Build Coastguard Worker 
4143*5e7646d2SAndroid Build Coastguard Worker    /*
4144*5e7646d2SAndroid Build Coastguard Worker     * Fold
4145*5e7646d2SAndroid Build Coastguard Worker     */
4146*5e7646d2SAndroid Build Coastguard Worker 
4147*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
4148*5e7646d2SAndroid Build Coastguard Worker     {
4149*5e7646d2SAndroid Build Coastguard Worker       value   = ippGetInteger(attr, i);
4150*5e7646d2SAndroid Build Coastguard Worker       keyword = ippEnumString("finishings", value);
4151*5e7646d2SAndroid Build Coastguard Worker 
4152*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(keyword, "cups-fold-", 10) || !strcmp(keyword, "fold") || !strncmp(keyword, "fold-", 5))
4153*5e7646d2SAndroid Build Coastguard Worker         break;
4154*5e7646d2SAndroid Build Coastguard Worker     }
4155*5e7646d2SAndroid Build Coastguard Worker 
4156*5e7646d2SAndroid Build Coastguard Worker     if (i < count)
4157*5e7646d2SAndroid Build Coastguard Worker     {
4158*5e7646d2SAndroid Build Coastguard Worker       static const char * const fold_keywords[] =
4159*5e7646d2SAndroid Build Coastguard Worker       {					/* FoldType keywords */
4160*5e7646d2SAndroid Build Coastguard Worker 	"Accordion",
4161*5e7646d2SAndroid Build Coastguard Worker 	"DoubleGate",
4162*5e7646d2SAndroid Build Coastguard Worker 	"Gate",
4163*5e7646d2SAndroid Build Coastguard Worker 	"Half",
4164*5e7646d2SAndroid Build Coastguard Worker 	"HalfZ",
4165*5e7646d2SAndroid Build Coastguard Worker 	"LeftGate",
4166*5e7646d2SAndroid Build Coastguard Worker 	"Letter",
4167*5e7646d2SAndroid Build Coastguard Worker 	"Parallel",
4168*5e7646d2SAndroid Build Coastguard Worker 	"XFold",
4169*5e7646d2SAndroid Build Coastguard Worker 	"RightGate",
4170*5e7646d2SAndroid Build Coastguard Worker 	"ZFold",
4171*5e7646d2SAndroid Build Coastguard Worker 	"EngineeringZ"
4172*5e7646d2SAndroid Build Coastguard Worker       };
4173*5e7646d2SAndroid Build Coastguard Worker 
4174*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(fin_options, "*FoldType");
4175*5e7646d2SAndroid Build Coastguard Worker 
4176*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OpenUI *FoldType: PickOne\n");
4177*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *FoldType\n");
4178*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.Translation FoldType/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Fold")));
4179*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*DefaultFoldType: None\n");
4180*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*FoldType None: \"\"\n");
4181*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.FoldType None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
4182*5e7646d2SAndroid Build Coastguard Worker 
4183*5e7646d2SAndroid Build Coastguard Worker       for (; i < count; i ++)
4184*5e7646d2SAndroid Build Coastguard Worker       {
4185*5e7646d2SAndroid Build Coastguard Worker         value   = ippGetInteger(attr, i);
4186*5e7646d2SAndroid Build Coastguard Worker         keyword = ippEnumString("finishings", value);
4187*5e7646d2SAndroid Build Coastguard Worker 
4188*5e7646d2SAndroid Build Coastguard Worker         if (!strncmp(keyword, "cups-fold-", 10))
4189*5e7646d2SAndroid Build Coastguard Worker           keyword += 5;
4190*5e7646d2SAndroid Build Coastguard Worker         else if (strcmp(keyword, "fold") && strncmp(keyword, "fold-", 5))
4191*5e7646d2SAndroid Build Coastguard Worker           continue;
4192*5e7646d2SAndroid Build Coastguard Worker 
4193*5e7646d2SAndroid Build Coastguard Worker         if (cupsArrayFind(names, (char *)keyword))
4194*5e7646d2SAndroid Build Coastguard Worker           continue;			/* Already did this finishing template */
4195*5e7646d2SAndroid Build Coastguard Worker 
4196*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(names, (char *)keyword);
4197*5e7646d2SAndroid Build Coastguard Worker 
4198*5e7646d2SAndroid Build Coastguard Worker 	snprintf(msgid, sizeof(msgid), "finishings.%d", value);
4199*5e7646d2SAndroid Build Coastguard Worker 	if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
4200*5e7646d2SAndroid Build Coastguard Worker 	  if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
4201*5e7646d2SAndroid Build Coastguard Worker 	    msgstr = keyword;
4202*5e7646d2SAndroid Build Coastguard Worker 
4203*5e7646d2SAndroid Build Coastguard Worker         if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
4204*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
4205*5e7646d2SAndroid Build Coastguard Worker         else if (value >= IPP_FINISHINGS_FOLD_ACCORDION && value <= IPP_FINISHINGS_FOLD_ENGINEERING_Z)
4206*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = fold_keywords[value - IPP_FINISHINGS_FOLD_ACCORDION];
4207*5e7646d2SAndroid Build Coastguard Worker         else if (value >= IPP_FINISHINGS_CUPS_FOLD_ACCORDION && value <= IPP_FINISHINGS_CUPS_FOLD_Z)
4208*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = fold_keywords[value - IPP_FINISHINGS_CUPS_FOLD_ACCORDION];
4209*5e7646d2SAndroid Build Coastguard Worker         else
4210*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = NULL;
4211*5e7646d2SAndroid Build Coastguard Worker 
4212*5e7646d2SAndroid Build Coastguard Worker         if (!ppd_keyword)
4213*5e7646d2SAndroid Build Coastguard Worker           continue;
4214*5e7646d2SAndroid Build Coastguard Worker 
4215*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*FoldType %s: \"\"\n", ppd_keyword);
4216*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*%s.FoldType %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
4217*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*FoldType %s\"\n", value, keyword, ppd_keyword);
4218*5e7646d2SAndroid Build Coastguard Worker       }
4219*5e7646d2SAndroid Build Coastguard Worker 
4220*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CloseUI: *FoldType\n");
4221*5e7646d2SAndroid Build Coastguard Worker     }
4222*5e7646d2SAndroid Build Coastguard Worker 
4223*5e7646d2SAndroid Build Coastguard Worker    /*
4224*5e7646d2SAndroid Build Coastguard Worker     * Punch
4225*5e7646d2SAndroid Build Coastguard Worker     */
4226*5e7646d2SAndroid Build Coastguard Worker 
4227*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
4228*5e7646d2SAndroid Build Coastguard Worker     {
4229*5e7646d2SAndroid Build Coastguard Worker       value   = ippGetInteger(attr, i);
4230*5e7646d2SAndroid Build Coastguard Worker       keyword = ippEnumString("finishings", value);
4231*5e7646d2SAndroid Build Coastguard Worker 
4232*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(keyword, "cups-punch-", 11) || !strncmp(keyword, "punch-", 6))
4233*5e7646d2SAndroid Build Coastguard Worker         break;
4234*5e7646d2SAndroid Build Coastguard Worker     }
4235*5e7646d2SAndroid Build Coastguard Worker 
4236*5e7646d2SAndroid Build Coastguard Worker     if (i < count)
4237*5e7646d2SAndroid Build Coastguard Worker     {
4238*5e7646d2SAndroid Build Coastguard Worker       static const char * const punch_keywords[] =
4239*5e7646d2SAndroid Build Coastguard Worker       {					/* PunchMedia keywords */
4240*5e7646d2SAndroid Build Coastguard Worker 	"SinglePortrait",
4241*5e7646d2SAndroid Build Coastguard Worker 	"SingleRevLandscape",
4242*5e7646d2SAndroid Build Coastguard Worker 	"SingleLandscape",
4243*5e7646d2SAndroid Build Coastguard Worker 	"SingleRevPortrait",
4244*5e7646d2SAndroid Build Coastguard Worker 	"DualPortrait",
4245*5e7646d2SAndroid Build Coastguard Worker 	"DualLandscape",
4246*5e7646d2SAndroid Build Coastguard Worker 	"DualRevPortrait",
4247*5e7646d2SAndroid Build Coastguard Worker 	"DualRevLandscape",
4248*5e7646d2SAndroid Build Coastguard Worker 	"TriplePortrait",
4249*5e7646d2SAndroid Build Coastguard Worker 	"TripleLandscape",
4250*5e7646d2SAndroid Build Coastguard Worker 	"TripleRevPortrait",
4251*5e7646d2SAndroid Build Coastguard Worker 	"TripleRevLandscape",
4252*5e7646d2SAndroid Build Coastguard Worker 	"QuadPortrait",
4253*5e7646d2SAndroid Build Coastguard Worker 	"QuadLandscape",
4254*5e7646d2SAndroid Build Coastguard Worker 	"QuadRevPortrait",
4255*5e7646d2SAndroid Build Coastguard Worker 	"QuadRevLandscape",
4256*5e7646d2SAndroid Build Coastguard Worker 	"MultiplePortrait",
4257*5e7646d2SAndroid Build Coastguard Worker 	"MultipleLandscape",
4258*5e7646d2SAndroid Build Coastguard Worker 	"MultipleRevPortrait",
4259*5e7646d2SAndroid Build Coastguard Worker 	"MultipleRevLandscape"
4260*5e7646d2SAndroid Build Coastguard Worker       };
4261*5e7646d2SAndroid Build Coastguard Worker 
4262*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(fin_options, "*PunchMedia");
4263*5e7646d2SAndroid Build Coastguard Worker 
4264*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OpenUI *PunchMedia: PickOne\n");
4265*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *PunchMedia\n");
4266*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.Translation PunchMedia/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Punch")));
4267*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*DefaultPunchMedia: None\n");
4268*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*PunchMedia None: \"\"\n");
4269*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.PunchMedia None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
4270*5e7646d2SAndroid Build Coastguard Worker 
4271*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < count; i ++)
4272*5e7646d2SAndroid Build Coastguard Worker       {
4273*5e7646d2SAndroid Build Coastguard Worker         value   = ippGetInteger(attr, i);
4274*5e7646d2SAndroid Build Coastguard Worker         keyword = ippEnumString("finishings", value);
4275*5e7646d2SAndroid Build Coastguard Worker 
4276*5e7646d2SAndroid Build Coastguard Worker         if (!strncmp(keyword, "cups-punch-", 11))
4277*5e7646d2SAndroid Build Coastguard Worker           keyword += 5;
4278*5e7646d2SAndroid Build Coastguard Worker         else if (strncmp(keyword, "punch-", 6))
4279*5e7646d2SAndroid Build Coastguard Worker           continue;
4280*5e7646d2SAndroid Build Coastguard Worker 
4281*5e7646d2SAndroid Build Coastguard Worker         if (cupsArrayFind(names, (char *)keyword))
4282*5e7646d2SAndroid Build Coastguard Worker           continue;			/* Already did this finishing template */
4283*5e7646d2SAndroid Build Coastguard Worker 
4284*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(names, (char *)keyword);
4285*5e7646d2SAndroid Build Coastguard Worker 
4286*5e7646d2SAndroid Build Coastguard Worker 	snprintf(msgid, sizeof(msgid), "finishings.%d", value);
4287*5e7646d2SAndroid Build Coastguard Worker 	if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
4288*5e7646d2SAndroid Build Coastguard Worker 	  if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
4289*5e7646d2SAndroid Build Coastguard Worker 	    msgstr = keyword;
4290*5e7646d2SAndroid Build Coastguard Worker 
4291*5e7646d2SAndroid Build Coastguard Worker         if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
4292*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
4293*5e7646d2SAndroid Build Coastguard Worker         else if (value >= IPP_FINISHINGS_PUNCH_TOP_LEFT && value <= IPP_FINISHINGS_PUNCH_MULTIPLE_BOTTOM)
4294*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = punch_keywords[value - IPP_FINISHINGS_PUNCH_TOP_LEFT];
4295*5e7646d2SAndroid Build Coastguard Worker         else if (value >= IPP_FINISHINGS_CUPS_PUNCH_TOP_LEFT && value <= IPP_FINISHINGS_CUPS_PUNCH_QUAD_BOTTOM)
4296*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = punch_keywords[value - IPP_FINISHINGS_CUPS_PUNCH_TOP_LEFT];
4297*5e7646d2SAndroid Build Coastguard Worker         else
4298*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = NULL;
4299*5e7646d2SAndroid Build Coastguard Worker 
4300*5e7646d2SAndroid Build Coastguard Worker         if (!ppd_keyword)
4301*5e7646d2SAndroid Build Coastguard Worker           continue;
4302*5e7646d2SAndroid Build Coastguard Worker 
4303*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*PunchMedia %s: \"\"\n", ppd_keyword);
4304*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*%s.PunchMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
4305*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*PunchMedia %s\"\n", value, keyword, ppd_keyword);
4306*5e7646d2SAndroid Build Coastguard Worker       }
4307*5e7646d2SAndroid Build Coastguard Worker 
4308*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CloseUI: *PunchMedia\n");
4309*5e7646d2SAndroid Build Coastguard Worker     }
4310*5e7646d2SAndroid Build Coastguard Worker 
4311*5e7646d2SAndroid Build Coastguard Worker    /*
4312*5e7646d2SAndroid Build Coastguard Worker     * Booklet
4313*5e7646d2SAndroid Build Coastguard Worker     */
4314*5e7646d2SAndroid Build Coastguard Worker 
4315*5e7646d2SAndroid Build Coastguard Worker     if (ippContainsInteger(attr, IPP_FINISHINGS_BOOKLET_MAKER))
4316*5e7646d2SAndroid Build Coastguard Worker     {
4317*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(fin_options, "*Booklet");
4318*5e7646d2SAndroid Build Coastguard Worker 
4319*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OpenUI *Booklet: Boolean\n");
4320*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *Booklet\n");
4321*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.Translation Booklet/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Booklet")));
4322*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*DefaultBooklet: False\n");
4323*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*Booklet False: \"\"\n");
4324*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*Booklet True: \"\"\n");
4325*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsIPPFinishings %d/booklet-maker: \"*Booklet True\"\n", IPP_FINISHINGS_BOOKLET_MAKER);
4326*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CloseUI: *Booklet\n");
4327*5e7646d2SAndroid Build Coastguard Worker     }
4328*5e7646d2SAndroid Build Coastguard Worker 
4329*5e7646d2SAndroid Build Coastguard Worker    /*
4330*5e7646d2SAndroid Build Coastguard Worker     * CutMedia
4331*5e7646d2SAndroid Build Coastguard Worker     */
4332*5e7646d2SAndroid Build Coastguard Worker 
4333*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
4334*5e7646d2SAndroid Build Coastguard Worker     {
4335*5e7646d2SAndroid Build Coastguard Worker       value   = ippGetInteger(attr, i);
4336*5e7646d2SAndroid Build Coastguard Worker       keyword = ippEnumString("finishings", value);
4337*5e7646d2SAndroid Build Coastguard Worker 
4338*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(keyword, "trim") || !strncmp(keyword, "trim-", 5))
4339*5e7646d2SAndroid Build Coastguard Worker         break;
4340*5e7646d2SAndroid Build Coastguard Worker     }
4341*5e7646d2SAndroid Build Coastguard Worker 
4342*5e7646d2SAndroid Build Coastguard Worker     if (i < count)
4343*5e7646d2SAndroid Build Coastguard Worker     {
4344*5e7646d2SAndroid Build Coastguard Worker       static const char * const trim_keywords[] =
4345*5e7646d2SAndroid Build Coastguard Worker       {				/* CutMedia keywords */
4346*5e7646d2SAndroid Build Coastguard Worker         "EndOfPage",
4347*5e7646d2SAndroid Build Coastguard Worker         "EndOfDoc",
4348*5e7646d2SAndroid Build Coastguard Worker         "EndOfSet",
4349*5e7646d2SAndroid Build Coastguard Worker         "EndOfJob"
4350*5e7646d2SAndroid Build Coastguard Worker       };
4351*5e7646d2SAndroid Build Coastguard Worker 
4352*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(fin_options, "*CutMedia");
4353*5e7646d2SAndroid Build Coastguard Worker 
4354*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OpenUI *CutMedia: PickOne\n");
4355*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *CutMedia\n");
4356*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.Translation CutMedia/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Cut")));
4357*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*DefaultCutMedia: None\n");
4358*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CutMedia None: \"\"\n");
4359*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.CutMedia None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
4360*5e7646d2SAndroid Build Coastguard Worker 
4361*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < count; i ++)
4362*5e7646d2SAndroid Build Coastguard Worker       {
4363*5e7646d2SAndroid Build Coastguard Worker         value   = ippGetInteger(attr, i);
4364*5e7646d2SAndroid Build Coastguard Worker         keyword = ippEnumString("finishings", value);
4365*5e7646d2SAndroid Build Coastguard Worker 
4366*5e7646d2SAndroid Build Coastguard Worker 	if (strcmp(keyword, "trim") && strncmp(keyword, "trim-", 5))
4367*5e7646d2SAndroid Build Coastguard Worker           continue;
4368*5e7646d2SAndroid Build Coastguard Worker 
4369*5e7646d2SAndroid Build Coastguard Worker         if (cupsArrayFind(names, (char *)keyword))
4370*5e7646d2SAndroid Build Coastguard Worker           continue;			/* Already did this finishing template */
4371*5e7646d2SAndroid Build Coastguard Worker 
4372*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(names, (char *)keyword);
4373*5e7646d2SAndroid Build Coastguard Worker 
4374*5e7646d2SAndroid Build Coastguard Worker 	snprintf(msgid, sizeof(msgid), "finishings.%d", value);
4375*5e7646d2SAndroid Build Coastguard Worker 	if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
4376*5e7646d2SAndroid Build Coastguard Worker 	  if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
4377*5e7646d2SAndroid Build Coastguard Worker 	    msgstr = keyword;
4378*5e7646d2SAndroid Build Coastguard Worker 
4379*5e7646d2SAndroid Build Coastguard Worker         if (value == IPP_FINISHINGS_TRIM)
4380*5e7646d2SAndroid Build Coastguard Worker           ppd_keyword = "Auto";
4381*5e7646d2SAndroid Build Coastguard Worker 	else
4382*5e7646d2SAndroid Build Coastguard Worker 	  ppd_keyword = trim_keywords[value - IPP_FINISHINGS_TRIM_AFTER_PAGES];
4383*5e7646d2SAndroid Build Coastguard Worker 
4384*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*CutMedia %s: \"\"\n", ppd_keyword);
4385*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*%s.CutMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
4386*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*CutMedia %s\"\n", value, keyword, ppd_keyword);
4387*5e7646d2SAndroid Build Coastguard Worker       }
4388*5e7646d2SAndroid Build Coastguard Worker 
4389*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CloseUI: *CutMedia\n");
4390*5e7646d2SAndroid Build Coastguard Worker     }
4391*5e7646d2SAndroid Build Coastguard Worker 
4392*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(names);
4393*5e7646d2SAndroid Build Coastguard Worker   }
4394*5e7646d2SAndroid Build Coastguard Worker 
4395*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "finishings-col-database", IPP_TAG_BEGIN_COLLECTION)) != NULL)
4396*5e7646d2SAndroid Build Coastguard Worker   {
4397*5e7646d2SAndroid Build Coastguard Worker     ipp_t	*finishing_col;		/* Current finishing collection */
4398*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *finishing_attr;	/* Current finishing member attribute */
4399*5e7646d2SAndroid Build Coastguard Worker     cups_array_t *templates;		/* Finishing templates */
4400*5e7646d2SAndroid Build Coastguard Worker 
4401*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*OpenUI *cupsFinishingTemplate: PickOne\n");
4402*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *cupsFinishingTemplate\n");
4403*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*%s.Translation cupsFinishingTemplate/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Finishing Preset")));
4404*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*DefaultcupsFinishingTemplate: none\n");
4405*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*cupsFinishingTemplate none: \"\"\n");
4406*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*%s.cupsFinishingTemplate none/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
4407*5e7646d2SAndroid Build Coastguard Worker 
4408*5e7646d2SAndroid Build Coastguard Worker     templates = cupsArrayNew((cups_array_func_t)strcmp, NULL);
4409*5e7646d2SAndroid Build Coastguard Worker     count     = ippGetCount(attr);
4410*5e7646d2SAndroid Build Coastguard Worker 
4411*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < count; i ++)
4412*5e7646d2SAndroid Build Coastguard Worker     {
4413*5e7646d2SAndroid Build Coastguard Worker       finishing_col = ippGetCollection(attr, i);
4414*5e7646d2SAndroid Build Coastguard Worker       keyword       = ippGetString(ippFindAttribute(finishing_col, "finishing-template", IPP_TAG_ZERO), 0, NULL);
4415*5e7646d2SAndroid Build Coastguard Worker 
4416*5e7646d2SAndroid Build Coastguard Worker       if (!keyword || cupsArrayFind(templates, (void *)keyword))
4417*5e7646d2SAndroid Build Coastguard Worker         continue;
4418*5e7646d2SAndroid Build Coastguard Worker 
4419*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(keyword, "none"))
4420*5e7646d2SAndroid Build Coastguard Worker         continue;
4421*5e7646d2SAndroid Build Coastguard Worker 
4422*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(templates, (void *)keyword);
4423*5e7646d2SAndroid Build Coastguard Worker 
4424*5e7646d2SAndroid Build Coastguard Worker       snprintf(msgid, sizeof(msgid), "finishing-template.%s", keyword);
4425*5e7646d2SAndroid Build Coastguard Worker       if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
4426*5e7646d2SAndroid Build Coastguard Worker 	if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
4427*5e7646d2SAndroid Build Coastguard Worker 	  msgstr = keyword;
4428*5e7646d2SAndroid Build Coastguard Worker 
4429*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsFinishingTemplate %s: \"\n", keyword);
4430*5e7646d2SAndroid Build Coastguard Worker       for (finishing_attr = ippFirstAttribute(finishing_col); finishing_attr; finishing_attr = ippNextAttribute(finishing_col))
4431*5e7646d2SAndroid Build Coastguard Worker       {
4432*5e7646d2SAndroid Build Coastguard Worker         if (ippGetValueTag(finishing_attr) == IPP_TAG_BEGIN_COLLECTION)
4433*5e7646d2SAndroid Build Coastguard Worker         {
4434*5e7646d2SAndroid Build Coastguard Worker 	  const char *name = ippGetName(finishing_attr);
4435*5e7646d2SAndroid Build Coastguard Worker 					/* Member attribute name */
4436*5e7646d2SAndroid Build Coastguard Worker 
4437*5e7646d2SAndroid Build Coastguard Worker           if (strcmp(name, "media-size"))
4438*5e7646d2SAndroid Build Coastguard Worker             cupsFilePrintf(fp, "%% %s\n", name);
4439*5e7646d2SAndroid Build Coastguard Worker 	}
4440*5e7646d2SAndroid Build Coastguard Worker       }
4441*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "\"\n");
4442*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.cupsFinishingTemplate %s/%s: \"\"\n", lang->language, keyword, msgstr);
4443*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*End\n");
4444*5e7646d2SAndroid Build Coastguard Worker     }
4445*5e7646d2SAndroid Build Coastguard Worker 
4446*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *cupsFinishingTemplate\n");
4447*5e7646d2SAndroid Build Coastguard Worker 
4448*5e7646d2SAndroid Build Coastguard Worker     if (cupsArrayCount(fin_options))
4449*5e7646d2SAndroid Build Coastguard Worker     {
4450*5e7646d2SAndroid Build Coastguard Worker       const char	*fin_option;	/* Current finishing option */
4451*5e7646d2SAndroid Build Coastguard Worker 
4452*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*cupsUIConstraint finishing-template: \"*cupsFinishingTemplate");
4453*5e7646d2SAndroid Build Coastguard Worker       for (fin_option = (const char *)cupsArrayFirst(fin_options); fin_option; fin_option = (const char *)cupsArrayNext(fin_options))
4454*5e7646d2SAndroid Build Coastguard Worker         cupsFilePrintf(fp, " %s", fin_option);
4455*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "\"\n");
4456*5e7646d2SAndroid Build Coastguard Worker 
4457*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*cupsUIResolver finishing-template: \"*cupsFinishingTemplate None");
4458*5e7646d2SAndroid Build Coastguard Worker       for (fin_option = (const char *)cupsArrayFirst(fin_options); fin_option; fin_option = (const char *)cupsArrayNext(fin_options))
4459*5e7646d2SAndroid Build Coastguard Worker         cupsFilePrintf(fp, " %s None", fin_option);
4460*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "\"\n");
4461*5e7646d2SAndroid Build Coastguard Worker     }
4462*5e7646d2SAndroid Build Coastguard Worker 
4463*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(templates);
4464*5e7646d2SAndroid Build Coastguard Worker   }
4465*5e7646d2SAndroid Build Coastguard Worker 
4466*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(fin_options);
4467*5e7646d2SAndroid Build Coastguard Worker 
4468*5e7646d2SAndroid Build Coastguard Worker  /*
4469*5e7646d2SAndroid Build Coastguard Worker   * cupsPrintQuality and DefaultResolution...
4470*5e7646d2SAndroid Build Coastguard Worker   */
4471*5e7646d2SAndroid Build Coastguard Worker 
4472*5e7646d2SAndroid Build Coastguard Worker   quality = ippFindAttribute(response, "print-quality-supported", IPP_TAG_ENUM);
4473*5e7646d2SAndroid Build Coastguard Worker 
4474*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
4475*5e7646d2SAndroid Build Coastguard Worker   {
4476*5e7646d2SAndroid Build Coastguard Worker     int lowdpi = 0, hidpi = 0;    /* Lower and higher resolution */
4477*5e7646d2SAndroid Build Coastguard Worker 
4478*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, count = ippGetCount(attr); i < count; i ++)
4479*5e7646d2SAndroid Build Coastguard Worker     {
4480*5e7646d2SAndroid Build Coastguard Worker       const char *rs = ippGetString(attr, i, NULL);
4481*5e7646d2SAndroid Build Coastguard Worker           /* RS value */
4482*5e7646d2SAndroid Build Coastguard Worker 
4483*5e7646d2SAndroid Build Coastguard Worker       if (_cups_strncasecmp(rs, "RS", 2))
4484*5e7646d2SAndroid Build Coastguard Worker         continue;
4485*5e7646d2SAndroid Build Coastguard Worker 
4486*5e7646d2SAndroid Build Coastguard Worker       lowdpi = atoi(rs + 2);
4487*5e7646d2SAndroid Build Coastguard Worker       if ((rs = strrchr(rs, '-')) != NULL)
4488*5e7646d2SAndroid Build Coastguard Worker         hidpi = atoi(rs + 1);
4489*5e7646d2SAndroid Build Coastguard Worker       else
4490*5e7646d2SAndroid Build Coastguard Worker         hidpi = lowdpi;
4491*5e7646d2SAndroid Build Coastguard Worker       break;
4492*5e7646d2SAndroid Build Coastguard Worker     }
4493*5e7646d2SAndroid Build Coastguard Worker 
4494*5e7646d2SAndroid Build Coastguard Worker     if (lowdpi == 0)
4495*5e7646d2SAndroid Build Coastguard Worker     {
4496*5e7646d2SAndroid Build Coastguard Worker      /*
4497*5e7646d2SAndroid Build Coastguard Worker       * Invalid "urf-supported" value...
4498*5e7646d2SAndroid Build Coastguard Worker       */
4499*5e7646d2SAndroid Build Coastguard Worker 
4500*5e7646d2SAndroid Build Coastguard Worker       goto bad_ppd;
4501*5e7646d2SAndroid Build Coastguard Worker     }
4502*5e7646d2SAndroid Build Coastguard Worker     else
4503*5e7646d2SAndroid Build Coastguard Worker     {
4504*5e7646d2SAndroid Build Coastguard Worker      /*
4505*5e7646d2SAndroid Build Coastguard Worker       * Generate print qualities based on low and high DPIs...
4506*5e7646d2SAndroid Build Coastguard Worker       */
4507*5e7646d2SAndroid Build Coastguard Worker 
4508*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*DefaultResolution: %ddpi\n", lowdpi);
4509*5e7646d2SAndroid Build Coastguard Worker 
4510*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
4511*5e7646d2SAndroid Build Coastguard Worker 			 "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
4512*5e7646d2SAndroid Build Coastguard Worker 			 "*%s.Translation cupsPrintQuality/%s: \"\"\n"
4513*5e7646d2SAndroid Build Coastguard Worker 			 "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
4514*5e7646d2SAndroid Build Coastguard Worker       if ((lowdpi & 1) == 0)
4515*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi / 2, lang->language, _cupsLangString(lang, _("Draft")));
4516*5e7646d2SAndroid Build Coastguard Worker       else if (ippContainsInteger(quality, IPP_QUALITY_DRAFT))
4517*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Draft")));
4518*5e7646d2SAndroid Build Coastguard Worker 
4519*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Normal")));
4520*5e7646d2SAndroid Build Coastguard Worker 
4521*5e7646d2SAndroid Build Coastguard Worker       if (hidpi > lowdpi || ippContainsInteger(quality, IPP_QUALITY_HIGH))
4522*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", hidpi, hidpi, lang->language, _cupsLangString(lang, _("High")));
4523*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
4524*5e7646d2SAndroid Build Coastguard Worker     }
4525*5e7646d2SAndroid Build Coastguard Worker   }
4526*5e7646d2SAndroid Build Coastguard Worker   else if ((attr = ippFindAttribute(response, "pwg-raster-document-resolution-supported", IPP_TAG_RESOLUTION)) != NULL)
4527*5e7646d2SAndroid Build Coastguard Worker   {
4528*5e7646d2SAndroid Build Coastguard Worker    /*
4529*5e7646d2SAndroid Build Coastguard Worker     * Make a sorted list of resolutions.
4530*5e7646d2SAndroid Build Coastguard Worker     */
4531*5e7646d2SAndroid Build Coastguard Worker 
4532*5e7646d2SAndroid Build Coastguard Worker     count = ippGetCount(attr);
4533*5e7646d2SAndroid Build Coastguard Worker     if (count > (int)(sizeof(resolutions) / sizeof(resolutions[0])))
4534*5e7646d2SAndroid Build Coastguard Worker       count = (int)(sizeof(resolutions) / sizeof(resolutions[0]));
4535*5e7646d2SAndroid Build Coastguard Worker 
4536*5e7646d2SAndroid Build Coastguard Worker     resolutions[0] = 0; /* Not in loop to silence Clang static analyzer... */
4537*5e7646d2SAndroid Build Coastguard Worker     for (i = 1; i < count; i ++)
4538*5e7646d2SAndroid Build Coastguard Worker       resolutions[i] = i;
4539*5e7646d2SAndroid Build Coastguard Worker 
4540*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < (count - 1); i ++)
4541*5e7646d2SAndroid Build Coastguard Worker     {
4542*5e7646d2SAndroid Build Coastguard Worker       for (j = i + 1; j < count; j ++)
4543*5e7646d2SAndroid Build Coastguard Worker       {
4544*5e7646d2SAndroid Build Coastguard Worker         int       ix, iy,               /* First X and Y resolution */
4545*5e7646d2SAndroid Build Coastguard Worker                   jx, jy,               /* Second X and Y resolution */
4546*5e7646d2SAndroid Build Coastguard Worker                   temp;                 /* Swap variable */
4547*5e7646d2SAndroid Build Coastguard Worker         ipp_res_t units;                /* Resolution units */
4548*5e7646d2SAndroid Build Coastguard Worker 
4549*5e7646d2SAndroid Build Coastguard Worker         ix = ippGetResolution(attr, resolutions[i], &iy, &units);
4550*5e7646d2SAndroid Build Coastguard Worker         jx = ippGetResolution(attr, resolutions[j], &jy, &units);
4551*5e7646d2SAndroid Build Coastguard Worker 
4552*5e7646d2SAndroid Build Coastguard Worker         if (ix > jx || (ix == jx && iy > jy))
4553*5e7646d2SAndroid Build Coastguard Worker         {
4554*5e7646d2SAndroid Build Coastguard Worker          /*
4555*5e7646d2SAndroid Build Coastguard Worker           * Swap these two resolutions...
4556*5e7646d2SAndroid Build Coastguard Worker           */
4557*5e7646d2SAndroid Build Coastguard Worker 
4558*5e7646d2SAndroid Build Coastguard Worker           temp           = resolutions[i];
4559*5e7646d2SAndroid Build Coastguard Worker           resolutions[i] = resolutions[j];
4560*5e7646d2SAndroid Build Coastguard Worker           resolutions[j] = temp;
4561*5e7646d2SAndroid Build Coastguard Worker         }
4562*5e7646d2SAndroid Build Coastguard Worker       }
4563*5e7646d2SAndroid Build Coastguard Worker     }
4564*5e7646d2SAndroid Build Coastguard Worker 
4565*5e7646d2SAndroid Build Coastguard Worker    /*
4566*5e7646d2SAndroid Build Coastguard Worker     * Generate print quality options...
4567*5e7646d2SAndroid Build Coastguard Worker     */
4568*5e7646d2SAndroid Build Coastguard Worker 
4569*5e7646d2SAndroid Build Coastguard Worker     pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, ppdname, sizeof(ppdname));
4570*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
4571*5e7646d2SAndroid Build Coastguard Worker 
4572*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
4573*5e7646d2SAndroid Build Coastguard Worker 		       "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
4574*5e7646d2SAndroid Build Coastguard Worker 		       "*%s.Translation cupsPrintQuality/%s: \"\"\n"
4575*5e7646d2SAndroid Build Coastguard Worker 		       "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
4576*5e7646d2SAndroid Build Coastguard Worker     if (count > 2 || ippContainsInteger(quality, IPP_QUALITY_DRAFT))
4577*5e7646d2SAndroid Build Coastguard Worker     {
4578*5e7646d2SAndroid Build Coastguard Worker       pwg_ppdize_resolution(attr, resolutions[0], &xres, &yres, NULL, 0);
4579*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
4580*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.cupsPrintQuality Draft/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Draft")));
4581*5e7646d2SAndroid Build Coastguard Worker     }
4582*5e7646d2SAndroid Build Coastguard Worker 
4583*5e7646d2SAndroid Build Coastguard Worker     pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, NULL, 0);
4584*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
4585*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*%s.cupsPrintQuality Normal/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Normal")));
4586*5e7646d2SAndroid Build Coastguard Worker 
4587*5e7646d2SAndroid Build Coastguard Worker     if (count > 1 || ippContainsInteger(quality, IPP_QUALITY_HIGH))
4588*5e7646d2SAndroid Build Coastguard Worker     {
4589*5e7646d2SAndroid Build Coastguard Worker       pwg_ppdize_resolution(attr, resolutions[count - 1], &xres, &yres, NULL, 0);
4590*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
4591*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*%s.cupsPrintQuality High/%s: \"\"\n", lang->language, _cupsLangString(lang, _("High")));
4592*5e7646d2SAndroid Build Coastguard Worker     }
4593*5e7646d2SAndroid Build Coastguard Worker 
4594*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
4595*5e7646d2SAndroid Build Coastguard Worker   }
4596*5e7646d2SAndroid Build Coastguard Worker   else if (is_apple || is_pwg)
4597*5e7646d2SAndroid Build Coastguard Worker     goto bad_ppd;
4598*5e7646d2SAndroid Build Coastguard Worker   else
4599*5e7646d2SAndroid Build Coastguard Worker   {
4600*5e7646d2SAndroid Build Coastguard Worker     if ((attr = ippFindAttribute(response, "printer-resolution-default", IPP_TAG_RESOLUTION)) != NULL)
4601*5e7646d2SAndroid Build Coastguard Worker     {
4602*5e7646d2SAndroid Build Coastguard Worker       pwg_ppdize_resolution(attr, 0, &xres, &yres, ppdname, sizeof(ppdname));
4603*5e7646d2SAndroid Build Coastguard Worker     }
4604*5e7646d2SAndroid Build Coastguard Worker     else
4605*5e7646d2SAndroid Build Coastguard Worker     {
4606*5e7646d2SAndroid Build Coastguard Worker       xres = yres = 300;
4607*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ppdname, "300dpi", sizeof(ppdname));
4608*5e7646d2SAndroid Build Coastguard Worker     }
4609*5e7646d2SAndroid Build Coastguard Worker 
4610*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
4611*5e7646d2SAndroid Build Coastguard Worker 
4612*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
4613*5e7646d2SAndroid Build Coastguard Worker                        "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
4614*5e7646d2SAndroid Build Coastguard Worker                        "*%s.Translation cupsPrintQuality/%s: \"\"\n"
4615*5e7646d2SAndroid Build Coastguard Worker                        "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
4616*5e7646d2SAndroid Build Coastguard Worker     if (ippContainsInteger(quality, IPP_QUALITY_DRAFT))
4617*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Draft")));
4618*5e7646d2SAndroid Build Coastguard Worker 
4619*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Normal")));
4620*5e7646d2SAndroid Build Coastguard Worker 
4621*5e7646d2SAndroid Build Coastguard Worker     if (ippContainsInteger(quality, IPP_QUALITY_HIGH))
4622*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("High")));
4623*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
4624*5e7646d2SAndroid Build Coastguard Worker   }
4625*5e7646d2SAndroid Build Coastguard Worker 
4626*5e7646d2SAndroid Build Coastguard Worker  /*
4627*5e7646d2SAndroid Build Coastguard Worker   * Presets...
4628*5e7646d2SAndroid Build Coastguard Worker   */
4629*5e7646d2SAndroid Build Coastguard Worker 
4630*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "job-presets-supported", IPP_TAG_BEGIN_COLLECTION)) != NULL)
4631*5e7646d2SAndroid Build Coastguard Worker   {
4632*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, count = ippGetCount(attr); i < count; i ++)
4633*5e7646d2SAndroid Build Coastguard Worker     {
4634*5e7646d2SAndroid Build Coastguard Worker       ipp_t	*preset = ippGetCollection(attr, i);
4635*5e7646d2SAndroid Build Coastguard Worker 					/* Preset collection */
4636*5e7646d2SAndroid Build Coastguard Worker       const char *preset_name = ippGetString(ippFindAttribute(preset, "preset-name", IPP_TAG_ZERO), 0, NULL),
4637*5e7646d2SAndroid Build Coastguard Worker 					/* Preset name */
4638*5e7646d2SAndroid Build Coastguard Worker 		*localized_name;	/* Localized preset name */
4639*5e7646d2SAndroid Build Coastguard Worker       ipp_attribute_t *member;		/* Member attribute in preset */
4640*5e7646d2SAndroid Build Coastguard Worker       const char *member_name;		/* Member attribute name */
4641*5e7646d2SAndroid Build Coastguard Worker       char      	member_value[256];	/* Member attribute value */
4642*5e7646d2SAndroid Build Coastguard Worker 
4643*5e7646d2SAndroid Build Coastguard Worker       if (!preset || !preset_name)
4644*5e7646d2SAndroid Build Coastguard Worker         continue;
4645*5e7646d2SAndroid Build Coastguard Worker 
4646*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(fp, "*APPrinterPreset %s: \"\n", preset_name);
4647*5e7646d2SAndroid Build Coastguard Worker       for (member = ippFirstAttribute(preset); member; member = ippNextAttribute(preset))
4648*5e7646d2SAndroid Build Coastguard Worker       {
4649*5e7646d2SAndroid Build Coastguard Worker         member_name = ippGetName(member);
4650*5e7646d2SAndroid Build Coastguard Worker 
4651*5e7646d2SAndroid Build Coastguard Worker         if (!member_name || !strcmp(member_name, "preset-name"))
4652*5e7646d2SAndroid Build Coastguard Worker           continue;
4653*5e7646d2SAndroid Build Coastguard Worker 
4654*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(member_name, "finishings"))
4655*5e7646d2SAndroid Build Coastguard Worker         {
4656*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0, count = ippGetCount(member); i < count; i ++)
4657*5e7646d2SAndroid Build Coastguard Worker 	  {
4658*5e7646d2SAndroid Build Coastguard Worker 	    const char *option = NULL;	/* PPD option name */
4659*5e7646d2SAndroid Build Coastguard Worker 
4660*5e7646d2SAndroid Build Coastguard Worker 	    keyword = ippEnumString("finishings", ippGetInteger(member, i));
4661*5e7646d2SAndroid Build Coastguard Worker 
4662*5e7646d2SAndroid Build Coastguard Worker 	    if (!strcmp(keyword, "booklet-maker"))
4663*5e7646d2SAndroid Build Coastguard Worker 	    {
4664*5e7646d2SAndroid Build Coastguard Worker 	      option  = "Booklet";
4665*5e7646d2SAndroid Build Coastguard Worker 	      keyword = "True";
4666*5e7646d2SAndroid Build Coastguard Worker 	    }
4667*5e7646d2SAndroid Build Coastguard Worker 	    else if (!strncmp(keyword, "fold-", 5))
4668*5e7646d2SAndroid Build Coastguard Worker 	      option = "FoldType";
4669*5e7646d2SAndroid Build Coastguard Worker 	    else if (!strncmp(keyword, "punch-", 6))
4670*5e7646d2SAndroid Build Coastguard Worker 	      option = "PunchMedia";
4671*5e7646d2SAndroid Build Coastguard Worker 	    else if (!strncmp(keyword, "bind-", 5) || !strncmp(keyword, "edge-stitch-", 12) || !strcmp(keyword, "saddle-stitch") || !strncmp(keyword, "staple-", 7))
4672*5e7646d2SAndroid Build Coastguard Worker 	      option = "StapleLocation";
4673*5e7646d2SAndroid Build Coastguard Worker 
4674*5e7646d2SAndroid Build Coastguard Worker 	    if (option && keyword)
4675*5e7646d2SAndroid Build Coastguard Worker 	      cupsFilePrintf(fp, "*%s %s\n", option, keyword);
4676*5e7646d2SAndroid Build Coastguard Worker 	  }
4677*5e7646d2SAndroid Build Coastguard Worker         }
4678*5e7646d2SAndroid Build Coastguard Worker         else if (!strcmp(member_name, "finishings-col"))
4679*5e7646d2SAndroid Build Coastguard Worker         {
4680*5e7646d2SAndroid Build Coastguard Worker           ipp_t *fin_col;		/* finishings-col value */
4681*5e7646d2SAndroid Build Coastguard Worker 
4682*5e7646d2SAndroid Build Coastguard Worker           for (i = 0, count = ippGetCount(member); i < count; i ++)
4683*5e7646d2SAndroid Build Coastguard Worker           {
4684*5e7646d2SAndroid Build Coastguard Worker             fin_col = ippGetCollection(member, i);
4685*5e7646d2SAndroid Build Coastguard Worker 
4686*5e7646d2SAndroid Build Coastguard Worker             if ((keyword = ippGetString(ippFindAttribute(fin_col, "finishing-template", IPP_TAG_ZERO), 0, NULL)) != NULL)
4687*5e7646d2SAndroid Build Coastguard Worker               cupsFilePrintf(fp, "*cupsFinishingTemplate %s\n", keyword);
4688*5e7646d2SAndroid Build Coastguard Worker           }
4689*5e7646d2SAndroid Build Coastguard Worker         }
4690*5e7646d2SAndroid Build Coastguard Worker         else if (!strcmp(member_name, "media"))
4691*5e7646d2SAndroid Build Coastguard Worker         {
4692*5e7646d2SAndroid Build Coastguard Worker          /*
4693*5e7646d2SAndroid Build Coastguard Worker           * Map media to PageSize...
4694*5e7646d2SAndroid Build Coastguard Worker           */
4695*5e7646d2SAndroid Build Coastguard Worker 
4696*5e7646d2SAndroid Build Coastguard Worker           if ((pwg = pwgMediaForPWG(ippGetString(member, 0, NULL))) != NULL && pwg->ppd)
4697*5e7646d2SAndroid Build Coastguard Worker             cupsFilePrintf(fp, "*PageSize %s\n", pwg->ppd);
4698*5e7646d2SAndroid Build Coastguard Worker         }
4699*5e7646d2SAndroid Build Coastguard Worker         else if (!strcmp(member_name, "media-col"))
4700*5e7646d2SAndroid Build Coastguard Worker         {
4701*5e7646d2SAndroid Build Coastguard Worker           media_col = ippGetCollection(member, 0);
4702*5e7646d2SAndroid Build Coastguard Worker 
4703*5e7646d2SAndroid Build Coastguard Worker           if ((media_size = ippGetCollection(ippFindAttribute(media_col, "media-size", IPP_TAG_BEGIN_COLLECTION), 0)) != NULL)
4704*5e7646d2SAndroid Build Coastguard Worker           {
4705*5e7646d2SAndroid Build Coastguard Worker             x_dim = ippFindAttribute(media_size, "x-dimension", IPP_TAG_INTEGER);
4706*5e7646d2SAndroid Build Coastguard Worker             y_dim = ippFindAttribute(media_size, "y-dimension", IPP_TAG_INTEGER);
4707*5e7646d2SAndroid Build Coastguard Worker             if ((pwg = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0))) != NULL && pwg->ppd)
4708*5e7646d2SAndroid Build Coastguard Worker 	      cupsFilePrintf(fp, "*PageSize %s\n", pwg->ppd);
4709*5e7646d2SAndroid Build Coastguard Worker           }
4710*5e7646d2SAndroid Build Coastguard Worker 
4711*5e7646d2SAndroid Build Coastguard Worker           if ((keyword = ippGetString(ippFindAttribute(media_col, "media-source", IPP_TAG_ZERO), 0, NULL)) != NULL)
4712*5e7646d2SAndroid Build Coastguard Worker           {
4713*5e7646d2SAndroid Build Coastguard Worker             pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
4714*5e7646d2SAndroid Build Coastguard Worker             cupsFilePrintf(fp, "*InputSlot %s\n", keyword);
4715*5e7646d2SAndroid Build Coastguard Worker 	  }
4716*5e7646d2SAndroid Build Coastguard Worker 
4717*5e7646d2SAndroid Build Coastguard Worker           if ((keyword = ippGetString(ippFindAttribute(media_col, "media-type", IPP_TAG_ZERO), 0, NULL)) != NULL)
4718*5e7646d2SAndroid Build Coastguard Worker           {
4719*5e7646d2SAndroid Build Coastguard Worker             pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
4720*5e7646d2SAndroid Build Coastguard Worker             cupsFilePrintf(fp, "*MediaType %s\n", keyword);
4721*5e7646d2SAndroid Build Coastguard Worker 	  }
4722*5e7646d2SAndroid Build Coastguard Worker         }
4723*5e7646d2SAndroid Build Coastguard Worker         else if (!strcmp(member_name, "print-quality"))
4724*5e7646d2SAndroid Build Coastguard Worker         {
4725*5e7646d2SAndroid Build Coastguard Worker 	 /*
4726*5e7646d2SAndroid Build Coastguard Worker 	  * Map print-quality to cupsPrintQuality...
4727*5e7646d2SAndroid Build Coastguard Worker 	  */
4728*5e7646d2SAndroid Build Coastguard Worker 
4729*5e7646d2SAndroid Build Coastguard Worker           int qval = ippGetInteger(member, 0);
4730*5e7646d2SAndroid Build Coastguard Worker 					/* print-quality value */
4731*5e7646d2SAndroid Build Coastguard Worker 	  static const char * const qualities[] = { "Draft", "Normal", "High" };
4732*5e7646d2SAndroid Build Coastguard Worker 					/* cupsPrintQuality values */
4733*5e7646d2SAndroid Build Coastguard Worker 
4734*5e7646d2SAndroid Build Coastguard Worker           if (qval >= IPP_QUALITY_DRAFT && qval <= IPP_QUALITY_HIGH)
4735*5e7646d2SAndroid Build Coastguard Worker             cupsFilePrintf(fp, "*cupsPrintQuality %s\n", qualities[qval - IPP_QUALITY_DRAFT]);
4736*5e7646d2SAndroid Build Coastguard Worker         }
4737*5e7646d2SAndroid Build Coastguard Worker         else if (!strcmp(member_name, "output-bin"))
4738*5e7646d2SAndroid Build Coastguard Worker         {
4739*5e7646d2SAndroid Build Coastguard Worker           pwg_ppdize_name(ippGetString(member, 0, NULL), ppdname, sizeof(ppdname));
4740*5e7646d2SAndroid Build Coastguard Worker           cupsFilePrintf(fp, "*OutputBin %s\n", ppdname);
4741*5e7646d2SAndroid Build Coastguard Worker         }
4742*5e7646d2SAndroid Build Coastguard Worker         else if (!strcmp(member_name, "sides"))
4743*5e7646d2SAndroid Build Coastguard Worker         {
4744*5e7646d2SAndroid Build Coastguard Worker           keyword = ippGetString(member, 0, NULL);
4745*5e7646d2SAndroid Build Coastguard Worker           if (keyword && !strcmp(keyword, "one-sided"))
4746*5e7646d2SAndroid Build Coastguard Worker             cupsFilePuts(fp, "*Duplex None\n");
4747*5e7646d2SAndroid Build Coastguard Worker 	  else if (keyword && !strcmp(keyword, "two-sided-long-edge"))
4748*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(fp, "*Duplex DuplexNoTumble\n");
4749*5e7646d2SAndroid Build Coastguard Worker 	  else if (keyword && !strcmp(keyword, "two-sided-short-edge"))
4750*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(fp, "*Duplex DuplexTumble\n");
4751*5e7646d2SAndroid Build Coastguard Worker         }
4752*5e7646d2SAndroid Build Coastguard Worker         else
4753*5e7646d2SAndroid Build Coastguard Worker         {
4754*5e7646d2SAndroid Build Coastguard Worker          /*
4755*5e7646d2SAndroid Build Coastguard Worker           * Add attribute name and value as-is...
4756*5e7646d2SAndroid Build Coastguard Worker           */
4757*5e7646d2SAndroid Build Coastguard Worker 
4758*5e7646d2SAndroid Build Coastguard Worker           ippAttributeString(member, member_value, sizeof(member_value));
4759*5e7646d2SAndroid Build Coastguard Worker           cupsFilePrintf(fp, "*%s %s\n", member_name, member_value);
4760*5e7646d2SAndroid Build Coastguard Worker 	}
4761*5e7646d2SAndroid Build Coastguard Worker       }
4762*5e7646d2SAndroid Build Coastguard Worker 
4763*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(fp, "\"\n*End\n");
4764*5e7646d2SAndroid Build Coastguard Worker 
4765*5e7646d2SAndroid Build Coastguard Worker       if ((localized_name = _cupsMessageLookup(strings, preset_name)) != preset_name)
4766*5e7646d2SAndroid Build Coastguard Worker         cupsFilePrintf(fp, "*%s.APPrinterPreset %s/%s: \"\"\n", lang->language, preset_name, localized_name);
4767*5e7646d2SAndroid Build Coastguard Worker     }
4768*5e7646d2SAndroid Build Coastguard Worker   }
4769*5e7646d2SAndroid Build Coastguard Worker 
4770*5e7646d2SAndroid Build Coastguard Worker  /*
4771*5e7646d2SAndroid Build Coastguard Worker   * Close up and return...
4772*5e7646d2SAndroid Build Coastguard Worker   */
4773*5e7646d2SAndroid Build Coastguard Worker 
4774*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(fp);
4775*5e7646d2SAndroid Build Coastguard Worker 
4776*5e7646d2SAndroid Build Coastguard Worker   return (buffer);
4777*5e7646d2SAndroid Build Coastguard Worker 
4778*5e7646d2SAndroid Build Coastguard Worker  /*
4779*5e7646d2SAndroid Build Coastguard Worker   * If we get here then there was a problem creating the PPD...
4780*5e7646d2SAndroid Build Coastguard Worker   */
4781*5e7646d2SAndroid Build Coastguard Worker 
4782*5e7646d2SAndroid Build Coastguard Worker   bad_ppd:
4783*5e7646d2SAndroid Build Coastguard Worker 
4784*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(fp);
4785*5e7646d2SAndroid Build Coastguard Worker   unlink(buffer);
4786*5e7646d2SAndroid Build Coastguard Worker   *buffer = '\0';
4787*5e7646d2SAndroid Build Coastguard Worker 
4788*5e7646d2SAndroid Build Coastguard Worker   _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Printer does not support required IPP attributes or document formats."), 1);
4789*5e7646d2SAndroid Build Coastguard Worker 
4790*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
4791*5e7646d2SAndroid Build Coastguard Worker }
4792*5e7646d2SAndroid Build Coastguard Worker 
4793*5e7646d2SAndroid Build Coastguard Worker 
4794*5e7646d2SAndroid Build Coastguard Worker /*
4795*5e7646d2SAndroid Build Coastguard Worker  * '_pwgInputSlotForSource()' - Get the InputSlot name for the given PWG
4796*5e7646d2SAndroid Build Coastguard Worker  *                              media-source.
4797*5e7646d2SAndroid Build Coastguard Worker  */
4798*5e7646d2SAndroid Build Coastguard Worker 
4799*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - InputSlot name */
_pwgInputSlotForSource(const char * media_source,char * name,size_t namesize)4800*5e7646d2SAndroid Build Coastguard Worker _pwgInputSlotForSource(
4801*5e7646d2SAndroid Build Coastguard Worker     const char *media_source,		/* I - PWG media-source */
4802*5e7646d2SAndroid Build Coastguard Worker     char       *name,			/* I - Name buffer */
4803*5e7646d2SAndroid Build Coastguard Worker     size_t     namesize)		/* I - Size of name buffer */
4804*5e7646d2SAndroid Build Coastguard Worker {
4805*5e7646d2SAndroid Build Coastguard Worker  /*
4806*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4807*5e7646d2SAndroid Build Coastguard Worker   */
4808*5e7646d2SAndroid Build Coastguard Worker 
4809*5e7646d2SAndroid Build Coastguard Worker   if (!media_source || !name || namesize < PPD_MAX_NAME)
4810*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
4811*5e7646d2SAndroid Build Coastguard Worker 
4812*5e7646d2SAndroid Build Coastguard Worker   if (_cups_strcasecmp(media_source, "main"))
4813*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Cassette", namesize);
4814*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "alternate"))
4815*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Multipurpose", namesize);
4816*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "large-capacity"))
4817*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "LargeCapacity", namesize);
4818*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "bottom"))
4819*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Lower", namesize);
4820*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "middle"))
4821*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Middle", namesize);
4822*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "top"))
4823*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Upper", namesize);
4824*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "rear"))
4825*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Rear", namesize);
4826*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "side"))
4827*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Side", namesize);
4828*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "envelope"))
4829*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Envelope", namesize);
4830*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "main-roll"))
4831*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Roll", namesize);
4832*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_source, "alternate-roll"))
4833*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Roll2", namesize);
4834*5e7646d2SAndroid Build Coastguard Worker   else
4835*5e7646d2SAndroid Build Coastguard Worker     pwg_ppdize_name(media_source, name, namesize);
4836*5e7646d2SAndroid Build Coastguard Worker 
4837*5e7646d2SAndroid Build Coastguard Worker   return (name);
4838*5e7646d2SAndroid Build Coastguard Worker }
4839*5e7646d2SAndroid Build Coastguard Worker 
4840*5e7646d2SAndroid Build Coastguard Worker 
4841*5e7646d2SAndroid Build Coastguard Worker /*
4842*5e7646d2SAndroid Build Coastguard Worker  * '_pwgMediaTypeForType()' - Get the MediaType name for the given PWG
4843*5e7646d2SAndroid Build Coastguard Worker  *                            media-type.
4844*5e7646d2SAndroid Build Coastguard Worker  */
4845*5e7646d2SAndroid Build Coastguard Worker 
4846*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - MediaType name */
_pwgMediaTypeForType(const char * media_type,char * name,size_t namesize)4847*5e7646d2SAndroid Build Coastguard Worker _pwgMediaTypeForType(
4848*5e7646d2SAndroid Build Coastguard Worker     const char *media_type,		/* I - PWG media-type */
4849*5e7646d2SAndroid Build Coastguard Worker     char       *name,			/* I - Name buffer */
4850*5e7646d2SAndroid Build Coastguard Worker     size_t     namesize)		/* I - Size of name buffer */
4851*5e7646d2SAndroid Build Coastguard Worker {
4852*5e7646d2SAndroid Build Coastguard Worker  /*
4853*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4854*5e7646d2SAndroid Build Coastguard Worker   */
4855*5e7646d2SAndroid Build Coastguard Worker 
4856*5e7646d2SAndroid Build Coastguard Worker   if (!media_type || !name || namesize < PPD_MAX_NAME)
4857*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
4858*5e7646d2SAndroid Build Coastguard Worker 
4859*5e7646d2SAndroid Build Coastguard Worker   if (_cups_strcasecmp(media_type, "auto"))
4860*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Auto", namesize);
4861*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "cardstock"))
4862*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Cardstock", namesize);
4863*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "envelope"))
4864*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Envelope", namesize);
4865*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "photographic-glossy"))
4866*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Glossy", namesize);
4867*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "photographic-high-gloss"))
4868*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "HighGloss", namesize);
4869*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "photographic-matte"))
4870*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Matte", namesize);
4871*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "stationery"))
4872*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Plain", namesize);
4873*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "stationery-coated"))
4874*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Coated", namesize);
4875*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "stationery-inkjet"))
4876*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Inkjet", namesize);
4877*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "stationery-letterhead"))
4878*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Letterhead", namesize);
4879*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "stationery-preprinted"))
4880*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Preprinted", namesize);
4881*5e7646d2SAndroid Build Coastguard Worker   else if (_cups_strcasecmp(media_type, "transparency"))
4882*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, "Transparency", namesize);
4883*5e7646d2SAndroid Build Coastguard Worker   else
4884*5e7646d2SAndroid Build Coastguard Worker     pwg_ppdize_name(media_type, name, namesize);
4885*5e7646d2SAndroid Build Coastguard Worker 
4886*5e7646d2SAndroid Build Coastguard Worker   return (name);
4887*5e7646d2SAndroid Build Coastguard Worker }
4888*5e7646d2SAndroid Build Coastguard Worker 
4889*5e7646d2SAndroid Build Coastguard Worker 
4890*5e7646d2SAndroid Build Coastguard Worker /*
4891*5e7646d2SAndroid Build Coastguard Worker  * '_pwgPageSizeForMedia()' - Get the PageSize name for the given media.
4892*5e7646d2SAndroid Build Coastguard Worker  */
4893*5e7646d2SAndroid Build Coastguard Worker 
4894*5e7646d2SAndroid Build Coastguard Worker const char *				/* O - PageSize name */
_pwgPageSizeForMedia(pwg_media_t * media,char * name,size_t namesize)4895*5e7646d2SAndroid Build Coastguard Worker _pwgPageSizeForMedia(
4896*5e7646d2SAndroid Build Coastguard Worker     pwg_media_t *media,			/* I - Media */
4897*5e7646d2SAndroid Build Coastguard Worker     char        *name,			/* I - PageSize name buffer */
4898*5e7646d2SAndroid Build Coastguard Worker     size_t      namesize)		/* I - Size of name buffer */
4899*5e7646d2SAndroid Build Coastguard Worker {
4900*5e7646d2SAndroid Build Coastguard Worker   const char	*sizeptr,		/* Pointer to size in PWG name */
4901*5e7646d2SAndroid Build Coastguard Worker 		*dimptr;		/* Pointer to dimensions in PWG name */
4902*5e7646d2SAndroid Build Coastguard Worker 
4903*5e7646d2SAndroid Build Coastguard Worker 
4904*5e7646d2SAndroid Build Coastguard Worker  /*
4905*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
4906*5e7646d2SAndroid Build Coastguard Worker   */
4907*5e7646d2SAndroid Build Coastguard Worker 
4908*5e7646d2SAndroid Build Coastguard Worker   if (!media || !name || namesize < PPD_MAX_NAME)
4909*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
4910*5e7646d2SAndroid Build Coastguard Worker 
4911*5e7646d2SAndroid Build Coastguard Worker  /*
4912*5e7646d2SAndroid Build Coastguard Worker   * Copy or generate a PageSize name...
4913*5e7646d2SAndroid Build Coastguard Worker   */
4914*5e7646d2SAndroid Build Coastguard Worker 
4915*5e7646d2SAndroid Build Coastguard Worker   if (media->ppd)
4916*5e7646d2SAndroid Build Coastguard Worker   {
4917*5e7646d2SAndroid Build Coastguard Worker    /*
4918*5e7646d2SAndroid Build Coastguard Worker     * Use a standard Adobe name...
4919*5e7646d2SAndroid Build Coastguard Worker     */
4920*5e7646d2SAndroid Build Coastguard Worker 
4921*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, media->ppd, namesize);
4922*5e7646d2SAndroid Build Coastguard Worker   }
4923*5e7646d2SAndroid Build Coastguard Worker   else if (!media->pwg || !strncmp(media->pwg, "custom_", 7) ||
4924*5e7646d2SAndroid Build Coastguard Worker            (sizeptr = strchr(media->pwg, '_')) == NULL ||
4925*5e7646d2SAndroid Build Coastguard Worker 	   (dimptr = strchr(sizeptr + 1, '_')) == NULL ||
4926*5e7646d2SAndroid Build Coastguard Worker 	   (size_t)(dimptr - sizeptr) > namesize)
4927*5e7646d2SAndroid Build Coastguard Worker   {
4928*5e7646d2SAndroid Build Coastguard Worker    /*
4929*5e7646d2SAndroid Build Coastguard Worker     * Use a name of the form "wNNNhNNN"...
4930*5e7646d2SAndroid Build Coastguard Worker     */
4931*5e7646d2SAndroid Build Coastguard Worker 
4932*5e7646d2SAndroid Build Coastguard Worker     snprintf(name, namesize, "w%dh%d", (int)PWG_TO_POINTS(media->width),
4933*5e7646d2SAndroid Build Coastguard Worker              (int)PWG_TO_POINTS(media->length));
4934*5e7646d2SAndroid Build Coastguard Worker   }
4935*5e7646d2SAndroid Build Coastguard Worker   else
4936*5e7646d2SAndroid Build Coastguard Worker   {
4937*5e7646d2SAndroid Build Coastguard Worker    /*
4938*5e7646d2SAndroid Build Coastguard Worker     * Copy the size name from class_sizename_dimensions...
4939*5e7646d2SAndroid Build Coastguard Worker     */
4940*5e7646d2SAndroid Build Coastguard Worker 
4941*5e7646d2SAndroid Build Coastguard Worker     memcpy(name, sizeptr + 1, (size_t)(dimptr - sizeptr - 1));
4942*5e7646d2SAndroid Build Coastguard Worker     name[dimptr - sizeptr - 1] = '\0';
4943*5e7646d2SAndroid Build Coastguard Worker   }
4944*5e7646d2SAndroid Build Coastguard Worker 
4945*5e7646d2SAndroid Build Coastguard Worker   return (name);
4946*5e7646d2SAndroid Build Coastguard Worker }
4947*5e7646d2SAndroid Build Coastguard Worker 
4948*5e7646d2SAndroid Build Coastguard Worker 
4949*5e7646d2SAndroid Build Coastguard Worker /*
4950*5e7646d2SAndroid Build Coastguard Worker  * 'cups_get_url()' - Get a copy of the file at the given URL.
4951*5e7646d2SAndroid Build Coastguard Worker  */
4952*5e7646d2SAndroid Build Coastguard Worker 
4953*5e7646d2SAndroid Build Coastguard Worker static int				/* O  - 1 on success, 0 on failure */
cups_get_url(http_t ** http,const char * url,char * name,size_t namesize)4954*5e7646d2SAndroid Build Coastguard Worker cups_get_url(http_t     **http,		/* IO - Current HTTP connection */
4955*5e7646d2SAndroid Build Coastguard Worker              const char *url,		/* I  - URL to get */
4956*5e7646d2SAndroid Build Coastguard Worker              char       *name,		/* I  - Temporary filename */
4957*5e7646d2SAndroid Build Coastguard Worker              size_t     namesize)	/* I  - Size of temporary filename buffer */
4958*5e7646d2SAndroid Build Coastguard Worker {
4959*5e7646d2SAndroid Build Coastguard Worker   char			scheme[32],	/* URL scheme */
4960*5e7646d2SAndroid Build Coastguard Worker 			userpass[256],	/* URL username:password */
4961*5e7646d2SAndroid Build Coastguard Worker 			host[256],	/* URL host */
4962*5e7646d2SAndroid Build Coastguard Worker 			curhost[256],	/* Current host */
4963*5e7646d2SAndroid Build Coastguard Worker 			resource[256];	/* URL resource */
4964*5e7646d2SAndroid Build Coastguard Worker   int			port;		/* URL port */
4965*5e7646d2SAndroid Build Coastguard Worker   http_encryption_t	encryption;	/* Type of encryption to use */
4966*5e7646d2SAndroid Build Coastguard Worker   http_status_t		status;		/* Status of GET request */
4967*5e7646d2SAndroid Build Coastguard Worker   int			fd;		/* Temporary file */
4968*5e7646d2SAndroid Build Coastguard Worker 
4969*5e7646d2SAndroid Build Coastguard Worker 
4970*5e7646d2SAndroid Build Coastguard Worker   if (httpSeparateURI(HTTP_URI_CODING_ALL, url, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
4971*5e7646d2SAndroid Build Coastguard Worker     return (0);
4972*5e7646d2SAndroid Build Coastguard Worker 
4973*5e7646d2SAndroid Build Coastguard Worker   if (port == 443 || !strcmp(scheme, "https"))
4974*5e7646d2SAndroid Build Coastguard Worker     encryption = HTTP_ENCRYPTION_ALWAYS;
4975*5e7646d2SAndroid Build Coastguard Worker   else
4976*5e7646d2SAndroid Build Coastguard Worker     encryption = HTTP_ENCRYPTION_IF_REQUESTED;
4977*5e7646d2SAndroid Build Coastguard Worker 
4978*5e7646d2SAndroid Build Coastguard Worker   if (!*http || strcasecmp(host, httpGetHostname(*http, curhost, sizeof(curhost))) || httpAddrPort(httpGetAddress(*http)) != port)
4979*5e7646d2SAndroid Build Coastguard Worker   {
4980*5e7646d2SAndroid Build Coastguard Worker     httpClose(*http);
4981*5e7646d2SAndroid Build Coastguard Worker     *http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 5000, NULL);
4982*5e7646d2SAndroid Build Coastguard Worker   }
4983*5e7646d2SAndroid Build Coastguard Worker 
4984*5e7646d2SAndroid Build Coastguard Worker   if (!*http)
4985*5e7646d2SAndroid Build Coastguard Worker     return (0);
4986*5e7646d2SAndroid Build Coastguard Worker 
4987*5e7646d2SAndroid Build Coastguard Worker   if ((fd = cupsTempFd(name, (int)namesize)) < 0)
4988*5e7646d2SAndroid Build Coastguard Worker     return (0);
4989*5e7646d2SAndroid Build Coastguard Worker 
4990*5e7646d2SAndroid Build Coastguard Worker   status = cupsGetFd(*http, resource, fd);
4991*5e7646d2SAndroid Build Coastguard Worker 
4992*5e7646d2SAndroid Build Coastguard Worker   close(fd);
4993*5e7646d2SAndroid Build Coastguard Worker 
4994*5e7646d2SAndroid Build Coastguard Worker   if (status != HTTP_STATUS_OK)
4995*5e7646d2SAndroid Build Coastguard Worker   {
4996*5e7646d2SAndroid Build Coastguard Worker     unlink(name);
4997*5e7646d2SAndroid Build Coastguard Worker     *name = '\0';
4998*5e7646d2SAndroid Build Coastguard Worker     return (0);
4999*5e7646d2SAndroid Build Coastguard Worker   }
5000*5e7646d2SAndroid Build Coastguard Worker 
5001*5e7646d2SAndroid Build Coastguard Worker   return (1);
5002*5e7646d2SAndroid Build Coastguard Worker }
5003*5e7646d2SAndroid Build Coastguard Worker 
5004*5e7646d2SAndroid Build Coastguard Worker 
5005*5e7646d2SAndroid Build Coastguard Worker /*
5006*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_add_finishing()' - Add a finishings value.
5007*5e7646d2SAndroid Build Coastguard Worker  */
5008*5e7646d2SAndroid Build Coastguard Worker 
5009*5e7646d2SAndroid Build Coastguard Worker static void
pwg_add_finishing(cups_array_t * finishings,ipp_finishings_t template,const char * name,const char * value)5010*5e7646d2SAndroid Build Coastguard Worker pwg_add_finishing(
5011*5e7646d2SAndroid Build Coastguard Worker     cups_array_t     *finishings,	/* I - Finishings array */
5012*5e7646d2SAndroid Build Coastguard Worker     ipp_finishings_t template,		/* I - Finishing template */
5013*5e7646d2SAndroid Build Coastguard Worker     const char       *name,		/* I - PPD option */
5014*5e7646d2SAndroid Build Coastguard Worker     const char       *value)		/* I - PPD choice */
5015*5e7646d2SAndroid Build Coastguard Worker {
5016*5e7646d2SAndroid Build Coastguard Worker   _pwg_finishings_t	*f;		/* New finishings value */
5017*5e7646d2SAndroid Build Coastguard Worker 
5018*5e7646d2SAndroid Build Coastguard Worker 
5019*5e7646d2SAndroid Build Coastguard Worker   if ((f = (_pwg_finishings_t *)calloc(1, sizeof(_pwg_finishings_t))) != NULL)
5020*5e7646d2SAndroid Build Coastguard Worker   {
5021*5e7646d2SAndroid Build Coastguard Worker     f->value       = template;
5022*5e7646d2SAndroid Build Coastguard Worker     f->num_options = cupsAddOption(name, value, 0, &f->options);
5023*5e7646d2SAndroid Build Coastguard Worker 
5024*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(finishings, f);
5025*5e7646d2SAndroid Build Coastguard Worker   }
5026*5e7646d2SAndroid Build Coastguard Worker }
5027*5e7646d2SAndroid Build Coastguard Worker 
5028*5e7646d2SAndroid Build Coastguard Worker 
5029*5e7646d2SAndroid Build Coastguard Worker /*
5030*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_add_message()' - Add a message to the PPD cached strings.
5031*5e7646d2SAndroid Build Coastguard Worker  */
5032*5e7646d2SAndroid Build Coastguard Worker 
5033*5e7646d2SAndroid Build Coastguard Worker static void
pwg_add_message(cups_array_t * a,const char * msg,const char * str)5034*5e7646d2SAndroid Build Coastguard Worker pwg_add_message(cups_array_t *a,	/* I - Message catalog */
5035*5e7646d2SAndroid Build Coastguard Worker                 const char   *msg,	/* I - Message identifier */
5036*5e7646d2SAndroid Build Coastguard Worker                 const char   *str)	/* I - Localized string */
5037*5e7646d2SAndroid Build Coastguard Worker {
5038*5e7646d2SAndroid Build Coastguard Worker   _cups_message_t	*m;		/* New message */
5039*5e7646d2SAndroid Build Coastguard Worker 
5040*5e7646d2SAndroid Build Coastguard Worker 
5041*5e7646d2SAndroid Build Coastguard Worker   if ((m = calloc(1, sizeof(_cups_message_t))) != NULL)
5042*5e7646d2SAndroid Build Coastguard Worker   {
5043*5e7646d2SAndroid Build Coastguard Worker     m->msg = strdup(msg);
5044*5e7646d2SAndroid Build Coastguard Worker     m->str = strdup(str);
5045*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(a, m);
5046*5e7646d2SAndroid Build Coastguard Worker   }
5047*5e7646d2SAndroid Build Coastguard Worker }
5048*5e7646d2SAndroid Build Coastguard Worker 
5049*5e7646d2SAndroid Build Coastguard Worker 
5050*5e7646d2SAndroid Build Coastguard Worker /*
5051*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_compare_finishings()' - Compare two finishings values.
5052*5e7646d2SAndroid Build Coastguard Worker  */
5053*5e7646d2SAndroid Build Coastguard Worker 
5054*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
pwg_compare_finishings(_pwg_finishings_t * a,_pwg_finishings_t * b)5055*5e7646d2SAndroid Build Coastguard Worker pwg_compare_finishings(
5056*5e7646d2SAndroid Build Coastguard Worker     _pwg_finishings_t *a,		/* I - First finishings value */
5057*5e7646d2SAndroid Build Coastguard Worker     _pwg_finishings_t *b)		/* I - Second finishings value */
5058*5e7646d2SAndroid Build Coastguard Worker {
5059*5e7646d2SAndroid Build Coastguard Worker   return ((int)b->value - (int)a->value);
5060*5e7646d2SAndroid Build Coastguard Worker }
5061*5e7646d2SAndroid Build Coastguard Worker 
5062*5e7646d2SAndroid Build Coastguard Worker 
5063*5e7646d2SAndroid Build Coastguard Worker /*
5064*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_compare_sizes()' - Compare two media sizes...
5065*5e7646d2SAndroid Build Coastguard Worker  */
5066*5e7646d2SAndroid Build Coastguard Worker 
5067*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
pwg_compare_sizes(cups_size_t * a,cups_size_t * b)5068*5e7646d2SAndroid Build Coastguard Worker pwg_compare_sizes(cups_size_t *a,	/* I - First media size */
5069*5e7646d2SAndroid Build Coastguard Worker                   cups_size_t *b)	/* I - Second media size */
5070*5e7646d2SAndroid Build Coastguard Worker {
5071*5e7646d2SAndroid Build Coastguard Worker   return (strcmp(a->media, b->media));
5072*5e7646d2SAndroid Build Coastguard Worker }
5073*5e7646d2SAndroid Build Coastguard Worker 
5074*5e7646d2SAndroid Build Coastguard Worker 
5075*5e7646d2SAndroid Build Coastguard Worker /*
5076*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_copy_size()' - Copy a media size.
5077*5e7646d2SAndroid Build Coastguard Worker  */
5078*5e7646d2SAndroid Build Coastguard Worker 
5079*5e7646d2SAndroid Build Coastguard Worker static cups_size_t *			/* O - New media size */
pwg_copy_size(cups_size_t * size)5080*5e7646d2SAndroid Build Coastguard Worker pwg_copy_size(cups_size_t *size)	/* I - Media size to copy */
5081*5e7646d2SAndroid Build Coastguard Worker {
5082*5e7646d2SAndroid Build Coastguard Worker   cups_size_t	*newsize = (cups_size_t *)calloc(1, sizeof(cups_size_t));
5083*5e7646d2SAndroid Build Coastguard Worker 					/* New media size */
5084*5e7646d2SAndroid Build Coastguard Worker 
5085*5e7646d2SAndroid Build Coastguard Worker   if (newsize)
5086*5e7646d2SAndroid Build Coastguard Worker     memcpy(newsize, size, sizeof(cups_size_t));
5087*5e7646d2SAndroid Build Coastguard Worker 
5088*5e7646d2SAndroid Build Coastguard Worker   return (newsize);
5089*5e7646d2SAndroid Build Coastguard Worker }
5090*5e7646d2SAndroid Build Coastguard Worker 
5091*5e7646d2SAndroid Build Coastguard Worker 
5092*5e7646d2SAndroid Build Coastguard Worker /*
5093*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_free_finishings()' - Free a finishings value.
5094*5e7646d2SAndroid Build Coastguard Worker  */
5095*5e7646d2SAndroid Build Coastguard Worker 
5096*5e7646d2SAndroid Build Coastguard Worker static void
pwg_free_finishings(_pwg_finishings_t * f)5097*5e7646d2SAndroid Build Coastguard Worker pwg_free_finishings(
5098*5e7646d2SAndroid Build Coastguard Worker     _pwg_finishings_t *f)		/* I - Finishings value */
5099*5e7646d2SAndroid Build Coastguard Worker {
5100*5e7646d2SAndroid Build Coastguard Worker   cupsFreeOptions(f->num_options, f->options);
5101*5e7646d2SAndroid Build Coastguard Worker   free(f);
5102*5e7646d2SAndroid Build Coastguard Worker }
5103*5e7646d2SAndroid Build Coastguard Worker 
5104*5e7646d2SAndroid Build Coastguard Worker 
5105*5e7646d2SAndroid Build Coastguard Worker /*
5106*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_ppdize_name()' - Convert an IPP keyword to a PPD keyword.
5107*5e7646d2SAndroid Build Coastguard Worker  */
5108*5e7646d2SAndroid Build Coastguard Worker 
5109*5e7646d2SAndroid Build Coastguard Worker static void
pwg_ppdize_name(const char * ipp,char * name,size_t namesize)5110*5e7646d2SAndroid Build Coastguard Worker pwg_ppdize_name(const char *ipp,	/* I - IPP keyword */
5111*5e7646d2SAndroid Build Coastguard Worker                 char       *name,	/* I - Name buffer */
5112*5e7646d2SAndroid Build Coastguard Worker 		size_t     namesize)	/* I - Size of name buffer */
5113*5e7646d2SAndroid Build Coastguard Worker {
5114*5e7646d2SAndroid Build Coastguard Worker   char	*ptr,				/* Pointer into name buffer */
5115*5e7646d2SAndroid Build Coastguard Worker 	*end;				/* End of name buffer */
5116*5e7646d2SAndroid Build Coastguard Worker 
5117*5e7646d2SAndroid Build Coastguard Worker 
5118*5e7646d2SAndroid Build Coastguard Worker   if (!ipp)
5119*5e7646d2SAndroid Build Coastguard Worker   {
5120*5e7646d2SAndroid Build Coastguard Worker     *name = '\0';
5121*5e7646d2SAndroid Build Coastguard Worker     return;
5122*5e7646d2SAndroid Build Coastguard Worker   }
5123*5e7646d2SAndroid Build Coastguard Worker 
5124*5e7646d2SAndroid Build Coastguard Worker   *name = (char)toupper(*ipp++);
5125*5e7646d2SAndroid Build Coastguard Worker 
5126*5e7646d2SAndroid Build Coastguard Worker   for (ptr = name + 1, end = name + namesize - 1; *ipp && ptr < end;)
5127*5e7646d2SAndroid Build Coastguard Worker   {
5128*5e7646d2SAndroid Build Coastguard Worker     if (*ipp == '-' && _cups_isalnum(ipp[1]))
5129*5e7646d2SAndroid Build Coastguard Worker     {
5130*5e7646d2SAndroid Build Coastguard Worker       ipp ++;
5131*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = (char)toupper(*ipp++ & 255);
5132*5e7646d2SAndroid Build Coastguard Worker     }
5133*5e7646d2SAndroid Build Coastguard Worker     else
5134*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = *ipp++;
5135*5e7646d2SAndroid Build Coastguard Worker   }
5136*5e7646d2SAndroid Build Coastguard Worker 
5137*5e7646d2SAndroid Build Coastguard Worker   *ptr = '\0';
5138*5e7646d2SAndroid Build Coastguard Worker }
5139*5e7646d2SAndroid Build Coastguard Worker 
5140*5e7646d2SAndroid Build Coastguard Worker 
5141*5e7646d2SAndroid Build Coastguard Worker /*
5142*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_ppdize_resolution()' - Convert PWG resolution values to PPD values.
5143*5e7646d2SAndroid Build Coastguard Worker  */
5144*5e7646d2SAndroid Build Coastguard Worker 
5145*5e7646d2SAndroid Build Coastguard Worker static void
pwg_ppdize_resolution(ipp_attribute_t * attr,int element,int * xres,int * yres,char * name,size_t namesize)5146*5e7646d2SAndroid Build Coastguard Worker pwg_ppdize_resolution(
5147*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - Attribute to convert */
5148*5e7646d2SAndroid Build Coastguard Worker     int             element,		/* I - Element to convert */
5149*5e7646d2SAndroid Build Coastguard Worker     int             *xres,		/* O - X resolution in DPI */
5150*5e7646d2SAndroid Build Coastguard Worker     int             *yres,		/* O - Y resolution in DPI */
5151*5e7646d2SAndroid Build Coastguard Worker     char            *name,		/* I - Name buffer */
5152*5e7646d2SAndroid Build Coastguard Worker     size_t          namesize)		/* I - Size of name buffer */
5153*5e7646d2SAndroid Build Coastguard Worker {
5154*5e7646d2SAndroid Build Coastguard Worker   ipp_res_t units;			/* Units for resolution */
5155*5e7646d2SAndroid Build Coastguard Worker 
5156*5e7646d2SAndroid Build Coastguard Worker 
5157*5e7646d2SAndroid Build Coastguard Worker   *xres = ippGetResolution(attr, element, yres, &units);
5158*5e7646d2SAndroid Build Coastguard Worker 
5159*5e7646d2SAndroid Build Coastguard Worker   if (units == IPP_RES_PER_CM)
5160*5e7646d2SAndroid Build Coastguard Worker   {
5161*5e7646d2SAndroid Build Coastguard Worker     *xres = (int)(*xres * 2.54);
5162*5e7646d2SAndroid Build Coastguard Worker     *yres = (int)(*yres * 2.54);
5163*5e7646d2SAndroid Build Coastguard Worker   }
5164*5e7646d2SAndroid Build Coastguard Worker 
5165*5e7646d2SAndroid Build Coastguard Worker   if (name && namesize > 4)
5166*5e7646d2SAndroid Build Coastguard Worker   {
5167*5e7646d2SAndroid Build Coastguard Worker     if (*xres == *yres)
5168*5e7646d2SAndroid Build Coastguard Worker       snprintf(name, namesize, "%ddpi", *xres);
5169*5e7646d2SAndroid Build Coastguard Worker     else
5170*5e7646d2SAndroid Build Coastguard Worker       snprintf(name, namesize, "%dx%ddpi", *xres, *yres);
5171*5e7646d2SAndroid Build Coastguard Worker   }
5172*5e7646d2SAndroid Build Coastguard Worker }
5173*5e7646d2SAndroid Build Coastguard Worker 
5174*5e7646d2SAndroid Build Coastguard Worker 
5175*5e7646d2SAndroid Build Coastguard Worker /*
5176*5e7646d2SAndroid Build Coastguard Worker  * 'pwg_unppdize_name()' - Convert a PPD keyword to a lowercase IPP keyword.
5177*5e7646d2SAndroid Build Coastguard Worker  */
5178*5e7646d2SAndroid Build Coastguard Worker 
5179*5e7646d2SAndroid Build Coastguard Worker static void
pwg_unppdize_name(const char * ppd,char * name,size_t namesize,const char * dashchars)5180*5e7646d2SAndroid Build Coastguard Worker pwg_unppdize_name(const char *ppd,	/* I - PPD keyword */
5181*5e7646d2SAndroid Build Coastguard Worker 		  char       *name,	/* I - Name buffer */
5182*5e7646d2SAndroid Build Coastguard Worker                   size_t     namesize,	/* I - Size of name buffer */
5183*5e7646d2SAndroid Build Coastguard Worker                   const char *dashchars)/* I - Characters to be replaced by dashes */
5184*5e7646d2SAndroid Build Coastguard Worker {
5185*5e7646d2SAndroid Build Coastguard Worker   char	*ptr,				/* Pointer into name buffer */
5186*5e7646d2SAndroid Build Coastguard Worker 	*end;				/* End of name buffer */
5187*5e7646d2SAndroid Build Coastguard Worker   int   nodash = 1;                     /* Next char in IPP name cannot be a
5188*5e7646d2SAndroid Build Coastguard Worker                                            dash (first char or after a dash) */
5189*5e7646d2SAndroid Build Coastguard Worker 
5190*5e7646d2SAndroid Build Coastguard Worker 
5191*5e7646d2SAndroid Build Coastguard Worker   if (_cups_islower(*ppd))
5192*5e7646d2SAndroid Build Coastguard Worker   {
5193*5e7646d2SAndroid Build Coastguard Worker    /*
5194*5e7646d2SAndroid Build Coastguard Worker     * Already lowercase name, use as-is?
5195*5e7646d2SAndroid Build Coastguard Worker     */
5196*5e7646d2SAndroid Build Coastguard Worker 
5197*5e7646d2SAndroid Build Coastguard Worker     const char *ppdptr;			/* Pointer into PPD keyword */
5198*5e7646d2SAndroid Build Coastguard Worker 
5199*5e7646d2SAndroid Build Coastguard Worker     for (ppdptr = ppd + 1; *ppdptr; ppdptr ++)
5200*5e7646d2SAndroid Build Coastguard Worker       if (_cups_isupper(*ppdptr) || strchr(dashchars, *ppdptr) ||
5201*5e7646d2SAndroid Build Coastguard Worker 	  (*ppdptr == '-' && *(ppdptr - 1) == '-') ||
5202*5e7646d2SAndroid Build Coastguard Worker 	  (*ppdptr == '-' && *(ppdptr + 1) == '\0'))
5203*5e7646d2SAndroid Build Coastguard Worker         break;
5204*5e7646d2SAndroid Build Coastguard Worker 
5205*5e7646d2SAndroid Build Coastguard Worker     if (!*ppdptr)
5206*5e7646d2SAndroid Build Coastguard Worker     {
5207*5e7646d2SAndroid Build Coastguard Worker       strlcpy(name, ppd, namesize);
5208*5e7646d2SAndroid Build Coastguard Worker       return;
5209*5e7646d2SAndroid Build Coastguard Worker     }
5210*5e7646d2SAndroid Build Coastguard Worker   }
5211*5e7646d2SAndroid Build Coastguard Worker 
5212*5e7646d2SAndroid Build Coastguard Worker   for (ptr = name, end = name + namesize - 1; *ppd && ptr < end; ppd ++)
5213*5e7646d2SAndroid Build Coastguard Worker   {
5214*5e7646d2SAndroid Build Coastguard Worker     if (_cups_isalnum(*ppd))
5215*5e7646d2SAndroid Build Coastguard Worker     {
5216*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = (char)tolower(*ppd & 255);
5217*5e7646d2SAndroid Build Coastguard Worker       nodash = 0;
5218*5e7646d2SAndroid Build Coastguard Worker     }
5219*5e7646d2SAndroid Build Coastguard Worker     else if (*ppd == '-' || strchr(dashchars, *ppd))
5220*5e7646d2SAndroid Build Coastguard Worker     {
5221*5e7646d2SAndroid Build Coastguard Worker       if (nodash == 0)
5222*5e7646d2SAndroid Build Coastguard Worker       {
5223*5e7646d2SAndroid Build Coastguard Worker 	*ptr++ = '-';
5224*5e7646d2SAndroid Build Coastguard Worker 	nodash = 1;
5225*5e7646d2SAndroid Build Coastguard Worker       }
5226*5e7646d2SAndroid Build Coastguard Worker     }
5227*5e7646d2SAndroid Build Coastguard Worker     else
5228*5e7646d2SAndroid Build Coastguard Worker     {
5229*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = *ppd;
5230*5e7646d2SAndroid Build Coastguard Worker       nodash = 0;
5231*5e7646d2SAndroid Build Coastguard Worker     }
5232*5e7646d2SAndroid Build Coastguard Worker 
5233*5e7646d2SAndroid Build Coastguard Worker     if (nodash == 0)
5234*5e7646d2SAndroid Build Coastguard Worker     {
5235*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) &&
5236*5e7646d2SAndroid Build Coastguard Worker 	  _cups_isupper(ppd[1]) && ptr < end)
5237*5e7646d2SAndroid Build Coastguard Worker       {
5238*5e7646d2SAndroid Build Coastguard Worker 	*ptr++ = '-';
5239*5e7646d2SAndroid Build Coastguard Worker 	nodash = 1;
5240*5e7646d2SAndroid Build Coastguard Worker       }
5241*5e7646d2SAndroid Build Coastguard Worker       else if (!isdigit(*ppd & 255) && isdigit(ppd[1] & 255))
5242*5e7646d2SAndroid Build Coastguard Worker       {
5243*5e7646d2SAndroid Build Coastguard Worker 	*ptr++ = '-';
5244*5e7646d2SAndroid Build Coastguard Worker 	nodash = 1;
5245*5e7646d2SAndroid Build Coastguard Worker       }
5246*5e7646d2SAndroid Build Coastguard Worker     }
5247*5e7646d2SAndroid Build Coastguard Worker   }
5248*5e7646d2SAndroid Build Coastguard Worker 
5249*5e7646d2SAndroid Build Coastguard Worker   /* Remove trailing dashes */
5250*5e7646d2SAndroid Build Coastguard Worker   while (ptr > name && *(ptr - 1) == '-')
5251*5e7646d2SAndroid Build Coastguard Worker     ptr --;
5252*5e7646d2SAndroid Build Coastguard Worker 
5253*5e7646d2SAndroid Build Coastguard Worker   *ptr = '\0';
5254*5e7646d2SAndroid Build Coastguard Worker }
5255