]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/pwg-media.c
Full sweep of all Clang warnings, plus some bug fixes for incorrect memcpy usage.
[thirdparty/cups.git] / cups / pwg-media.c
index 1272e761786ccb47227ca7bfe12125392700697a..ca0ed8fc514e0263413321f54ac1557974c6b7cd 100644 (file)
@@ -1,34 +1,17 @@
 /*
  * "$Id$"
  *
- *   PWG media name API implementation for CUPS.
+ * PWG media name API implementation for CUPS.
  *
- *   Copyright 2009-2013 by Apple Inc.
+ * Copyright 2009-2014 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/".
+ * 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:
- *
- *   pwgFormatSizeName()      - Generate a PWG self-describing media size name.
- *   pwgInitSize()           - Initialize a pwg_size_t structure using IPP Job
- *                             Template attributes.
- *   pwgMediaForLegacy()      - Find a PWG media size by ISO/IPP legacy name.
- *   pwgMediaForPPD()        - Find a PWG media size by Adobe PPD name.
- *   pwgMediaForPWG()        - Find a PWG media size by 5101.1 self-describing
- *                             name.
- *   pwgMediaForSize()       - Get the PWG media size for the given
- *                             dimensions.
- *   pwg_compare_legacy()     - Compare two sizes using the legacy names.
- *   pwg_compare_ppd()       - Compare two sizes using the PPD names.
- *   pwg_compare_pwg()       - Compare two sizes using the PWG names.
- *   pwg_format_inches()      - Convert and format PWG units as inches.
- *   pwg_format_millimeters() - Convert and format PWG units as millimeters.
+ * This file is subject to the Apple OS-Developed Software exception.
  */
 
 /*
@@ -56,6 +39,8 @@ static int    pwg_compare_pwg(pwg_media_t *a, pwg_media_t *b);
 static int     pwg_compare_ppd(pwg_media_t *a, pwg_media_t *b);
 static char    *pwg_format_inches(char *buf, size_t bufsize, int val);
 static char    *pwg_format_millimeters(char *buf, size_t bufsize, int val);
+static int     pwg_scan_measurement(const char *buf, char **bufptr, int numer,
+                                    int denom);
 
 
 /*
@@ -230,13 +215,11 @@ static pwg_media_t const cups_pwg_media[] =
   _PWG_MEDIA_MM("prc_4_110x208mm", NULL, "EnvPRC4", 110, 208),
   _PWG_MEDIA_MM("prc_8_120x309mm", NULL, "EnvPRC8", 120, 309),
   _PWG_MEDIA_MM("prc_6_120x320mm", NULL, NULL, 120, 320),
-  _PWG_MEDIA_MM("prc_3_125x176mm", NULL, "EnvPRC3", 125, 176),
   _PWG_MEDIA_MM("prc_16k_146x215mm", NULL, "PRC16K", 146, 215),
   _PWG_MEDIA_MM("prc_7_160x230mm", NULL, "EnvPRC7", 160, 230),
   _PWG_MEDIA_MM("om_juuro-ku-kai_198x275mm", NULL, NULL, 198, 275),
   _PWG_MEDIA_MM("om_pa-kai_267x389mm", NULL, NULL, 267, 389),
   _PWG_MEDIA_MM("om_dai-pa-kai_275x395mm", NULL, NULL, 275, 395),
-  _PWG_MEDIA_MM("prc_10_324x458mm", NULL, "EnvPRC10", 324, 458),
 
   /* Chinese Standard Sheet Media Inch Sizes */
   _PWG_MEDIA_IN("roc_16k_7.75x10.75in", NULL, "roc16k", 7.75, 10.75),
@@ -248,7 +231,6 @@ static pwg_media_t const cups_pwg_media[] =
   /* Other Metric Standard Sheet Media Sizes */
   _PWG_MEDIA_MM("om_small-photo_100x150mm", NULL, "om_small-photo", 100, 150),
   _PWG_MEDIA_MM("om_italian_110x230mm", NULL, "EnvItalian", 110, 230),
