xref: /aosp_15_r20/external/libcups/cups/dest-options.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Destination option/media support for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2012-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 "debug-internal.h"
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker 
18*5e7646d2SAndroid Build Coastguard Worker /*
19*5e7646d2SAndroid Build Coastguard Worker  * Local constants...
20*5e7646d2SAndroid Build Coastguard Worker  */
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_MEDIA_READY_TTL	30	/* Life of xxx-ready values */
23*5e7646d2SAndroid Build Coastguard Worker 
24*5e7646d2SAndroid Build Coastguard Worker 
25*5e7646d2SAndroid Build Coastguard Worker /*
26*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
27*5e7646d2SAndroid Build Coastguard Worker  */
28*5e7646d2SAndroid Build Coastguard Worker 
29*5e7646d2SAndroid Build Coastguard Worker static void		cups_add_dconstres(cups_array_t *a, ipp_t *collection);
30*5e7646d2SAndroid Build Coastguard Worker static int		cups_collection_contains(ipp_t *test, ipp_t *match);
31*5e7646d2SAndroid Build Coastguard Worker static size_t		cups_collection_string(ipp_attribute_t *attr, char *buffer, size_t bufsize) _CUPS_NONNULL((1,2));
32*5e7646d2SAndroid Build Coastguard Worker static int		cups_compare_dconstres(_cups_dconstres_t *a,
33*5e7646d2SAndroid Build Coastguard Worker 			                       _cups_dconstres_t *b);
34*5e7646d2SAndroid Build Coastguard Worker static int		cups_compare_media_db(_cups_media_db_t *a,
35*5e7646d2SAndroid Build Coastguard Worker 			                      _cups_media_db_t *b);
36*5e7646d2SAndroid Build Coastguard Worker static _cups_media_db_t	*cups_copy_media_db(_cups_media_db_t *mdb);
37*5e7646d2SAndroid Build Coastguard Worker static void		cups_create_cached(http_t *http, cups_dinfo_t *dinfo,
38*5e7646d2SAndroid Build Coastguard Worker 			                   unsigned flags);
39*5e7646d2SAndroid Build Coastguard Worker static void		cups_create_constraints(cups_dinfo_t *dinfo);
40*5e7646d2SAndroid Build Coastguard Worker static void		cups_create_defaults(cups_dinfo_t *dinfo);
41*5e7646d2SAndroid Build Coastguard Worker static void		cups_create_media_db(cups_dinfo_t *dinfo,
42*5e7646d2SAndroid Build Coastguard Worker 			                     unsigned flags);
43*5e7646d2SAndroid Build Coastguard Worker static void		cups_free_media_db(_cups_media_db_t *mdb);
44*5e7646d2SAndroid Build Coastguard Worker static int		cups_get_media_db(http_t *http, cups_dinfo_t *dinfo,
45*5e7646d2SAndroid Build Coastguard Worker 			                  pwg_media_t *pwg, unsigned flags,
46*5e7646d2SAndroid Build Coastguard Worker 			                  cups_size_t *size);
47*5e7646d2SAndroid Build Coastguard Worker static int		cups_is_close_media_db(_cups_media_db_t *a,
48*5e7646d2SAndroid Build Coastguard Worker 			                       _cups_media_db_t *b);
49*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*cups_test_constraints(cups_dinfo_t *dinfo,
50*5e7646d2SAndroid Build Coastguard Worker 					       const char *new_option,
51*5e7646d2SAndroid Build Coastguard Worker 					       const char *new_value,
52*5e7646d2SAndroid Build Coastguard Worker 					       int num_options,
53*5e7646d2SAndroid Build Coastguard Worker 					       cups_option_t *options,
54*5e7646d2SAndroid Build Coastguard Worker 					       int *num_conflicts,
55*5e7646d2SAndroid Build Coastguard Worker 					       cups_option_t **conflicts);
56*5e7646d2SAndroid Build Coastguard Worker static void		cups_update_ready(http_t *http, cups_dinfo_t *dinfo);
57*5e7646d2SAndroid Build Coastguard Worker 
58*5e7646d2SAndroid Build Coastguard Worker 
59*5e7646d2SAndroid Build Coastguard Worker /*
60*5e7646d2SAndroid Build Coastguard Worker  * 'cupsAddDestMediaOptions()' - Add the option corresponding to the specified media size.
61*5e7646d2SAndroid Build Coastguard Worker  *
62*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 2.3/macOS 10.14@
63*5e7646d2SAndroid Build Coastguard Worker  */
64*5e7646d2SAndroid Build Coastguard Worker 
65*5e7646d2SAndroid Build Coastguard Worker int					/* O  - New number of options */
cupsAddDestMediaOptions(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,unsigned flags,cups_size_t * size,int num_options,cups_option_t ** options)66*5e7646d2SAndroid Build Coastguard Worker cupsAddDestMediaOptions(
67*5e7646d2SAndroid Build Coastguard Worker     http_t        *http,		/* I  - Connection to destination */
68*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t   *dest,		/* I  - Destination */
69*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t  *dinfo,		/* I  - Destination information */
70*5e7646d2SAndroid Build Coastguard Worker     unsigned      flags,		/* I  - Media matching flags */
71*5e7646d2SAndroid Build Coastguard Worker     cups_size_t   *size,		/* I  - Media size */
72*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I  - Current number of options */
73*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **options)		/* IO - Options */
74*5e7646d2SAndroid Build Coastguard Worker {
75*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*db;		/* Media database */
76*5e7646d2SAndroid Build Coastguard Worker   _cups_media_db_t	*mdb;		/* Media database entry */
77*5e7646d2SAndroid Build Coastguard Worker   char			value[2048];	/* Option value */
78*5e7646d2SAndroid Build Coastguard Worker 
79*5e7646d2SAndroid Build Coastguard Worker 
80*5e7646d2SAndroid Build Coastguard Worker  /*
81*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
82*5e7646d2SAndroid Build Coastguard Worker   */
83*5e7646d2SAndroid Build Coastguard Worker 
84*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || !size || !options)
85*5e7646d2SAndroid Build Coastguard Worker   {
86*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
87*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
88*5e7646d2SAndroid Build Coastguard Worker   }
89*5e7646d2SAndroid Build Coastguard Worker 
90*5e7646d2SAndroid Build Coastguard Worker  /*
91*5e7646d2SAndroid Build Coastguard Worker   * Find the matching media size...
92*5e7646d2SAndroid Build Coastguard Worker   */
93*5e7646d2SAndroid Build Coastguard Worker 
94*5e7646d2SAndroid Build Coastguard Worker   if (flags & CUPS_MEDIA_FLAGS_READY)
95*5e7646d2SAndroid Build Coastguard Worker     db = dinfo->ready_db;
96*5e7646d2SAndroid Build Coastguard Worker   else
97*5e7646d2SAndroid Build Coastguard Worker     db = dinfo->media_db;
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1cupsAddDestMediaOptions: size->media=\"%s\"", size->media));
100*5e7646d2SAndroid Build Coastguard Worker 
101*5e7646d2SAndroid Build Coastguard Worker   for (mdb = (_cups_media_db_t *)cupsArrayFirst(db); mdb; mdb = (_cups_media_db_t *)cupsArrayNext(db))
102*5e7646d2SAndroid Build Coastguard Worker   {
103*5e7646d2SAndroid Build Coastguard Worker     if (mdb->key && !strcmp(mdb->key, size->media))
104*5e7646d2SAndroid Build Coastguard Worker       break;
105*5e7646d2SAndroid Build Coastguard Worker     else if (mdb->size_name && !strcmp(mdb->size_name, size->media))
106*5e7646d2SAndroid Build Coastguard Worker       break;
107*5e7646d2SAndroid Build Coastguard Worker   }
108*5e7646d2SAndroid Build Coastguard Worker 
109*5e7646d2SAndroid Build Coastguard Worker   if (!mdb)
110*5e7646d2SAndroid Build Coastguard Worker   {
111*5e7646d2SAndroid Build Coastguard Worker     for (mdb = (_cups_media_db_t *)cupsArrayFirst(db); mdb; mdb = (_cups_media_db_t *)cupsArrayNext(db))
112*5e7646d2SAndroid Build Coastguard Worker     {
113*5e7646d2SAndroid Build Coastguard Worker       if (mdb->width == size->width && mdb->length == size->length && mdb->bottom == size->bottom && mdb->left == size->left && mdb->right == size->right && mdb->top == size->top)
114*5e7646d2SAndroid Build Coastguard Worker 	break;
115*5e7646d2SAndroid Build Coastguard Worker     }
116*5e7646d2SAndroid Build Coastguard Worker   }
117*5e7646d2SAndroid Build Coastguard Worker 
118*5e7646d2SAndroid Build Coastguard Worker   if (!mdb)
119*5e7646d2SAndroid Build Coastguard Worker   {
120*5e7646d2SAndroid Build Coastguard Worker     for (mdb = (_cups_media_db_t *)cupsArrayFirst(db); mdb; mdb = (_cups_media_db_t *)cupsArrayNext(db))
121*5e7646d2SAndroid Build Coastguard Worker     {
122*5e7646d2SAndroid Build Coastguard Worker       if (mdb->width == size->width && mdb->length == size->length)
123*5e7646d2SAndroid Build Coastguard Worker 	break;
124*5e7646d2SAndroid Build Coastguard Worker     }
125*5e7646d2SAndroid Build Coastguard Worker   }
126*5e7646d2SAndroid Build Coastguard Worker 
127*5e7646d2SAndroid Build Coastguard Worker   if (!mdb)
128*5e7646d2SAndroid Build Coastguard Worker   {
129*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsAddDestMediaOptions: Unable to find matching size.");
130*5e7646d2SAndroid Build Coastguard Worker     return (num_options);
131*5e7646d2SAndroid Build Coastguard Worker   }
132*5e7646d2SAndroid Build Coastguard Worker 
133*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1cupsAddDestMediaOptions: MATCH mdb%p [key=\"%s\" size_name=\"%s\" source=\"%s\" type=\"%s\" width=%d length=%d B%d L%d R%d T%d]", (void *)mdb, mdb->key, mdb->size_name, mdb->source, mdb->type, mdb->width, mdb->length, mdb->bottom, mdb->left, mdb->right, mdb->top));
134*5e7646d2SAndroid Build Coastguard Worker 
135*5e7646d2SAndroid Build Coastguard Worker   if (mdb->source)
136*5e7646d2SAndroid Build Coastguard Worker   {
137*5e7646d2SAndroid Build Coastguard Worker     if (mdb->type)
138*5e7646d2SAndroid Build Coastguard Worker       snprintf(value, sizeof(value), "{media-size={x-dimension=%d y-dimension=%d} media-bottom-margin=%d media-left-margin=%d media-right-margin=%d media-top-margin=%d media-source=\"%s\" media-type=\"%s\"}", mdb->width, mdb->length, mdb->bottom, mdb->left, mdb->right, mdb->top, mdb->source, mdb->type);
139*5e7646d2SAndroid Build Coastguard Worker     else
140*5e7646d2SAndroid Build Coastguard Worker       snprintf(value, sizeof(value), "{media-size={x-dimension=%d y-dimension=%d} media-bottom-margin=%d media-left-margin=%d media-right-margin=%d media-top-margin=%d media-source=\"%s\"}", mdb->width, mdb->length, mdb->bottom, mdb->left, mdb->right, mdb->top, mdb->source);
141*5e7646d2SAndroid Build Coastguard Worker   }
142*5e7646d2SAndroid Build Coastguard Worker   else if (mdb->type)
143*5e7646d2SAndroid Build Coastguard Worker   {
144*5e7646d2SAndroid Build Coastguard Worker     snprintf(value, sizeof(value), "{media-size={x-dimension=%d y-dimension=%d} media-bottom-margin=%d media-left-margin=%d media-right-margin=%d media-top-margin=%d media-type=\"%s\"}", mdb->width, mdb->length, mdb->bottom, mdb->left, mdb->right, mdb->top, mdb->type);
145*5e7646d2SAndroid Build Coastguard Worker   }
146*5e7646d2SAndroid Build Coastguard Worker   else
147*5e7646d2SAndroid Build Coastguard Worker   {
148*5e7646d2SAndroid Build Coastguard Worker     snprintf(value, sizeof(value), "{media-size={x-dimension=%d y-dimension=%d} media-bottom-margin=%d media-left-margin=%d media-right-margin=%d media-top-margin=%d}", mdb->width, mdb->length, mdb->bottom, mdb->left, mdb->right, mdb->top);
149*5e7646d2SAndroid Build Coastguard Worker   }
150*5e7646d2SAndroid Build Coastguard Worker 
151*5e7646d2SAndroid Build Coastguard Worker   num_options = cupsAddOption("media-col", value, num_options, options);
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
154*5e7646d2SAndroid Build Coastguard Worker }
155*5e7646d2SAndroid Build Coastguard Worker 
156*5e7646d2SAndroid Build Coastguard Worker 
157*5e7646d2SAndroid Build Coastguard Worker /*
158*5e7646d2SAndroid Build Coastguard Worker  * 'cupsCheckDestSupported()' - Check that the option and value are supported
159*5e7646d2SAndroid Build Coastguard Worker  *                              by the destination.
160*5e7646d2SAndroid Build Coastguard Worker  *
161*5e7646d2SAndroid Build Coastguard Worker  * Returns 1 if supported, 0 otherwise.
162*5e7646d2SAndroid Build Coastguard Worker  *
163*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
164*5e7646d2SAndroid Build Coastguard Worker  */
165*5e7646d2SAndroid Build Coastguard Worker 
166*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 if supported, 0 otherwise */
cupsCheckDestSupported(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,const char * option,const char * value)167*5e7646d2SAndroid Build Coastguard Worker cupsCheckDestSupported(
168*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
169*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
170*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
171*5e7646d2SAndroid Build Coastguard Worker     const char   *option,		/* I - Option */
172*5e7646d2SAndroid Build Coastguard Worker     const char   *value)		/* I - Value or @code NULL@ */
173*5e7646d2SAndroid Build Coastguard Worker {
174*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
175*5e7646d2SAndroid Build Coastguard Worker   char			temp[1024];	/* Temporary string */
176*5e7646d2SAndroid Build Coastguard Worker   int			int_value;	/* Integer value */
177*5e7646d2SAndroid Build Coastguard Worker   int			xres_value,	/* Horizontal resolution */
178*5e7646d2SAndroid Build Coastguard Worker 			yres_value;	/* Vertical resolution */
179*5e7646d2SAndroid Build Coastguard Worker   ipp_res_t		units_value;	/* Resolution units */
180*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Attribute */
181*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*attrval;	/* Current attribute value */
182*5e7646d2SAndroid Build Coastguard Worker   _ipp_option_t		*map;		/* Option mapping information */
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker 
185*5e7646d2SAndroid Build Coastguard Worker  /*
186*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
187*5e7646d2SAndroid Build Coastguard Worker   */
188*5e7646d2SAndroid Build Coastguard Worker 
189*5e7646d2SAndroid Build Coastguard Worker   if (!http)
190*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
191*5e7646d2SAndroid Build Coastguard Worker 
192*5e7646d2SAndroid Build Coastguard Worker  /*
193*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
194*5e7646d2SAndroid Build Coastguard Worker   */
195*5e7646d2SAndroid Build Coastguard Worker 
196*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || !option)
197*5e7646d2SAndroid Build Coastguard Worker     return (0);
198*5e7646d2SAndroid Build Coastguard Worker 
199*5e7646d2SAndroid Build Coastguard Worker  /*
200*5e7646d2SAndroid Build Coastguard Worker   * Lookup the attribute...
201*5e7646d2SAndroid Build Coastguard Worker   */
202*5e7646d2SAndroid Build Coastguard Worker 
203*5e7646d2SAndroid Build Coastguard Worker   if (strstr(option, "-supported"))
204*5e7646d2SAndroid Build Coastguard Worker     attr = ippFindAttribute(dinfo->attrs, option, IPP_TAG_ZERO);
205*5e7646d2SAndroid Build Coastguard Worker   else
206*5e7646d2SAndroid Build Coastguard Worker   {
207*5e7646d2SAndroid Build Coastguard Worker     snprintf(temp, sizeof(temp), "%s-supported", option);
208*5e7646d2SAndroid Build Coastguard Worker     attr = ippFindAttribute(dinfo->attrs, temp, IPP_TAG_ZERO);
209*5e7646d2SAndroid Build Coastguard Worker   }
210*5e7646d2SAndroid Build Coastguard Worker 
211*5e7646d2SAndroid Build Coastguard Worker   if (!attr)
212*5e7646d2SAndroid Build Coastguard Worker     return (0);
213*5e7646d2SAndroid Build Coastguard Worker 
214*5e7646d2SAndroid Build Coastguard Worker   if (!value)
215*5e7646d2SAndroid Build Coastguard Worker     return (1);
216*5e7646d2SAndroid Build Coastguard Worker 
217*5e7646d2SAndroid Build Coastguard Worker /*
218*5e7646d2SAndroid Build Coastguard Worker   * Compare values...
219*5e7646d2SAndroid Build Coastguard Worker   */
220*5e7646d2SAndroid Build Coastguard Worker 
221*5e7646d2SAndroid Build Coastguard Worker   if (!strcmp(option, "media") && !strncmp(value, "custom_", 7))
222*5e7646d2SAndroid Build Coastguard Worker   {
223*5e7646d2SAndroid Build Coastguard Worker    /*
224*5e7646d2SAndroid Build Coastguard Worker     * Check range of custom media sizes...
225*5e7646d2SAndroid Build Coastguard Worker     */
226*5e7646d2SAndroid Build Coastguard Worker 
227*5e7646d2SAndroid Build Coastguard Worker     pwg_media_t	*pwg;		/* Current PWG media size info */
228*5e7646d2SAndroid Build Coastguard Worker     int		min_width,	/* Minimum width */
229*5e7646d2SAndroid Build Coastguard Worker 		min_length,	/* Minimum length */
230*5e7646d2SAndroid Build Coastguard Worker 		max_width,	/* Maximum width */
231*5e7646d2SAndroid Build Coastguard Worker 		max_length;	/* Maximum length */
232*5e7646d2SAndroid Build Coastguard Worker 
233*5e7646d2SAndroid Build Coastguard Worker    /*
234*5e7646d2SAndroid Build Coastguard Worker     * Get the minimum and maximum size...
235*5e7646d2SAndroid Build Coastguard Worker     */
236*5e7646d2SAndroid Build Coastguard Worker 
237*5e7646d2SAndroid Build Coastguard Worker     min_width = min_length = INT_MAX;
238*5e7646d2SAndroid Build Coastguard Worker     max_width = max_length = 0;
239*5e7646d2SAndroid Build Coastguard Worker 
240*5e7646d2SAndroid Build Coastguard Worker     for (i = attr->num_values, attrval = attr->values;
241*5e7646d2SAndroid Build Coastguard Worker 	 i > 0;
242*5e7646d2SAndroid Build Coastguard Worker 	 i --, attrval ++)
243*5e7646d2SAndroid Build Coastguard Worker     {
244*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(attrval->string.text, "custom_min_", 11) &&
245*5e7646d2SAndroid Build Coastguard Worker           (pwg = pwgMediaForPWG(attrval->string.text)) != NULL)
246*5e7646d2SAndroid Build Coastguard Worker       {
247*5e7646d2SAndroid Build Coastguard Worker         min_width  = pwg->width;
248*5e7646d2SAndroid Build Coastguard Worker         min_length = pwg->length;
249*5e7646d2SAndroid Build Coastguard Worker       }
250*5e7646d2SAndroid Build Coastguard Worker       else if (!strncmp(attrval->string.text, "custom_max_", 11) &&
251*5e7646d2SAndroid Build Coastguard Worker 	       (pwg = pwgMediaForPWG(attrval->string.text)) != NULL)
252*5e7646d2SAndroid Build Coastguard Worker       {
253*5e7646d2SAndroid Build Coastguard Worker         max_width  = pwg->width;
254*5e7646d2SAndroid Build Coastguard Worker         max_length = pwg->length;
255*5e7646d2SAndroid Build Coastguard Worker       }
256*5e7646d2SAndroid Build Coastguard Worker     }
257*5e7646d2SAndroid Build Coastguard Worker 
258*5e7646d2SAndroid Build Coastguard Worker    /*
259*5e7646d2SAndroid Build Coastguard Worker     * Check the range...
260*5e7646d2SAndroid Build Coastguard Worker     */
261*5e7646d2SAndroid Build Coastguard Worker 
262*5e7646d2SAndroid Build Coastguard Worker     if (min_width < INT_MAX && max_width > 0 &&
263*5e7646d2SAndroid Build Coastguard Worker         (pwg = pwgMediaForPWG(value)) != NULL &&
264*5e7646d2SAndroid Build Coastguard Worker         pwg->width >= min_width && pwg->width <= max_width &&
265*5e7646d2SAndroid Build Coastguard Worker         pwg->length >= min_length && pwg->length <= max_length)
266*5e7646d2SAndroid Build Coastguard Worker       return (1);
267*5e7646d2SAndroid Build Coastguard Worker   }
268*5e7646d2SAndroid Build Coastguard Worker   else
269*5e7646d2SAndroid Build Coastguard Worker   {
270*5e7646d2SAndroid Build Coastguard Worker    /*
271*5e7646d2SAndroid Build Coastguard Worker     * Check literal values...
272*5e7646d2SAndroid Build Coastguard Worker     */
273*5e7646d2SAndroid Build Coastguard Worker 
274*5e7646d2SAndroid Build Coastguard Worker     map = _ippFindOption(option);
275*5e7646d2SAndroid Build Coastguard Worker 
276*5e7646d2SAndroid Build Coastguard Worker     switch (attr->value_tag)
277*5e7646d2SAndroid Build Coastguard Worker     {
278*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_INTEGER :
279*5e7646d2SAndroid Build Coastguard Worker           if (map && map->value_tag == IPP_TAG_STRING)
280*5e7646d2SAndroid Build Coastguard Worker             return (strlen(value) <= (size_t)attr->values[0].integer);
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ENUM :
283*5e7646d2SAndroid Build Coastguard Worker           int_value = atoi(value);
284*5e7646d2SAndroid Build Coastguard Worker 
285*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < attr->num_values; i ++)
286*5e7646d2SAndroid Build Coastguard Worker             if (attr->values[i].integer == int_value)
287*5e7646d2SAndroid Build Coastguard Worker               return (1);
288*5e7646d2SAndroid Build Coastguard Worker           break;
289*5e7646d2SAndroid Build Coastguard Worker 
290*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BOOLEAN :
291*5e7646d2SAndroid Build Coastguard Worker           return (attr->values[0].boolean);
292*5e7646d2SAndroid Build Coastguard Worker 
293*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RANGE :
294*5e7646d2SAndroid Build Coastguard Worker           if (map && map->value_tag == IPP_TAG_STRING)
295*5e7646d2SAndroid Build Coastguard Worker             int_value = (int)strlen(value);
296*5e7646d2SAndroid Build Coastguard Worker           else
297*5e7646d2SAndroid Build Coastguard Worker             int_value = atoi(value);
298*5e7646d2SAndroid Build Coastguard Worker 
299*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < attr->num_values; i ++)
300*5e7646d2SAndroid Build Coastguard Worker             if (int_value >= attr->values[i].range.lower &&
301*5e7646d2SAndroid Build Coastguard Worker                 int_value <= attr->values[i].range.upper)
302*5e7646d2SAndroid Build Coastguard Worker               return (1);
303*5e7646d2SAndroid Build Coastguard Worker           break;
304*5e7646d2SAndroid Build Coastguard Worker 
305*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RESOLUTION :
306*5e7646d2SAndroid Build Coastguard Worker           if (sscanf(value, "%dx%d%15s", &xres_value, &yres_value, temp) != 3)
307*5e7646d2SAndroid Build Coastguard Worker           {
308*5e7646d2SAndroid Build Coastguard Worker             if (sscanf(value, "%d%15s", &xres_value, temp) != 2)
309*5e7646d2SAndroid Build Coastguard Worker               return (0);
310*5e7646d2SAndroid Build Coastguard Worker 
311*5e7646d2SAndroid Build Coastguard Worker             yres_value = xres_value;
312*5e7646d2SAndroid Build Coastguard Worker           }
313*5e7646d2SAndroid Build Coastguard Worker 
314*5e7646d2SAndroid Build Coastguard Worker           if (!strcmp(temp, "dpi"))
315*5e7646d2SAndroid Build Coastguard Worker             units_value = IPP_RES_PER_INCH;
316*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(temp, "dpc") || !strcmp(temp, "dpcm"))
317*5e7646d2SAndroid Build Coastguard Worker             units_value = IPP_RES_PER_CM;
318*5e7646d2SAndroid Build Coastguard Worker           else
319*5e7646d2SAndroid Build Coastguard Worker             return (0);
320*5e7646d2SAndroid Build Coastguard Worker 
321*5e7646d2SAndroid Build Coastguard Worker           for (i = attr->num_values, attrval = attr->values;
322*5e7646d2SAndroid Build Coastguard Worker                i > 0;
323*5e7646d2SAndroid Build Coastguard Worker                i --, attrval ++)
324*5e7646d2SAndroid Build Coastguard Worker           {
325*5e7646d2SAndroid Build Coastguard Worker             if (attrval->resolution.xres == xres_value &&
326*5e7646d2SAndroid Build Coastguard Worker                 attrval->resolution.yres == yres_value &&
327*5e7646d2SAndroid Build Coastguard Worker                 attrval->resolution.units == units_value)
328*5e7646d2SAndroid Build Coastguard Worker               return (1);
329*5e7646d2SAndroid Build Coastguard Worker           }
330*5e7646d2SAndroid Build Coastguard Worker           break;
331*5e7646d2SAndroid Build Coastguard Worker 
332*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXT :
333*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAME :
334*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_KEYWORD :
335*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_CHARSET :
336*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URI :
337*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URISCHEME :
338*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_MIMETYPE :
339*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_LANGUAGE :
340*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXTLANG :
341*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAMELANG :
342*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < attr->num_values; i ++)
343*5e7646d2SAndroid Build Coastguard Worker             if (!strcmp(attr->values[i].string.text, value))
344*5e7646d2SAndroid Build Coastguard Worker               return (1);
345*5e7646d2SAndroid Build Coastguard Worker           break;
346*5e7646d2SAndroid Build Coastguard Worker 
347*5e7646d2SAndroid Build Coastguard Worker       default :
348*5e7646d2SAndroid Build Coastguard Worker           break;
349*5e7646d2SAndroid Build Coastguard Worker     }
350*5e7646d2SAndroid Build Coastguard Worker   }
351*5e7646d2SAndroid Build Coastguard Worker 
352*5e7646d2SAndroid Build Coastguard Worker  /*
353*5e7646d2SAndroid Build Coastguard Worker   * If we get there the option+value is not supported...
354*5e7646d2SAndroid Build Coastguard Worker   */
355*5e7646d2SAndroid Build Coastguard Worker 
356*5e7646d2SAndroid Build Coastguard Worker   return (0);
357*5e7646d2SAndroid Build Coastguard Worker }
358*5e7646d2SAndroid Build Coastguard Worker 
359*5e7646d2SAndroid Build Coastguard Worker 
360*5e7646d2SAndroid Build Coastguard Worker /*
361*5e7646d2SAndroid Build Coastguard Worker  * 'cupsCopyDestConflicts()' - Get conflicts and resolutions for a new
362*5e7646d2SAndroid Build Coastguard Worker  *                             option/value pair.
363*5e7646d2SAndroid Build Coastguard Worker  *
364*5e7646d2SAndroid Build Coastguard Worker  * "num_options" and "options" represent the currently selected options by the
365*5e7646d2SAndroid Build Coastguard Worker  * user.  "new_option" and "new_value" are the setting the user has just
366*5e7646d2SAndroid Build Coastguard Worker  * changed.
367*5e7646d2SAndroid Build Coastguard Worker  *
368*5e7646d2SAndroid Build Coastguard Worker  * Returns 1 if there is a conflict, 0 if there are no conflicts, and -1 if
369*5e7646d2SAndroid Build Coastguard Worker  * there was an unrecoverable error such as a resolver loop.
370*5e7646d2SAndroid Build Coastguard Worker  *
371*5e7646d2SAndroid Build Coastguard Worker  * If "num_conflicts" and "conflicts" are not @code NULL@, they are set to
372*5e7646d2SAndroid Build Coastguard Worker  * contain the list of conflicting option/value pairs.  Similarly, if
373*5e7646d2SAndroid Build Coastguard Worker  * "num_resolved" and "resolved" are not @code NULL@ they will be set to the
374*5e7646d2SAndroid Build Coastguard Worker  * list of changes needed to resolve the conflict.
375*5e7646d2SAndroid Build Coastguard Worker  *
376*5e7646d2SAndroid Build Coastguard Worker  * If cupsCopyDestConflicts returns 1 but "num_resolved" and "resolved" are set
377*5e7646d2SAndroid Build Coastguard Worker  * to 0 and @code NULL@, respectively, then the conflict cannot be resolved.
378*5e7646d2SAndroid Build Coastguard Worker  *
379*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
380*5e7646d2SAndroid Build Coastguard Worker  */
381*5e7646d2SAndroid Build Coastguard Worker 
382*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 if there is a conflict, 0 if none, -1 on error */
cupsCopyDestConflicts(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,int num_options,cups_option_t * options,const char * new_option,const char * new_value,int * num_conflicts,cups_option_t ** conflicts,int * num_resolved,cups_option_t ** resolved)383*5e7646d2SAndroid Build Coastguard Worker cupsCopyDestConflicts(
384*5e7646d2SAndroid Build Coastguard Worker     http_t        *http,		/* I - Connection to destination */
385*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t   *dest,		/* I - Destination */
386*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t  *dinfo,		/* I - Destination information */
387*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of current options */
388*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options,		/* I - Current options */
389*5e7646d2SAndroid Build Coastguard Worker     const char    *new_option,		/* I - New option */
390*5e7646d2SAndroid Build Coastguard Worker     const char    *new_value,		/* I - New value */
391*5e7646d2SAndroid Build Coastguard Worker     int           *num_conflicts,	/* O - Number of conflicting options */
392*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **conflicts,		/* O - Conflicting options */
393*5e7646d2SAndroid Build Coastguard Worker     int           *num_resolved,	/* O - Number of options to resolve */
394*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **resolved)		/* O - Resolved options */
395*5e7646d2SAndroid Build Coastguard Worker {
396*5e7646d2SAndroid Build Coastguard Worker   int		i,			/* Looping var */
397*5e7646d2SAndroid Build Coastguard Worker 		have_conflicts = 0,	/* Do we have conflicts? */
398*5e7646d2SAndroid Build Coastguard Worker 		changed,		/* Did we change something? */
399*5e7646d2SAndroid Build Coastguard Worker 		tries,			/* Number of tries for resolution */
400*5e7646d2SAndroid Build Coastguard Worker 		num_myconf = 0,		/* My number of conflicting options */
401*5e7646d2SAndroid Build Coastguard Worker 		num_myres = 0;		/* My number of resolved options */
402*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*myconf = NULL,		/* My conflicting options */
403*5e7646d2SAndroid Build Coastguard Worker 		*myres = NULL,		/* My resolved options */
404*5e7646d2SAndroid Build Coastguard Worker 		*myoption,		/* My current option */
405*5e7646d2SAndroid Build Coastguard Worker 		*option;		/* Current option */
406*5e7646d2SAndroid Build Coastguard Worker   cups_array_t	*active = NULL,		/* Active conflicts */
407*5e7646d2SAndroid Build Coastguard Worker 		*pass = NULL,		/* Resolvers for this pass */
408*5e7646d2SAndroid Build Coastguard Worker 		*resolvers = NULL,	/* Resolvers we have used */
409*5e7646d2SAndroid Build Coastguard Worker 		*test;			/* Test array for conflicts */
410*5e7646d2SAndroid Build Coastguard Worker   _cups_dconstres_t *c,			/* Current constraint */
411*5e7646d2SAndroid Build Coastguard Worker 		*r;			/* Current resolver */
412*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attr;		/* Current attribute */
413*5e7646d2SAndroid Build Coastguard Worker   char		value[2048];		/* Current attribute value as string */
414*5e7646d2SAndroid Build Coastguard Worker   const char	*myvalue;		/* Current value of an option */
415*5e7646d2SAndroid Build Coastguard Worker 
416*5e7646d2SAndroid Build Coastguard Worker 
417*5e7646d2SAndroid Build Coastguard Worker  /*
418*5e7646d2SAndroid Build Coastguard Worker   * Clear returned values...
419*5e7646d2SAndroid Build Coastguard Worker   */
420*5e7646d2SAndroid Build Coastguard Worker 
421*5e7646d2SAndroid Build Coastguard Worker   if (num_conflicts)
422*5e7646d2SAndroid Build Coastguard Worker     *num_conflicts = 0;
423*5e7646d2SAndroid Build Coastguard Worker 
424*5e7646d2SAndroid Build Coastguard Worker   if (conflicts)
425*5e7646d2SAndroid Build Coastguard Worker     *conflicts = NULL;
426*5e7646d2SAndroid Build Coastguard Worker 
427*5e7646d2SAndroid Build Coastguard Worker   if (num_resolved)
428*5e7646d2SAndroid Build Coastguard Worker     *num_resolved = 0;
429*5e7646d2SAndroid Build Coastguard Worker 
430*5e7646d2SAndroid Build Coastguard Worker   if (resolved)
431*5e7646d2SAndroid Build Coastguard Worker     *resolved = NULL;
432*5e7646d2SAndroid Build Coastguard Worker 
433*5e7646d2SAndroid Build Coastguard Worker  /*
434*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
435*5e7646d2SAndroid Build Coastguard Worker   */
436*5e7646d2SAndroid Build Coastguard Worker 
437*5e7646d2SAndroid Build Coastguard Worker   if (!http)
438*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
439*5e7646d2SAndroid Build Coastguard Worker 
440*5e7646d2SAndroid Build Coastguard Worker  /*
441*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
442*5e7646d2SAndroid Build Coastguard Worker   */
443*5e7646d2SAndroid Build Coastguard Worker 
444*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo ||
445*5e7646d2SAndroid Build Coastguard Worker       (num_conflicts != NULL) != (conflicts != NULL) ||
446*5e7646d2SAndroid Build Coastguard Worker       (num_resolved != NULL) != (resolved != NULL))
447*5e7646d2SAndroid Build Coastguard Worker     return (0);
448*5e7646d2SAndroid Build Coastguard Worker 
449*5e7646d2SAndroid Build Coastguard Worker  /*
450*5e7646d2SAndroid Build Coastguard Worker   * Load constraints as needed...
451*5e7646d2SAndroid Build Coastguard Worker   */
452*5e7646d2SAndroid Build Coastguard Worker 
453*5e7646d2SAndroid Build Coastguard Worker   if (!dinfo->constraints)
454*5e7646d2SAndroid Build Coastguard Worker     cups_create_constraints(dinfo);
455*5e7646d2SAndroid Build Coastguard Worker 
456*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(dinfo->constraints) == 0)
457*5e7646d2SAndroid Build Coastguard Worker     return (0);
458*5e7646d2SAndroid Build Coastguard Worker 
459*5e7646d2SAndroid Build Coastguard Worker   if (!dinfo->num_defaults)
460*5e7646d2SAndroid Build Coastguard Worker     cups_create_defaults(dinfo);
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker  /*
463*5e7646d2SAndroid Build Coastguard Worker   * If we are resolving, create a shadow array...
464*5e7646d2SAndroid Build Coastguard Worker   */
465*5e7646d2SAndroid Build Coastguard Worker 
466*5e7646d2SAndroid Build Coastguard Worker   if (num_resolved)
467*5e7646d2SAndroid Build Coastguard Worker   {
468*5e7646d2SAndroid Build Coastguard Worker     for (i = num_options, option = options; i > 0; i --, option ++)
469*5e7646d2SAndroid Build Coastguard Worker       num_myres = cupsAddOption(option->name, option->value, num_myres, &myres);
470*5e7646d2SAndroid Build Coastguard Worker 
471*5e7646d2SAndroid Build Coastguard Worker     if (new_option && new_value)
472*5e7646d2SAndroid Build Coastguard Worker       num_myres = cupsAddOption(new_option, new_value, num_myres, &myres);
473*5e7646d2SAndroid Build Coastguard Worker   }
474*5e7646d2SAndroid Build Coastguard Worker   else
475*5e7646d2SAndroid Build Coastguard Worker   {
476*5e7646d2SAndroid Build Coastguard Worker     num_myres = num_options;
477*5e7646d2SAndroid Build Coastguard Worker     myres     = options;
478*5e7646d2SAndroid Build Coastguard Worker   }
479*5e7646d2SAndroid Build Coastguard Worker 
480*5e7646d2SAndroid Build Coastguard Worker  /*
481*5e7646d2SAndroid Build Coastguard Worker   * Check for any conflicts...
482*5e7646d2SAndroid Build Coastguard Worker   */
483*5e7646d2SAndroid Build Coastguard Worker 
484*5e7646d2SAndroid Build Coastguard Worker   if (num_resolved)
485*5e7646d2SAndroid Build Coastguard Worker     pass = cupsArrayNew((cups_array_func_t)cups_compare_dconstres, NULL);
486*5e7646d2SAndroid Build Coastguard Worker 
487*5e7646d2SAndroid Build Coastguard Worker   for (tries = 0; tries < 100; tries ++)
488*5e7646d2SAndroid Build Coastguard Worker   {
489*5e7646d2SAndroid Build Coastguard Worker    /*
490*5e7646d2SAndroid Build Coastguard Worker     * Check for any conflicts...
491*5e7646d2SAndroid Build Coastguard Worker     */
492*5e7646d2SAndroid Build Coastguard Worker 
493*5e7646d2SAndroid Build Coastguard Worker     if (num_conflicts || num_resolved)
494*5e7646d2SAndroid Build Coastguard Worker     {
495*5e7646d2SAndroid Build Coastguard Worker       cupsFreeOptions(num_myconf, myconf);
496*5e7646d2SAndroid Build Coastguard Worker 
497*5e7646d2SAndroid Build Coastguard Worker       num_myconf = 0;
498*5e7646d2SAndroid Build Coastguard Worker       myconf     = NULL;
499*5e7646d2SAndroid Build Coastguard Worker       active     = cups_test_constraints(dinfo, new_option, new_value,
500*5e7646d2SAndroid Build Coastguard Worker                                          num_myres, myres, &num_myconf,
501*5e7646d2SAndroid Build Coastguard Worker                                          &myconf);
502*5e7646d2SAndroid Build Coastguard Worker     }
503*5e7646d2SAndroid Build Coastguard Worker     else
504*5e7646d2SAndroid Build Coastguard Worker       active = cups_test_constraints(dinfo, new_option, new_value, num_myres,
505*5e7646d2SAndroid Build Coastguard Worker 				     myres, NULL, NULL);
506*5e7646d2SAndroid Build Coastguard Worker 
507*5e7646d2SAndroid Build Coastguard Worker     have_conflicts = (active != NULL);
508*5e7646d2SAndroid Build Coastguard Worker 
509*5e7646d2SAndroid Build Coastguard Worker     if (!active || !num_resolved)
510*5e7646d2SAndroid Build Coastguard Worker       break;				/* All done */
511*5e7646d2SAndroid Build Coastguard Worker 
512*5e7646d2SAndroid Build Coastguard Worker    /*
513*5e7646d2SAndroid Build Coastguard Worker     * Scan the constraints that were triggered to apply resolvers...
514*5e7646d2SAndroid Build Coastguard Worker     */
515*5e7646d2SAndroid Build Coastguard Worker 
516*5e7646d2SAndroid Build Coastguard Worker     if (!resolvers)
517*5e7646d2SAndroid Build Coastguard Worker       resolvers = cupsArrayNew((cups_array_func_t)cups_compare_dconstres, NULL);
518*5e7646d2SAndroid Build Coastguard Worker 
519*5e7646d2SAndroid Build Coastguard Worker     for (c = (_cups_dconstres_t *)cupsArrayFirst(active), changed = 0;
520*5e7646d2SAndroid Build Coastguard Worker          c;
521*5e7646d2SAndroid Build Coastguard Worker          c = (_cups_dconstres_t *)cupsArrayNext(active))
522*5e7646d2SAndroid Build Coastguard Worker     {
523*5e7646d2SAndroid Build Coastguard Worker       if (cupsArrayFind(pass, c))
524*5e7646d2SAndroid Build Coastguard Worker         continue;			/* Already applied this resolver... */
525*5e7646d2SAndroid Build Coastguard Worker 
526*5e7646d2SAndroid Build Coastguard Worker       if (cupsArrayFind(resolvers, c))
527*5e7646d2SAndroid Build Coastguard Worker       {
528*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("1cupsCopyDestConflicts: Resolver loop with %s.",
529*5e7646d2SAndroid Build Coastguard Worker                       c->name));
530*5e7646d2SAndroid Build Coastguard Worker         have_conflicts = -1;
531*5e7646d2SAndroid Build Coastguard Worker         goto cleanup;
532*5e7646d2SAndroid Build Coastguard Worker       }
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker       if ((r = cupsArrayFind(dinfo->resolvers, c)) == NULL)
535*5e7646d2SAndroid Build Coastguard Worker       {
536*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("1cupsCopyDestConflicts: Resolver %s not found.",
537*5e7646d2SAndroid Build Coastguard Worker                       c->name));
538*5e7646d2SAndroid Build Coastguard Worker         have_conflicts = -1;
539*5e7646d2SAndroid Build Coastguard Worker         goto cleanup;
540*5e7646d2SAndroid Build Coastguard Worker       }
541*5e7646d2SAndroid Build Coastguard Worker 
542*5e7646d2SAndroid Build Coastguard Worker      /*
543*5e7646d2SAndroid Build Coastguard Worker       * Add the options from the resolver...
544*5e7646d2SAndroid Build Coastguard Worker       */
545*5e7646d2SAndroid Build Coastguard Worker 
546*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(pass, r);
547*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(resolvers, r);
548*5e7646d2SAndroid Build Coastguard Worker 
549*5e7646d2SAndroid Build Coastguard Worker       for (attr = ippFirstAttribute(r->collection);
550*5e7646d2SAndroid Build Coastguard Worker            attr;
551*5e7646d2SAndroid Build Coastguard Worker            attr = ippNextAttribute(r->collection))
552*5e7646d2SAndroid Build Coastguard Worker       {
553*5e7646d2SAndroid Build Coastguard Worker         if (new_option && !strcmp(attr->name, new_option))
554*5e7646d2SAndroid Build Coastguard Worker           continue;			/* Ignore this if we just changed it */
555*5e7646d2SAndroid Build Coastguard Worker 
556*5e7646d2SAndroid Build Coastguard Worker         if (ippAttributeString(attr, value, sizeof(value)) >= sizeof(value))
557*5e7646d2SAndroid Build Coastguard Worker           continue;			/* Ignore if the value is too long */
558*5e7646d2SAndroid Build Coastguard Worker 
559*5e7646d2SAndroid Build Coastguard Worker         if ((test = cups_test_constraints(dinfo, attr->name, value, num_myres,
560*5e7646d2SAndroid Build Coastguard Worker                                           myres, NULL, NULL)) == NULL)
561*5e7646d2SAndroid Build Coastguard Worker         {
562*5e7646d2SAndroid Build Coastguard Worker          /*
563*5e7646d2SAndroid Build Coastguard Worker           * That worked, flag it...
564*5e7646d2SAndroid Build Coastguard Worker           */
565*5e7646d2SAndroid Build Coastguard Worker 
566*5e7646d2SAndroid Build Coastguard Worker           changed = 1;
567*5e7646d2SAndroid Build Coastguard Worker         }
568*5e7646d2SAndroid Build Coastguard Worker         else
569*5e7646d2SAndroid Build Coastguard Worker           cupsArrayDelete(test);
570*5e7646d2SAndroid Build Coastguard Worker 
571*5e7646d2SAndroid Build Coastguard Worker        /*
572*5e7646d2SAndroid Build Coastguard Worker 	* Add the option/value from the resolver regardless of whether it
573*5e7646d2SAndroid Build Coastguard Worker 	* worked; this makes sure that we can cascade several changes to
574*5e7646d2SAndroid Build Coastguard Worker 	* make things resolve...
575*5e7646d2SAndroid Build Coastguard Worker 	*/
576*5e7646d2SAndroid Build Coastguard Worker 
577*5e7646d2SAndroid Build Coastguard Worker 	num_myres = cupsAddOption(attr->name, value, num_myres, &myres);
578*5e7646d2SAndroid Build Coastguard Worker       }
579*5e7646d2SAndroid Build Coastguard Worker     }
580*5e7646d2SAndroid Build Coastguard Worker 
581*5e7646d2SAndroid Build Coastguard Worker     if (!changed)
582*5e7646d2SAndroid Build Coastguard Worker     {
583*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("1cupsCopyDestConflicts: Unable to resolve constraints.");
584*5e7646d2SAndroid Build Coastguard Worker       have_conflicts = -1;
585*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
586*5e7646d2SAndroid Build Coastguard Worker     }
587*5e7646d2SAndroid Build Coastguard Worker 
588*5e7646d2SAndroid Build Coastguard Worker     cupsArrayClear(pass);
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(active);
591*5e7646d2SAndroid Build Coastguard Worker     active = NULL;
592*5e7646d2SAndroid Build Coastguard Worker   }
593*5e7646d2SAndroid Build Coastguard Worker 
594*5e7646d2SAndroid Build Coastguard Worker   if (tries >= 100)
595*5e7646d2SAndroid Build Coastguard Worker   {
596*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsCopyDestConflicts: Unable to resolve after 100 tries.");
597*5e7646d2SAndroid Build Coastguard Worker     have_conflicts = -1;
598*5e7646d2SAndroid Build Coastguard Worker     goto cleanup;
599*5e7646d2SAndroid Build Coastguard Worker   }
600*5e7646d2SAndroid Build Coastguard Worker 
601*5e7646d2SAndroid Build Coastguard Worker  /*
602*5e7646d2SAndroid Build Coastguard Worker   * Copy resolved options as needed...
603*5e7646d2SAndroid Build Coastguard Worker   */
604*5e7646d2SAndroid Build Coastguard Worker 
605*5e7646d2SAndroid Build Coastguard Worker   if (num_resolved)
606*5e7646d2SAndroid Build Coastguard Worker   {
607*5e7646d2SAndroid Build Coastguard Worker     for (i = num_myres, myoption = myres; i > 0; i --, myoption ++)
608*5e7646d2SAndroid Build Coastguard Worker     {
609*5e7646d2SAndroid Build Coastguard Worker       if ((myvalue = cupsGetOption(myoption->name, num_options,
610*5e7646d2SAndroid Build Coastguard Worker                                    options)) == NULL ||
611*5e7646d2SAndroid Build Coastguard Worker           strcmp(myvalue, myoption->value))
612*5e7646d2SAndroid Build Coastguard Worker       {
613*5e7646d2SAndroid Build Coastguard Worker         if (new_option && !strcmp(new_option, myoption->name) &&
614*5e7646d2SAndroid Build Coastguard Worker             new_value && !strcmp(new_value, myoption->value))
615*5e7646d2SAndroid Build Coastguard Worker           continue;
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker         *num_resolved = cupsAddOption(myoption->name, myoption->value,
618*5e7646d2SAndroid Build Coastguard Worker                                       *num_resolved, resolved);
619*5e7646d2SAndroid Build Coastguard Worker       }
620*5e7646d2SAndroid Build Coastguard Worker     }
621*5e7646d2SAndroid Build Coastguard Worker   }
622*5e7646d2SAndroid Build Coastguard Worker 
623*5e7646d2SAndroid Build Coastguard Worker  /*
624*5e7646d2SAndroid Build Coastguard Worker   * Clean up...
625*5e7646d2SAndroid Build Coastguard Worker   */
626*5e7646d2SAndroid Build Coastguard Worker 
627*5e7646d2SAndroid Build Coastguard Worker   cleanup:
628*5e7646d2SAndroid Build Coastguard Worker 
629*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(active);
630*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(pass);
631*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(resolvers);
632*5e7646d2SAndroid Build Coastguard Worker 
633*5e7646d2SAndroid Build Coastguard Worker   if (num_resolved)
634*5e7646d2SAndroid Build Coastguard Worker   {
635*5e7646d2SAndroid Build Coastguard Worker    /*
636*5e7646d2SAndroid Build Coastguard Worker     * Free shadow copy of options...
637*5e7646d2SAndroid Build Coastguard Worker     */
638*5e7646d2SAndroid Build Coastguard Worker 
639*5e7646d2SAndroid Build Coastguard Worker     cupsFreeOptions(num_myres, myres);
640*5e7646d2SAndroid Build Coastguard Worker   }
641*5e7646d2SAndroid Build Coastguard Worker 
642*5e7646d2SAndroid Build Coastguard Worker   if (num_conflicts)
643*5e7646d2SAndroid Build Coastguard Worker   {
644*5e7646d2SAndroid Build Coastguard Worker    /*
645*5e7646d2SAndroid Build Coastguard Worker     * Return conflicting options to caller...
646*5e7646d2SAndroid Build Coastguard Worker     */
647*5e7646d2SAndroid Build Coastguard Worker 
648*5e7646d2SAndroid Build Coastguard Worker     *num_conflicts = num_myconf;
649*5e7646d2SAndroid Build Coastguard Worker     *conflicts     = myconf;
650*5e7646d2SAndroid Build Coastguard Worker   }
651*5e7646d2SAndroid Build Coastguard Worker   else
652*5e7646d2SAndroid Build Coastguard Worker   {
653*5e7646d2SAndroid Build Coastguard Worker    /*
654*5e7646d2SAndroid Build Coastguard Worker     * Free conflicting options...
655*5e7646d2SAndroid Build Coastguard Worker     */
656*5e7646d2SAndroid Build Coastguard Worker 
657*5e7646d2SAndroid Build Coastguard Worker     cupsFreeOptions(num_myconf, myconf);
658*5e7646d2SAndroid Build Coastguard Worker   }
659*5e7646d2SAndroid Build Coastguard Worker 
660*5e7646d2SAndroid Build Coastguard Worker   return (have_conflicts);
661*5e7646d2SAndroid Build Coastguard Worker }
662*5e7646d2SAndroid Build Coastguard Worker 
663*5e7646d2SAndroid Build Coastguard Worker 
664*5e7646d2SAndroid Build Coastguard Worker /*
665*5e7646d2SAndroid Build Coastguard Worker  * 'cupsCopyDestInfo()' - Get the supported values/capabilities for the
666*5e7646d2SAndroid Build Coastguard Worker  *                        destination.
667*5e7646d2SAndroid Build Coastguard Worker  *
668*5e7646d2SAndroid Build Coastguard Worker  * The caller is responsible for calling @link cupsFreeDestInfo@ on the return
669*5e7646d2SAndroid Build Coastguard Worker  * value. @code NULL@ is returned on error.
670*5e7646d2SAndroid Build Coastguard Worker  *
671*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
672*5e7646d2SAndroid Build Coastguard Worker  */
673*5e7646d2SAndroid Build Coastguard Worker 
674*5e7646d2SAndroid Build Coastguard Worker cups_dinfo_t *				/* O - Destination information */
cupsCopyDestInfo(http_t * http,cups_dest_t * dest)675*5e7646d2SAndroid Build Coastguard Worker cupsCopyDestInfo(
676*5e7646d2SAndroid Build Coastguard Worker     http_t      *http,			/* I - Connection to destination */
677*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t *dest)			/* I - Destination */
678*5e7646d2SAndroid Build Coastguard Worker {
679*5e7646d2SAndroid Build Coastguard Worker   cups_dinfo_t	*dinfo;			/* Destination information */
680*5e7646d2SAndroid Build Coastguard Worker   unsigned	dflags;			/* Destination flags */
681*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request,		/* Get-Printer-Attributes request */
682*5e7646d2SAndroid Build Coastguard Worker 		*response;		/* Supported attributes */
683*5e7646d2SAndroid Build Coastguard Worker   int		tries,			/* Number of tries so far */
684*5e7646d2SAndroid Build Coastguard Worker 		delay,			/* Current retry delay */
685*5e7646d2SAndroid Build Coastguard Worker 		prev_delay;		/* Next retry delay */
686*5e7646d2SAndroid Build Coastguard Worker   const char	*uri;			/* Printer URI */
687*5e7646d2SAndroid Build Coastguard Worker   char		resource[1024];		/* Resource path */
688*5e7646d2SAndroid Build Coastguard Worker   int		version;		/* IPP version */
689*5e7646d2SAndroid Build Coastguard Worker   ipp_status_t	status;			/* Status of request */
690*5e7646d2SAndroid Build Coastguard Worker   _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */
691*5e7646d2SAndroid Build Coastguard Worker   static const char * const requested_attrs[] =
692*5e7646d2SAndroid Build Coastguard Worker   {					/* Requested attributes */
693*5e7646d2SAndroid Build Coastguard Worker     "job-template",
694*5e7646d2SAndroid Build Coastguard Worker     "media-col-database",
695*5e7646d2SAndroid Build Coastguard Worker     "printer-description"
696*5e7646d2SAndroid Build Coastguard Worker   };
697*5e7646d2SAndroid Build Coastguard Worker 
698*5e7646d2SAndroid Build Coastguard Worker 
699*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("cupsCopyDestInfo(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : ""));
700*5e7646d2SAndroid Build Coastguard Worker 
701*5e7646d2SAndroid Build Coastguard Worker  /*
702*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
703*5e7646d2SAndroid Build Coastguard Worker   */
704*5e7646d2SAndroid Build Coastguard Worker 
705*5e7646d2SAndroid Build Coastguard Worker   if (!http)
706*5e7646d2SAndroid Build Coastguard Worker   {
707*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsCopyDestInfo: Default server connection.");
708*5e7646d2SAndroid Build Coastguard Worker     http   = _cupsConnect();
709*5e7646d2SAndroid Build Coastguard Worker     dflags = CUPS_DEST_FLAGS_NONE;
710*5e7646d2SAndroid Build Coastguard Worker   }
711*5e7646d2SAndroid Build Coastguard Worker #ifdef AF_LOCAL
712*5e7646d2SAndroid Build Coastguard Worker   else if (httpAddrFamily(http->hostaddr) == AF_LOCAL)
713*5e7646d2SAndroid Build Coastguard Worker   {
714*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsCopyDestInfo: Connection to server (domain socket).");
715*5e7646d2SAndroid Build Coastguard Worker     dflags = CUPS_DEST_FLAGS_NONE;
716*5e7646d2SAndroid Build Coastguard Worker   }
717*5e7646d2SAndroid Build Coastguard Worker #endif /* AF_LOCAL */
718*5e7646d2SAndroid Build Coastguard Worker   else if ((strcmp(http->hostname, cg->server) && cg->server[0] != '/') || cg->ipp_port != httpAddrPort(http->hostaddr))
719*5e7646d2SAndroid Build Coastguard Worker   {
720*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1cupsCopyDestInfo: Connection to device (%s).", http->hostname));
721*5e7646d2SAndroid Build Coastguard Worker     dflags = CUPS_DEST_FLAGS_DEVICE;
722*5e7646d2SAndroid Build Coastguard Worker   }
723*5e7646d2SAndroid Build Coastguard Worker   else
724*5e7646d2SAndroid Build Coastguard Worker   {
725*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1cupsCopyDestInfo: Connection to server (%s).", http->hostname));
726*5e7646d2SAndroid Build Coastguard Worker     dflags = CUPS_DEST_FLAGS_NONE;
727*5e7646d2SAndroid Build Coastguard Worker   }
728*5e7646d2SAndroid Build Coastguard Worker 
729*5e7646d2SAndroid Build Coastguard Worker  /*
730*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
731*5e7646d2SAndroid Build Coastguard Worker   */
732*5e7646d2SAndroid Build Coastguard Worker 
733*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest)
734*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
735*5e7646d2SAndroid Build Coastguard Worker 
736*5e7646d2SAndroid Build Coastguard Worker  /*
737*5e7646d2SAndroid Build Coastguard Worker   * Get the printer URI and resource path...
738*5e7646d2SAndroid Build Coastguard Worker   */
739*5e7646d2SAndroid Build Coastguard Worker 
740*5e7646d2SAndroid Build Coastguard Worker   if ((uri = _cupsGetDestResource(dest, dflags, resource, sizeof(resource))) == NULL)
741*5e7646d2SAndroid Build Coastguard Worker   {
742*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsCopyDestInfo: Unable to get resource.");
743*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
744*5e7646d2SAndroid Build Coastguard Worker   }
745*5e7646d2SAndroid Build Coastguard Worker 
746*5e7646d2SAndroid Build Coastguard Worker  /*
747*5e7646d2SAndroid Build Coastguard Worker   * Get the supported attributes...
748*5e7646d2SAndroid Build Coastguard Worker   */
749*5e7646d2SAndroid Build Coastguard Worker 
750*5e7646d2SAndroid Build Coastguard Worker   delay      = 1;
751*5e7646d2SAndroid Build Coastguard Worker   prev_delay = 1;
752*5e7646d2SAndroid Build Coastguard Worker   tries      = 0;
753*5e7646d2SAndroid Build Coastguard Worker   version    = 20;
754*5e7646d2SAndroid Build Coastguard Worker 
755*5e7646d2SAndroid Build Coastguard Worker   do
756*5e7646d2SAndroid Build Coastguard Worker   {
757*5e7646d2SAndroid Build Coastguard Worker    /*
758*5e7646d2SAndroid Build Coastguard Worker     * Send a Get-Printer-Attributes request...
759*5e7646d2SAndroid Build Coastguard Worker     */
760*5e7646d2SAndroid Build Coastguard Worker 
761*5e7646d2SAndroid Build Coastguard Worker     request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
762*5e7646d2SAndroid Build Coastguard Worker 
763*5e7646d2SAndroid Build Coastguard Worker     ippSetVersion(request, version / 10, version % 10);
764*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
765*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
766*5e7646d2SAndroid Build Coastguard Worker     ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested_attrs) / sizeof(requested_attrs[0])), NULL, requested_attrs);
767*5e7646d2SAndroid Build Coastguard Worker     response = cupsDoRequest(http, request, resource);
768*5e7646d2SAndroid Build Coastguard Worker     status   = cupsLastError();
769*5e7646d2SAndroid Build Coastguard Worker 
770*5e7646d2SAndroid Build Coastguard Worker     if (status > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
771*5e7646d2SAndroid Build Coastguard Worker     {
772*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("1cupsCopyDestInfo: Get-Printer-Attributes for '%s' returned %s (%s)", dest->name, ippErrorString(status), cupsLastErrorString()));
773*5e7646d2SAndroid Build Coastguard Worker 
774*5e7646d2SAndroid Build Coastguard Worker       ippDelete(response);
775*5e7646d2SAndroid Build Coastguard Worker       response = NULL;
776*5e7646d2SAndroid Build Coastguard Worker 
777*5e7646d2SAndroid Build Coastguard Worker       if ((status == IPP_STATUS_ERROR_BAD_REQUEST || status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) && version > 11)
778*5e7646d2SAndroid Build Coastguard Worker       {
779*5e7646d2SAndroid Build Coastguard Worker         version = 11;
780*5e7646d2SAndroid Build Coastguard Worker       }
781*5e7646d2SAndroid Build Coastguard Worker       else if (status == IPP_STATUS_ERROR_BUSY)
782*5e7646d2SAndroid Build Coastguard Worker       {
783*5e7646d2SAndroid Build Coastguard Worker         sleep((unsigned)delay);
784*5e7646d2SAndroid Build Coastguard Worker 
785*5e7646d2SAndroid Build Coastguard Worker         delay = _cupsNextDelay(delay, &prev_delay);
786*5e7646d2SAndroid Build Coastguard Worker       }
787*5e7646d2SAndroid Build Coastguard Worker       else
788*5e7646d2SAndroid Build Coastguard Worker         return (NULL);
789*5e7646d2SAndroid Build Coastguard Worker     }
790*5e7646d2SAndroid Build Coastguard Worker 
791*5e7646d2SAndroid Build Coastguard Worker     tries ++;
792*5e7646d2SAndroid Build Coastguard Worker   }
793*5e7646d2SAndroid Build Coastguard Worker   while (!response && tries < 10);
794*5e7646d2SAndroid Build Coastguard Worker 
795*5e7646d2SAndroid Build Coastguard Worker   if (!response)
796*5e7646d2SAndroid Build Coastguard Worker   {
797*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1cupsCopyDestInfo: Unable to get printer attributes.");
798*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
799*5e7646d2SAndroid Build Coastguard Worker   }
800*5e7646d2SAndroid Build Coastguard Worker 
801*5e7646d2SAndroid Build Coastguard Worker  /*
802*5e7646d2SAndroid Build Coastguard Worker   * Allocate a cups_dinfo_t structure and return it...
803*5e7646d2SAndroid Build Coastguard Worker   */
804*5e7646d2SAndroid Build Coastguard Worker 
805*5e7646d2SAndroid Build Coastguard Worker   if ((dinfo = calloc(1, sizeof(cups_dinfo_t))) == NULL)
806*5e7646d2SAndroid Build Coastguard Worker   {
807*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
808*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
809*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
810*5e7646d2SAndroid Build Coastguard Worker   }
811*5e7646d2SAndroid Build Coastguard Worker 
812*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1cupsCopyDestInfo: version=%d, uri=\"%s\", resource=\"%s\".", version, uri, resource));
813*5e7646d2SAndroid Build Coastguard Worker 
814*5e7646d2SAndroid Build Coastguard Worker   dinfo->version  = version;
815*5e7646d2SAndroid Build Coastguard Worker   dinfo->uri      = uri;
816*5e7646d2SAndroid Build Coastguard Worker   dinfo->resource = _cupsStrAlloc(resource);
817*5e7646d2SAndroid Build Coastguard Worker   dinfo->attrs    = response;
818*5e7646d2SAndroid Build Coastguard Worker 
819*5e7646d2SAndroid Build Coastguard Worker   return (dinfo);
820*5e7646d2SAndroid Build Coastguard Worker }
821*5e7646d2SAndroid Build Coastguard Worker 
822*5e7646d2SAndroid Build Coastguard Worker 
823*5e7646d2SAndroid Build Coastguard Worker /*
824*5e7646d2SAndroid Build Coastguard Worker  * 'cupsFindDestDefault()' - Find the default value(s) for the given option.
825*5e7646d2SAndroid Build Coastguard Worker  *
826*5e7646d2SAndroid Build Coastguard Worker  * The returned value is an IPP attribute. Use the @code ippGetBoolean@,
827*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCollection@, @code ippGetCount@, @code ippGetDate@,
828*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetInteger@, @code ippGetOctetString@, @code ippGetRange@,
829*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetResolution@, @code ippGetString@, and @code ippGetValueTag@
830*5e7646d2SAndroid Build Coastguard Worker  * functions to inspect the default value(s) as needed.
831*5e7646d2SAndroid Build Coastguard Worker  *
832*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
833*5e7646d2SAndroid Build Coastguard Worker  */
834*5e7646d2SAndroid Build Coastguard Worker 
835*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - Default attribute or @code NULL@ for none */
cupsFindDestDefault(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,const char * option)836*5e7646d2SAndroid Build Coastguard Worker cupsFindDestDefault(
837*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
838*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
839*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
840*5e7646d2SAndroid Build Coastguard Worker     const char   *option)		/* I - Option/attribute name */
841*5e7646d2SAndroid Build Coastguard Worker {
842*5e7646d2SAndroid Build Coastguard Worker   char	name[IPP_MAX_NAME];		/* Attribute name */
843*5e7646d2SAndroid Build Coastguard Worker 
844*5e7646d2SAndroid Build Coastguard Worker 
845*5e7646d2SAndroid Build Coastguard Worker  /*
846*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
847*5e7646d2SAndroid Build Coastguard Worker   */
848*5e7646d2SAndroid Build Coastguard Worker 
849*5e7646d2SAndroid Build Coastguard Worker   if (!http)
850*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
851*5e7646d2SAndroid Build Coastguard Worker 
852*5e7646d2SAndroid Build Coastguard Worker  /*
853*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
854*5e7646d2SAndroid Build Coastguard Worker   */
855*5e7646d2SAndroid Build Coastguard Worker 
856*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || !option)
857*5e7646d2SAndroid Build Coastguard Worker   {
858*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
859*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
860*5e7646d2SAndroid Build Coastguard Worker   }
861*5e7646d2SAndroid Build Coastguard Worker 
862*5e7646d2SAndroid Build Coastguard Worker  /*
863*5e7646d2SAndroid Build Coastguard Worker   * Find and return the attribute...
864*5e7646d2SAndroid Build Coastguard Worker   */
865*5e7646d2SAndroid Build Coastguard Worker 
866*5e7646d2SAndroid Build Coastguard Worker   snprintf(name, sizeof(name), "%s-default", option);
867*5e7646d2SAndroid Build Coastguard Worker   return (ippFindAttribute(dinfo->attrs, name, IPP_TAG_ZERO));
868*5e7646d2SAndroid Build Coastguard Worker }
869*5e7646d2SAndroid Build Coastguard Worker 
870*5e7646d2SAndroid Build Coastguard Worker 
871*5e7646d2SAndroid Build Coastguard Worker /*
872*5e7646d2SAndroid Build Coastguard Worker  * 'cupsFindDestReady()' - Find the default value(s) for the given option.
873*5e7646d2SAndroid Build Coastguard Worker  *
874*5e7646d2SAndroid Build Coastguard Worker  * The returned value is an IPP attribute. Use the @code ippGetBoolean@,
875*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCollection@, @code ippGetCount@, @code ippGetDate@,
876*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetInteger@, @code ippGetOctetString@, @code ippGetRange@,
877*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetResolution@, @code ippGetString@, and @code ippGetValueTag@
878*5e7646d2SAndroid Build Coastguard Worker  * functions to inspect the default value(s) as needed.
879*5e7646d2SAndroid Build Coastguard Worker  *
880*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
881*5e7646d2SAndroid Build Coastguard Worker  */
882*5e7646d2SAndroid Build Coastguard Worker 
883*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - Default attribute or @code NULL@ for none */
cupsFindDestReady(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,const char * option)884*5e7646d2SAndroid Build Coastguard Worker cupsFindDestReady(
885*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
886*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
887*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
888*5e7646d2SAndroid Build Coastguard Worker     const char   *option)		/* I - Option/attribute name */
889*5e7646d2SAndroid Build Coastguard Worker {
890*5e7646d2SAndroid Build Coastguard Worker   char	name[IPP_MAX_NAME];		/* Attribute name */
891*5e7646d2SAndroid Build Coastguard Worker 
892*5e7646d2SAndroid Build Coastguard Worker 
893*5e7646d2SAndroid Build Coastguard Worker  /*
894*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
895*5e7646d2SAndroid Build Coastguard Worker   */
896*5e7646d2SAndroid Build Coastguard Worker 
897*5e7646d2SAndroid Build Coastguard Worker   if (!http)
898*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
899*5e7646d2SAndroid Build Coastguard Worker 
900*5e7646d2SAndroid Build Coastguard Worker  /*
901*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
902*5e7646d2SAndroid Build Coastguard Worker   */
903*5e7646d2SAndroid Build Coastguard Worker 
904*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || !option)
905*5e7646d2SAndroid Build Coastguard Worker   {
906*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
907*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
908*5e7646d2SAndroid Build Coastguard Worker   }
909*5e7646d2SAndroid Build Coastguard Worker 
910*5e7646d2SAndroid Build Coastguard Worker  /*
911*5e7646d2SAndroid Build Coastguard Worker   * Find and return the attribute...
912*5e7646d2SAndroid Build Coastguard Worker   */
913*5e7646d2SAndroid Build Coastguard Worker 
914*5e7646d2SAndroid Build Coastguard Worker   cups_update_ready(http, dinfo);
915*5e7646d2SAndroid Build Coastguard Worker 
916*5e7646d2SAndroid Build Coastguard Worker   snprintf(name, sizeof(name), "%s-ready", option);
917*5e7646d2SAndroid Build Coastguard Worker   return (ippFindAttribute(dinfo->ready_attrs, name, IPP_TAG_ZERO));
918*5e7646d2SAndroid Build Coastguard Worker }
919*5e7646d2SAndroid Build Coastguard Worker 
920*5e7646d2SAndroid Build Coastguard Worker 
921*5e7646d2SAndroid Build Coastguard Worker /*
922*5e7646d2SAndroid Build Coastguard Worker  * 'cupsFindDestSupported()' - Find the default value(s) for the given option.
923*5e7646d2SAndroid Build Coastguard Worker  *
924*5e7646d2SAndroid Build Coastguard Worker  * The returned value is an IPP attribute. Use the @code ippGetBoolean@,
925*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetCollection@, @code ippGetCount@, @code ippGetDate@,
926*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetInteger@, @code ippGetOctetString@, @code ippGetRange@,
927*5e7646d2SAndroid Build Coastguard Worker  * @code ippGetResolution@, @code ippGetString@, and @code ippGetValueTag@
928*5e7646d2SAndroid Build Coastguard Worker  * functions to inspect the default value(s) as needed.
929*5e7646d2SAndroid Build Coastguard Worker  *
930*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
931*5e7646d2SAndroid Build Coastguard Worker  */
932*5e7646d2SAndroid Build Coastguard Worker 
933*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t	*			/* O - Default attribute or @code NULL@ for none */
cupsFindDestSupported(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,const char * option)934*5e7646d2SAndroid Build Coastguard Worker cupsFindDestSupported(
935*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
936*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
937*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
938*5e7646d2SAndroid Build Coastguard Worker     const char   *option)		/* I - Option/attribute name */
939*5e7646d2SAndroid Build Coastguard Worker {
940*5e7646d2SAndroid Build Coastguard Worker   char	name[IPP_MAX_NAME];		/* Attribute name */
941*5e7646d2SAndroid Build Coastguard Worker 
942*5e7646d2SAndroid Build Coastguard Worker 
943*5e7646d2SAndroid Build Coastguard Worker  /*
944*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
945*5e7646d2SAndroid Build Coastguard Worker   */
946*5e7646d2SAndroid Build Coastguard Worker 
947*5e7646d2SAndroid Build Coastguard Worker   if (!http)
948*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
949*5e7646d2SAndroid Build Coastguard Worker 
950*5e7646d2SAndroid Build Coastguard Worker  /*
951*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
952*5e7646d2SAndroid Build Coastguard Worker   */
953*5e7646d2SAndroid Build Coastguard Worker 
954*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || !option)
955*5e7646d2SAndroid Build Coastguard Worker   {
956*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
957*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
958*5e7646d2SAndroid Build Coastguard Worker   }
959*5e7646d2SAndroid Build Coastguard Worker 
960*5e7646d2SAndroid Build Coastguard Worker  /*
961*5e7646d2SAndroid Build Coastguard Worker   * Find and return the attribute...
962*5e7646d2SAndroid Build Coastguard Worker   */
963*5e7646d2SAndroid Build Coastguard Worker 
964*5e7646d2SAndroid Build Coastguard Worker   snprintf(name, sizeof(name), "%s-supported", option);
965*5e7646d2SAndroid Build Coastguard Worker   return (ippFindAttribute(dinfo->attrs, name, IPP_TAG_ZERO));
966*5e7646d2SAndroid Build Coastguard Worker }
967*5e7646d2SAndroid Build Coastguard Worker 
968*5e7646d2SAndroid Build Coastguard Worker 
969*5e7646d2SAndroid Build Coastguard Worker /*
970*5e7646d2SAndroid Build Coastguard Worker  * 'cupsFreeDestInfo()' - Free destination information obtained using
971*5e7646d2SAndroid Build Coastguard Worker  *                        @link cupsCopyDestInfo@.
972*5e7646d2SAndroid Build Coastguard Worker  *
973*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
974*5e7646d2SAndroid Build Coastguard Worker  */
975*5e7646d2SAndroid Build Coastguard Worker 
976*5e7646d2SAndroid Build Coastguard Worker void
cupsFreeDestInfo(cups_dinfo_t * dinfo)977*5e7646d2SAndroid Build Coastguard Worker cupsFreeDestInfo(cups_dinfo_t *dinfo)	/* I - Destination information */
978*5e7646d2SAndroid Build Coastguard Worker {
979*5e7646d2SAndroid Build Coastguard Worker  /*
980*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
981*5e7646d2SAndroid Build Coastguard Worker   */
982*5e7646d2SAndroid Build Coastguard Worker 
983*5e7646d2SAndroid Build Coastguard Worker   if (!dinfo)
984*5e7646d2SAndroid Build Coastguard Worker     return;
985*5e7646d2SAndroid Build Coastguard Worker 
986*5e7646d2SAndroid Build Coastguard Worker  /*
987*5e7646d2SAndroid Build Coastguard Worker   * Free memory and return...
988*5e7646d2SAndroid Build Coastguard Worker   */
989*5e7646d2SAndroid Build Coastguard Worker 
990*5e7646d2SAndroid Build Coastguard Worker   _cupsStrFree(dinfo->resource);
991*5e7646d2SAndroid Build Coastguard Worker 
992*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(dinfo->constraints);
993*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(dinfo->resolvers);
994*5e7646d2SAndroid Build Coastguard Worker 
995*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(dinfo->localizations);
996*5e7646d2SAndroid Build Coastguard Worker 
997*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(dinfo->media_db);
998*5e7646d2SAndroid Build Coastguard Worker 
999*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(dinfo->cached_db);
1000*5e7646d2SAndroid Build Coastguard Worker 
1001*5e7646d2SAndroid Build Coastguard Worker   ippDelete(dinfo->ready_attrs);
1002*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(dinfo->ready_db);
1003*5e7646d2SAndroid Build Coastguard Worker 
1004*5e7646d2SAndroid Build Coastguard Worker   ippDelete(dinfo->attrs);
1005*5e7646d2SAndroid Build Coastguard Worker 
1006*5e7646d2SAndroid Build Coastguard Worker   free(dinfo);
1007*5e7646d2SAndroid Build Coastguard Worker }
1008*5e7646d2SAndroid Build Coastguard Worker 
1009*5e7646d2SAndroid Build Coastguard Worker 
1010*5e7646d2SAndroid Build Coastguard Worker /*
1011*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetDestMediaByIndex()' - Get a media name, dimension, and margins for a
1012*5e7646d2SAndroid Build Coastguard Worker  *                               specific size.
1013*5e7646d2SAndroid Build Coastguard Worker  *
1014*5e7646d2SAndroid Build Coastguard Worker  * The @code flags@ parameter determines which set of media are indexed.  For
1015*5e7646d2SAndroid Build Coastguard Worker  * example, passing @code CUPS_MEDIA_FLAGS_BORDERLESS@ will get the Nth
1016*5e7646d2SAndroid Build Coastguard Worker  * borderless size supported by the printer.
1017*5e7646d2SAndroid Build Coastguard Worker  *
1018*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
1019*5e7646d2SAndroid Build Coastguard Worker  */
1020*5e7646d2SAndroid Build Coastguard Worker 
1021*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
cupsGetDestMediaByIndex(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,int n,unsigned flags,cups_size_t * size)1022*5e7646d2SAndroid Build Coastguard Worker cupsGetDestMediaByIndex(
1023*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
1024*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
1025*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
1026*5e7646d2SAndroid Build Coastguard Worker     int          n,			/* I - Media size number (0-based) */
1027*5e7646d2SAndroid Build Coastguard Worker     unsigned     flags,			/* I - Media flags */
1028*5e7646d2SAndroid Build Coastguard Worker     cups_size_t  *size)			/* O - Media size information */
1029*5e7646d2SAndroid Build Coastguard Worker {
1030*5e7646d2SAndroid Build Coastguard Worker   _cups_media_db_t	*nsize;		/* Size for N */
1031*5e7646d2SAndroid Build Coastguard Worker   pwg_media_t		*pwg;		/* PWG media name for size */
1032*5e7646d2SAndroid Build Coastguard Worker 
1033*5e7646d2SAndroid Build Coastguard Worker 
1034*5e7646d2SAndroid Build Coastguard Worker  /*
1035*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
1036*5e7646d2SAndroid Build Coastguard Worker   */
1037*5e7646d2SAndroid Build Coastguard Worker 
1038*5e7646d2SAndroid Build Coastguard Worker   if (!http)
1039*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
1040*5e7646d2SAndroid Build Coastguard Worker 
1041*5e7646d2SAndroid Build Coastguard Worker  /*
1042*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1043*5e7646d2SAndroid Build Coastguard Worker   */
1044*5e7646d2SAndroid Build Coastguard Worker 
1045*5e7646d2SAndroid Build Coastguard Worker   if (size)
1046*5e7646d2SAndroid Build Coastguard Worker     memset(size, 0, sizeof(cups_size_t));
1047*5e7646d2SAndroid Build Coastguard Worker 
1048*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || n < 0 || !size)
1049*5e7646d2SAndroid Build Coastguard Worker   {
1050*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
1051*5e7646d2SAndroid Build Coastguard Worker     return (0);
1052*5e7646d2SAndroid Build Coastguard Worker   }
1053*5e7646d2SAndroid Build Coastguard Worker 
1054*5e7646d2SAndroid Build Coastguard Worker  /*
1055*5e7646d2SAndroid Build Coastguard Worker   * Load media list as needed...
1056*5e7646d2SAndroid Build Coastguard Worker   */
1057*5e7646d2SAndroid Build Coastguard Worker 
1058*5e7646d2SAndroid Build Coastguard Worker   if (flags & CUPS_MEDIA_FLAGS_READY)
1059*5e7646d2SAndroid Build Coastguard Worker     cups_update_ready(http, dinfo);
1060*5e7646d2SAndroid Build Coastguard Worker 
1061*5e7646d2SAndroid Build Coastguard Worker   if (!dinfo->cached_db || dinfo->cached_flags != flags)
1062*5e7646d2SAndroid Build Coastguard Worker     cups_create_cached(http, dinfo, flags);
1063*5e7646d2SAndroid Build Coastguard Worker 
1064*5e7646d2SAndroid Build Coastguard Worker  /*
1065*5e7646d2SAndroid Build Coastguard Worker   * Copy the size over and return...
1066*5e7646d2SAndroid Build Coastguard Worker   */
1067*5e7646d2SAndroid Build Coastguard Worker 
1068*5e7646d2SAndroid Build Coastguard Worker   if ((nsize = (_cups_media_db_t *)cupsArrayIndex(dinfo->cached_db, n)) == NULL)
1069*5e7646d2SAndroid Build Coastguard Worker   {
1070*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
1071*5e7646d2SAndroid Build Coastguard Worker     return (0);
1072*5e7646d2SAndroid Build Coastguard Worker   }
1073*5e7646d2SAndroid Build Coastguard Worker 
1074*5e7646d2SAndroid Build Coastguard Worker   if (nsize->key)
1075*5e7646d2SAndroid Build Coastguard Worker     strlcpy(size->media, nsize->key, sizeof(size->media));
1076*5e7646d2SAndroid Build Coastguard Worker   else if (nsize->size_name)
1077*5e7646d2SAndroid Build Coastguard Worker     strlcpy(size->media, nsize->size_name, sizeof(size->media));
1078*5e7646d2SAndroid Build Coastguard Worker   else if ((pwg = pwgMediaForSize(nsize->width, nsize->length)) != NULL)
1079*5e7646d2SAndroid Build Coastguard Worker     strlcpy(size->media, pwg->pwg, sizeof(size->media));
1080*5e7646d2SAndroid Build Coastguard Worker   else
1081*5e7646d2SAndroid Build Coastguard Worker   {
1082*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
1083*5e7646d2SAndroid Build Coastguard Worker     return (0);
1084*5e7646d2SAndroid Build Coastguard Worker   }
1085*5e7646d2SAndroid Build Coastguard Worker 
1086*5e7646d2SAndroid Build Coastguard Worker   size->width  = nsize->width;
1087*5e7646d2SAndroid Build Coastguard Worker   size->length = nsize->length;
1088*5e7646d2SAndroid Build Coastguard Worker   size->bottom = nsize->bottom;
1089*5e7646d2SAndroid Build Coastguard Worker   size->left   = nsize->left;
1090*5e7646d2SAndroid Build Coastguard Worker   size->right  = nsize->right;
1091*5e7646d2SAndroid Build Coastguard Worker   size->top    = nsize->top;
1092*5e7646d2SAndroid Build Coastguard Worker 
1093*5e7646d2SAndroid Build Coastguard Worker   return (1);
1094*5e7646d2SAndroid Build Coastguard Worker }
1095*5e7646d2SAndroid Build Coastguard Worker 
1096*5e7646d2SAndroid Build Coastguard Worker 
1097*5e7646d2SAndroid Build Coastguard Worker /*
1098*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetDestMediaByName()' - Get media names, dimensions, and margins.
1099*5e7646d2SAndroid Build Coastguard Worker  *
1100*5e7646d2SAndroid Build Coastguard Worker  * The "media" string is a PWG media name.  "Flags" provides some matching
1101*5e7646d2SAndroid Build Coastguard Worker  * guidance (multiple flags can be combined):
1102*5e7646d2SAndroid Build Coastguard Worker  *
1103*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_DEFAULT    = find the closest size supported by the printer,
1104*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size,
1105*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_DUPLEX     = find a size compatible with 2-sided printing,
1106*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_EXACT      = find an exact match for the size, and
1107*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_READY      = if the printer supports media sensing, find the
1108*5e7646d2SAndroid Build Coastguard Worker  *                               size amongst the "ready" media.
1109*5e7646d2SAndroid Build Coastguard Worker  *
1110*5e7646d2SAndroid Build Coastguard Worker  * The matching result (if any) is returned in the "cups_size_t" structure.
1111*5e7646d2SAndroid Build Coastguard Worker  *
1112*5e7646d2SAndroid Build Coastguard Worker  * Returns 1 when there is a match and 0 if there is not a match.
1113*5e7646d2SAndroid Build Coastguard Worker  *
1114*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
1115*5e7646d2SAndroid Build Coastguard Worker  */
1116*5e7646d2SAndroid Build Coastguard Worker 
1117*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on match, 0 on failure */
cupsGetDestMediaByName(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,const char * media,unsigned flags,cups_size_t * size)1118*5e7646d2SAndroid Build Coastguard Worker cupsGetDestMediaByName(
1119*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
1120*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
1121*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
1122*5e7646d2SAndroid Build Coastguard Worker     const char   *media,		/* I - Media name */
1123*5e7646d2SAndroid Build Coastguard Worker     unsigned     flags,			/* I - Media matching flags */
1124*5e7646d2SAndroid Build Coastguard Worker     cups_size_t  *size)			/* O - Media size information */
1125*5e7646d2SAndroid Build Coastguard Worker {
1126*5e7646d2SAndroid Build Coastguard Worker   pwg_media_t		*pwg;		/* PWG media info */
1127*5e7646d2SAndroid Build Coastguard Worker 
1128*5e7646d2SAndroid Build Coastguard Worker 
1129*5e7646d2SAndroid Build Coastguard Worker  /*
1130*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
1131*5e7646d2SAndroid Build Coastguard Worker   */
1132*5e7646d2SAndroid Build Coastguard Worker 
1133*5e7646d2SAndroid Build Coastguard Worker   if (!http)
1134*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
1135*5e7646d2SAndroid Build Coastguard Worker 
1136*5e7646d2SAndroid Build Coastguard Worker  /*
1137*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1138*5e7646d2SAndroid Build Coastguard Worker   */
1139*5e7646d2SAndroid Build Coastguard Worker 
1140*5e7646d2SAndroid Build Coastguard Worker   if (size)
1141*5e7646d2SAndroid Build Coastguard Worker     memset(size, 0, sizeof(cups_size_t));
1142*5e7646d2SAndroid Build Coastguard Worker 
1143*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || !media || !size)
1144*5e7646d2SAndroid Build Coastguard Worker   {
1145*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
1146*5e7646d2SAndroid Build Coastguard Worker     return (0);
1147*5e7646d2SAndroid Build Coastguard Worker   }
1148*5e7646d2SAndroid Build Coastguard Worker 
1149*5e7646d2SAndroid Build Coastguard Worker  /*
1150*5e7646d2SAndroid Build Coastguard Worker   * Lookup the media size name...
1151*5e7646d2SAndroid Build Coastguard Worker   */
1152*5e7646d2SAndroid Build Coastguard Worker 
1153*5e7646d2SAndroid Build Coastguard Worker   if ((pwg = pwgMediaForPWG(media)) == NULL)
1154*5e7646d2SAndroid Build Coastguard Worker     if ((pwg = pwgMediaForLegacy(media)) == NULL)
1155*5e7646d2SAndroid Build Coastguard Worker     {
1156*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("1cupsGetDestMediaByName: Unknown size '%s'.", media));
1157*5e7646d2SAndroid Build Coastguard Worker       _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown media size name."), 1);
1158*5e7646d2SAndroid Build Coastguard Worker       return (0);
1159*5e7646d2SAndroid Build Coastguard Worker     }
1160*5e7646d2SAndroid Build Coastguard Worker 
1161*5e7646d2SAndroid Build Coastguard Worker  /*
1162*5e7646d2SAndroid Build Coastguard Worker   * Lookup the size...
1163*5e7646d2SAndroid Build Coastguard Worker   */
1164*5e7646d2SAndroid Build Coastguard Worker 
1165*5e7646d2SAndroid Build Coastguard Worker   return (cups_get_media_db(http, dinfo, pwg, flags, size));
1166*5e7646d2SAndroid Build Coastguard Worker }
1167*5e7646d2SAndroid Build Coastguard Worker 
1168*5e7646d2SAndroid Build Coastguard Worker 
1169*5e7646d2SAndroid Build Coastguard Worker /*
1170*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetDestMediaBySize()' - Get media names, dimensions, and margins.
1171*5e7646d2SAndroid Build Coastguard Worker  *
1172*5e7646d2SAndroid Build Coastguard Worker  * "Width" and "length" are the dimensions in hundredths of millimeters.
1173*5e7646d2SAndroid Build Coastguard Worker  * "Flags" provides some matching guidance (multiple flags can be combined):
1174*5e7646d2SAndroid Build Coastguard Worker  *
1175*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_DEFAULT    = find the closest size supported by the printer,
1176*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size,
1177*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_DUPLEX     = find a size compatible with 2-sided printing,
1178*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_EXACT      = find an exact match for the size, and
1179*5e7646d2SAndroid Build Coastguard Worker  * CUPS_MEDIA_FLAGS_READY      = if the printer supports media sensing, find the
1180*5e7646d2SAndroid Build Coastguard Worker  *                               size amongst the "ready" media.
1181*5e7646d2SAndroid Build Coastguard Worker  *
1182*5e7646d2SAndroid Build Coastguard Worker  * The matching result (if any) is returned in the "cups_size_t" structure.
1183*5e7646d2SAndroid Build Coastguard Worker  *
1184*5e7646d2SAndroid Build Coastguard Worker  * Returns 1 when there is a match and 0 if there is not a match.
1185*5e7646d2SAndroid Build Coastguard Worker  *
1186*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.6/macOS 10.8@
1187*5e7646d2SAndroid Build Coastguard Worker  */
1188*5e7646d2SAndroid Build Coastguard Worker 
1189*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on match, 0 on failure */
cupsGetDestMediaBySize(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,int width,int length,unsigned flags,cups_size_t * size)1190*5e7646d2SAndroid Build Coastguard Worker cupsGetDestMediaBySize(
1191*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
1192*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
1193*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
1194*5e7646d2SAndroid Build Coastguard Worker     int         width,			/* I - Media width in hundredths of
1195*5e7646d2SAndroid Build Coastguard Worker 					 *     of millimeters */
1196*5e7646d2SAndroid Build Coastguard Worker     int         length,			/* I - Media length in hundredths of
1197*5e7646d2SAndroid Build Coastguard Worker 					 *     of millimeters */
1198*5e7646d2SAndroid Build Coastguard Worker     unsigned     flags,			/* I - Media matching flags */
1199*5e7646d2SAndroid Build Coastguard Worker     cups_size_t  *size)			/* O - Media size information */
1200*5e7646d2SAndroid Build Coastguard Worker {
1201*5e7646d2SAndroid Build Coastguard Worker   pwg_media_t		*pwg;		/* PWG media info */
1202*5e7646d2SAndroid Build Coastguard Worker 
1203*5e7646d2SAndroid Build Coastguard Worker 
1204*5e7646d2SAndroid Build Coastguard Worker  /*
1205*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
1206*5e7646d2SAndroid Build Coastguard Worker   */
1207*5e7646d2SAndroid Build Coastguard Worker 
1208*5e7646d2SAndroid Build Coastguard Worker   if (!http)
1209*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
1210*5e7646d2SAndroid Build Coastguard Worker 
1211*5e7646d2SAndroid Build Coastguard Worker  /*
1212*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1213*5e7646d2SAndroid Build Coastguard Worker   */
1214*5e7646d2SAndroid Build Coastguard Worker 
1215*5e7646d2SAndroid Build Coastguard Worker   if (size)
1216*5e7646d2SAndroid Build Coastguard Worker     memset(size, 0, sizeof(cups_size_t));
1217*5e7646d2SAndroid Build Coastguard Worker 
1218*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || width <= 0 || length <= 0 || !size)
1219*5e7646d2SAndroid Build Coastguard Worker   {
1220*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
1221*5e7646d2SAndroid Build Coastguard Worker     return (0);
1222*5e7646d2SAndroid Build Coastguard Worker   }
1223*5e7646d2SAndroid Build Coastguard Worker 
1224*5e7646d2SAndroid Build Coastguard Worker  /*
1225*5e7646d2SAndroid Build Coastguard Worker   * Lookup the media size name...
1226*5e7646d2SAndroid Build Coastguard Worker   */
1227*5e7646d2SAndroid Build Coastguard Worker 
1228*5e7646d2SAndroid Build Coastguard Worker   if ((pwg = pwgMediaForSize(width, length)) == NULL)
1229*5e7646d2SAndroid Build Coastguard Worker   {
1230*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1cupsGetDestMediaBySize: Invalid size %dx%d.", width,
1231*5e7646d2SAndroid Build Coastguard Worker                   length));
1232*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid media size."), 1);
1233*5e7646d2SAndroid Build Coastguard Worker     return (0);
1234*5e7646d2SAndroid Build Coastguard Worker   }
1235*5e7646d2SAndroid Build Coastguard Worker 
1236*5e7646d2SAndroid Build Coastguard Worker  /*
1237*5e7646d2SAndroid Build Coastguard Worker   * Lookup the size...
1238*5e7646d2SAndroid Build Coastguard Worker   */
1239*5e7646d2SAndroid Build Coastguard Worker 
1240*5e7646d2SAndroid Build Coastguard Worker   return (cups_get_media_db(http, dinfo, pwg, flags, size));
1241*5e7646d2SAndroid Build Coastguard Worker }
1242*5e7646d2SAndroid Build Coastguard Worker 
1243*5e7646d2SAndroid Build Coastguard Worker 
1244*5e7646d2SAndroid Build Coastguard Worker /*
1245*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetDestMediaCount()' - Get the number of sizes supported by a
1246*5e7646d2SAndroid Build Coastguard Worker  *                             destination.
1247*5e7646d2SAndroid Build Coastguard Worker  *
1248*5e7646d2SAndroid Build Coastguard Worker  * The @code flags@ parameter determines the set of media sizes that are
1249*5e7646d2SAndroid Build Coastguard Worker  * counted.  For example, passing @code CUPS_MEDIA_FLAGS_BORDERLESS@ will return
1250*5e7646d2SAndroid Build Coastguard Worker  * the number of borderless sizes.
1251*5e7646d2SAndroid Build Coastguard Worker  *
1252*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
1253*5e7646d2SAndroid Build Coastguard Worker  */
1254*5e7646d2SAndroid Build Coastguard Worker 
1255*5e7646d2SAndroid Build Coastguard Worker int					/* O - Number of sizes */
cupsGetDestMediaCount(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,unsigned flags)1256*5e7646d2SAndroid Build Coastguard Worker cupsGetDestMediaCount(
1257*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
1258*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
1259*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
1260*5e7646d2SAndroid Build Coastguard Worker     unsigned     flags)			/* I - Media flags */
1261*5e7646d2SAndroid Build Coastguard Worker {
1262*5e7646d2SAndroid Build Coastguard Worker  /*
1263*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
1264*5e7646d2SAndroid Build Coastguard Worker   */
1265*5e7646d2SAndroid Build Coastguard Worker 
1266*5e7646d2SAndroid Build Coastguard Worker   if (!http)
1267*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
1268*5e7646d2SAndroid Build Coastguard Worker 
1269*5e7646d2SAndroid Build Coastguard Worker  /*
1270*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1271*5e7646d2SAndroid Build Coastguard Worker   */
1272*5e7646d2SAndroid Build Coastguard Worker 
1273*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo)
1274*5e7646d2SAndroid Build Coastguard Worker   {
1275*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
1276*5e7646d2SAndroid Build Coastguard Worker     return (0);
1277*5e7646d2SAndroid Build Coastguard Worker   }
1278*5e7646d2SAndroid Build Coastguard Worker 
1279*5e7646d2SAndroid Build Coastguard Worker  /*
1280*5e7646d2SAndroid Build Coastguard Worker   * Load media list as needed...
1281*5e7646d2SAndroid Build Coastguard Worker   */
1282*5e7646d2SAndroid Build Coastguard Worker 
1283*5e7646d2SAndroid Build Coastguard Worker   if (flags & CUPS_MEDIA_FLAGS_READY)
1284*5e7646d2SAndroid Build Coastguard Worker     cups_update_ready(http, dinfo);
1285*5e7646d2SAndroid Build Coastguard Worker 
1286*5e7646d2SAndroid Build Coastguard Worker   if (!dinfo->cached_db || dinfo->cached_flags != flags)
1287*5e7646d2SAndroid Build Coastguard Worker     cups_create_cached(http, dinfo, flags);
1288*5e7646d2SAndroid Build Coastguard Worker 
1289*5e7646d2SAndroid Build Coastguard Worker   return (cupsArrayCount(dinfo->cached_db));
1290*5e7646d2SAndroid Build Coastguard Worker }
1291*5e7646d2SAndroid Build Coastguard Worker 
1292*5e7646d2SAndroid Build Coastguard Worker 
1293*5e7646d2SAndroid Build Coastguard Worker /*
1294*5e7646d2SAndroid Build Coastguard Worker  * 'cupsGetDestMediaDefault()' - Get the default size for a destination.
1295*5e7646d2SAndroid Build Coastguard Worker  *
1296*5e7646d2SAndroid Build Coastguard Worker  * The @code flags@ parameter determines which default size is returned.  For
1297*5e7646d2SAndroid Build Coastguard Worker  * example, passing @code CUPS_MEDIA_FLAGS_BORDERLESS@ will return the default
1298*5e7646d2SAndroid Build Coastguard Worker  * borderless size, typically US Letter or A4, but sometimes 4x6 photo media.
1299*5e7646d2SAndroid Build Coastguard Worker  *
1300*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 1.7/macOS 10.9@
1301*5e7646d2SAndroid Build Coastguard Worker  */
1302*5e7646d2SAndroid Build Coastguard Worker 
1303*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
cupsGetDestMediaDefault(http_t * http,cups_dest_t * dest,cups_dinfo_t * dinfo,unsigned flags,cups_size_t * size)1304*5e7646d2SAndroid Build Coastguard Worker cupsGetDestMediaDefault(
1305*5e7646d2SAndroid Build Coastguard Worker     http_t       *http,			/* I - Connection to destination */
1306*5e7646d2SAndroid Build Coastguard Worker     cups_dest_t  *dest,			/* I - Destination */
1307*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
1308*5e7646d2SAndroid Build Coastguard Worker     unsigned     flags,			/* I - Media flags */
1309*5e7646d2SAndroid Build Coastguard Worker     cups_size_t  *size)			/* O - Media size information */
1310*5e7646d2SAndroid Build Coastguard Worker {
1311*5e7646d2SAndroid Build Coastguard Worker   const char	*media;			/* Default media size */
1312*5e7646d2SAndroid Build Coastguard Worker 
1313*5e7646d2SAndroid Build Coastguard Worker 
1314*5e7646d2SAndroid Build Coastguard Worker  /*
1315*5e7646d2SAndroid Build Coastguard Worker   * Get the default connection as needed...
1316*5e7646d2SAndroid Build Coastguard Worker   */
1317*5e7646d2SAndroid Build Coastguard Worker 
1318*5e7646d2SAndroid Build Coastguard Worker   if (!http)
1319*5e7646d2SAndroid Build Coastguard Worker     http = _cupsConnect();
1320*5e7646d2SAndroid Build Coastguard Worker 
1321*5e7646d2SAndroid Build Coastguard Worker  /*
1322*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
1323*5e7646d2SAndroid Build Coastguard Worker   */
1324*5e7646d2SAndroid Build Coastguard Worker 
1325*5e7646d2SAndroid Build Coastguard Worker   if (size)
1326*5e7646d2SAndroid Build Coastguard Worker     memset(size, 0, sizeof(cups_size_t));
1327*5e7646d2SAndroid Build Coastguard Worker 
1328*5e7646d2SAndroid Build Coastguard Worker   if (!http || !dest || !dinfo || !size)
1329*5e7646d2SAndroid Build Coastguard Worker   {
1330*5e7646d2SAndroid Build Coastguard Worker     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
1331*5e7646d2SAndroid Build Coastguard Worker     return (0);
1332*5e7646d2SAndroid Build Coastguard Worker   }
1333*5e7646d2SAndroid Build Coastguard Worker 
1334*5e7646d2SAndroid Build Coastguard Worker  /*
1335*5e7646d2SAndroid Build Coastguard Worker   * Get the default media size, if any...
1336*5e7646d2SAndroid Build Coastguard Worker   */
1337*5e7646d2SAndroid Build Coastguard Worker 
1338*5e7646d2SAndroid Build Coastguard Worker   if ((media = cupsGetOption("media", dest->num_options, dest->options)) == NULL)
1339*5e7646d2SAndroid Build Coastguard Worker     media = "na_letter_8.5x11in";
1340*5e7646d2SAndroid Build Coastguard Worker 
1341*5e7646d2SAndroid Build Coastguard Worker   if (cupsGetDestMediaByName(http, dest, dinfo, media, flags, size))
1342*5e7646d2SAndroid Build Coastguard Worker     return (1);
1343*5e7646d2SAndroid Build Coastguard Worker 
1344*5e7646d2SAndroid Build Coastguard Worker   if (strcmp(media, "na_letter_8.5x11in") && cupsGetDestMediaByName(http, dest, dinfo, "iso_a4_210x297mm", flags, size))
1345*5e7646d2SAndroid Build Coastguard Worker     return (1);
1346*5e7646d2SAndroid Build Coastguard Worker 
1347*5e7646d2SAndroid Build Coastguard Worker   if (strcmp(media, "iso_a4_210x297mm") && cupsGetDestMediaByName(http, dest, dinfo, "na_letter_8.5x11in", flags, size))
1348*5e7646d2SAndroid Build Coastguard Worker     return (1);
1349*5e7646d2SAndroid Build Coastguard Worker 
1350*5e7646d2SAndroid Build Coastguard Worker   if ((flags & CUPS_MEDIA_FLAGS_BORDERLESS) && cupsGetDestMediaByName(http, dest, dinfo, "na_index_4x6in", flags, size))
1351*5e7646d2SAndroid Build Coastguard Worker     return (1);
1352*5e7646d2SAndroid Build Coastguard Worker 
1353*5e7646d2SAndroid Build Coastguard Worker  /*
1354*5e7646d2SAndroid Build Coastguard Worker   * Fall back to the first matching media size...
1355*5e7646d2SAndroid Build Coastguard Worker   */
1356*5e7646d2SAndroid Build Coastguard Worker 
1357*5e7646d2SAndroid Build Coastguard Worker   return (cupsGetDestMediaByIndex(http, dest, dinfo, 0, flags, size));
1358*5e7646d2SAndroid Build Coastguard Worker }
1359*5e7646d2SAndroid Build Coastguard Worker 
1360*5e7646d2SAndroid Build Coastguard Worker 
1361*5e7646d2SAndroid Build Coastguard Worker /*
1362*5e7646d2SAndroid Build Coastguard Worker  * 'cups_add_dconstres()' - Add a constraint or resolver to an array.
1363*5e7646d2SAndroid Build Coastguard Worker  */
1364*5e7646d2SAndroid Build Coastguard Worker 
1365*5e7646d2SAndroid Build Coastguard Worker static void
cups_add_dconstres(cups_array_t * a,ipp_t * collection)1366*5e7646d2SAndroid Build Coastguard Worker cups_add_dconstres(
1367*5e7646d2SAndroid Build Coastguard Worker     cups_array_t *a,			/* I - Array */
1368*5e7646d2SAndroid Build Coastguard Worker     ipp_t        *collection)		/* I - Collection value */
1369*5e7646d2SAndroid Build Coastguard Worker {
1370*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Attribute */
1371*5e7646d2SAndroid Build Coastguard Worker   _cups_dconstres_t	*temp;		/* Current constraint/resolver */
1372*5e7646d2SAndroid Build Coastguard Worker 
1373*5e7646d2SAndroid Build Coastguard Worker 
1374*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(collection, "resolver-name",
1375*5e7646d2SAndroid Build Coastguard Worker                                IPP_TAG_NAME)) == NULL)
1376*5e7646d2SAndroid Build Coastguard Worker     return;
1377*5e7646d2SAndroid Build Coastguard Worker 
1378*5e7646d2SAndroid Build Coastguard Worker   if ((temp = calloc(1, sizeof(_cups_dconstres_t))) == NULL)
1379*5e7646d2SAndroid Build Coastguard Worker     return;
1380*5e7646d2SAndroid Build Coastguard Worker 
1381*5e7646d2SAndroid Build Coastguard Worker   temp->name       = attr->values[0].string.text;
1382*5e7646d2SAndroid Build Coastguard Worker   temp->collection = collection;
1383*5e7646d2SAndroid Build Coastguard Worker 
1384*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(a, temp);
1385*5e7646d2SAndroid Build Coastguard Worker }
1386*5e7646d2SAndroid Build Coastguard Worker 
1387*5e7646d2SAndroid Build Coastguard Worker 
1388*5e7646d2SAndroid Build Coastguard Worker /*
1389*5e7646d2SAndroid Build Coastguard Worker  * 'cups_collection_contains()' - Check whether test collection is contained in the matching collection.
1390*5e7646d2SAndroid Build Coastguard Worker  */
1391*5e7646d2SAndroid Build Coastguard Worker 
1392*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on a match, 0 on a non-match */
cups_collection_contains(ipp_t * test,ipp_t * match)1393*5e7646d2SAndroid Build Coastguard Worker cups_collection_contains(ipp_t *test,	/* I - Collection to test */
1394*5e7646d2SAndroid Build Coastguard Worker                          ipp_t *match)	/* I - Matching values */
1395*5e7646d2SAndroid Build Coastguard Worker {
1396*5e7646d2SAndroid Build Coastguard Worker   int			i, j,		/* Looping vars */
1397*5e7646d2SAndroid Build Coastguard Worker 			mcount,		/* Number of match values */
1398*5e7646d2SAndroid Build Coastguard Worker 			tcount;		/* Number of test values */
1399*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*tattr,		/* Testing attribute */
1400*5e7646d2SAndroid Build Coastguard Worker 			*mattr;		/* Matching attribute */
1401*5e7646d2SAndroid Build Coastguard Worker   const char		*tval;		/* Testing string value */
1402*5e7646d2SAndroid Build Coastguard Worker 
1403*5e7646d2SAndroid Build Coastguard Worker 
1404*5e7646d2SAndroid Build Coastguard Worker   for (mattr = ippFirstAttribute(match); mattr; mattr = ippNextAttribute(match))
1405*5e7646d2SAndroid Build Coastguard Worker   {
1406*5e7646d2SAndroid Build Coastguard Worker     if ((tattr = ippFindAttribute(test, ippGetName(mattr), IPP_TAG_ZERO)) == NULL)
1407*5e7646d2SAndroid Build Coastguard Worker       return (0);
1408*5e7646d2SAndroid Build Coastguard Worker 
1409*5e7646d2SAndroid Build Coastguard Worker     tcount = ippGetCount(tattr);
1410*5e7646d2SAndroid Build Coastguard Worker 
1411*5e7646d2SAndroid Build Coastguard Worker     switch (ippGetValueTag(mattr))
1412*5e7646d2SAndroid Build Coastguard Worker     {
1413*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_INTEGER :
1414*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ENUM :
1415*5e7646d2SAndroid Build Coastguard Worker           if (ippGetValueTag(tattr) != ippGetValueTag(mattr))
1416*5e7646d2SAndroid Build Coastguard Worker             return (0);
1417*5e7646d2SAndroid Build Coastguard Worker 
1418*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < tcount; i ++)
1419*5e7646d2SAndroid Build Coastguard Worker           {
1420*5e7646d2SAndroid Build Coastguard Worker             if (!ippContainsInteger(mattr, ippGetInteger(tattr, i)))
1421*5e7646d2SAndroid Build Coastguard Worker               return (0);
1422*5e7646d2SAndroid Build Coastguard Worker           }
1423*5e7646d2SAndroid Build Coastguard Worker           break;
1424*5e7646d2SAndroid Build Coastguard Worker 
1425*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RANGE :
1426*5e7646d2SAndroid Build Coastguard Worker           if (ippGetValueTag(tattr) != IPP_TAG_INTEGER)
1427*5e7646d2SAndroid Build Coastguard Worker             return (0);
1428*5e7646d2SAndroid Build Coastguard Worker 
1429*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < tcount; i ++)
1430*5e7646d2SAndroid Build Coastguard Worker           {
1431*5e7646d2SAndroid Build Coastguard Worker             if (!ippContainsInteger(mattr, ippGetInteger(tattr, i)))
1432*5e7646d2SAndroid Build Coastguard Worker               return (0);
1433*5e7646d2SAndroid Build Coastguard Worker           }
1434*5e7646d2SAndroid Build Coastguard Worker           break;
1435*5e7646d2SAndroid Build Coastguard Worker 
1436*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BOOLEAN :
1437*5e7646d2SAndroid Build Coastguard Worker           if (ippGetValueTag(tattr) != IPP_TAG_BOOLEAN || ippGetBoolean(tattr, 0) != ippGetBoolean(mattr, 0))
1438*5e7646d2SAndroid Build Coastguard Worker             return (0);
1439*5e7646d2SAndroid Build Coastguard Worker           break;
1440*5e7646d2SAndroid Build Coastguard Worker 
1441*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXTLANG :
1442*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAMELANG :
1443*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXT :
1444*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAME :
1445*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_KEYWORD :
1446*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URI :
1447*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URISCHEME :
1448*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_CHARSET :
1449*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_LANGUAGE :
1450*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_MIMETYPE :
1451*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < tcount; i ++)
1452*5e7646d2SAndroid Build Coastguard Worker           {
1453*5e7646d2SAndroid Build Coastguard Worker             if ((tval = ippGetString(tattr, i, NULL)) == NULL || !ippContainsString(mattr, tval))
1454*5e7646d2SAndroid Build Coastguard Worker               return (0);
1455*5e7646d2SAndroid Build Coastguard Worker           }
1456*5e7646d2SAndroid Build Coastguard Worker           break;
1457*5e7646d2SAndroid Build Coastguard Worker 
1458*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BEGIN_COLLECTION :
1459*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < tcount; i ++)
1460*5e7646d2SAndroid Build Coastguard Worker           {
1461*5e7646d2SAndroid Build Coastguard Worker             ipp_t *tcol = ippGetCollection(tattr, i);
1462*5e7646d2SAndroid Build Coastguard Worker 					/* Testing collection */
1463*5e7646d2SAndroid Build Coastguard Worker 
1464*5e7646d2SAndroid Build Coastguard Worker             for (j = 0, mcount = ippGetCount(mattr); j < mcount; j ++)
1465*5e7646d2SAndroid Build Coastguard Worker               if (!cups_collection_contains(tcol, ippGetCollection(mattr, j)))
1466*5e7646d2SAndroid Build Coastguard Worker                 return (0);
1467*5e7646d2SAndroid Build Coastguard Worker           }
1468*5e7646d2SAndroid Build Coastguard Worker           break;
1469*5e7646d2SAndroid Build Coastguard Worker 
1470*5e7646d2SAndroid Build Coastguard Worker       default :
1471*5e7646d2SAndroid Build Coastguard Worker           return (0);
1472*5e7646d2SAndroid Build Coastguard Worker     }
1473*5e7646d2SAndroid Build Coastguard Worker   }
1474*5e7646d2SAndroid Build Coastguard Worker 
1475*5e7646d2SAndroid Build Coastguard Worker   return (1);
1476*5e7646d2SAndroid Build Coastguard Worker }
1477*5e7646d2SAndroid Build Coastguard Worker 
1478*5e7646d2SAndroid Build Coastguard Worker 
1479*5e7646d2SAndroid Build Coastguard Worker /*
1480*5e7646d2SAndroid Build Coastguard Worker  * 'cups_collection_string()' - Convert an IPP collection to an option string.
1481*5e7646d2SAndroid Build Coastguard Worker  */
1482*5e7646d2SAndroid Build Coastguard Worker 
1483*5e7646d2SAndroid Build Coastguard Worker static size_t				/* O - Number of bytes needed */
cups_collection_string(ipp_attribute_t * attr,char * buffer,size_t bufsize)1484*5e7646d2SAndroid Build Coastguard Worker cups_collection_string(
1485*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - Collection attribute */
1486*5e7646d2SAndroid Build Coastguard Worker     char            *buffer,		/* I - String buffer */
1487*5e7646d2SAndroid Build Coastguard Worker     size_t          bufsize)		/* I - Size of buffer */
1488*5e7646d2SAndroid Build Coastguard Worker {
1489*5e7646d2SAndroid Build Coastguard Worker   int			i, j,		/* Looping vars */
1490*5e7646d2SAndroid Build Coastguard Worker 			count,		/* Number of collection values */
1491*5e7646d2SAndroid Build Coastguard Worker 			mcount;		/* Number of member values */
1492*5e7646d2SAndroid Build Coastguard Worker   ipp_t			*col;		/* Collection */
1493*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*first,		/* First member attribute */
1494*5e7646d2SAndroid Build Coastguard Worker 			*member;	/* Member attribute */
1495*5e7646d2SAndroid Build Coastguard Worker   char			*bufptr,	/* Pointer into buffer */
1496*5e7646d2SAndroid Build Coastguard Worker 			*bufend,	/* End of buffer */
1497*5e7646d2SAndroid Build Coastguard Worker 			temp[100];	/* Temporary string */
1498*5e7646d2SAndroid Build Coastguard Worker   const char		*mptr;		/* Pointer into member value */
1499*5e7646d2SAndroid Build Coastguard Worker   int			mlen;		/* Length of octetString */
1500*5e7646d2SAndroid Build Coastguard Worker 
1501*5e7646d2SAndroid Build Coastguard Worker 
1502*5e7646d2SAndroid Build Coastguard Worker   bufptr = buffer;
1503*5e7646d2SAndroid Build Coastguard Worker   bufend = buffer + bufsize - 1;
1504*5e7646d2SAndroid Build Coastguard Worker 
1505*5e7646d2SAndroid Build Coastguard Worker   for (i = 0, count = ippGetCount(attr); i < count; i ++)
1506*5e7646d2SAndroid Build Coastguard Worker   {
1507*5e7646d2SAndroid Build Coastguard Worker     col = ippGetCollection(attr, i);
1508*5e7646d2SAndroid Build Coastguard Worker 
1509*5e7646d2SAndroid Build Coastguard Worker     if (i)
1510*5e7646d2SAndroid Build Coastguard Worker     {
1511*5e7646d2SAndroid Build Coastguard Worker       if (bufptr < bufend)
1512*5e7646d2SAndroid Build Coastguard Worker         *bufptr++ = ',';
1513*5e7646d2SAndroid Build Coastguard Worker       else
1514*5e7646d2SAndroid Build Coastguard Worker         bufptr ++;
1515*5e7646d2SAndroid Build Coastguard Worker     }
1516*5e7646d2SAndroid Build Coastguard Worker 
1517*5e7646d2SAndroid Build Coastguard Worker     if (bufptr < bufend)
1518*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = '{';
1519*5e7646d2SAndroid Build Coastguard Worker     else
1520*5e7646d2SAndroid Build Coastguard Worker       bufptr ++;
1521*5e7646d2SAndroid Build Coastguard Worker 
1522*5e7646d2SAndroid Build Coastguard Worker     for (member = first = ippFirstAttribute(col); member; member = ippNextAttribute(col))
1523*5e7646d2SAndroid Build Coastguard Worker     {
1524*5e7646d2SAndroid Build Coastguard Worker       const char *mname = ippGetName(member);
1525*5e7646d2SAndroid Build Coastguard Worker 
1526*5e7646d2SAndroid Build Coastguard Worker       if (member != first)
1527*5e7646d2SAndroid Build Coastguard Worker       {
1528*5e7646d2SAndroid Build Coastguard Worker 	if (bufptr < bufend)
1529*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = ' ';
1530*5e7646d2SAndroid Build Coastguard Worker 	else
1531*5e7646d2SAndroid Build Coastguard Worker 	  bufptr ++;
1532*5e7646d2SAndroid Build Coastguard Worker       }
1533*5e7646d2SAndroid Build Coastguard Worker 
1534*5e7646d2SAndroid Build Coastguard Worker       if (ippGetValueTag(member) == IPP_TAG_BOOLEAN)
1535*5e7646d2SAndroid Build Coastguard Worker       {
1536*5e7646d2SAndroid Build Coastguard Worker         if (!ippGetBoolean(member, 0))
1537*5e7646d2SAndroid Build Coastguard Worker         {
1538*5e7646d2SAndroid Build Coastguard Worker 	  if (bufptr < bufend)
1539*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(bufptr, "no", (size_t)(bufend - bufptr + 1));
1540*5e7646d2SAndroid Build Coastguard Worker 	  bufptr += 2;
1541*5e7646d2SAndroid Build Coastguard Worker         }
1542*5e7646d2SAndroid Build Coastguard Worker 
1543*5e7646d2SAndroid Build Coastguard Worker 	if (bufptr < bufend)
1544*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(bufptr, mname, (size_t)(bufend - bufptr + 1));
1545*5e7646d2SAndroid Build Coastguard Worker 	bufptr += strlen(mname);
1546*5e7646d2SAndroid Build Coastguard Worker         continue;
1547*5e7646d2SAndroid Build Coastguard Worker       }
1548*5e7646d2SAndroid Build Coastguard Worker 
1549*5e7646d2SAndroid Build Coastguard Worker       if (bufptr < bufend)
1550*5e7646d2SAndroid Build Coastguard Worker         strlcpy(bufptr, mname, (size_t)(bufend - bufptr + 1));
1551*5e7646d2SAndroid Build Coastguard Worker       bufptr += strlen(mname);
1552*5e7646d2SAndroid Build Coastguard Worker 
1553*5e7646d2SAndroid Build Coastguard Worker       if (bufptr < bufend)
1554*5e7646d2SAndroid Build Coastguard Worker         *bufptr++ = '=';
1555*5e7646d2SAndroid Build Coastguard Worker       else
1556*5e7646d2SAndroid Build Coastguard Worker         bufptr ++;
1557*5e7646d2SAndroid Build Coastguard Worker 
1558*5e7646d2SAndroid Build Coastguard Worker       if (ippGetValueTag(member) == IPP_TAG_BEGIN_COLLECTION)
1559*5e7646d2SAndroid Build Coastguard Worker       {
1560*5e7646d2SAndroid Build Coastguard Worker        /*
1561*5e7646d2SAndroid Build Coastguard Worker 	* Convert sub-collection...
1562*5e7646d2SAndroid Build Coastguard Worker 	*/
1563*5e7646d2SAndroid Build Coastguard Worker 
1564*5e7646d2SAndroid Build Coastguard Worker 	bufptr += cups_collection_string(member, bufptr, bufptr < bufend ? (size_t)(bufend - bufptr + 1) : 0);
1565*5e7646d2SAndroid Build Coastguard Worker       }
1566*5e7646d2SAndroid Build Coastguard Worker       else
1567*5e7646d2SAndroid Build Coastguard Worker       {
1568*5e7646d2SAndroid Build Coastguard Worker        /*
1569*5e7646d2SAndroid Build Coastguard Worker         * Convert simple type...
1570*5e7646d2SAndroid Build Coastguard Worker         */
1571*5e7646d2SAndroid Build Coastguard Worker 
1572*5e7646d2SAndroid Build Coastguard Worker 	for (j = 0, mcount = ippGetCount(member); j < mcount; j ++)
1573*5e7646d2SAndroid Build Coastguard Worker 	{
1574*5e7646d2SAndroid Build Coastguard Worker 	  if (j)
1575*5e7646d2SAndroid Build Coastguard Worker 	  {
1576*5e7646d2SAndroid Build Coastguard Worker 	    if (bufptr < bufend)
1577*5e7646d2SAndroid Build Coastguard Worker 	      *bufptr++ = ',';
1578*5e7646d2SAndroid Build Coastguard Worker 	    else
1579*5e7646d2SAndroid Build Coastguard Worker 	      bufptr ++;
1580*5e7646d2SAndroid Build Coastguard Worker 	  }
1581*5e7646d2SAndroid Build Coastguard Worker 
1582*5e7646d2SAndroid Build Coastguard Worker           switch (ippGetValueTag(member))
1583*5e7646d2SAndroid Build Coastguard Worker           {
1584*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_INTEGER :
1585*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_ENUM :
1586*5e7646d2SAndroid Build Coastguard Worker                 bufptr += snprintf(bufptr, bufptr < bufend ? (size_t)(bufend - bufptr + 1) : 0, "%d", ippGetInteger(member, j));
1587*5e7646d2SAndroid Build Coastguard Worker                 break;
1588*5e7646d2SAndroid Build Coastguard Worker 
1589*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_STRING :
1590*5e7646d2SAndroid Build Coastguard Worker 		if (bufptr < bufend)
1591*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = '\"';
1592*5e7646d2SAndroid Build Coastguard Worker 		else
1593*5e7646d2SAndroid Build Coastguard Worker 		  bufptr ++;
1594*5e7646d2SAndroid Build Coastguard Worker 
1595*5e7646d2SAndroid Build Coastguard Worker 	        for (mptr = (const char *)ippGetOctetString(member, j, &mlen); mlen > 0; mlen --, mptr ++)
1596*5e7646d2SAndroid Build Coastguard Worker 	        {
1597*5e7646d2SAndroid Build Coastguard Worker 	          if (*mptr == '\"' || *mptr == '\\')
1598*5e7646d2SAndroid Build Coastguard Worker 	          {
1599*5e7646d2SAndroid Build Coastguard Worker 		    if (bufptr < bufend)
1600*5e7646d2SAndroid Build Coastguard Worker 		      *bufptr++ = '\\';
1601*5e7646d2SAndroid Build Coastguard Worker 		    else
1602*5e7646d2SAndroid Build Coastguard Worker 		      bufptr ++;
1603*5e7646d2SAndroid Build Coastguard Worker 		  }
1604*5e7646d2SAndroid Build Coastguard Worker 
1605*5e7646d2SAndroid Build Coastguard Worker 		  if (bufptr < bufend)
1606*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = *mptr;
1607*5e7646d2SAndroid Build Coastguard Worker 		  else
1608*5e7646d2SAndroid Build Coastguard Worker 		    bufptr ++;
1609*5e7646d2SAndroid Build Coastguard Worker                 }
1610*5e7646d2SAndroid Build Coastguard Worker 
1611*5e7646d2SAndroid Build Coastguard Worker 		if (bufptr < bufend)
1612*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = '\"';
1613*5e7646d2SAndroid Build Coastguard Worker 		else
1614*5e7646d2SAndroid Build Coastguard Worker 		  bufptr ++;
1615*5e7646d2SAndroid Build Coastguard Worker 	        break;
1616*5e7646d2SAndroid Build Coastguard Worker 
1617*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_DATE :
1618*5e7646d2SAndroid Build Coastguard Worker 		{
1619*5e7646d2SAndroid Build Coastguard Worker 		  unsigned year;	/* Year */
1620*5e7646d2SAndroid Build Coastguard Worker 		  const ipp_uchar_t *date = ippGetDate(member, j);
1621*5e7646d2SAndroid Build Coastguard Worker 					/* Date value */
1622*5e7646d2SAndroid Build Coastguard Worker 
1623*5e7646d2SAndroid Build Coastguard Worker 		  year = ((unsigned)date[0] << 8) + (unsigned)date[1];
1624*5e7646d2SAndroid Build Coastguard Worker 
1625*5e7646d2SAndroid Build Coastguard Worker 		  if (date[9] == 0 && date[10] == 0)
1626*5e7646d2SAndroid Build Coastguard Worker 		    snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ", year, date[2], date[3], date[4], date[5], date[6]);
1627*5e7646d2SAndroid Build Coastguard Worker 		  else
1628*5e7646d2SAndroid Build Coastguard Worker 		    snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u", year, date[2], date[3], date[4], date[5], date[6], date[8], date[9], date[10]);
1629*5e7646d2SAndroid Build Coastguard Worker 
1630*5e7646d2SAndroid Build Coastguard Worker 		  if (bufptr < bufend)
1631*5e7646d2SAndroid Build Coastguard Worker 		    strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1));
1632*5e7646d2SAndroid Build Coastguard Worker 
1633*5e7646d2SAndroid Build Coastguard Worker 		  bufptr += strlen(temp);
1634*5e7646d2SAndroid Build Coastguard Worker 		}
1635*5e7646d2SAndroid Build Coastguard Worker                 break;
1636*5e7646d2SAndroid Build Coastguard Worker 
1637*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_RESOLUTION :
1638*5e7646d2SAndroid Build Coastguard Worker                 {
1639*5e7646d2SAndroid Build Coastguard Worker                   int		xres,	/* Horizontal resolution */
1640*5e7646d2SAndroid Build Coastguard Worker 				yres;	/* Vertical resolution */
1641*5e7646d2SAndroid Build Coastguard Worker                   ipp_res_t	units;	/* Resolution units */
1642*5e7646d2SAndroid Build Coastguard Worker 
1643*5e7646d2SAndroid Build Coastguard Worker                   xres = ippGetResolution(member, j, &yres, &units);
1644*5e7646d2SAndroid Build Coastguard Worker 
1645*5e7646d2SAndroid Build Coastguard Worker                   if (xres == yres)
1646*5e7646d2SAndroid Build Coastguard Worker                     snprintf(temp, sizeof(temp), "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
1647*5e7646d2SAndroid Build Coastguard Worker 		  else
1648*5e7646d2SAndroid Build Coastguard Worker                     snprintf(temp, sizeof(temp), "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
1649*5e7646d2SAndroid Build Coastguard Worker 
1650*5e7646d2SAndroid Build Coastguard Worker 		  if (bufptr < bufend)
1651*5e7646d2SAndroid Build Coastguard Worker 		    strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1));
1652*5e7646d2SAndroid Build Coastguard Worker 
1653*5e7646d2SAndroid Build Coastguard Worker 		  bufptr += strlen(temp);
1654*5e7646d2SAndroid Build Coastguard Worker                 }
1655*5e7646d2SAndroid Build Coastguard Worker                 break;
1656*5e7646d2SAndroid Build Coastguard Worker 
1657*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_RANGE :
1658*5e7646d2SAndroid Build Coastguard Worker                 {
1659*5e7646d2SAndroid Build Coastguard Worker                   int		lower,	/* Lower bound */
1660*5e7646d2SAndroid Build Coastguard Worker 				upper;	/* Upper bound */
1661*5e7646d2SAndroid Build Coastguard Worker 
1662*5e7646d2SAndroid Build Coastguard Worker                   lower = ippGetRange(member, j, &upper);
1663*5e7646d2SAndroid Build Coastguard Worker 
1664*5e7646d2SAndroid Build Coastguard Worker 		  snprintf(temp, sizeof(temp), "%d-%d", lower, upper);
1665*5e7646d2SAndroid Build Coastguard Worker 
1666*5e7646d2SAndroid Build Coastguard Worker 		  if (bufptr < bufend)
1667*5e7646d2SAndroid Build Coastguard Worker 		    strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1));
1668*5e7646d2SAndroid Build Coastguard Worker 
1669*5e7646d2SAndroid Build Coastguard Worker 		  bufptr += strlen(temp);
1670*5e7646d2SAndroid Build Coastguard Worker                 }
1671*5e7646d2SAndroid Build Coastguard Worker                 break;
1672*5e7646d2SAndroid Build Coastguard Worker 
1673*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_TEXTLANG :
1674*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_NAMELANG :
1675*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_TEXT :
1676*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_NAME :
1677*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_KEYWORD :
1678*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_URI :
1679*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_URISCHEME :
1680*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_CHARSET :
1681*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_LANGUAGE :
1682*5e7646d2SAndroid Build Coastguard Worker             case IPP_TAG_MIMETYPE :
1683*5e7646d2SAndroid Build Coastguard Worker 		if (bufptr < bufend)
1684*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = '\"';
1685*5e7646d2SAndroid Build Coastguard Worker 		else
1686*5e7646d2SAndroid Build Coastguard Worker 		  bufptr ++;
1687*5e7646d2SAndroid Build Coastguard Worker 
1688*5e7646d2SAndroid Build Coastguard Worker 	        for (mptr = ippGetString(member, j, NULL); *mptr; mptr ++)
1689*5e7646d2SAndroid Build Coastguard Worker 	        {
1690*5e7646d2SAndroid Build Coastguard Worker 	          if (*mptr == '\"' || *mptr == '\\')
1691*5e7646d2SAndroid Build Coastguard Worker 	          {
1692*5e7646d2SAndroid Build Coastguard Worker 		    if (bufptr < bufend)
1693*5e7646d2SAndroid Build Coastguard Worker 		      *bufptr++ = '\\';
1694*5e7646d2SAndroid Build Coastguard Worker 		    else
1695*5e7646d2SAndroid Build Coastguard Worker 		      bufptr ++;
1696*5e7646d2SAndroid Build Coastguard Worker 		  }
1697*5e7646d2SAndroid Build Coastguard Worker 
1698*5e7646d2SAndroid Build Coastguard Worker 		  if (bufptr < bufend)
1699*5e7646d2SAndroid Build Coastguard Worker 		    *bufptr++ = *mptr;
1700*5e7646d2SAndroid Build Coastguard Worker 		  else
1701*5e7646d2SAndroid Build Coastguard Worker 		    bufptr ++;
1702*5e7646d2SAndroid Build Coastguard Worker                 }
1703*5e7646d2SAndroid Build Coastguard Worker 
1704*5e7646d2SAndroid Build Coastguard Worker 		if (bufptr < bufend)
1705*5e7646d2SAndroid Build Coastguard Worker 		  *bufptr++ = '\"';
1706*5e7646d2SAndroid Build Coastguard Worker 		else
1707*5e7646d2SAndroid Build Coastguard Worker 		  bufptr ++;
1708*5e7646d2SAndroid Build Coastguard Worker                 break;
1709*5e7646d2SAndroid Build Coastguard Worker 
1710*5e7646d2SAndroid Build Coastguard Worker             default :
1711*5e7646d2SAndroid Build Coastguard Worker                 break;
1712*5e7646d2SAndroid Build Coastguard Worker           }
1713*5e7646d2SAndroid Build Coastguard Worker 	}
1714*5e7646d2SAndroid Build Coastguard Worker       }
1715*5e7646d2SAndroid Build Coastguard Worker     }
1716*5e7646d2SAndroid Build Coastguard Worker 
1717*5e7646d2SAndroid Build Coastguard Worker     if (bufptr < bufend)
1718*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = '}';
1719*5e7646d2SAndroid Build Coastguard Worker     else
1720*5e7646d2SAndroid Build Coastguard Worker       bufptr ++;
1721*5e7646d2SAndroid Build Coastguard Worker   }
1722*5e7646d2SAndroid Build Coastguard Worker 
1723*5e7646d2SAndroid Build Coastguard Worker   *bufptr = '\0';
1724*5e7646d2SAndroid Build Coastguard Worker   return ((size_t)(bufptr - buffer + 1));
1725*5e7646d2SAndroid Build Coastguard Worker }
1726*5e7646d2SAndroid Build Coastguard Worker 
1727*5e7646d2SAndroid Build Coastguard Worker 
1728*5e7646d2SAndroid Build Coastguard Worker /*
1729*5e7646d2SAndroid Build Coastguard Worker  * 'cups_compare_dconstres()' - Compare to resolver entries.
1730*5e7646d2SAndroid Build Coastguard Worker  */
1731*5e7646d2SAndroid Build Coastguard Worker 
1732*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
cups_compare_dconstres(_cups_dconstres_t * a,_cups_dconstres_t * b)1733*5e7646d2SAndroid Build Coastguard Worker cups_compare_dconstres(
1734*5e7646d2SAndroid Build Coastguard Worker     _cups_dconstres_t *a,		/* I - First resolver */
1735*5e7646d2SAndroid Build Coastguard Worker     _cups_dconstres_t *b)		/* I - Second resolver */
1736*5e7646d2SAndroid Build Coastguard Worker {
1737*5e7646d2SAndroid Build Coastguard Worker   return (strcmp(a->name, b->name));
1738*5e7646d2SAndroid Build Coastguard Worker }
1739*5e7646d2SAndroid Build Coastguard Worker 
1740*5e7646d2SAndroid Build Coastguard Worker 
1741*5e7646d2SAndroid Build Coastguard Worker /*
1742*5e7646d2SAndroid Build Coastguard Worker  * 'cups_compare_media_db()' - Compare two media entries.
1743*5e7646d2SAndroid Build Coastguard Worker  */
1744*5e7646d2SAndroid Build Coastguard Worker 
1745*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
cups_compare_media_db(_cups_media_db_t * a,_cups_media_db_t * b)1746*5e7646d2SAndroid Build Coastguard Worker cups_compare_media_db(
1747*5e7646d2SAndroid Build Coastguard Worker     _cups_media_db_t *a,		/* I - First media entries */
1748*5e7646d2SAndroid Build Coastguard Worker     _cups_media_db_t *b)		/* I - Second media entries */
1749*5e7646d2SAndroid Build Coastguard Worker {
1750*5e7646d2SAndroid Build Coastguard Worker   int	result;				/* Result of comparison */
1751*5e7646d2SAndroid Build Coastguard Worker 
1752*5e7646d2SAndroid Build Coastguard Worker 
1753*5e7646d2SAndroid Build Coastguard Worker   if ((result = a->width - b->width) == 0)
1754*5e7646d2SAndroid Build Coastguard Worker     result = a->length - b->length;
1755*5e7646d2SAndroid Build Coastguard Worker 
1756*5e7646d2SAndroid Build Coastguard Worker   return (result);
1757*5e7646d2SAndroid Build Coastguard Worker }
1758*5e7646d2SAndroid Build Coastguard Worker 
1759*5e7646d2SAndroid Build Coastguard Worker 
1760*5e7646d2SAndroid Build Coastguard Worker /*
1761*5e7646d2SAndroid Build Coastguard Worker  * 'cups_copy_media_db()' - Copy a media entry.
1762*5e7646d2SAndroid Build Coastguard Worker  */
1763*5e7646d2SAndroid Build Coastguard Worker 
1764*5e7646d2SAndroid Build Coastguard Worker static _cups_media_db_t *		/* O - New media entry */
cups_copy_media_db(_cups_media_db_t * mdb)1765*5e7646d2SAndroid Build Coastguard Worker cups_copy_media_db(
1766*5e7646d2SAndroid Build Coastguard Worker     _cups_media_db_t *mdb)		/* I - Media entry to copy */
1767*5e7646d2SAndroid Build Coastguard Worker {
1768*5e7646d2SAndroid Build Coastguard Worker   _cups_media_db_t *temp;		/* New media entry */
1769*5e7646d2SAndroid Build Coastguard Worker 
1770*5e7646d2SAndroid Build Coastguard Worker 
1771*5e7646d2SAndroid Build Coastguard Worker   if ((temp = calloc(1, sizeof(_cups_media_db_t))) == NULL)
1772*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1773*5e7646d2SAndroid Build Coastguard Worker 
1774*5e7646d2SAndroid Build Coastguard Worker   if (mdb->color)
1775*5e7646d2SAndroid Build Coastguard Worker     temp->color = _cupsStrAlloc(mdb->color);
1776*5e7646d2SAndroid Build Coastguard Worker   if (mdb->key)
1777*5e7646d2SAndroid Build Coastguard Worker     temp->key = _cupsStrAlloc(mdb->key);
1778*5e7646d2SAndroid Build Coastguard Worker   if (mdb->info)
1779*5e7646d2SAndroid Build Coastguard Worker     temp->info = _cupsStrAlloc(mdb->info);
1780*5e7646d2SAndroid Build Coastguard Worker   if (mdb->size_name)
1781*5e7646d2SAndroid Build Coastguard Worker     temp->size_name = _cupsStrAlloc(mdb->size_name);
1782*5e7646d2SAndroid Build Coastguard Worker   if (mdb->source)
1783*5e7646d2SAndroid Build Coastguard Worker     temp->source = _cupsStrAlloc(mdb->source);
1784*5e7646d2SAndroid Build Coastguard Worker   if (mdb->type)
1785*5e7646d2SAndroid Build Coastguard Worker     temp->type = _cupsStrAlloc(mdb->type);
1786*5e7646d2SAndroid Build Coastguard Worker 
1787*5e7646d2SAndroid Build Coastguard Worker   temp->width  = mdb->width;
1788*5e7646d2SAndroid Build Coastguard Worker   temp->length = mdb->length;
1789*5e7646d2SAndroid Build Coastguard Worker   temp->bottom = mdb->bottom;
1790*5e7646d2SAndroid Build Coastguard Worker   temp->left   = mdb->left;
1791*5e7646d2SAndroid Build Coastguard Worker   temp->right  = mdb->right;
1792*5e7646d2SAndroid Build Coastguard Worker   temp->top    = mdb->top;
1793*5e7646d2SAndroid Build Coastguard Worker 
1794*5e7646d2SAndroid Build Coastguard Worker   return (temp);
1795*5e7646d2SAndroid Build Coastguard Worker }
1796*5e7646d2SAndroid Build Coastguard Worker 
1797*5e7646d2SAndroid Build Coastguard Worker 
1798*5e7646d2SAndroid Build Coastguard Worker /*
1799*5e7646d2SAndroid Build Coastguard Worker  * 'cups_create_cached()' - Create the media selection cache.
1800*5e7646d2SAndroid Build Coastguard Worker  */
1801*5e7646d2SAndroid Build Coastguard Worker 
1802*5e7646d2SAndroid Build Coastguard Worker static void
cups_create_cached(http_t * http,cups_dinfo_t * dinfo,unsigned flags)1803*5e7646d2SAndroid Build Coastguard Worker cups_create_cached(http_t       *http,	/* I - Connection to destination */
1804*5e7646d2SAndroid Build Coastguard Worker                    cups_dinfo_t *dinfo,	/* I - Destination information */
1805*5e7646d2SAndroid Build Coastguard Worker                    unsigned     flags)	/* I - Media selection flags */
1806*5e7646d2SAndroid Build Coastguard Worker {
1807*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*db;		/* Media database array to use */
1808*5e7646d2SAndroid Build Coastguard Worker   _cups_media_db_t	*mdb,		/* Media database entry */
1809*5e7646d2SAndroid Build Coastguard Worker 			*first;		/* First entry this size */
1810*5e7646d2SAndroid Build Coastguard Worker 
1811*5e7646d2SAndroid Build Coastguard Worker 
1812*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3cups_create_cached(http=%p, dinfo=%p, flags=%u)", (void *)http, (void *)dinfo, flags));
1813*5e7646d2SAndroid Build Coastguard Worker 
1814*5e7646d2SAndroid Build Coastguard Worker   if (dinfo->cached_db)
1815*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(dinfo->cached_db);
1816*5e7646d2SAndroid Build Coastguard Worker 
1817*5e7646d2SAndroid Build Coastguard Worker   dinfo->cached_db    = cupsArrayNew(NULL, NULL);
1818*5e7646d2SAndroid Build Coastguard Worker   dinfo->cached_flags = flags;
1819*5e7646d2SAndroid Build Coastguard Worker 
1820*5e7646d2SAndroid Build Coastguard Worker   if (flags & CUPS_MEDIA_FLAGS_READY)
1821*5e7646d2SAndroid Build Coastguard Worker   {
1822*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("4cups_create_cached: ready media");
1823*5e7646d2SAndroid Build Coastguard Worker 
1824*5e7646d2SAndroid Build Coastguard Worker     cups_update_ready(http, dinfo);
1825*5e7646d2SAndroid Build Coastguard Worker     db = dinfo->ready_db;
1826*5e7646d2SAndroid Build Coastguard Worker   }
1827*5e7646d2SAndroid Build Coastguard Worker   else
1828*5e7646d2SAndroid Build Coastguard Worker   {
1829*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("4cups_create_cached: supported media");
1830*5e7646d2SAndroid Build Coastguard Worker 
1831*5e7646d2SAndroid Build Coastguard Worker     if (!dinfo->media_db)
1832*5e7646d2SAndroid Build Coastguard Worker       cups_create_media_db(dinfo, CUPS_MEDIA_FLAGS_DEFAULT);
1833*5e7646d2SAndroid Build Coastguard Worker 
1834*5e7646d2SAndroid Build Coastguard Worker     db = dinfo->media_db;
1835*5e7646d2SAndroid Build Coastguard Worker   }
1836*5e7646d2SAndroid Build Coastguard Worker 
1837*5e7646d2SAndroid Build Coastguard Worker   for (mdb = (_cups_media_db_t *)cupsArrayFirst(db), first = mdb;
1838*5e7646d2SAndroid Build Coastguard Worker        mdb;
1839*5e7646d2SAndroid Build Coastguard Worker        mdb = (_cups_media_db_t *)cupsArrayNext(db))
1840*5e7646d2SAndroid Build Coastguard Worker   {
1841*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4cups_create_cached: %p key=\"%s\", type=\"%s\", %dx%d, B%d L%d R%d T%d", (void *)mdb, mdb->key, mdb->type, mdb->width, mdb->length, mdb->bottom, mdb->left, mdb->right, mdb->top));
1842*5e7646d2SAndroid Build Coastguard Worker 
1843*5e7646d2SAndroid Build Coastguard Worker     if (flags & CUPS_MEDIA_FLAGS_BORDERLESS)
1844*5e7646d2SAndroid Build Coastguard Worker     {
1845*5e7646d2SAndroid Build Coastguard Worker       if (!mdb->left && !mdb->right && !mdb->top && !mdb->bottom)
1846*5e7646d2SAndroid Build Coastguard Worker       {
1847*5e7646d2SAndroid Build Coastguard Worker         DEBUG_printf(("4cups_create_cached: add %p", (void *)mdb));
1848*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(dinfo->cached_db, mdb);
1849*5e7646d2SAndroid Build Coastguard Worker       }
1850*5e7646d2SAndroid Build Coastguard Worker     }
1851*5e7646d2SAndroid Build Coastguard Worker     else if (flags & CUPS_MEDIA_FLAGS_DUPLEX)
1852*5e7646d2SAndroid Build Coastguard Worker     {
1853*5e7646d2SAndroid Build Coastguard Worker       if (first->width != mdb->width || first->length != mdb->length)
1854*5e7646d2SAndroid Build Coastguard Worker       {
1855*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_printf(("4cups_create_cached: add %p", (void *)first));
1856*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(dinfo->cached_db, first);
1857*5e7646d2SAndroid Build Coastguard Worker         first = mdb;
1858*5e7646d2SAndroid Build Coastguard Worker       }
1859*5e7646d2SAndroid Build Coastguard Worker       else if (mdb->left >= first->left && mdb->right >= first->right && mdb->top >= first->top && mdb->bottom >= first->bottom &&
1860*5e7646d2SAndroid Build Coastguard Worker 	       (mdb->left != first->left || mdb->right != first->right || mdb->top != first->top || mdb->bottom != first->bottom))
1861*5e7646d2SAndroid Build Coastguard Worker         first = mdb;
1862*5e7646d2SAndroid Build Coastguard Worker     }
1863*5e7646d2SAndroid Build Coastguard Worker     else
1864*5e7646d2SAndroid Build Coastguard Worker     {
1865*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("4cups_create_cached: add %p", (void *)mdb));
1866*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(dinfo->cached_db, mdb);
1867*5e7646d2SAndroid Build Coastguard Worker     }
1868*5e7646d2SAndroid Build Coastguard Worker   }
1869*5e7646d2SAndroid Build Coastguard Worker 
1870*5e7646d2SAndroid Build Coastguard Worker   if (flags & CUPS_MEDIA_FLAGS_DUPLEX)
1871*5e7646d2SAndroid Build Coastguard Worker   {
1872*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("4cups_create_cached: add %p", (void *)first));
1873*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(dinfo->cached_db, first);
1874*5e7646d2SAndroid Build Coastguard Worker   }
1875*5e7646d2SAndroid Build Coastguard Worker }
1876*5e7646d2SAndroid Build Coastguard Worker 
1877*5e7646d2SAndroid Build Coastguard Worker 
1878*5e7646d2SAndroid Build Coastguard Worker /*
1879*5e7646d2SAndroid Build Coastguard Worker  * 'cups_create_constraints()' - Create the constraints and resolvers arrays.
1880*5e7646d2SAndroid Build Coastguard Worker  */
1881*5e7646d2SAndroid Build Coastguard Worker 
1882*5e7646d2SAndroid Build Coastguard Worker static void
cups_create_constraints(cups_dinfo_t * dinfo)1883*5e7646d2SAndroid Build Coastguard Worker cups_create_constraints(
1884*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo)		/* I - Destination information */
1885*5e7646d2SAndroid Build Coastguard Worker {
1886*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
1887*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Attribute */
1888*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*val;		/* Current value */
1889*5e7646d2SAndroid Build Coastguard Worker 
1890*5e7646d2SAndroid Build Coastguard Worker 
1891*5e7646d2SAndroid Build Coastguard Worker   dinfo->constraints = cupsArrayNew3(NULL, NULL, NULL, 0, NULL,
1892*5e7646d2SAndroid Build Coastguard Worker                                      (cups_afree_func_t)free);
1893*5e7646d2SAndroid Build Coastguard Worker   dinfo->resolvers   = cupsArrayNew3((cups_array_func_t)cups_compare_dconstres,
1894*5e7646d2SAndroid Build Coastguard Worker 				     NULL, NULL, 0, NULL,
1895*5e7646d2SAndroid Build Coastguard Worker                                      (cups_afree_func_t)free);
1896*5e7646d2SAndroid Build Coastguard Worker 
1897*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(dinfo->attrs, "job-constraints-supported",
1898*5e7646d2SAndroid Build Coastguard Worker 			       IPP_TAG_BEGIN_COLLECTION)) != NULL)
1899*5e7646d2SAndroid Build Coastguard Worker   {
1900*5e7646d2SAndroid Build Coastguard Worker     for (i = attr->num_values, val = attr->values; i > 0; i --, val ++)
1901*5e7646d2SAndroid Build Coastguard Worker       cups_add_dconstres(dinfo->constraints, val->collection);
1902*5e7646d2SAndroid Build Coastguard Worker   }
1903*5e7646d2SAndroid Build Coastguard Worker 
1904*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(dinfo->attrs, "job-resolvers-supported",
1905*5e7646d2SAndroid Build Coastguard Worker 			       IPP_TAG_BEGIN_COLLECTION)) != NULL)
1906*5e7646d2SAndroid Build Coastguard Worker   {
1907*5e7646d2SAndroid Build Coastguard Worker     for (i = attr->num_values, val = attr->values; i > 0; i --, val ++)
1908*5e7646d2SAndroid Build Coastguard Worker       cups_add_dconstres(dinfo->resolvers, val->collection);
1909*5e7646d2SAndroid Build Coastguard Worker   }
1910*5e7646d2SAndroid Build Coastguard Worker }
1911*5e7646d2SAndroid Build Coastguard Worker 
1912*5e7646d2SAndroid Build Coastguard Worker 
1913*5e7646d2SAndroid Build Coastguard Worker /*
1914*5e7646d2SAndroid Build Coastguard Worker  * 'cups_create_defaults()' - Create the -default option array.
1915*5e7646d2SAndroid Build Coastguard Worker  */
1916*5e7646d2SAndroid Build Coastguard Worker 
1917*5e7646d2SAndroid Build Coastguard Worker static void
cups_create_defaults(cups_dinfo_t * dinfo)1918*5e7646d2SAndroid Build Coastguard Worker cups_create_defaults(
1919*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo)		/* I - Destination information */
1920*5e7646d2SAndroid Build Coastguard Worker {
1921*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Current attribute */
1922*5e7646d2SAndroid Build Coastguard Worker   char			name[IPP_MAX_NAME + 1],
1923*5e7646d2SAndroid Build Coastguard Worker 					/* Current name */
1924*5e7646d2SAndroid Build Coastguard Worker 			*nameptr,	/* Pointer into current name */
1925*5e7646d2SAndroid Build Coastguard Worker 			value[2048];	/* Current value */
1926*5e7646d2SAndroid Build Coastguard Worker 
1927*5e7646d2SAndroid Build Coastguard Worker 
1928*5e7646d2SAndroid Build Coastguard Worker  /*
1929*5e7646d2SAndroid Build Coastguard Worker   * Iterate through the printer attributes looking for xxx-default and adding
1930*5e7646d2SAndroid Build Coastguard Worker   * xxx=value to the defaults option array.
1931*5e7646d2SAndroid Build Coastguard Worker   */
1932*5e7646d2SAndroid Build Coastguard Worker 
1933*5e7646d2SAndroid Build Coastguard Worker   for (attr = ippFirstAttribute(dinfo->attrs); attr; attr = ippNextAttribute(dinfo->attrs))
1934*5e7646d2SAndroid Build Coastguard Worker   {
1935*5e7646d2SAndroid Build Coastguard Worker     if (!ippGetName(attr) || ippGetGroupTag(attr) != IPP_TAG_PRINTER)
1936*5e7646d2SAndroid Build Coastguard Worker       continue;
1937*5e7646d2SAndroid Build Coastguard Worker 
1938*5e7646d2SAndroid Build Coastguard Worker     strlcpy(name, ippGetName(attr), sizeof(name));
1939*5e7646d2SAndroid Build Coastguard Worker     if ((nameptr = name + strlen(name) - 8) <= name || strcmp(nameptr, "-default"))
1940*5e7646d2SAndroid Build Coastguard Worker       continue;
1941*5e7646d2SAndroid Build Coastguard Worker 
1942*5e7646d2SAndroid Build Coastguard Worker     *nameptr = '\0';
1943*5e7646d2SAndroid Build Coastguard Worker 
1944*5e7646d2SAndroid Build Coastguard Worker     if (ippGetValueTag(attr) == IPP_TAG_BEGIN_COLLECTION)
1945*5e7646d2SAndroid Build Coastguard Worker     {
1946*5e7646d2SAndroid Build Coastguard Worker       if (cups_collection_string(attr, value, sizeof(value)) >= sizeof(value))
1947*5e7646d2SAndroid Build Coastguard Worker         continue;
1948*5e7646d2SAndroid Build Coastguard Worker     }
1949*5e7646d2SAndroid Build Coastguard Worker     else if (ippAttributeString(attr, value, sizeof(value)) >= sizeof(value))
1950*5e7646d2SAndroid Build Coastguard Worker       continue;
1951*5e7646d2SAndroid Build Coastguard Worker 
1952*5e7646d2SAndroid Build Coastguard Worker     dinfo->num_defaults = cupsAddOption(name, value, dinfo->num_defaults, &dinfo->defaults);
1953*5e7646d2SAndroid Build Coastguard Worker   }
1954*5e7646d2SAndroid Build Coastguard Worker }
1955*5e7646d2SAndroid Build Coastguard Worker 
1956*5e7646d2SAndroid Build Coastguard Worker 
1957*5e7646d2SAndroid Build Coastguard Worker /*
1958*5e7646d2SAndroid Build Coastguard Worker  * 'cups_create_media_db()' - Create the media database.
1959*5e7646d2SAndroid Build Coastguard Worker  */
1960*5e7646d2SAndroid Build Coastguard Worker 
1961*5e7646d2SAndroid Build Coastguard Worker static void
cups_create_media_db(cups_dinfo_t * dinfo,unsigned flags)1962*5e7646d2SAndroid Build Coastguard Worker cups_create_media_db(
1963*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t *dinfo,		/* I - Destination information */
1964*5e7646d2SAndroid Build Coastguard Worker     unsigned     flags)			/* I - Media flags */
1965*5e7646d2SAndroid Build Coastguard Worker {
1966*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
1967*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*val;		/* Current value */
1968*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*media_col_db,	/* media-col-database */
1969*5e7646d2SAndroid Build Coastguard Worker 			*media_attr,	/* media-xxx */
1970*5e7646d2SAndroid Build Coastguard Worker 			*x_dimension,	/* x-dimension */
1971*5e7646d2SAndroid Build Coastguard Worker 			*y_dimension;	/* y-dimension */
1972*5e7646d2SAndroid Build Coastguard Worker   pwg_media_t		*pwg;		/* PWG media info */
1973*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*db;		/* New media database array */
1974*5e7646d2SAndroid Build Coastguard Worker   _cups_media_db_t	mdb;		/* Media entry */
1975*5e7646d2SAndroid Build Coastguard Worker   char			media_key[256];	/* Synthesized media-key value */
1976*5e7646d2SAndroid Build Coastguard Worker 
1977*5e7646d2SAndroid Build Coastguard Worker 
1978*5e7646d2SAndroid Build Coastguard Worker   db = cupsArrayNew3((cups_array_func_t)cups_compare_media_db,
1979*5e7646d2SAndroid Build Coastguard Worker 		     NULL, NULL, 0,
1980*5e7646d2SAndroid Build Coastguard Worker 		     (cups_acopy_func_t)cups_copy_media_db,
1981*5e7646d2SAndroid Build Coastguard Worker 		     (cups_afree_func_t)cups_free_media_db);
1982*5e7646d2SAndroid Build Coastguard Worker 
1983*5e7646d2SAndroid Build Coastguard Worker   if (flags == CUPS_MEDIA_FLAGS_READY)
1984*5e7646d2SAndroid Build Coastguard Worker   {
1985*5e7646d2SAndroid Build Coastguard Worker     dinfo->ready_db = db;
1986*5e7646d2SAndroid Build Coastguard Worker 
1987*5e7646d2SAndroid Build Coastguard Worker     media_col_db = ippFindAttribute(dinfo->ready_attrs, "media-col-ready",
1988*5e7646d2SAndroid Build Coastguard Worker 				    IPP_TAG_BEGIN_COLLECTION);
1989*5e7646d2SAndroid Build Coastguard Worker     media_attr   = ippFindAttribute(dinfo->ready_attrs, "media-ready",
1990*5e7646d2SAndroid Build Coastguard Worker 				    IPP_TAG_ZERO);
1991*5e7646d2SAndroid Build Coastguard Worker   }
1992*5e7646d2SAndroid Build Coastguard Worker   else
1993*5e7646d2SAndroid Build Coastguard Worker   {
1994*5e7646d2SAndroid Build Coastguard Worker     dinfo->media_db        = db;
1995*5e7646d2SAndroid Build Coastguard Worker     dinfo->min_size.width  = INT_MAX;
1996*5e7646d2SAndroid Build Coastguard Worker     dinfo->min_size.length = INT_MAX;
1997*5e7646d2SAndroid Build Coastguard Worker     dinfo->max_size.width  = 0;
1998*5e7646d2SAndroid Build Coastguard Worker     dinfo->max_size.length = 0;
1999*5e7646d2SAndroid Build Coastguard Worker 
2000*5e7646d2SAndroid Build Coastguard Worker     media_col_db = ippFindAttribute(dinfo->attrs, "media-col-database",
2001*5e7646d2SAndroid Build Coastguard Worker 				    IPP_TAG_BEGIN_COLLECTION);
2002*5e7646d2SAndroid Build Coastguard Worker     media_attr   = ippFindAttribute(dinfo->attrs, "media-supported",
2003*5e7646d2SAndroid Build Coastguard Worker 				    IPP_TAG_ZERO);
2004*5e7646d2SAndroid Build Coastguard Worker   }
2005*5e7646d2SAndroid Build Coastguard Worker 
2006*5e7646d2SAndroid Build Coastguard Worker   if (media_col_db)
2007*5e7646d2SAndroid Build Coastguard Worker   {
2008*5e7646d2SAndroid Build Coastguard Worker     _ipp_value_t	*custom = NULL;	/* Custom size range value */
2009*5e7646d2SAndroid Build Coastguard Worker 
2010*5e7646d2SAndroid Build Coastguard Worker     for (i = media_col_db->num_values, val = media_col_db->values;
2011*5e7646d2SAndroid Build Coastguard Worker          i > 0;
2012*5e7646d2SAndroid Build Coastguard Worker          i --, val ++)
2013*5e7646d2SAndroid Build Coastguard Worker     {
2014*5e7646d2SAndroid Build Coastguard Worker       memset(&mdb, 0, sizeof(mdb));
2015*5e7646d2SAndroid Build Coastguard Worker 
2016*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-size",
2017*5e7646d2SAndroid Build Coastguard Worker                                          IPP_TAG_BEGIN_COLLECTION)) != NULL)
2018*5e7646d2SAndroid Build Coastguard Worker       {
2019*5e7646d2SAndroid Build Coastguard Worker         ipp_t	*media_size = media_attr->values[0].collection;
2020*5e7646d2SAndroid Build Coastguard Worker 					/* media-size collection value */
2021*5e7646d2SAndroid Build Coastguard Worker 
2022*5e7646d2SAndroid Build Coastguard Worker         if ((x_dimension = ippFindAttribute(media_size, "x-dimension",
2023*5e7646d2SAndroid Build Coastguard Worker                                             IPP_TAG_INTEGER)) != NULL &&
2024*5e7646d2SAndroid Build Coastguard Worker 	    (y_dimension = ippFindAttribute(media_size, "y-dimension",
2025*5e7646d2SAndroid Build Coastguard Worker 					    IPP_TAG_INTEGER)) != NULL)
2026*5e7646d2SAndroid Build Coastguard Worker 	{
2027*5e7646d2SAndroid Build Coastguard Worker 	 /*
2028*5e7646d2SAndroid Build Coastguard Worker 	  * Fixed size...
2029*5e7646d2SAndroid Build Coastguard Worker 	  */
2030*5e7646d2SAndroid Build Coastguard Worker 
2031*5e7646d2SAndroid Build Coastguard Worker 	  mdb.width  = x_dimension->values[0].integer;
2032*5e7646d2SAndroid Build Coastguard Worker 	  mdb.length = y_dimension->values[0].integer;
2033*5e7646d2SAndroid Build Coastguard Worker 	}
2034*5e7646d2SAndroid Build Coastguard Worker 	else if ((x_dimension = ippFindAttribute(media_size, "x-dimension",
2035*5e7646d2SAndroid Build Coastguard Worker 						 IPP_TAG_INTEGER)) != NULL &&
2036*5e7646d2SAndroid Build Coastguard Worker 		 (y_dimension = ippFindAttribute(media_size, "y-dimension",
2037*5e7646d2SAndroid Build Coastguard Worker 						 IPP_TAG_RANGE)) != NULL)
2038*5e7646d2SAndroid Build Coastguard Worker 	{
2039*5e7646d2SAndroid Build Coastguard Worker 	 /*
2040*5e7646d2SAndroid Build Coastguard Worker 	  * Roll limits...
2041*5e7646d2SAndroid Build Coastguard Worker 	  */
2042*5e7646d2SAndroid Build Coastguard Worker 
2043*5e7646d2SAndroid Build Coastguard Worker 	  mdb.width  = x_dimension->values[0].integer;
2044*5e7646d2SAndroid Build Coastguard Worker 	  mdb.length = y_dimension->values[0].range.upper;
2045*5e7646d2SAndroid Build Coastguard Worker 	}
2046*5e7646d2SAndroid Build Coastguard Worker         else if (flags != CUPS_MEDIA_FLAGS_READY &&
2047*5e7646d2SAndroid Build Coastguard Worker                  (x_dimension = ippFindAttribute(media_size, "x-dimension",
2048*5e7646d2SAndroid Build Coastguard Worker 					         IPP_TAG_RANGE)) != NULL &&
2049*5e7646d2SAndroid Build Coastguard Worker 		 (y_dimension = ippFindAttribute(media_size, "y-dimension",
2050*5e7646d2SAndroid Build Coastguard Worker 						 IPP_TAG_RANGE)) != NULL)
2051*5e7646d2SAndroid Build Coastguard Worker 	{
2052*5e7646d2SAndroid Build Coastguard Worker 	 /*
2053*5e7646d2SAndroid Build Coastguard Worker 	  * Custom size range; save this as the custom size value with default
2054*5e7646d2SAndroid Build Coastguard Worker 	  * margins, then continue; we'll capture the real margins below...
2055*5e7646d2SAndroid Build Coastguard Worker 	  */
2056*5e7646d2SAndroid Build Coastguard Worker 
2057*5e7646d2SAndroid Build Coastguard Worker 	  custom = val;
2058*5e7646d2SAndroid Build Coastguard Worker 
2059*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->min_size.width  = x_dimension->values[0].range.lower;
2060*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->min_size.length = y_dimension->values[0].range.lower;
2061*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->min_size.left   =
2062*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->min_size.right  = 635; /* Default 1/4" side margins */
2063*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->min_size.top    =
2064*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->min_size.bottom = 1270; /* Default 1/2" top/bottom margins */
2065*5e7646d2SAndroid Build Coastguard Worker 
2066*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->max_size.width  = x_dimension->values[0].range.upper;
2067*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->max_size.length = y_dimension->values[0].range.upper;
2068*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->max_size.left   =
2069*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->max_size.right  = 635; /* Default 1/4" side margins */
2070*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->max_size.top    =
2071*5e7646d2SAndroid Build Coastguard Worker 	  dinfo->max_size.bottom = 1270; /* Default 1/2" top/bottom margins */
2072*5e7646d2SAndroid Build Coastguard Worker 	  continue;
2073*5e7646d2SAndroid Build Coastguard Worker 	}
2074*5e7646d2SAndroid Build Coastguard Worker       }
2075*5e7646d2SAndroid Build Coastguard Worker 
2076*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-color", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD))
2077*5e7646d2SAndroid Build Coastguard Worker         mdb.color = media_attr->values[0].string.text;
2078*5e7646d2SAndroid Build Coastguard Worker 
2079*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-info", IPP_TAG_TEXT)) != NULL)
2080*5e7646d2SAndroid Build Coastguard Worker         mdb.info = media_attr->values[0].string.text;
2081*5e7646d2SAndroid Build Coastguard Worker 
2082*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-key", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD))
2083*5e7646d2SAndroid Build Coastguard Worker         mdb.key = media_attr->values[0].string.text;
2084*5e7646d2SAndroid Build Coastguard Worker 
2085*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-size-name", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD))
2086*5e7646d2SAndroid Build Coastguard Worker         mdb.size_name = media_attr->values[0].string.text;
2087*5e7646d2SAndroid Build Coastguard Worker 
2088*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-source", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD))
2089*5e7646d2SAndroid Build Coastguard Worker         mdb.source = media_attr->values[0].string.text;
2090*5e7646d2SAndroid Build Coastguard Worker 
2091*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-type", IPP_TAG_ZERO)) != NULL && (media_attr->value_tag == IPP_TAG_NAME || media_attr->value_tag == IPP_TAG_NAMELANG || media_attr->value_tag == IPP_TAG_KEYWORD))
2092*5e7646d2SAndroid Build Coastguard Worker         mdb.type = media_attr->values[0].string.text;
2093*5e7646d2SAndroid Build Coastguard Worker 
2094*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-bottom-margin", IPP_TAG_INTEGER)) != NULL)
2095*5e7646d2SAndroid Build Coastguard Worker         mdb.bottom = media_attr->values[0].integer;
2096*5e7646d2SAndroid Build Coastguard Worker 
2097*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-left-margin", IPP_TAG_INTEGER)) != NULL)
2098*5e7646d2SAndroid Build Coastguard Worker         mdb.left = media_attr->values[0].integer;
2099*5e7646d2SAndroid Build Coastguard Worker 
2100*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-right-margin", IPP_TAG_INTEGER)) != NULL)
2101*5e7646d2SAndroid Build Coastguard Worker         mdb.right = media_attr->values[0].integer;
2102*5e7646d2SAndroid Build Coastguard Worker 
2103*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(val->collection, "media-top-margin", IPP_TAG_INTEGER)) != NULL)
2104*5e7646d2SAndroid Build Coastguard Worker         mdb.top = media_attr->values[0].integer;
2105*5e7646d2SAndroid Build Coastguard Worker 
2106*5e7646d2SAndroid Build Coastguard Worker       if (!mdb.key)
2107*5e7646d2SAndroid Build Coastguard Worker       {
2108*5e7646d2SAndroid Build Coastguard Worker         if (!mdb.size_name && (pwg = pwgMediaForSize(mdb.width, mdb.length)) != NULL)
2109*5e7646d2SAndroid Build Coastguard Worker 	  mdb.size_name = (char *)pwg->pwg;
2110*5e7646d2SAndroid Build Coastguard Worker 
2111*5e7646d2SAndroid Build Coastguard Worker         if (!mdb.size_name)
2112*5e7646d2SAndroid Build Coastguard Worker         {
2113*5e7646d2SAndroid Build Coastguard Worker          /*
2114*5e7646d2SAndroid Build Coastguard Worker           * Use a CUPS-specific identifier if we don't have a size name...
2115*5e7646d2SAndroid Build Coastguard Worker           */
2116*5e7646d2SAndroid Build Coastguard Worker 
2117*5e7646d2SAndroid Build Coastguard Worker 	  if (flags & CUPS_MEDIA_FLAGS_READY)
2118*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(media_key, sizeof(media_key), "cups-media-ready-%d", i + 1);
2119*5e7646d2SAndroid Build Coastguard Worker 	  else
2120*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(media_key, sizeof(media_key), "cups-media-%d", i + 1);
2121*5e7646d2SAndroid Build Coastguard Worker         }
2122*5e7646d2SAndroid Build Coastguard Worker         else if (mdb.source)
2123*5e7646d2SAndroid Build Coastguard Worker         {
2124*5e7646d2SAndroid Build Coastguard Worker          /*
2125*5e7646d2SAndroid Build Coastguard Worker           * Generate key using size name, source, and type (if set)...
2126*5e7646d2SAndroid Build Coastguard Worker           */
2127*5e7646d2SAndroid Build Coastguard Worker 
2128*5e7646d2SAndroid Build Coastguard Worker           if (mdb.type)
2129*5e7646d2SAndroid Build Coastguard Worker             snprintf(media_key, sizeof(media_key), "%s_%s_%s", mdb.size_name, mdb.source, mdb.type);
2130*5e7646d2SAndroid Build Coastguard Worker 	  else
2131*5e7646d2SAndroid Build Coastguard Worker             snprintf(media_key, sizeof(media_key), "%s_%s", mdb.size_name, mdb.source);
2132*5e7646d2SAndroid Build Coastguard Worker         }
2133*5e7646d2SAndroid Build Coastguard Worker         else if (mdb.type)
2134*5e7646d2SAndroid Build Coastguard Worker         {
2135*5e7646d2SAndroid Build Coastguard Worker          /*
2136*5e7646d2SAndroid Build Coastguard Worker           * Generate key using size name and type...
2137*5e7646d2SAndroid Build Coastguard Worker           */
2138*5e7646d2SAndroid Build Coastguard Worker 
2139*5e7646d2SAndroid Build Coastguard Worker 	  snprintf(media_key, sizeof(media_key), "%s_%s", mdb.size_name, mdb.type);
2140*5e7646d2SAndroid Build Coastguard Worker         }
2141*5e7646d2SAndroid Build Coastguard Worker         else
2142*5e7646d2SAndroid Build Coastguard Worker         {
2143*5e7646d2SAndroid Build Coastguard Worker          /*
2144*5e7646d2SAndroid Build Coastguard Worker           * Key is just the size name...
2145*5e7646d2SAndroid Build Coastguard Worker           */
2146*5e7646d2SAndroid Build Coastguard Worker 
2147*5e7646d2SAndroid Build Coastguard Worker           strlcpy(media_key, mdb.size_name, sizeof(media_key));
2148*5e7646d2SAndroid Build Coastguard Worker         }
2149*5e7646d2SAndroid Build Coastguard Worker 
2150*5e7646d2SAndroid Build Coastguard Worker        /*
2151*5e7646d2SAndroid Build Coastguard Worker         * Append "_borderless" for borderless media...
2152*5e7646d2SAndroid Build Coastguard Worker         */
2153*5e7646d2SAndroid Build Coastguard Worker 
2154*5e7646d2SAndroid Build Coastguard Worker         if (!mdb.bottom && !mdb.left && !mdb.right && !mdb.top)
2155*5e7646d2SAndroid Build Coastguard Worker           strlcat(media_key, "_borderless", sizeof(media_key));
2156*5e7646d2SAndroid Build Coastguard Worker 
2157*5e7646d2SAndroid Build Coastguard Worker         mdb.key = media_key;
2158*5e7646d2SAndroid Build Coastguard Worker       }
2159*5e7646d2SAndroid Build Coastguard Worker 
2160*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("1cups_create_media_db: Adding media: key=\"%s\", width=%d, length=%d, source=\"%s\", type=\"%s\".", mdb.key, mdb.width, mdb.length, mdb.source, mdb.type));
2161*5e7646d2SAndroid Build Coastguard Worker 
2162*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(db, &mdb);
2163*5e7646d2SAndroid Build Coastguard Worker     }
2164*5e7646d2SAndroid Build Coastguard Worker 
2165*5e7646d2SAndroid Build Coastguard Worker     if (custom)
2166*5e7646d2SAndroid Build Coastguard Worker     {
2167*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(custom->collection,
2168*5e7646d2SAndroid Build Coastguard Worker                                          "media-bottom-margin",
2169*5e7646d2SAndroid Build Coastguard Worker                                          IPP_TAG_INTEGER)) != NULL)
2170*5e7646d2SAndroid Build Coastguard Worker       {
2171*5e7646d2SAndroid Build Coastguard Worker         dinfo->min_size.top =
2172*5e7646d2SAndroid Build Coastguard Worker         dinfo->max_size.top = media_attr->values[0].integer;
2173*5e7646d2SAndroid Build Coastguard Worker       }
2174*5e7646d2SAndroid Build Coastguard Worker 
2175*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(custom->collection,
2176*5e7646d2SAndroid Build Coastguard Worker                                          "media-left-margin",
2177*5e7646d2SAndroid Build Coastguard Worker                                          IPP_TAG_INTEGER)) != NULL)
2178*5e7646d2SAndroid Build Coastguard Worker       {
2179*5e7646d2SAndroid Build Coastguard Worker         dinfo->min_size.left =
2180*5e7646d2SAndroid Build Coastguard Worker         dinfo->max_size.left = media_attr->values[0].integer;
2181*5e7646d2SAndroid Build Coastguard Worker       }
2182*5e7646d2SAndroid Build Coastguard Worker 
2183*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(custom->collection,
2184*5e7646d2SAndroid Build Coastguard Worker                                          "media-right-margin",
2185*5e7646d2SAndroid Build Coastguard Worker                                          IPP_TAG_INTEGER)) != NULL)
2186*5e7646d2SAndroid Build Coastguard Worker       {
2187*5e7646d2SAndroid Build Coastguard Worker         dinfo->min_size.right =
2188*5e7646d2SAndroid Build Coastguard Worker         dinfo->max_size.right = media_attr->values[0].integer;
2189*5e7646d2SAndroid Build Coastguard Worker       }
2190*5e7646d2SAndroid Build Coastguard Worker 
2191*5e7646d2SAndroid Build Coastguard Worker       if ((media_attr = ippFindAttribute(custom->collection,
2192*5e7646d2SAndroid Build Coastguard Worker                                          "media-top-margin",
2193*5e7646d2SAndroid Build Coastguard Worker                                          IPP_TAG_INTEGER)) != NULL)
2194*5e7646d2SAndroid Build Coastguard Worker       {
2195*5e7646d2SAndroid Build Coastguard Worker         dinfo->min_size.top =
2196*5e7646d2SAndroid Build Coastguard Worker         dinfo->max_size.top = media_attr->values[0].integer;
2197*5e7646d2SAndroid Build Coastguard Worker       }
2198*5e7646d2SAndroid Build Coastguard Worker     }
2199*5e7646d2SAndroid Build Coastguard Worker   }
2200*5e7646d2SAndroid Build Coastguard Worker   else if (media_attr &&
2201*5e7646d2SAndroid Build Coastguard Worker            (media_attr->value_tag == IPP_TAG_NAME ||
2202*5e7646d2SAndroid Build Coastguard Worker             media_attr->value_tag == IPP_TAG_NAMELANG ||
2203*5e7646d2SAndroid Build Coastguard Worker             media_attr->value_tag == IPP_TAG_KEYWORD))
2204*5e7646d2SAndroid Build Coastguard Worker   {
2205*5e7646d2SAndroid Build Coastguard Worker     memset(&mdb, 0, sizeof(mdb));
2206*5e7646d2SAndroid Build Coastguard Worker 
2207*5e7646d2SAndroid Build Coastguard Worker     mdb.left   =
2208*5e7646d2SAndroid Build Coastguard Worker     mdb.right  = 635; /* Default 1/4" side margins */
2209*5e7646d2SAndroid Build Coastguard Worker     mdb.top    =
2210*5e7646d2SAndroid Build Coastguard Worker     mdb.bottom = 1270; /* Default 1/2" top/bottom margins */
2211*5e7646d2SAndroid Build Coastguard Worker 
2212*5e7646d2SAndroid Build Coastguard Worker     for (i = media_attr->num_values, val = media_attr->values;
2213*5e7646d2SAndroid Build Coastguard Worker          i > 0;
2214*5e7646d2SAndroid Build Coastguard Worker          i --, val ++)
2215*5e7646d2SAndroid Build Coastguard Worker     {
2216*5e7646d2SAndroid Build Coastguard Worker       if ((pwg = pwgMediaForPWG(val->string.text)) == NULL)
2217*5e7646d2SAndroid Build Coastguard Worker         if ((pwg = pwgMediaForLegacy(val->string.text)) == NULL)
2218*5e7646d2SAndroid Build Coastguard Worker 	{
2219*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("3cups_create_media_db: Ignoring unknown size '%s'.",
2220*5e7646d2SAndroid Build Coastguard Worker 			val->string.text));
2221*5e7646d2SAndroid Build Coastguard Worker 	  continue;
2222*5e7646d2SAndroid Build Coastguard Worker 	}
2223*5e7646d2SAndroid Build Coastguard Worker 
2224*5e7646d2SAndroid Build Coastguard Worker       mdb.width  = pwg->width;
2225*5e7646d2SAndroid Build Coastguard Worker       mdb.length = pwg->length;
2226*5e7646d2SAndroid Build Coastguard Worker 
2227*5e7646d2SAndroid Build Coastguard Worker       if (flags != CUPS_MEDIA_FLAGS_READY &&
2228*5e7646d2SAndroid Build Coastguard Worker           !strncmp(val->string.text, "custom_min_", 11))
2229*5e7646d2SAndroid Build Coastguard Worker       {
2230*5e7646d2SAndroid Build Coastguard Worker         mdb.size_name   = NULL;
2231*5e7646d2SAndroid Build Coastguard Worker         dinfo->min_size = mdb;
2232*5e7646d2SAndroid Build Coastguard Worker       }
2233*5e7646d2SAndroid Build Coastguard Worker       else if (flags != CUPS_MEDIA_FLAGS_READY &&
2234*5e7646d2SAndroid Build Coastguard Worker 	       !strncmp(val->string.text, "custom_max_", 11))
2235*5e7646d2SAndroid Build Coastguard Worker       {
2236*5e7646d2SAndroid Build Coastguard Worker         mdb.size_name   = NULL;
2237*5e7646d2SAndroid Build Coastguard Worker         dinfo->max_size = mdb;
2238*5e7646d2SAndroid Build Coastguard Worker       }
2239*5e7646d2SAndroid Build Coastguard Worker       else
2240*5e7646d2SAndroid Build Coastguard Worker       {
2241*5e7646d2SAndroid Build Coastguard Worker         mdb.size_name = val->string.text;
2242*5e7646d2SAndroid Build Coastguard Worker 
2243*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(db, &mdb);
2244*5e7646d2SAndroid Build Coastguard Worker       }
2245*5e7646d2SAndroid Build Coastguard Worker     }
2246*5e7646d2SAndroid Build Coastguard Worker   }
2247*5e7646d2SAndroid Build Coastguard Worker }
2248*5e7646d2SAndroid Build Coastguard Worker 
2249*5e7646d2SAndroid Build Coastguard Worker 
2250*5e7646d2SAndroid Build Coastguard Worker /*
2251*5e7646d2SAndroid Build Coastguard Worker  * 'cups_free_media_cb()' - Free a media entry.
2252*5e7646d2SAndroid Build Coastguard Worker  */
2253*5e7646d2SAndroid Build Coastguard Worker 
2254*5e7646d2SAndroid Build Coastguard Worker static void
cups_free_media_db(_cups_media_db_t * mdb)2255*5e7646d2SAndroid Build Coastguard Worker cups_free_media_db(
2256*5e7646d2SAndroid Build Coastguard Worker     _cups_media_db_t *mdb)		/* I - Media entry to free */
2257*5e7646d2SAndroid Build Coastguard Worker {
2258*5e7646d2SAndroid Build Coastguard Worker   if (mdb->color)
2259*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(mdb->color);
2260*5e7646d2SAndroid Build Coastguard Worker   if (mdb->key)
2261*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(mdb->key);
2262*5e7646d2SAndroid Build Coastguard Worker   if (mdb->info)
2263*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(mdb->info);
2264*5e7646d2SAndroid Build Coastguard Worker   if (mdb->size_name)
2265*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(mdb->size_name);
2266*5e7646d2SAndroid Build Coastguard Worker   if (mdb->source)
2267*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(mdb->source);
2268*5e7646d2SAndroid Build Coastguard Worker   if (mdb->type)
2269*5e7646d2SAndroid Build Coastguard Worker     _cupsStrFree(mdb->type);
2270*5e7646d2SAndroid Build Coastguard Worker 
2271*5e7646d2SAndroid Build Coastguard Worker   free(mdb);
2272*5e7646d2SAndroid Build Coastguard Worker }
2273*5e7646d2SAndroid Build Coastguard Worker 
2274*5e7646d2SAndroid Build Coastguard Worker 
2275*5e7646d2SAndroid Build Coastguard Worker /*
2276*5e7646d2SAndroid Build Coastguard Worker  * 'cups_get_media_db()' - Lookup the media entry for a given size.
2277*5e7646d2SAndroid Build Coastguard Worker  */
2278*5e7646d2SAndroid Build Coastguard Worker 
2279*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on match, 0 on failure */
cups_get_media_db(http_t * http,cups_dinfo_t * dinfo,pwg_media_t * pwg,unsigned flags,cups_size_t * size)2280*5e7646d2SAndroid Build Coastguard Worker cups_get_media_db(http_t       *http,	/* I - Connection to destination */
2281*5e7646d2SAndroid Build Coastguard Worker                   cups_dinfo_t *dinfo,	/* I - Destination information */
2282*5e7646d2SAndroid Build Coastguard Worker                   pwg_media_t  *pwg,	/* I - PWG media info */
2283*5e7646d2SAndroid Build Coastguard Worker                   unsigned     flags,	/* I - Media matching flags */
2284*5e7646d2SAndroid Build Coastguard Worker                   cups_size_t  *size)	/* O - Media size/margin/name info */
2285*5e7646d2SAndroid Build Coastguard Worker {
2286*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*db;		/* Which media database to query */
2287*5e7646d2SAndroid Build Coastguard Worker   _cups_media_db_t	*mdb,		/* Current media database entry */
2288*5e7646d2SAndroid Build Coastguard Worker 			*best = NULL,	/* Best matching entry */
2289*5e7646d2SAndroid Build Coastguard Worker 			key;		/* Search key */
2290*5e7646d2SAndroid Build Coastguard Worker 
2291*5e7646d2SAndroid Build Coastguard Worker 
2292*5e7646d2SAndroid Build Coastguard Worker  /*
2293*5e7646d2SAndroid Build Coastguard Worker   * Create the media database as needed...
2294*5e7646d2SAndroid Build Coastguard Worker   */
2295*5e7646d2SAndroid Build Coastguard Worker 
2296*5e7646d2SAndroid Build Coastguard Worker   if (flags & CUPS_MEDIA_FLAGS_READY)
2297*5e7646d2SAndroid Build Coastguard Worker   {
2298*5e7646d2SAndroid Build Coastguard Worker     cups_update_ready(http, dinfo);
2299*5e7646d2SAndroid Build Coastguard Worker     db = dinfo->ready_db;
2300*5e7646d2SAndroid Build Coastguard Worker   }
2301*5e7646d2SAndroid Build Coastguard Worker   else
2302*5e7646d2SAndroid Build Coastguard Worker   {
2303*5e7646d2SAndroid Build Coastguard Worker     if (!dinfo->media_db)
2304*5e7646d2SAndroid Build Coastguard Worker       cups_create_media_db(dinfo, CUPS_MEDIA_FLAGS_DEFAULT);
2305*5e7646d2SAndroid Build Coastguard Worker 
2306*5e7646d2SAndroid Build Coastguard Worker     db = dinfo->media_db;
2307*5e7646d2SAndroid Build Coastguard Worker   }
2308*5e7646d2SAndroid Build Coastguard Worker 
2309*5e7646d2SAndroid Build Coastguard Worker  /*
2310*5e7646d2SAndroid Build Coastguard Worker   * Find a match...
2311*5e7646d2SAndroid Build Coastguard Worker   */
2312*5e7646d2SAndroid Build Coastguard Worker 
2313*5e7646d2SAndroid Build Coastguard Worker   memset(&key, 0, sizeof(key));
2314*5e7646d2SAndroid Build Coastguard Worker   key.width  = pwg->width;
2315*5e7646d2SAndroid Build Coastguard Worker   key.length = pwg->length;
2316*5e7646d2SAndroid Build Coastguard Worker 
2317*5e7646d2SAndroid Build Coastguard Worker   if ((mdb = cupsArrayFind(db, &key)) != NULL)
2318*5e7646d2SAndroid Build Coastguard Worker   {
2319*5e7646d2SAndroid Build Coastguard Worker    /*
2320*5e7646d2SAndroid Build Coastguard Worker     * Found an exact match, let's figure out the best margins for the flags
2321*5e7646d2SAndroid Build Coastguard Worker     * supplied...
2322*5e7646d2SAndroid Build Coastguard Worker     */
2323*5e7646d2SAndroid Build Coastguard Worker 
2324*5e7646d2SAndroid Build Coastguard Worker     best = mdb;
2325*5e7646d2SAndroid Build Coastguard Worker 
2326*5e7646d2SAndroid Build Coastguard Worker     if (flags & CUPS_MEDIA_FLAGS_BORDERLESS)
2327*5e7646d2SAndroid Build Coastguard Worker     {
2328*5e7646d2SAndroid Build Coastguard Worker      /*
2329*5e7646d2SAndroid Build Coastguard Worker       * Look for the smallest margins...
2330*5e7646d2SAndroid Build Coastguard Worker       */
2331*5e7646d2SAndroid Build Coastguard Worker 
2332*5e7646d2SAndroid Build Coastguard Worker       if (best->left != 0 || best->right != 0 || best->top != 0 || best->bottom != 0)
2333*5e7646d2SAndroid Build Coastguard Worker       {
2334*5e7646d2SAndroid Build Coastguard Worker 	for (mdb = (_cups_media_db_t *)cupsArrayNext(db);
2335*5e7646d2SAndroid Build Coastguard Worker 	     mdb && !cups_compare_media_db(mdb, &key);
2336*5e7646d2SAndroid Build Coastguard Worker 	     mdb = (_cups_media_db_t *)cupsArrayNext(db))
2337*5e7646d2SAndroid Build Coastguard Worker 	{
2338*5e7646d2SAndroid Build Coastguard Worker 	  if (mdb->left <= best->left && mdb->right <= best->right &&
2339*5e7646d2SAndroid Build Coastguard Worker 	      mdb->top <= best->top && mdb->bottom <= best->bottom)
2340*5e7646d2SAndroid Build Coastguard Worker 	  {
2341*5e7646d2SAndroid Build Coastguard Worker 	    best = mdb;
2342*5e7646d2SAndroid Build Coastguard Worker 	    if (mdb->left == 0 && mdb->right == 0 && mdb->bottom == 0 &&
2343*5e7646d2SAndroid Build Coastguard Worker 		mdb->top == 0)
2344*5e7646d2SAndroid Build Coastguard Worker 	      break;
2345*5e7646d2SAndroid Build Coastguard Worker 	  }
2346*5e7646d2SAndroid Build Coastguard Worker 	}
2347*5e7646d2SAndroid Build Coastguard Worker       }
2348*5e7646d2SAndroid Build Coastguard Worker 
2349*5e7646d2SAndroid Build Coastguard Worker      /*
2350*5e7646d2SAndroid Build Coastguard Worker       * If we need an exact match, return no-match if the size is not
2351*5e7646d2SAndroid Build Coastguard Worker       * borderless.
2352*5e7646d2SAndroid Build Coastguard Worker       */
2353*5e7646d2SAndroid Build Coastguard Worker 
2354*5e7646d2SAndroid Build Coastguard Worker       if ((flags & CUPS_MEDIA_FLAGS_EXACT) &&
2355*5e7646d2SAndroid Build Coastguard Worker           (best->left || best->right || best->top || best->bottom))
2356*5e7646d2SAndroid Build Coastguard Worker         return (0);
2357*5e7646d2SAndroid Build Coastguard Worker     }
2358*5e7646d2SAndroid Build Coastguard Worker     else if (flags & CUPS_MEDIA_FLAGS_DUPLEX)
2359*5e7646d2SAndroid Build Coastguard Worker     {
2360*5e7646d2SAndroid Build Coastguard Worker      /*
2361*5e7646d2SAndroid Build Coastguard Worker       * Look for the largest margins...
2362*5e7646d2SAndroid Build Coastguard Worker       */
2363*5e7646d2SAndroid Build Coastguard Worker 
2364*5e7646d2SAndroid Build Coastguard Worker       for (mdb = (_cups_media_db_t *)cupsArrayNext(db);
2365*5e7646d2SAndroid Build Coastguard Worker 	   mdb && !cups_compare_media_db(mdb, &key);
2366*5e7646d2SAndroid Build Coastguard Worker 	   mdb = (_cups_media_db_t *)cupsArrayNext(db))
2367*5e7646d2SAndroid Build Coastguard Worker       {
2368*5e7646d2SAndroid Build Coastguard Worker 	if (mdb->left >= best->left && mdb->right >= best->right &&
2369*5e7646d2SAndroid Build Coastguard Worker 	    mdb->top >= best->top && mdb->bottom >= best->bottom &&
2370*5e7646d2SAndroid Build Coastguard Worker 	    (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
2371*5e7646d2SAndroid Build Coastguard Worker 	  best = mdb;
2372*5e7646d2SAndroid Build Coastguard Worker       }
2373*5e7646d2SAndroid Build Coastguard Worker     }
2374*5e7646d2SAndroid Build Coastguard Worker     else
2375*5e7646d2SAndroid Build Coastguard Worker     {
2376*5e7646d2SAndroid Build Coastguard Worker      /*
2377*5e7646d2SAndroid Build Coastguard Worker       * Look for the smallest non-zero margins...
2378*5e7646d2SAndroid Build Coastguard Worker       */
2379*5e7646d2SAndroid Build Coastguard Worker 
2380*5e7646d2SAndroid Build Coastguard Worker       for (mdb = (_cups_media_db_t *)cupsArrayNext(db);
2381*5e7646d2SAndroid Build Coastguard Worker 	   mdb && !cups_compare_media_db(mdb, &key);
2382*5e7646d2SAndroid Build Coastguard Worker 	   mdb = (_cups_media_db_t *)cupsArrayNext(db))
2383*5e7646d2SAndroid Build Coastguard Worker       {
2384*5e7646d2SAndroid Build Coastguard Worker 	if (((mdb->left > 0 && mdb->left <= best->left) || best->left == 0) &&
2385*5e7646d2SAndroid Build Coastguard Worker 	    ((mdb->right > 0 && mdb->right <= best->right) || best->right == 0) &&
2386*5e7646d2SAndroid Build Coastguard Worker 	    ((mdb->top > 0 && mdb->top <= best->top) || best->top == 0) &&
2387*5e7646d2SAndroid Build Coastguard Worker 	    ((mdb->bottom > 0 && mdb->bottom <= best->bottom) || best->bottom == 0) &&
2388*5e7646d2SAndroid Build Coastguard Worker 	    (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
2389*5e7646d2SAndroid Build Coastguard Worker 	  best = mdb;
2390*5e7646d2SAndroid Build Coastguard Worker       }
2391*5e7646d2SAndroid Build Coastguard Worker     }
2392*5e7646d2SAndroid Build Coastguard Worker   }
2393*5e7646d2SAndroid Build Coastguard Worker   else if (flags & CUPS_MEDIA_FLAGS_EXACT)
2394*5e7646d2SAndroid Build Coastguard Worker   {
2395*5e7646d2SAndroid Build Coastguard Worker    /*
2396*5e7646d2SAndroid Build Coastguard Worker     * See if we can do this as a custom size...
2397*5e7646d2SAndroid Build Coastguard Worker     */
2398*5e7646d2SAndroid Build Coastguard Worker 
2399*5e7646d2SAndroid Build Coastguard Worker     if (pwg->width < dinfo->min_size.width ||
2400*5e7646d2SAndroid Build Coastguard Worker         pwg->width > dinfo->max_size.width ||
2401*5e7646d2SAndroid Build Coastguard Worker         pwg->length < dinfo->min_size.length ||
2402*5e7646d2SAndroid Build Coastguard Worker         pwg->length > dinfo->max_size.length)
2403*5e7646d2SAndroid Build Coastguard Worker       return (0);			/* Out of range */
2404*5e7646d2SAndroid Build Coastguard Worker 
2405*5e7646d2SAndroid Build Coastguard Worker     if ((flags & CUPS_MEDIA_FLAGS_BORDERLESS) &&
2406*5e7646d2SAndroid Build Coastguard Worker         (dinfo->min_size.left > 0 || dinfo->min_size.right > 0 ||
2407*5e7646d2SAndroid Build Coastguard Worker          dinfo->min_size.top > 0 || dinfo->min_size.bottom > 0))
2408*5e7646d2SAndroid Build Coastguard Worker       return (0);			/* Not borderless */
2409*5e7646d2SAndroid Build Coastguard Worker 
2410*5e7646d2SAndroid Build Coastguard Worker     key.size_name = (char *)pwg->pwg;
2411*5e7646d2SAndroid Build Coastguard Worker     key.bottom    = dinfo->min_size.bottom;
2412*5e7646d2SAndroid Build Coastguard Worker     key.left      = dinfo->min_size.left;
2413*5e7646d2SAndroid Build Coastguard Worker     key.right     = dinfo->min_size.right;
2414*5e7646d2SAndroid Build Coastguard Worker     key.top       = dinfo->min_size.top;
2415*5e7646d2SAndroid Build Coastguard Worker 
2416*5e7646d2SAndroid Build Coastguard Worker     best = &key;
2417*5e7646d2SAndroid Build Coastguard Worker   }
2418*5e7646d2SAndroid Build Coastguard Worker   else if (pwg->width >= dinfo->min_size.width &&
2419*5e7646d2SAndroid Build Coastguard Worker 	   pwg->width <= dinfo->max_size.width &&
2420*5e7646d2SAndroid Build Coastguard Worker 	   pwg->length >= dinfo->min_size.length &&
2421*5e7646d2SAndroid Build Coastguard Worker 	   pwg->length <= dinfo->max_size.length)
2422*5e7646d2SAndroid Build Coastguard Worker   {
2423*5e7646d2SAndroid Build Coastguard Worker    /*
2424*5e7646d2SAndroid Build Coastguard Worker     * Map to custom size...
2425*5e7646d2SAndroid Build Coastguard Worker     */
2426*5e7646d2SAndroid Build Coastguard Worker 
2427*5e7646d2SAndroid Build Coastguard Worker     key.size_name = (char *)pwg->pwg;
2428*5e7646d2SAndroid Build Coastguard Worker     key.bottom    = dinfo->min_size.bottom;
2429*5e7646d2SAndroid Build Coastguard Worker     key.left      = dinfo->min_size.left;
2430*5e7646d2SAndroid Build Coastguard Worker     key.right     = dinfo->min_size.right;
2431*5e7646d2SAndroid Build Coastguard Worker     key.top       = dinfo->min_size.top;
2432*5e7646d2SAndroid Build Coastguard Worker 
2433*5e7646d2SAndroid Build Coastguard Worker     best = &key;
2434*5e7646d2SAndroid Build Coastguard Worker   }
2435*5e7646d2SAndroid Build Coastguard Worker   else
2436*5e7646d2SAndroid Build Coastguard Worker   {
2437*5e7646d2SAndroid Build Coastguard Worker    /*
2438*5e7646d2SAndroid Build Coastguard Worker     * Find a close size...
2439*5e7646d2SAndroid Build Coastguard Worker     */
2440*5e7646d2SAndroid Build Coastguard Worker 
2441*5e7646d2SAndroid Build Coastguard Worker     for (mdb = (_cups_media_db_t *)cupsArrayFirst(db);
2442*5e7646d2SAndroid Build Coastguard Worker          mdb;
2443*5e7646d2SAndroid Build Coastguard Worker          mdb = (_cups_media_db_t *)cupsArrayNext(db))
2444*5e7646d2SAndroid Build Coastguard Worker       if (cups_is_close_media_db(mdb, &key))
2445*5e7646d2SAndroid Build Coastguard Worker         break;
2446*5e7646d2SAndroid Build Coastguard Worker 
2447*5e7646d2SAndroid Build Coastguard Worker     if (!mdb)
2448*5e7646d2SAndroid Build Coastguard Worker       return (0);
2449*5e7646d2SAndroid Build Coastguard Worker 
2450*5e7646d2SAndroid Build Coastguard Worker     best = mdb;
2451*5e7646d2SAndroid Build Coastguard Worker 
2452*5e7646d2SAndroid Build Coastguard Worker     if (flags & CUPS_MEDIA_FLAGS_BORDERLESS)
2453*5e7646d2SAndroid Build Coastguard Worker     {
2454*5e7646d2SAndroid Build Coastguard Worker      /*
2455*5e7646d2SAndroid Build Coastguard Worker       * Look for the smallest margins...
2456*5e7646d2SAndroid Build Coastguard Worker       */
2457*5e7646d2SAndroid Build Coastguard Worker 
2458*5e7646d2SAndroid Build Coastguard Worker       if (best->left != 0 || best->right != 0 || best->top != 0 ||
2459*5e7646d2SAndroid Build Coastguard Worker           best->bottom != 0)
2460*5e7646d2SAndroid Build Coastguard Worker       {
2461*5e7646d2SAndroid Build Coastguard Worker 	for (mdb = (_cups_media_db_t *)cupsArrayNext(db);
2462*5e7646d2SAndroid Build Coastguard Worker 	     mdb && cups_is_close_media_db(mdb, &key);
2463*5e7646d2SAndroid Build Coastguard Worker 	     mdb = (_cups_media_db_t *)cupsArrayNext(db))
2464*5e7646d2SAndroid Build Coastguard Worker 	{
2465*5e7646d2SAndroid Build Coastguard Worker 	  if (mdb->left <= best->left && mdb->right <= best->right &&
2466*5e7646d2SAndroid Build Coastguard Worker 	      mdb->top <= best->top && mdb->bottom <= best->bottom &&
2467*5e7646d2SAndroid Build Coastguard Worker 	      (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
2468*5e7646d2SAndroid Build Coastguard Worker 	  {
2469*5e7646d2SAndroid Build Coastguard Worker 	    best = mdb;
2470*5e7646d2SAndroid Build Coastguard Worker 	    if (mdb->left == 0 && mdb->right == 0 && mdb->bottom == 0 &&
2471*5e7646d2SAndroid Build Coastguard Worker 		mdb->top == 0)
2472*5e7646d2SAndroid Build Coastguard Worker 	      break;
2473*5e7646d2SAndroid Build Coastguard Worker 	  }
2474*5e7646d2SAndroid Build Coastguard Worker 	}
2475*5e7646d2SAndroid Build Coastguard Worker       }
2476*5e7646d2SAndroid Build Coastguard Worker     }
2477*5e7646d2SAndroid Build Coastguard Worker     else if (flags & CUPS_MEDIA_FLAGS_DUPLEX)
2478*5e7646d2SAndroid Build Coastguard Worker     {
2479*5e7646d2SAndroid Build Coastguard Worker      /*
2480*5e7646d2SAndroid Build Coastguard Worker       * Look for the largest margins...
2481*5e7646d2SAndroid Build Coastguard Worker       */
2482*5e7646d2SAndroid Build Coastguard Worker 
2483*5e7646d2SAndroid Build Coastguard Worker       for (mdb = (_cups_media_db_t *)cupsArrayNext(db);
2484*5e7646d2SAndroid Build Coastguard Worker 	   mdb && cups_is_close_media_db(mdb, &key);
2485*5e7646d2SAndroid Build Coastguard Worker 	   mdb = (_cups_media_db_t *)cupsArrayNext(db))
2486*5e7646d2SAndroid Build Coastguard Worker       {
2487*5e7646d2SAndroid Build Coastguard Worker 	if (mdb->left >= best->left && mdb->right >= best->right &&
2488*5e7646d2SAndroid Build Coastguard Worker 	    mdb->top >= best->top && mdb->bottom >= best->bottom &&
2489*5e7646d2SAndroid Build Coastguard Worker 	    (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
2490*5e7646d2SAndroid Build Coastguard Worker 	  best = mdb;
2491*5e7646d2SAndroid Build Coastguard Worker       }
2492*5e7646d2SAndroid Build Coastguard Worker     }
2493*5e7646d2SAndroid Build Coastguard Worker     else
2494*5e7646d2SAndroid Build Coastguard Worker     {
2495*5e7646d2SAndroid Build Coastguard Worker      /*
2496*5e7646d2SAndroid Build Coastguard Worker       * Look for the smallest non-zero margins...
2497*5e7646d2SAndroid Build Coastguard Worker       */
2498*5e7646d2SAndroid Build Coastguard Worker 
2499*5e7646d2SAndroid Build Coastguard Worker       for (mdb = (_cups_media_db_t *)cupsArrayNext(db);
2500*5e7646d2SAndroid Build Coastguard Worker 	   mdb && cups_is_close_media_db(mdb, &key);
2501*5e7646d2SAndroid Build Coastguard Worker 	   mdb = (_cups_media_db_t *)cupsArrayNext(db))
2502*5e7646d2SAndroid Build Coastguard Worker       {
2503*5e7646d2SAndroid Build Coastguard Worker 	if (((mdb->left > 0 && mdb->left <= best->left) || best->left == 0) &&
2504*5e7646d2SAndroid Build Coastguard Worker 	    ((mdb->right > 0 && mdb->right <= best->right) ||
2505*5e7646d2SAndroid Build Coastguard Worker 	     best->right == 0) &&
2506*5e7646d2SAndroid Build Coastguard Worker 	    ((mdb->top > 0 && mdb->top <= best->top) || best->top == 0) &&
2507*5e7646d2SAndroid Build Coastguard Worker 	    ((mdb->bottom > 0 && mdb->bottom <= best->bottom) ||
2508*5e7646d2SAndroid Build Coastguard Worker 	     best->bottom == 0) &&
2509*5e7646d2SAndroid Build Coastguard Worker 	    (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
2510*5e7646d2SAndroid Build Coastguard Worker 	  best = mdb;
2511*5e7646d2SAndroid Build Coastguard Worker       }
2512*5e7646d2SAndroid Build Coastguard Worker     }
2513*5e7646d2SAndroid Build Coastguard Worker   }
2514*5e7646d2SAndroid Build Coastguard Worker 
2515*5e7646d2SAndroid Build Coastguard Worker   if (best)
2516*5e7646d2SAndroid Build Coastguard Worker   {
2517*5e7646d2SAndroid Build Coastguard Worker    /*
2518*5e7646d2SAndroid Build Coastguard Worker     * Return the matching size...
2519*5e7646d2SAndroid Build Coastguard Worker     */
2520*5e7646d2SAndroid Build Coastguard Worker 
2521*5e7646d2SAndroid Build Coastguard Worker     if (best->key)
2522*5e7646d2SAndroid Build Coastguard Worker       strlcpy(size->media, best->key, sizeof(size->media));
2523*5e7646d2SAndroid Build Coastguard Worker     else if (best->size_name)
2524*5e7646d2SAndroid Build Coastguard Worker       strlcpy(size->media, best->size_name, sizeof(size->media));
2525*5e7646d2SAndroid Build Coastguard Worker     else if (pwg && pwg->pwg)
2526*5e7646d2SAndroid Build Coastguard Worker       strlcpy(size->media, pwg->pwg, sizeof(size->media));
2527*5e7646d2SAndroid Build Coastguard Worker     else
2528*5e7646d2SAndroid Build Coastguard Worker       strlcpy(size->media, "unknown", sizeof(size->media));
2529*5e7646d2SAndroid Build Coastguard Worker 
2530*5e7646d2SAndroid Build Coastguard Worker     size->width  = best->width;
2531*5e7646d2SAndroid Build Coastguard Worker     size->length = best->length;
2532*5e7646d2SAndroid Build Coastguard Worker     size->bottom = best->bottom;
2533*5e7646d2SAndroid Build Coastguard Worker     size->left   = best->left;
2534*5e7646d2SAndroid Build Coastguard Worker     size->right  = best->right;
2535*5e7646d2SAndroid Build Coastguard Worker     size->top    = best->top;
2536*5e7646d2SAndroid Build Coastguard Worker 
2537*5e7646d2SAndroid Build Coastguard Worker     return (1);
2538*5e7646d2SAndroid Build Coastguard Worker   }
2539*5e7646d2SAndroid Build Coastguard Worker 
2540*5e7646d2SAndroid Build Coastguard Worker   return (0);
2541*5e7646d2SAndroid Build Coastguard Worker }
2542*5e7646d2SAndroid Build Coastguard Worker 
2543*5e7646d2SAndroid Build Coastguard Worker 
2544*5e7646d2SAndroid Build Coastguard Worker /*
2545*5e7646d2SAndroid Build Coastguard Worker  * 'cups_is_close_media_db()' - Compare two media entries to see if they are
2546*5e7646d2SAndroid Build Coastguard Worker  *                              close to the same size.
2547*5e7646d2SAndroid Build Coastguard Worker  *
2548*5e7646d2SAndroid Build Coastguard Worker  * Currently we use 5 points (from PostScript) as the matching range...
2549*5e7646d2SAndroid Build Coastguard Worker  */
2550*5e7646d2SAndroid Build Coastguard Worker 
2551*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 if the sizes are close */
cups_is_close_media_db(_cups_media_db_t * a,_cups_media_db_t * b)2552*5e7646d2SAndroid Build Coastguard Worker cups_is_close_media_db(
2553*5e7646d2SAndroid Build Coastguard Worker     _cups_media_db_t *a,		/* I - First media entries */
2554*5e7646d2SAndroid Build Coastguard Worker     _cups_media_db_t *b)		/* I - Second media entries */
2555*5e7646d2SAndroid Build Coastguard Worker {
2556*5e7646d2SAndroid Build Coastguard Worker   int	dwidth,				/* Difference in width */
2557*5e7646d2SAndroid Build Coastguard Worker 	dlength;			/* Difference in length */
2558*5e7646d2SAndroid Build Coastguard Worker 
2559*5e7646d2SAndroid Build Coastguard Worker 
2560*5e7646d2SAndroid Build Coastguard Worker   dwidth  = a->width - b->width;
2561*5e7646d2SAndroid Build Coastguard Worker   dlength = a->length - b->length;
2562*5e7646d2SAndroid Build Coastguard Worker 
2563*5e7646d2SAndroid Build Coastguard Worker   return (dwidth >= -176 && dwidth <= 176 &&
2564*5e7646d2SAndroid Build Coastguard Worker           dlength >= -176 && dlength <= 176);
2565*5e7646d2SAndroid Build Coastguard Worker }
2566*5e7646d2SAndroid Build Coastguard Worker 
2567*5e7646d2SAndroid Build Coastguard Worker 
2568*5e7646d2SAndroid Build Coastguard Worker /*
2569*5e7646d2SAndroid Build Coastguard Worker  * 'cups_test_constraints()' - Test constraints.
2570*5e7646d2SAndroid Build Coastguard Worker  */
2571*5e7646d2SAndroid Build Coastguard Worker 
2572*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *			/* O - Active constraints */
cups_test_constraints(cups_dinfo_t * dinfo,const char * new_option,const char * new_value,int num_options,cups_option_t * options,int * num_conflicts,cups_option_t ** conflicts)2573*5e7646d2SAndroid Build Coastguard Worker cups_test_constraints(
2574*5e7646d2SAndroid Build Coastguard Worker     cups_dinfo_t  *dinfo,		/* I - Destination information */
2575*5e7646d2SAndroid Build Coastguard Worker     const char    *new_option,		/* I - Newly selected option */
2576*5e7646d2SAndroid Build Coastguard Worker     const char    *new_value,		/* I - Newly selected value */
2577*5e7646d2SAndroid Build Coastguard Worker     int           num_options,		/* I - Number of options */
2578*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *options,		/* I - Options */
2579*5e7646d2SAndroid Build Coastguard Worker     int           *num_conflicts,	/* O - Number of conflicting options */
2580*5e7646d2SAndroid Build Coastguard Worker     cups_option_t **conflicts)		/* O - Conflicting options */
2581*5e7646d2SAndroid Build Coastguard Worker {
2582*5e7646d2SAndroid Build Coastguard Worker   int			i,		/* Looping var */
2583*5e7646d2SAndroid Build Coastguard Worker 			count,		/* Number of values */
2584*5e7646d2SAndroid Build Coastguard Worker 			match;		/* Value matches? */
2585*5e7646d2SAndroid Build Coastguard Worker   int			num_matching;	/* Number of matching options */
2586*5e7646d2SAndroid Build Coastguard Worker   cups_option_t		*matching;	/* Matching options */
2587*5e7646d2SAndroid Build Coastguard Worker   _cups_dconstres_t	*c;		/* Current constraint */
2588*5e7646d2SAndroid Build Coastguard Worker   cups_array_t		*active = NULL;	/* Active constraints */
2589*5e7646d2SAndroid Build Coastguard Worker   ipp_t			*col;		/* Collection value */
2590*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Current attribute */
2591*5e7646d2SAndroid Build Coastguard Worker   _ipp_value_t		*attrval;	/* Current attribute value */
2592*5e7646d2SAndroid Build Coastguard Worker   const char		*value;		/* Current value */
2593*5e7646d2SAndroid Build Coastguard Worker   char			temp[1024];	/* Temporary string */
2594*5e7646d2SAndroid Build Coastguard Worker   int			int_value;	/* Integer value */
2595*5e7646d2SAndroid Build Coastguard Worker   int			xres_value,	/* Horizontal resolution */
2596*5e7646d2SAndroid Build Coastguard Worker 			yres_value;	/* Vertical resolution */
2597*5e7646d2SAndroid Build Coastguard Worker   ipp_res_t		units_value;	/* Resolution units */
2598*5e7646d2SAndroid Build Coastguard Worker 
2599*5e7646d2SAndroid Build Coastguard Worker 
2600*5e7646d2SAndroid Build Coastguard Worker   for (c = (_cups_dconstres_t *)cupsArrayFirst(dinfo->constraints);
2601*5e7646d2SAndroid Build Coastguard Worker        c;
2602*5e7646d2SAndroid Build Coastguard Worker        c = (_cups_dconstres_t *)cupsArrayNext(dinfo->constraints))
2603*5e7646d2SAndroid Build Coastguard Worker   {
2604*5e7646d2SAndroid Build Coastguard Worker     num_matching = 0;
2605*5e7646d2SAndroid Build Coastguard Worker     matching     = NULL;
2606*5e7646d2SAndroid Build Coastguard Worker 
2607*5e7646d2SAndroid Build Coastguard Worker     for (attr = ippFirstAttribute(c->collection);
2608*5e7646d2SAndroid Build Coastguard Worker          attr;
2609*5e7646d2SAndroid Build Coastguard Worker          attr = ippNextAttribute(c->collection))
2610*5e7646d2SAndroid Build Coastguard Worker     {
2611*5e7646d2SAndroid Build Coastguard Worker      /*
2612*5e7646d2SAndroid Build Coastguard Worker       * Get the value for the current attribute in the constraint...
2613*5e7646d2SAndroid Build Coastguard Worker       */
2614*5e7646d2SAndroid Build Coastguard Worker 
2615*5e7646d2SAndroid Build Coastguard Worker       if (new_option && new_value && !strcmp(attr->name, new_option))
2616*5e7646d2SAndroid Build Coastguard Worker         value = new_value;
2617*5e7646d2SAndroid Build Coastguard Worker       else if ((value = cupsGetOption(attr->name, num_options, options)) == NULL)
2618*5e7646d2SAndroid Build Coastguard Worker         value = cupsGetOption(attr->name, dinfo->num_defaults, dinfo->defaults);
2619*5e7646d2SAndroid Build Coastguard Worker 
2620*5e7646d2SAndroid Build Coastguard Worker       if (!value)
2621*5e7646d2SAndroid Build Coastguard Worker       {
2622*5e7646d2SAndroid Build Coastguard Worker        /*
2623*5e7646d2SAndroid Build Coastguard Worker         * Not set so this constraint does not apply...
2624*5e7646d2SAndroid Build Coastguard Worker         */
2625*5e7646d2SAndroid Build Coastguard Worker 
2626*5e7646d2SAndroid Build Coastguard Worker         break;
2627*5e7646d2SAndroid Build Coastguard Worker       }
2628*5e7646d2SAndroid Build Coastguard Worker 
2629*5e7646d2SAndroid Build Coastguard Worker       match = 0;
2630*5e7646d2SAndroid Build Coastguard Worker 
2631*5e7646d2SAndroid Build Coastguard Worker       switch (attr->value_tag)
2632*5e7646d2SAndroid Build Coastguard Worker       {
2633*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_INTEGER :
2634*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_ENUM :
2635*5e7646d2SAndroid Build Coastguard Worker 	    int_value = atoi(value);
2636*5e7646d2SAndroid Build Coastguard Worker 
2637*5e7646d2SAndroid Build Coastguard Worker 	    for (i = attr->num_values, attrval = attr->values;
2638*5e7646d2SAndroid Build Coastguard Worker 	         i > 0;
2639*5e7646d2SAndroid Build Coastguard Worker 	         i --, attrval ++)
2640*5e7646d2SAndroid Build Coastguard Worker 	    {
2641*5e7646d2SAndroid Build Coastguard Worker 	      if (attrval->integer == int_value)
2642*5e7646d2SAndroid Build Coastguard Worker 	      {
2643*5e7646d2SAndroid Build Coastguard Worker 		match = 1;
2644*5e7646d2SAndroid Build Coastguard Worker 		break;
2645*5e7646d2SAndroid Build Coastguard Worker 	      }
2646*5e7646d2SAndroid Build Coastguard Worker             }
2647*5e7646d2SAndroid Build Coastguard Worker             break;
2648*5e7646d2SAndroid Build Coastguard Worker 
2649*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_BOOLEAN :
2650*5e7646d2SAndroid Build Coastguard Worker 	    int_value = !strcmp(value, "true");
2651*5e7646d2SAndroid Build Coastguard Worker 
2652*5e7646d2SAndroid Build Coastguard Worker 	    for (i = attr->num_values, attrval = attr->values;
2653*5e7646d2SAndroid Build Coastguard Worker 	         i > 0;
2654*5e7646d2SAndroid Build Coastguard Worker 	         i --, attrval ++)
2655*5e7646d2SAndroid Build Coastguard Worker 	    {
2656*5e7646d2SAndroid Build Coastguard Worker 	      if (attrval->boolean == int_value)
2657*5e7646d2SAndroid Build Coastguard Worker 	      {
2658*5e7646d2SAndroid Build Coastguard Worker 		match = 1;
2659*5e7646d2SAndroid Build Coastguard Worker 		break;
2660*5e7646d2SAndroid Build Coastguard Worker 	      }
2661*5e7646d2SAndroid Build Coastguard Worker             }
2662*5e7646d2SAndroid Build Coastguard Worker             break;
2663*5e7646d2SAndroid Build Coastguard Worker 
2664*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_RANGE :
2665*5e7646d2SAndroid Build Coastguard Worker 	    int_value = atoi(value);
2666*5e7646d2SAndroid Build Coastguard Worker 
2667*5e7646d2SAndroid Build Coastguard Worker 	    for (i = attr->num_values, attrval = attr->values;
2668*5e7646d2SAndroid Build Coastguard Worker 	         i > 0;
2669*5e7646d2SAndroid Build Coastguard Worker 	         i --, attrval ++)
2670*5e7646d2SAndroid Build Coastguard Worker 	    {
2671*5e7646d2SAndroid Build Coastguard Worker 	      if (int_value >= attrval->range.lower &&
2672*5e7646d2SAndroid Build Coastguard Worker 	          int_value <= attrval->range.upper)
2673*5e7646d2SAndroid Build Coastguard Worker 	      {
2674*5e7646d2SAndroid Build Coastguard Worker 		match = 1;
2675*5e7646d2SAndroid Build Coastguard Worker 		break;
2676*5e7646d2SAndroid Build Coastguard Worker 	      }
2677*5e7646d2SAndroid Build Coastguard Worker             }
2678*5e7646d2SAndroid Build Coastguard Worker             break;
2679*5e7646d2SAndroid Build Coastguard Worker 
2680*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_RESOLUTION :
2681*5e7646d2SAndroid Build Coastguard Worker 	    if (sscanf(value, "%dx%d%15s", &xres_value, &yres_value, temp) != 3)
2682*5e7646d2SAndroid Build Coastguard Worker 	    {
2683*5e7646d2SAndroid Build Coastguard Worker 	      if (sscanf(value, "%d%15s", &xres_value, temp) != 2)
2684*5e7646d2SAndroid Build Coastguard Worker 		break;
2685*5e7646d2SAndroid Build Coastguard Worker 
2686*5e7646d2SAndroid Build Coastguard Worker 	      yres_value = xres_value;
2687*5e7646d2SAndroid Build Coastguard Worker 	    }
2688*5e7646d2SAndroid Build Coastguard Worker 
2689*5e7646d2SAndroid Build Coastguard Worker 	    if (!strcmp(temp, "dpi"))
2690*5e7646d2SAndroid Build Coastguard Worker 	      units_value = IPP_RES_PER_INCH;
2691*5e7646d2SAndroid Build Coastguard Worker 	    else if (!strcmp(temp, "dpc") || !strcmp(temp, "dpcm"))
2692*5e7646d2SAndroid Build Coastguard Worker 	      units_value = IPP_RES_PER_CM;
2693*5e7646d2SAndroid Build Coastguard Worker 	    else
2694*5e7646d2SAndroid Build Coastguard Worker 	      break;
2695*5e7646d2SAndroid Build Coastguard Worker 
2696*5e7646d2SAndroid Build Coastguard Worker 	    for (i = attr->num_values, attrval = attr->values;
2697*5e7646d2SAndroid Build Coastguard Worker 		 i > 0;
2698*5e7646d2SAndroid Build Coastguard Worker 		 i --, attrval ++)
2699*5e7646d2SAndroid Build Coastguard Worker 	    {
2700*5e7646d2SAndroid Build Coastguard Worker 	      if (attrval->resolution.xres == xres_value &&
2701*5e7646d2SAndroid Build Coastguard Worker 		  attrval->resolution.yres == yres_value &&
2702*5e7646d2SAndroid Build Coastguard Worker 		  attrval->resolution.units == units_value)
2703*5e7646d2SAndroid Build Coastguard Worker 	      {
2704*5e7646d2SAndroid Build Coastguard Worker 	      	match = 1;
2705*5e7646d2SAndroid Build Coastguard Worker 		break;
2706*5e7646d2SAndroid Build Coastguard Worker 	      }
2707*5e7646d2SAndroid Build Coastguard Worker 	    }
2708*5e7646d2SAndroid Build Coastguard Worker             break;
2709*5e7646d2SAndroid Build Coastguard Worker 
2710*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_TEXT :
2711*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_NAME :
2712*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_KEYWORD :
2713*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_CHARSET :
2714*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_URI :
2715*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_URISCHEME :
2716*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_MIMETYPE :
2717*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_LANGUAGE :
2718*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_TEXTLANG :
2719*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_NAMELANG :
2720*5e7646d2SAndroid Build Coastguard Worker 	    for (i = attr->num_values, attrval = attr->values;
2721*5e7646d2SAndroid Build Coastguard Worker 	         i > 0;
2722*5e7646d2SAndroid Build Coastguard Worker 	         i --, attrval ++)
2723*5e7646d2SAndroid Build Coastguard Worker 	    {
2724*5e7646d2SAndroid Build Coastguard Worker 	      if (!strcmp(attrval->string.text, value))
2725*5e7646d2SAndroid Build Coastguard Worker 	      {
2726*5e7646d2SAndroid Build Coastguard Worker 		match = 1;
2727*5e7646d2SAndroid Build Coastguard Worker 		break;
2728*5e7646d2SAndroid Build Coastguard Worker 	      }
2729*5e7646d2SAndroid Build Coastguard Worker             }
2730*5e7646d2SAndroid Build Coastguard Worker 	    break;
2731*5e7646d2SAndroid Build Coastguard Worker 
2732*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_BEGIN_COLLECTION :
2733*5e7646d2SAndroid Build Coastguard Worker             col = ippNew();
2734*5e7646d2SAndroid Build Coastguard Worker             _cupsEncodeOption(col, IPP_TAG_ZERO, NULL, ippGetName(attr), value);
2735*5e7646d2SAndroid Build Coastguard Worker 
2736*5e7646d2SAndroid Build Coastguard Worker             for (i = 0, count = ippGetCount(attr); i < count; i ++)
2737*5e7646d2SAndroid Build Coastguard Worker             {
2738*5e7646d2SAndroid Build Coastguard Worker               if (cups_collection_contains(col, ippGetCollection(attr, i)))
2739*5e7646d2SAndroid Build Coastguard Worker               {
2740*5e7646d2SAndroid Build Coastguard Worker                 match = 1;
2741*5e7646d2SAndroid Build Coastguard Worker                 break;
2742*5e7646d2SAndroid Build Coastguard Worker 	      }
2743*5e7646d2SAndroid Build Coastguard Worker             }
2744*5e7646d2SAndroid Build Coastguard Worker 
2745*5e7646d2SAndroid Build Coastguard Worker             ippDelete(col);
2746*5e7646d2SAndroid Build Coastguard Worker             break;
2747*5e7646d2SAndroid Build Coastguard Worker 
2748*5e7646d2SAndroid Build Coastguard Worker         default :
2749*5e7646d2SAndroid Build Coastguard Worker             break;
2750*5e7646d2SAndroid Build Coastguard Worker       }
2751*5e7646d2SAndroid Build Coastguard Worker 
2752*5e7646d2SAndroid Build Coastguard Worker       if (!match)
2753*5e7646d2SAndroid Build Coastguard Worker         break;
2754*5e7646d2SAndroid Build Coastguard Worker 
2755*5e7646d2SAndroid Build Coastguard Worker       num_matching = cupsAddOption(attr->name, value, num_matching, &matching);
2756*5e7646d2SAndroid Build Coastguard Worker     }
2757*5e7646d2SAndroid Build Coastguard Worker 
2758*5e7646d2SAndroid Build Coastguard Worker     if (!attr)
2759*5e7646d2SAndroid Build Coastguard Worker     {
2760*5e7646d2SAndroid Build Coastguard Worker       if (!active)
2761*5e7646d2SAndroid Build Coastguard Worker         active = cupsArrayNew(NULL, NULL);
2762*5e7646d2SAndroid Build Coastguard Worker 
2763*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(active, c);
2764*5e7646d2SAndroid Build Coastguard Worker 
2765*5e7646d2SAndroid Build Coastguard Worker       if (num_conflicts && conflicts)
2766*5e7646d2SAndroid Build Coastguard Worker       {
2767*5e7646d2SAndroid Build Coastguard Worker         cups_option_t	*moption;	/* Matching option */
2768*5e7646d2SAndroid Build Coastguard Worker 
2769*5e7646d2SAndroid Build Coastguard Worker         for (i = num_matching, moption = matching; i > 0; i --, moption ++)
2770*5e7646d2SAndroid Build Coastguard Worker           *num_conflicts = cupsAddOption(moption->name, moption->value, *num_conflicts, conflicts);
2771*5e7646d2SAndroid Build Coastguard Worker       }
2772*5e7646d2SAndroid Build Coastguard Worker     }
2773*5e7646d2SAndroid Build Coastguard Worker 
2774*5e7646d2SAndroid Build Coastguard Worker     cupsFreeOptions(num_matching, matching);
2775*5e7646d2SAndroid Build Coastguard Worker   }
2776*5e7646d2SAndroid Build Coastguard Worker 
2777*5e7646d2SAndroid Build Coastguard Worker   return (active);
2778*5e7646d2SAndroid Build Coastguard Worker }
2779*5e7646d2SAndroid Build Coastguard Worker 
2780*5e7646d2SAndroid Build Coastguard Worker 
2781*5e7646d2SAndroid Build Coastguard Worker /*
2782*5e7646d2SAndroid Build Coastguard Worker  * 'cups_update_ready()' - Update xxx-ready attributes for the printer.
2783*5e7646d2SAndroid Build Coastguard Worker  */
2784*5e7646d2SAndroid Build Coastguard Worker 
2785*5e7646d2SAndroid Build Coastguard Worker static void
cups_update_ready(http_t * http,cups_dinfo_t * dinfo)2786*5e7646d2SAndroid Build Coastguard Worker cups_update_ready(http_t       *http,	/* I - Connection to destination */
2787*5e7646d2SAndroid Build Coastguard Worker                   cups_dinfo_t *dinfo)	/* I - Destination information */
2788*5e7646d2SAndroid Build Coastguard Worker {
2789*5e7646d2SAndroid Build Coastguard Worker   ipp_t	*request;			/* Get-Printer-Attributes request */
2790*5e7646d2SAndroid Build Coastguard Worker   static const char * const pattrs[] =	/* Printer attributes we want */
2791*5e7646d2SAndroid Build Coastguard Worker   {
2792*5e7646d2SAndroid Build Coastguard Worker     "finishings-col-ready",
2793*5e7646d2SAndroid Build Coastguard Worker     "finishings-ready",
2794*5e7646d2SAndroid Build Coastguard Worker     "job-finishings-col-ready",
2795*5e7646d2SAndroid Build Coastguard Worker     "job-finishings-ready",
2796*5e7646d2SAndroid Build Coastguard Worker     "media-col-ready",
2797*5e7646d2SAndroid Build Coastguard Worker     "media-ready"
2798*5e7646d2SAndroid Build Coastguard Worker   };
2799*5e7646d2SAndroid Build Coastguard Worker 
2800*5e7646d2SAndroid Build Coastguard Worker 
2801*5e7646d2SAndroid Build Coastguard Worker  /*
2802*5e7646d2SAndroid Build Coastguard Worker   * Don't update more than once every 30 seconds...
2803*5e7646d2SAndroid Build Coastguard Worker   */
2804*5e7646d2SAndroid Build Coastguard Worker 
2805*5e7646d2SAndroid Build Coastguard Worker   if ((time(NULL) - dinfo->ready_time) < _CUPS_MEDIA_READY_TTL)
2806*5e7646d2SAndroid Build Coastguard Worker     return;
2807*5e7646d2SAndroid Build Coastguard Worker 
2808*5e7646d2SAndroid Build Coastguard Worker  /*
2809*5e7646d2SAndroid Build Coastguard Worker   * Free any previous results...
2810*5e7646d2SAndroid Build Coastguard Worker   */
2811*5e7646d2SAndroid Build Coastguard Worker 
2812*5e7646d2SAndroid Build Coastguard Worker   if (dinfo->cached_flags & CUPS_MEDIA_FLAGS_READY)
2813*5e7646d2SAndroid Build Coastguard Worker   {
2814*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(dinfo->cached_db);
2815*5e7646d2SAndroid Build Coastguard Worker     dinfo->cached_db    = NULL;
2816*5e7646d2SAndroid Build Coastguard Worker     dinfo->cached_flags = CUPS_MEDIA_FLAGS_DEFAULT;
2817*5e7646d2SAndroid Build Coastguard Worker   }
2818*5e7646d2SAndroid Build Coastguard Worker 
2819*5e7646d2SAndroid Build Coastguard Worker   ippDelete(dinfo->ready_attrs);
2820*5e7646d2SAndroid Build Coastguard Worker   dinfo->ready_attrs = NULL;
2821*5e7646d2SAndroid Build Coastguard Worker 
2822*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(dinfo->ready_db);
2823*5e7646d2SAndroid Build Coastguard Worker   dinfo->ready_db = NULL;
2824*5e7646d2SAndroid Build Coastguard Worker 
2825*5e7646d2SAndroid Build Coastguard Worker  /*
2826*5e7646d2SAndroid Build Coastguard Worker   * Query the xxx-ready values...
2827*5e7646d2SAndroid Build Coastguard Worker   */
2828*5e7646d2SAndroid Build Coastguard Worker 
2829*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
2830*5e7646d2SAndroid Build Coastguard Worker   ippSetVersion(request, dinfo->version / 10, dinfo->version % 10);
2831*5e7646d2SAndroid Build Coastguard Worker 
2832*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
2833*5e7646d2SAndroid Build Coastguard Worker                dinfo->uri);
2834*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
2835*5e7646d2SAndroid Build Coastguard Worker                NULL, cupsUser());
2836*5e7646d2SAndroid Build Coastguard Worker   ippAddStrings(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
2837*5e7646d2SAndroid Build Coastguard Worker 
2838*5e7646d2SAndroid Build Coastguard Worker   dinfo->ready_attrs = cupsDoRequest(http, request, dinfo->resource);
2839*5e7646d2SAndroid Build Coastguard Worker 
2840*5e7646d2SAndroid Build Coastguard Worker  /*
2841*5e7646d2SAndroid Build Coastguard Worker   * Update the ready media database...
2842*5e7646d2SAndroid Build Coastguard Worker   */
2843*5e7646d2SAndroid Build Coastguard Worker 
2844*5e7646d2SAndroid Build Coastguard Worker   cups_create_media_db(dinfo, CUPS_MEDIA_FLAGS_READY);
2845*5e7646d2SAndroid Build Coastguard Worker 
2846*5e7646d2SAndroid Build Coastguard Worker  /*
2847*5e7646d2SAndroid Build Coastguard Worker   * Update last lookup time and return...
2848*5e7646d2SAndroid Build Coastguard Worker   */
2849*5e7646d2SAndroid Build Coastguard Worker 
2850*5e7646d2SAndroid Build Coastguard Worker   dinfo->ready_time = time(NULL);
2851*5e7646d2SAndroid Build Coastguard Worker }
2852