]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/dest-options.c
License change: Apache License, Version 2.0.
[thirdparty/cups.git] / cups / dest-options.c
index 4b03189c53192d06e82bf0a8f25b81c6fb17ed74..b849f70c7afb2cd3e05fbee0240ada805480121c 100644 (file)
@@ -1,55 +1,9 @@
 /*
- * "$Id$"
+ * Destination option/media support for CUPS.
  *
- *   Destination option/media support for CUPS.
+ * Copyright 2012-2017 by Apple Inc.
  *
- *   Copyright 2012-2013 by Apple Inc.
- *
- *   These coded instructions, statements, and computer programs are the
- *   property of Apple Inc. and are protected by Federal copyright
- *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- *   which should have been included with this file.  If this file is
- *   file is missing or damaged, see the license at "http://www.cups.org/".
- *
- *   This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- *   cupsCheckDestSupported()  - Check that the option and value are supported
- *                              by the destination.
- *   cupsCopyDestConflicts()   - Get conflicts and resolutions for a new
- *                              option/value pair.
- *   cupsCopyDestInfo()        - Get the supported values/capabilities for the
- *                              destination.
- *   cupsFindDestDefault()     - Find the default value(s) for the given
- *                              option.
- *   cupsFindDestReady()       - Find the default value(s) for the given
- *                              option.
- *   cupsFindDestSupported()   - Find the default value(s) for the given
- *                              option.
- *   cupsFreeDestInfo()        - Free destination information obtained using
- *                              @link cupsCopyDestInfo@.
- *   cupsGetDestMediaByIndex() - Get a media name, dimension, and margins for a
- *                              specific size.
- *   cupsGetDestMediaByName()  - Get media names, dimensions, and margins.
- *   cupsGetDestMediaBySize()  - Get media names, dimensions, and margins.
- *   cupsGetDestMediaCount()   - Get the number of sizes supported by a
- *                              destination.
- *   cupsGetDestMediaDefault() - Get the default size for a destination.
- *   cups_add_dconstres()      - Add a constraint or resolver to an array.
- *   cups_compare_dconstres()  - Compare to resolver entries.
- *   cups_compare_media_db()   - Compare two media entries.
- *   cups_copy_media_db()      - Copy a media entry.
- *   cups_create_cached()      - Create the media selection cache.
- *   cups_create_constraints() - Create the constraints and resolvers arrays.
- *   cups_create_defaults()    - Create the -default option array.
- *   cups_create_media_db()    - Create the media database.
- *   cups_free_media_cb()      - Free a media entry.
- *   cups_get_media_db()       - Lookup the media entry for a given size.
- *   cups_is_close_media_db()  - Compare two media entries to see if they are
- *                              close to the same size.
- *   cups_test_constraints()   - Test constraints.
- *   cups_update_ready()       - Update xxx-ready attributes for the printer.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
  */
 
 /*
@@ -104,7 +58,7 @@ static void          cups_update_ready(http_t *http, cups_dinfo_t *dinfo);
  *
  * Returns 1 if supported, 0 otherwise.
  *
- * @since CUPS 1.6/OS X 10.8@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
 int                                    /* O - 1 if supported, 0 otherwise */