-  _PWG_MEDIA_MM("om_postfix_114x229mm", NULL, NULL, 114, 229),
   _PWG_MEDIA_MM("om_large-photo_200x300", NULL, "om_large-photo", 200, 300),
   _PWG_MEDIA_MM("om_folio_210x330mm", "folio", "Folio", 210, 330),
   _PWG_MEDIA_MM("om_folio-sp_215x315mm", NULL, "FolioSP", 215, 315),
@@ -275,7 +257,7 @@ static pwg_media_t const cups_pwg_media[] =
  * units string is @code NULL@, otherwise inches ("in") or millimeters ("mm")
  * are used.
  *
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -375,10 +357,10 @@ pwgFormatSizeName(char       *keyword,    /* I - Keyword buffer */
   */
 
   uptr = usize;
-  (*format)(uptr, sizeof(usize) - (uptr - usize), width);
+  (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), width);
   uptr += strlen(uptr);
   *uptr++ = 'x';
-  (*format)(uptr, sizeof(usize) - (uptr - usize), length);
+  (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), length);
   uptr += strlen(uptr);
 
  /*
@@ -414,7 +396,7 @@ void _pwgGenerateSize(char *keyword, size_t keysize, const char *prefix,
  * member attribute was specified in the "media-col" Job Template attribute,
  * otherwise it is initialized to 0.
  *
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
  */
 
 int                                    /* O - 1 if size was initialized, 0 otherwise */
@@ -589,7 +571,7 @@ int _pwgInitSize(pwg_size_t *size, ipp_t *job, int *margins_set)
  * The "name" argument specifies the legacy ISO media size name, for example
  * "iso-a4" or "na-letter".
  *
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
  */
 
 pwg_media_t *                          /* O - Matching size or NULL */
@@ -651,7 +633,7 @@ pwg_media_t *_pwgMediaForLegacy(const char *legacy)
  * thread.  Custom names can be of the form "Custom.WIDTHxLENGTH[units]" or
  * "WIDTHxLENGTH[units]".
  *
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
  */
 
 pwg_media_t *                          /* O - Matching size or NULL */
@@ -706,72 +688,96 @@ pwgMediaForPPD(const char *ppd)           /* I - PPD size name */
     *   [Custom.]WIDTHxLENGTHpt[.FullBleed]  - Size in points [borderless]
     */
 
-    double             w, l,           /* Width and length of page */
-                       factor;         /* Unit scaling factor */
+    int                        w, l,           /* Width and length of page */
+                       numer,          /* Unit scaling factor */
+                       denom;          /* ... */
     char               *ptr;           /* Pointer into name */
-    struct lconv       *loc;           /* Locale data */
+    const char         *units;         /* Pointer to units */
     int                        custom;         /* Custom page size? */
 
+
     if (!_cups_strncasecmp(ppd, "Custom.", 7))
     {
       custom = 1;
-      factor = 2540.0 / 72.0;
+      numer  = 2540;
+      denom  = 72;
       ptr    = (char *)ppd + 7;
     }
     else
     {
       custom = 0;
-      factor = 2540.0;
+      numer  = 2540;
+      denom  = 1;
       ptr    = (char *)ppd;
     }
 
-    loc = localeconv();
-    w   = _cupsStrScand(ptr, &ptr, loc);
+   /*
+    * Find any units in the size...
+    */
 
-    if (ptr && ptr > ppd && *ptr == 'x')
+    units = strchr(ptr, '.');
+    while (units && isdigit(units[1] & 255))
+      units = strchr(units + 1, '.');
+
+    if (units)
+      units -= 2;
+    else
+      units = ptr + strlen(ptr) - 2;
+
+    if (units > ptr)
     {
-      l = _cupsStrScand(ptr + 1, &ptr, loc);
-
-      if (ptr &&
-         (!*ptr ||
-          !_cups_strcasecmp(ptr, "FullBleed") ||
-          !_cups_strcasecmp(ptr, ".FullBleed") ||
-          !_cups_strcasecmp(ptr, "cm") ||
-          !_cups_strcasecmp(ptr, "cm.FullBleed") ||
-          !_cups_strcasecmp(ptr, "ft") ||
-          !_cups_strcasecmp(ptr, "ft.FullBleed") ||
-          !_cups_strcasecmp(ptr, "in") ||
-          !_cups_strcasecmp(ptr, "in.FullBleed") ||
-          !_cups_strcasecmp(ptr, "m") ||
-          !_cups_strcasecmp(ptr, "m.FullBleed") ||
-          !_cups_strcasecmp(ptr, "mm") ||
-          !_cups_strcasecmp(ptr, "mm.FullBleed") ||
-          !_cups_strcasecmp(ptr, "pt") ||
-          !_cups_strcasecmp(ptr, "pt.FullBleed")))
+      if (isdigit(*units & 255) || *units == '.')
+        units ++;
+
+      if (!_cups_strncasecmp(units, "cm", 2))
+      {
+        numer = 1000;
+        denom = 1;
+      }
+      else if (!_cups_strncasecmp(units, "ft", 2))
+      {
+        numer = 2540 * 12;
+        denom = 1;
+      }
+      else if (!_cups_strncasecmp(units, "in", 2))
+      {
+       numer = 2540;
+        denom = 1;
+      }
+      else if (!_cups_strncasecmp(units, "mm", 2))
+      {
+        numer = 100;
+        denom = 1;
+      }
+      else if (*units == 'm' || *units == 'M')
       {
-       size = &(cg->pwg_media);
-
-       if (!_cups_strncasecmp(ptr, "cm", 2))
-         factor = 1000.0;
-       else if (!_cups_strncasecmp(ptr, "ft", 2))
-         factor = 2540.0 * 12.0;
-       else if (!_cups_strncasecmp(ptr, "in", 2))
-         factor = 2540.0;
-       else if (!_cups_strncasecmp(ptr, "mm", 2))
-         factor = 100.0;
-       else if (*ptr == 'm' || *ptr == 'M')
-         factor = 100000.0;
-       else if (!_cups_strncasecmp(ptr, "pt", 2))
-         factor = 2540.0 / 72.0;
+       numer = 100000;
+        denom = 1;
+      }
+      else if (!_cups_strncasecmp(units, "pt", 2))
+      {
+       numer = 2540;
+       denom = 72;
+      }
+    }
+
+    w = pwg_scan_measurement(ptr, &ptr, numer, denom);
 