@@ -113,7 +67,7 @@ cupsCheckDestSupported(
     cups_dest_t  *dest,                        /* I - Destination */
     cups_dinfo_t *dinfo,               /* I - Destination information */
     const char   *option,              /* I - Option */
-    const char   *value)               /* I - Value */
+    const char   *value)               /* I - Value or @code NULL@ */
 {
   int                  i;              /* Looping var */
   char                 temp[1024];     /* Temporary string */
@@ -125,11 +79,18 @@ cupsCheckDestSupported(
   _ipp_value_t         *attrval;       /* Current attribute value */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
 
-  if (!http || !dest || !dinfo || !option || !value)
+  if (!http || !dest || !dinfo || !option)
     return (0);
 
  /*
@@ -147,7 +108,10 @@ cupsCheckDestSupported(
   if (!attr)
     return (0);
 
- /*
+  if (!value)
+    return (1);
+
+/*
   * Compare values...
   */
 
@@ -301,7 +265,7 @@ cupsCheckDestSupported(
  * If cupsCopyDestConflicts returns 1 but "num_resolved" and "resolved" are set
  * to 0 and @code NULL@, respectively, then the conflict cannot be resolved.
  *
- * @since CUPS 1.6/OS X 10.8@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
 int                                    /* O - 1 if there is a conflict, 0 if none, -1 on error */
@@ -328,7 +292,7 @@ cupsCopyDestConflicts(
                *myres = NULL,          /* My resolved options */
                *myoption,              /* My current option */
                *option;                /* Current option */
-  cups_array_t *active,                /* Active conflicts */
+  cups_array_t *active = NULL,         /* Active conflicts */
                *pass = NULL,           /* Resolvers for this pass */
                *resolvers = NULL,      /* Resolvers we have used */
                *test;                  /* Test array for conflicts */
@@ -355,6 +319,13 @@ cupsCopyDestConflicts(
   if (resolved)
     *resolved = NULL;
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -586,7 +557,7 @@ cupsCopyDestConflicts(
  * The caller is responsible for calling @link cupsFreeDestInfo@ on the return
  * value. @code NULL@ is returned on error.
  *
- * @since CUPS 1.6/OS X 10.8@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
 cups_dinfo_t *                         /* O - Destination information */
@@ -612,8 +583,14 @@ cupsCopyDestInfo(
   };
 
 
-  DEBUG_printf(("cupsCopyDestSupported(http=%p, dest=%p(%s))", http, dest,
-                dest ? dest->name : ""));
+  DEBUG_printf(("cupsCopyDestSupported(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : ""));
+
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
 
  /*
   * Range check input...
@@ -669,7 +646,7 @@ cupsCopyDestInfo(
         version = 11;
       else if (status == IPP_STATUS_ERROR_BUSY)
       {
-        sleep(delay);
+        sleep((unsigned)delay);
 
         delay = _cupsNextDelay(delay, &prev_delay);
       }
@@ -713,7 +690,7 @@ cupsCopyDestInfo(
  * @code ippGetResolution@, @code ippGetString@, and @code ippGetValueTag@
  * functions to inspect the default value(s) as needed.
  *
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
  */
 
 ipp_attribute_t        *                       /* O - Default attribute or @code NULL@ for none */
@@ -726,6 +703,13 @@ cupsFindDestDefault(
   char name[IPP_MAX_NAME];             /* Attribute name */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -744,6 +728,7 @@ cupsFindDestDefault(
   return (ippFindAttribute(dinfo->attrs, name, IPP_TAG_ZERO));
 }
 
+
 /*
  * 'cupsFindDestReady()' - Find the default value(s) for the given option.
  *
@@ -753,7 +738,7 @@ cupsFindDestDefault(
  * @code ippGetResolution@, @code ippGetString@, and @code ippGetValueTag@
  * functions to inspect the default value(s) as needed.
  *
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
  */
 
 ipp_attribute_t        *                       /* O - Default attribute or @code NULL@ for none */
@@ -766,6 +751,13 @@ cupsFindDestReady(
   char name[IPP_MAX_NAME];             /* Attribute name */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -786,6 +778,7 @@ cupsFindDestReady(
   return (ippFindAttribute(dinfo->ready_attrs, name, IPP_TAG_ZERO));
 }
 
+
 /*
  * 'cupsFindDestSupported()' - Find the default value(s) for the given option.
  *
@@ -795,7 +788,7 @@ cupsFindDestReady(
  * @code ippGetResolution@, @code ippGetString@, and @code ippGetValueTag@
  * functions to inspect the default value(s) as needed.
  *
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
  */
 
 ipp_attribute_t        *                       /* O - Default attribute or @code NULL@ for none */
@@ -808,6 +801,13 @@ cupsFindDestSupported(
   char name[IPP_MAX_NAME];             /* Attribute name */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -830,6 +830,8 @@ cupsFindDestSupported(
 /*
  * 'cupsFreeDestInfo()' - Free destination information obtained using
  *                        @link cupsCopyDestInfo@.
+ *
+ * @since CUPS 1.6/macOS 10.8@
  */
 
 void
@@ -874,7 +876,7 @@ cupsFreeDestInfo(cups_dinfo_t *dinfo)       /* I - Destination information */
  * example, passing @code CUPS_MEDIA_FLAGS_BORDERLESS@ will get the Nth
  * borderless size supported by the printer.
  *
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -886,8 +888,16 @@ cupsGetDestMediaByIndex(
     unsigned     flags,                        /* I - Media flags */
     cups_size_t  *size)                        /* O - Media size information */
 {
-  cups_size_t  *nsize;                 /* Size for N */
+  _cups_media_db_t     *nsize;         /* Size for N */
+  pwg_media_t          *pwg;           /* PWG media name for size */
+
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
 
  /*
   * Range check input...
@@ -916,13 +926,30 @@ cupsGetDestMediaByIndex(
   * Copy the size over and return...
   */
 
-  if ((nsize = (cups_size_t *)cupsArrayIndex(dinfo->cached_db, n)) == NULL)
+  if ((nsize = (_cups_media_db_t *)cupsArrayIndex(dinfo->cached_db, n)) == NULL)
   {
     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
     return (0);
   }
 
-  memcpy(size, nsize, sizeof(cups_size_t));
+  if (nsize->size_name)
+    strlcpy(size->media, nsize->size_name, sizeof(size->media));
+  else if (nsize->key)
+    strlcpy(size->media, nsize->key, sizeof(size->media));
+  else if ((pwg = pwgMediaForSize(nsize->width, nsize->length)) != NULL)
+    strlcpy(size->media, pwg->pwg, sizeof(size->media));
+  else
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
+    return (0);
+  }
+
+  size->width  = nsize->width;
+  size->length = nsize->length;
+  size->bottom = nsize->bottom;
+  size->left   = nsize->left;
+  size->right  = nsize->right;
+  size->top    = nsize->top;
 
   return (1);
 }
@@ -945,7 +972,7 @@ cupsGetDestMediaByIndex(
  *
  * Returns 1 when there is a match and 0 if there is not a match.
  *
- * @since CUPS 1.6/OS X 10.8@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
 int                                    /* O - 1 on match, 0 on failure */
@@ -960,6 +987,13 @@ cupsGetDestMediaByName(
   pwg_media_t          *pwg;           /* PWG media info */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -1010,7 +1044,7 @@ cupsGetDestMediaByName(
  *
  * Returns 1 when there is a match and 0 if there is not a match.
  *
- * @since CUPS 1.6/OS X 10.8@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
 int                                    /* O - 1 on match, 0 on failure */
@@ -1028,6 +1062,13 @@ cupsGetDestMediaBySize(
   pwg_media_t          *pwg;           /* PWG media info */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -1069,7 +1110,7 @@ cupsGetDestMediaBySize(
  * counted.  For example, passing @code CUPS_MEDIA_FLAGS_BORDERLESS@ will return
  * the number of borderless sizes.
  *
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
  */
 
 int                                    /* O - Number of sizes */
@@ -1079,6 +1120,13 @@ cupsGetDestMediaCount(
     cups_dinfo_t *dinfo,               /* I - Destination information */
     unsigned     flags)                        /* I - Media flags */
 {
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -1110,7 +1158,7 @@ cupsGetDestMediaCount(
  * example, passing @code CUPS_MEDIA_FLAGS_BORDERLESS@ will return the default
  * borderless size, typically US Letter or A4, but sometimes 4x6 photo media.
  *
- * @since CUPS 1.7/OS X 10.9@
+ * @since CUPS 1.7/macOS 10.9@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -1124,6 +1172,13 @@ cupsGetDestMediaDefault(
   const char   *media;                 /* Default media size */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -1166,7 +1221,7 @@ cupsGetDestMediaDefault(
   * Fall back to the first matching media size...
   */
 
-  return (cupsGetDestMediaByIndex(http, dest, dinfo, flags, 0, size));
+  return (cupsGetDestMediaByIndex(http, dest, dinfo, 0, flags, size));
 }
 
 
@@ -1281,6 +1336,8 @@ cups_create_cached(http_t       *http,    /* I - Connection to destination */
                        *first;         /* First entry this size */
 
 
+  DEBUG_printf(("3cups_create_cached(http=%p, dinfo=%p, flags=%u)", (void *)http, (void *)dinfo, flags));
+
   if (dinfo->cached_db)
     cupsArrayDelete(dinfo->cached_db);
 
@@ -1289,11 +1346,15 @@ cups_create_cached(http_t       *http,  /* I - Connection to destination */
 
   if (flags & CUPS_MEDIA_FLAGS_READY)
   {
+    DEBUG_puts("4cups_create_cached: ready media");
+
     cups_update_ready(http, dinfo);
     db = dinfo->ready_db;
   }
   else
   {
+    DEBUG_puts("4cups_create_cached: supported media");
+
     if (!dinfo->media_db)
       cups_create_media_db(dinfo, CUPS_MEDIA_FLAGS_DEFAULT);
 
@@ -1304,26 +1365,40 @@ cups_create_cached(http_t       *http,  /* I - Connection to destination */
        mdb;
        mdb = (_cups_media_db_t *)cupsArrayNext(db))
   {
+    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));
+
     if (flags & CUPS_MEDIA_FLAGS_BORDERLESS)
     {
       if (!mdb->left && !mdb->right && !mdb->top && !mdb->bottom)
+      {
+        DEBUG_printf(("4cups_create_cached: add %p", (void *)mdb));
         cupsArrayAdd(dinfo->cached_db, mdb);
+      }
     }
     else if (flags & CUPS_MEDIA_FLAGS_DUPLEX)
     {
       if (first->width != mdb->width || first->length != mdb->length)
       {
+       DEBUG_printf(("4cups_create_cached: add %p", (void *)first));
         cupsArrayAdd(dinfo->cached_db, first);
         first = mdb;
       }
-      else if (mdb->left >= first->left && mdb->right >= first->right &&
-               mdb->top >= first->top && mdb->bottom >= first->bottom)
+      else if (mdb->left >= first->left && mdb->right >= first->right && mdb->top >= first->top && mdb->bottom >= first->bottom &&
+              (mdb->left != first->left || mdb->right != first->right || mdb->top != first->top || mdb->bottom != first->bottom))
         first = mdb;
     }
+    else
+    {
+      DEBUG_printf(("4cups_create_cached: add %p", (void *)mdb));
+      cupsArrayAdd(dinfo->cached_db, mdb);
+    }
   }
 
   if (flags & CUPS_MEDIA_FLAGS_DUPLEX)
+  {
+    DEBUG_printf(("4cups_create_cached: add %p", (void *)first));
     cupsArrayAdd(dinfo->cached_db, first);
+  }
 }
 
 
@@ -1757,8 +1832,7 @@ cups_get_media_db(http_t       *http,     /* I - Connection to destination */
       * Look for the smallest margins...
       */
 
-      if (best->left != 0 || best->right != 0 || best->top != 0 ||
-          best->bottom != 0)
+      if (best->left != 0 || best->right != 0 || best->top != 0 || best->bottom != 0)
       {
        for (mdb = (_cups_media_db_t *)cupsArrayNext(db);
             mdb && !cups_compare_media_db(mdb, &key);
@@ -1795,7 +1869,8 @@ cups_get_media_db(http_t       *http,     /* I - Connection to destination */
           mdb = (_cups_media_db_t *)cupsArrayNext(db))
       {
        if (mdb->left >= best->left && mdb->right >= best->right &&
-           mdb->top >= best->top && mdb->bottom >= best->bottom)
+           mdb->top >= best->top && mdb->bottom >= best->bottom &&
+           (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
          best = mdb;
       }
     }
@@ -1810,11 +1885,10 @@ cups_get_media_db(http_t       *http,   /* I - Connection to destination */
           mdb = (_cups_media_db_t *)cupsArrayNext(db))
       {
        if (((mdb->left > 0 && mdb->left <= best->left) || best->left == 0) &&
-           ((mdb->right > 0 && mdb->right <= best->right) ||
-            best->right == 0) &&
+           ((mdb->right > 0 && mdb->right <= best->right) || best->right == 0) &&
            ((mdb->top > 0 && mdb->top <= best->top) || best->top == 0) &&
-           ((mdb->bottom > 0 && mdb->bottom <= best->bottom) ||
-            best->bottom == 0))
+           ((mdb->bottom > 0 && mdb->bottom <= best->bottom) || best->bottom == 0) &&
+           (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
          best = mdb;
       }
     }
@@ -1892,7 +1966,8 @@ cups_get_media_db(http_t       *http,     /* I - Connection to destination */
             mdb = (_cups_media_db_t *)cupsArrayNext(db))
        {
          if (mdb->left <= best->left && mdb->right <= best->right &&
-             mdb->top <= best->top && mdb->bottom <= best->bottom)
+             mdb->top <= best->top && mdb->bottom <= best->bottom &&
+             (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
          {
            best = mdb;
            if (mdb->left == 0 && mdb->right == 0 && mdb->bottom == 0 &&
@@ -1913,7 +1988,8 @@ cups_get_media_db(http_t       *http,     /* I - Connection to destination */
           mdb = (_cups_media_db_t *)cupsArrayNext(db))
       {
        if (mdb->left >= best->left && mdb->right >= best->right &&
-           mdb->top >= best->top && mdb->bottom >= best->bottom)
+           mdb->top >= best->top && mdb->bottom >= best->bottom &&
+           (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
          best = mdb;
       }
     }
@@ -1932,7 +2008,8 @@ cups_get_media_db(http_t       *http,     /* I - Connection to destination */
             best->right == 0) &&
            ((mdb->top > 0 && mdb->top <= best->top) || best->top == 0) &&
            ((mdb->bottom > 0 && mdb->bottom <= best->bottom) ||
-            best->bottom == 0))
+            best->bottom == 0) &&
+           (mdb->bottom != best->bottom || mdb->left != best->left || mdb->right != best->right || mdb->top != best->top))
          best = mdb;
       }
     }
@@ -2246,9 +2323,7 @@ cups_update_ready(http_t       *http,     /* I - Connection to destination */
                dinfo->uri);
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
                NULL, cupsUser());
-  ippAddStrings(request, IPP_TAG_OPERATION,
-                IPP_TAG_KEYWORD | IPP_TAG_CUPS_CONST, "requested-attributes",
-                (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
+  ippAddStrings(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
 
   dinfo->ready_attrs = cupsDoRequest(http, request, dinfo->resource);
 
@@ -2264,8 +2339,3 @@ cups_update_ready(http_t       *http,     /* I - Connection to destination */
 
   dinfo->ready_time = time(NULL);
 }
-
-
-/*
- * End of "$Id$".
- */