+    if (ptr && ptr > ppd && *ptr == 'x')
+    {
+      l = pwg_scan_measurement(ptr + 1, &ptr, numer, denom);
+
+      if (ptr)
+      {
        /*
        * Not a standard size; convert it to a PWG custom name of the form:
        *
        *     [oe|om]_WIDTHxHEIGHTuu_WIDTHxHEIGHTuu
        */
 
-       size->width  = (int)(w * factor);
-       size->length = (int)(l * factor);
+       size         = &(cg->pwg_media);
+       size->width  = w;
+       size->length = l;
        size->pwg    = cg->pwg_name;
 
        pwgFormatSizeName(cg->pwg_name, sizeof(cg->pwg_name),
@@ -799,7 +805,7 @@ pwg_media_t *_pwgMediaForPPD(const char *ppd)
  * thread-local storage and is overwritten by each call to the function in the
  * thread.
  *
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
  */
 
 pwg_media_t *                          /* O - Matching size or NULL */
@@ -851,31 +857,29 @@ pwgMediaForPWG(const char *pwg)           /* I - PWG size name */
     * class_name_WWWxHHHmm
     */
 
-    double             w, l;           /* Width and length of page */
-    struct lconv       *loc;           /* Locale data */
+    int                w, l;                   /* Width and length of page */
+    int                numer;                  /* Scale factor for units */
+    const char *units = ptr + strlen(ptr) - 2;
+                                       /* Units from size */
 
     ptr ++;
-    loc = localeconv();
-    w   = _cupsStrScand(ptr, &ptr, loc);
+
+    if (units >= ptr && !strcmp(units, "in"))
+      numer = 2540;
+    else
+      numer = 100;
+
+    w = pwg_scan_measurement(ptr, &ptr, numer, 1);
 
     if (ptr && *ptr == 'x')
     {
-      l = _cupsStrScand(ptr + 1, &ptr, loc);
+      l = pwg_scan_measurement(ptr + 1, &ptr, numer, 1);
 
-      if (ptr && (!strcmp(ptr, "in") || !strcmp(ptr, "mm")))
+      if (ptr)
       {
-       size = &(cg->pwg_media);
-
-       if (!strcmp(ptr, "mm"))
-       {
-         size->width  = (int)(w * 100 + 0.5);
-         size->length = (int)(l * 100 + 0.5);
-       }
-       else
-       {
-         size->width  = (int)(w * 2540 + 0.5);
-         size->length = (int)(l * 2540 + 0.5);
-       }
+        size         = &(cg->pwg_media);
+        size->width  = w;
+        size->length = l;
 
         strlcpy(cg->pwg_name, pwg, sizeof(cg->pwg_name));
        size->pwg = cg->pwg_name;
@@ -901,7 +905,7 @@ pwg_media_t *_pwgMediaForPWG(const char *pwg)
  * thread-local storage and is overwritten by each call to the function in the
  * thread.
  *
- * @since CUPS 1.7@
+ * @since CUPS 1.7/OS X 10.9@
  */
 
 pwg_media_t *                          /* O - PWG media name */
@@ -978,6 +982,19 @@ pwg_media_t *_pwgMediaForSize(int width, int length)
 { return (pwgMediaForSize(width, length)); }
 
 
+/*
+ * '_pwgMediaTable()' - Return the internal media size table.
+ */
+
+const pwg_media_t *                    /* O - Pointer to first entry */
+_pwgMediaTable(size_t *num_media)      /* O - Number of entries */
+{
+  *num_media = sizeof(cups_pwg_media) / sizeof(cups_pwg_media[0]);
+
+  return (cups_pwg_media);
+}
+
+
 /*
  * 'pwg_compare_legacy()' - Compare two sizes using the legacy names.
  */
@@ -1091,6 +1108,63 @@ pwg_format_millimeters(char   *buf,      /* I - Buffer */
 }
 
 
+/*
+ * 'pwg_scan_measurement()' - Scan a measurement in inches or millimeters.
+ *
+ * The "factor" argument specifies the scale factor for the units to convert to
+ * hundredths of millimeters.  The returned value is NOT rounded but is an
+ * exact conversion of the fraction value (no floating point is used).
+ */
+
+static int                             /* O - Hundredths of millimeters */
+pwg_scan_measurement(
+    const char *buf,                   /* I - Number string */
+    char       **bufptr,               /* O - First byte after the number */
+    int        numer,                  /* I - Numerator from units */
+    int        denom)                  /* I - Denominator from units */
+{
+  int  value = 0,                      /* Measurement value */
+       fractional = 0,                 /* Fractional value */
+       divisor = 1,                    /* Fractional divisor */
+       digits = 10 * numer * denom;    /* Maximum fractional value to read */
+
+
+ /*
+  * Scan integer portion...
+  */
+
+  while (*buf >= '0' && *buf <= '9')
+    value = value * 10 + (*buf++) - '0';
+
+  if (*buf == '.')
+  {
+   /*
+    * Scan fractional portion...
+    */
+
+    buf ++;
+
+    while (divisor < digits && *buf >= '0' && *buf <= '9')
+    {
+      fractional = fractional * 10 + (*buf++) - '0';
+      divisor *= 10;
+    }
+
+   /*
+    * Skip trailing digits that won't contribute...
+    */
+
+    while (*buf >= '0' && *buf <= '9')
+      buf ++;
+  }
+
+  if (bufptr)
+    *bufptr = (char *)buf;
+
+  return (value * numer / denom + fractional * numer / denom / divisor);
+}
+
+
 /*
  * End of "$Id$".
  */