]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/ppd.c
Update dependencies.
[thirdparty/cups.git] / cups / ppd.c
index 65dd5bb49daf0b12a454c0910c8fcf73b63abf5b..54740b896c311d1d2af5db59f53ccf4fa9ac817a 100644 (file)
@@ -1,25 +1,17 @@
+#define DEBUG
 /*
  * "$Id$"
  *
  *   PPD file routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ *   Copyright 2007 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products 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 missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
+ *   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/".
  *
  *   PostScript is a trademark of Adobe Systems, Inc.
  *
@@ -48,6 +40,8 @@
  *   ppd_add_choice()       - Add a choice to an option.
  *   ppd_add_size()         - Add a page size.
  *   ppd_compare_attrs()    - Compare two attributes.
+ *   ppd_compare_choices()  - Compare two choices...
+ *   ppd_compare_consts()   - Compare two constraints.
  *   ppd_compare_coptions() - Compare two custom options.
  *   ppd_compare_cparams()  - Compare two custom parameters.
  *   ppd_compare_options()  - Compare two options.
@@ -58,6 +52,7 @@
  *   ppd_get_cparam()       - Get a custom parameter record.
  *   ppd_get_group()        - Find or create the named group as needed.
  *   ppd_get_option()       - Find or create the named option as needed.
+ *   ppd_hash_option()      - Generate a hash of the option name...
  *   ppd_read()             - Read a line from a PPD file, skipping comment
  *                            lines as necessary.
  */
@@ -90,6 +85,8 @@
 #define PPD_TEXT       4               /* Line contained human-readable text */
 #define PPD_STRING     8               /* Line contained a string or code */
 
+#define PPD_HASHSIZE   512             /* Size of hash */
+
 
 /*
  * Local functions...
@@ -101,6 +98,8 @@ static ppd_attr_t    *ppd_add_attr(ppd_file_t *ppd, const char *name,
 static ppd_choice_t    *ppd_add_choice(ppd_option_t *option, const char *name);
 static ppd_size_t      *ppd_add_size(ppd_file_t *ppd, const char *name);
 static int             ppd_compare_attrs(ppd_attr_t *a, ppd_attr_t *b);
+static int             ppd_compare_choices(ppd_choice_t *a, ppd_choice_t *b);
+static int             ppd_compare_consts(ppd_const_t *a, ppd_const_t *b);
 static int             ppd_compare_coptions(ppd_coption_t *a,
                                             ppd_coption_t *b);
 static int             ppd_compare_cparams(ppd_cparam_t *a, ppd_cparam_t *b);
@@ -116,6 +115,7 @@ static ppd_group_t  *ppd_get_group(ppd_file_t *ppd, const char *name,
                                       const char *text, _cups_globals_t *cg,
                                       cups_encoding_t encoding);
 static ppd_option_t    *ppd_get_option(ppd_group_t *group, const char *name);
+static int             ppd_hash_option(ppd_option_t *option);
 static int             ppd_read(cups_file_t *fp, char *keyword, char *option,
                                 char *text, char **string, int ignoreblank,
                                 _cups_globals_t *cg);
@@ -184,6 +184,7 @@ ppdClose(ppd_file_t *ppd)           /* I - PPD file record */
   }
 
   cupsArrayDelete(ppd->options);
+  cupsArrayDelete(ppd->marked);
 
  /*
   * Free any page sizes...
@@ -819,17 +820,17 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
       strlcpy(profile->resolution, name, sizeof(profile->resolution));
       strlcpy(profile->media_type, text, sizeof(profile->media_type));
 
-      profile->density      = _cupsStrScand(string, &sptr, loc);
-      profile->gamma        = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[0][0] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[0][1] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[0][2] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[1][0] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[1][1] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[1][2] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[2][0] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[2][1] = _cupsStrScand(sptr, &sptr, loc);
-      profile->matrix[2][2] = _cupsStrScand(sptr, &sptr, loc);
+      profile->density      = (float)_cupsStrScand(string, &sptr, loc);
+      profile->gamma        = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[0][0] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[0][1] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[0][2] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[1][0] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[1][1] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[1][2] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[2][0] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[2][1] = (float)_cupsStrScand(sptr, &sptr, loc);
+      profile->matrix[2][2] = (float)_cupsStrScand(sptr, &sptr, loc);
     }
     else if (!strcmp(keyword, "cupsFilter"))
     {
@@ -928,8 +929,8 @@ ppdOpen2(cups_file_t *fp)           /* I - File to read from */
       if (!strcmp(ctype, "curve"))
       {
         cparam->type = PPD_CUSTOM_CURVE;
-       cparam->minimum.custom_curve = _cupsStrScand(cminimum, NULL, loc);
-       cparam->maximum.custom_curve = _cupsStrScand(cmaximum, NULL, loc);
+       cparam->minimum.custom_curve = (float)_cupsStrScand(cminimum, NULL, loc);
+       cparam->maximum.custom_curve = (float)_cupsStrScand(cmaximum, NULL, loc);
       }
       else if (!strcmp(ctype, "int"))
       {
@@ -940,8 +941,8 @@ ppdOpen2(cups_file_t *fp)           /* I - File to read from */
       else if (!strcmp(ctype, "invcurve"))
       {
         cparam->type = PPD_CUSTOM_INVCURVE;
-       cparam->minimum.custom_invcurve = _cupsStrScand(cminimum, NULL, loc);
-       cparam->maximum.custom_invcurve = _cupsStrScand(cmaximum, NULL, loc);
+       cparam->minimum.custom_invcurve = (float)_cupsStrScand(cminimum, NULL, loc);
+       cparam->maximum.custom_invcurve = (float)_cupsStrScand(cmaximum, NULL, loc);
       }
       else if (!strcmp(ctype, "passcode"))
       {
@@ -958,14 +959,14 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
       else if (!strcmp(ctype, "points"))
       {
         cparam->type = PPD_CUSTOM_POINTS;
-       cparam->minimum.custom_points = _cupsStrScand(cminimum, NULL, loc);
-       cparam->maximum.custom_points = _cupsStrScand(cmaximum, NULL, loc);
+       cparam->minimum.custom_points = (float)_cupsStrScand(cminimum, NULL, loc);
+       cparam->maximum.custom_points = (float)_cupsStrScand(cmaximum, NULL, loc);
       }
       else if (!strcmp(ctype, "real"))
       {
         cparam->type = PPD_CUSTOM_REAL;
-       cparam->minimum.custom_real = _cupsStrScand(cminimum, NULL, loc);
-       cparam->maximum.custom_real = _cupsStrScand(cmaximum, NULL, loc);
+       cparam->minimum.custom_real = (float)_cupsStrScand(cminimum, NULL, loc);
+       cparam->maximum.custom_real = (float)_cupsStrScand(cmaximum, NULL, loc);
       }
       else if (!strcmp(ctype, "string"))
       {
@@ -1001,9 +1002,9 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
     else if (!strcmp(keyword, "HWMargins"))
     {
       for (i = 0, sptr = string; i < 4; i ++)
-        ppd->custom_margins[i] = _cupsStrScand(sptr, &sptr, loc);
+        ppd->custom_margins[i] = (float)_cupsStrScand(sptr, &sptr, loc);
     }
-    else if (!strncmp(keyword, "Custom", 6) && !strcmp(name, "True"))
+    else if (!strncmp(keyword, "Custom", 6) && !strcmp(name, "True") && !option)
     {
       DEBUG_puts("Processing Custom option...");
 
@@ -1013,11 +1014,15 @@ ppdOpen2(cups_file_t *fp)               /* I - File to read from */
 
       if ((option = ppdFindOption(ppd, keyword + 6)) == NULL)
       {
+        int            groupidx = -1;  /* Index for current group */
        ppd_group_t     *gtemp;         /* Temporary group */
 
 
         DEBUG_printf(("%s option not found for %s...\n", keyword + 6, keyword));
 
+        if (group)
+          groupidx = group - ppd->groups; /* Save index for current group */
+
        if ((gtemp = ppd_get_group(ppd, "General", _("General"), cg,
                                   encoding)) == NULL)
        {
@@ -1026,6 +1031,9 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
          goto error;
        }
 
+        if (group)
+          group = ppd->groups + groupidx; /* Restore group pointer */
+
        if ((option = ppd_get_option(gtemp, keyword + 6)) == NULL)
        {
          DEBUG_printf(("Unable to get %s option!\n", keyword + 6));
@@ -1076,6 +1084,41 @@ ppdOpen2(cups_file_t *fp)                /* I - File to read from */
        */
 
        ppd_add_size(ppd, "Custom");
+
+       if ((option = ppdFindOption(ppd, "PageRegion")) == NULL)
+       {
+         int           groupidx = -1;  /* Index to current group */
+         ppd_group_t   *gtemp;         /* Temporary group */
+
+          if (group)
+            groupidx = group - ppd->groups; /* Save index for current group */
+
+         if ((gtemp = ppd_get_group(ppd, "General", _("General"), cg,
+                                    encoding)) == NULL)
+         {
+           DEBUG_puts("Unable to get general group!");
+
+           goto error;
+         }
+
+          if (group)
+            group = ppd->groups + groupidx; /* Restore group pointer */
+
+         option = ppd_get_option(gtemp, "PageRegion");
+        }
+
+       if ((choice = ppd_add_choice(option, "Custom")) == NULL)
+       {
+         DEBUG_puts("Unable to add Custom choice!");
+
+         cg->ppd_status = PPD_ALLOC_ERROR;
+
+         goto error;
+       }
+
+       strlcpy(choice->text, text[0] ? text : _("Custom"),
+               sizeof(choice->text));
+        option = NULL;
       }
     }
     else if (!strcmp(keyword, "LandscapeOrientation"))
@@ -1171,6 +1214,8 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
       * Add an option record to the current sub-group, group, or file...
       */
 
+      printf("name=\"%s\" (%d)\n", name, strlen(name));
+
       if (name[0] == '*')
         _cups_strcpy(name, name + 1); /* Eliminate leading asterisk */
 
@@ -1400,7 +1445,7 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
     else if (!strcmp(keyword, "OrderDependency") ||
              !strcmp(keyword, "NonUIOrderDependency"))
     {
-      order = _cupsStrScand(string, &sptr, loc);
+      order = (float)_cupsStrScand(string, &sptr, loc);
 
       if (!sptr || sscanf(sptr, "%40s%40s", name, keyword) != 2)
       {
@@ -1523,10 +1568,10 @@ ppdOpen2(cups_file_t *fp)               /* I - File to read from */
              !strcmp(keyword, "NonUIConstraints"))
     {
       if (ppd->num_consts == 0)
-       constraint = calloc(1, sizeof(ppd_const_t));
+       constraint = calloc(2, sizeof(ppd_const_t));
       else
        constraint = realloc(ppd->consts,
-                            (ppd->num_consts + 1) * sizeof(ppd_const_t));
+                            (ppd->num_consts + 2) * sizeof(ppd_const_t));
 
       if (constraint == NULL)
       {
@@ -1687,6 +1732,56 @@ ppdOpen2(cups_file_t *fp)                /* I - File to read from */
            break;
       }
 
+     /*
+      * For CustomPageSize and InputSlot/ManualFeed, create a duplicate
+      * constraint for PageRegion...
+      */
+
+      if (!strcasecmp(constraint->option1, "CustomPageSize") &&
+          (!strcasecmp(constraint->option2, "InputSlot") ||
+          !strcasecmp(constraint->option2, "ManualFeed")))
+      {
+        ppd->num_consts ++;
+
+        strcpy(constraint[1].option1, "PageRegion");
+       strcpy(constraint[1].choice1, "Custom");
+       strcpy(constraint[1].option2, constraint->option2);
+       strcpy(constraint[1].choice2, constraint->choice2);
+      }
+      else if (!strcasecmp(constraint->option2, "CustomPageSize") &&
+               (!strcasecmp(constraint->option1, "InputSlot") ||
+               !strcasecmp(constraint->option1, "ManualFeed")))
+      {
+        ppd->num_consts ++;
+
+       strcpy(constraint[1].option1, constraint->option1);
+       strcpy(constraint[1].choice1, constraint->choice1);
+        strcpy(constraint[1].option2, "PageRegion");
+       strcpy(constraint[1].choice2, "Custom");
+      }
+
+     /*
+      * Handle CustomFoo option constraints...
+      */
+
+      if (!strncasecmp(constraint->option1, "Custom", 6) &&
+          !strcasecmp(constraint->choice1, "True"))
+      {
+        _cups_strcpy(constraint->option1, constraint->option1 + 6);
+       strcpy(constraint->choice1, "Custom");
+      }
+
+      if (!strncasecmp(constraint->option2, "Custom", 6) &&
+          !strcasecmp(constraint->choice2, "True"))
+      {
+        _cups_strcpy(constraint->option2, constraint->option2 + 6);
+       strcpy(constraint->choice2, "Custom");
+      }
+
+     /*
+      * Don't add this one as an attribute...
+      */
+
       ppd_free(string);
       string = NULL;
     }
@@ -1706,8 +1801,8 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
        goto error;
       }
 
-      size->width  = _cupsStrScand(string, &sptr, loc);
-      size->length = _cupsStrScand(sptr, NULL, loc);
+      size->width  = (float)_cupsStrScand(string, &sptr, loc);
+      size->length = (float)_cupsStrScand(sptr, NULL, loc);
 
       ppd_free(string);
       string = NULL;
@@ -1728,10 +1823,10 @@ ppdOpen2(cups_file_t *fp)               /* I - File to read from */
        goto error;
       }
 
-      size->left   = _cupsStrScand(string, &sptr, loc);
-      size->bottom = _cupsStrScand(sptr, &sptr, loc);
-      size->right  = _cupsStrScand(sptr, &sptr, loc);
-      size->top    = _cupsStrScand(sptr, NULL, loc);
+      size->left   = (float)_cupsStrScand(string, &sptr, loc);
+      size->bottom = (float)_cupsStrScand(sptr, &sptr, loc);
+      size->right  = (float)_cupsStrScand(sptr, &sptr, loc);
+      size->top    = (float)_cupsStrScand(sptr, NULL, loc);
 
       ppd_free(string);
       string = NULL;
@@ -1794,8 +1889,8 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
   cupsLangFree(language);
 
 #ifdef DEBUG
-  if (!feof(fp))
-    printf("Premature EOF at %lu...\n", (unsigned long)ftell(fp));
+  if (!cupsFileEOF(fp))
+    printf("Premature EOF at %lu...\n", (unsigned long)cupsFileTell(fp));
 #endif /* DEBUG */
 
   if (cg->ppd_status != PPD_OK)
@@ -1814,7 +1909,9 @@ ppdOpen2(cups_file_t *fp)         /* I - File to read from */
   * each choice and custom option...
   */
 
-  ppd->options = cupsArrayNew((cups_array_func_t)ppd_compare_options, NULL);
+  ppd->options = cupsArrayNew2((cups_array_func_t)ppd_compare_options, NULL,
+                               (cups_ahash_func_t)ppd_hash_option,
+                              PPD_HASHSIZE);
 
   for (i = ppd->num_groups, group = ppd->groups;
        i > 0;
@@ -1837,6 +1934,20 @@ ppdOpen2(cups_file_t *fp)                /* I - File to read from */
     }
   }
 
+ /*
+  * Sort the constraints...
+  */
+
+  if (ppd->num_consts > 1)
+    qsort(ppd->consts, ppd->num_consts, sizeof(ppd_const_t),
+          (int (*)(const void *, const void *))ppd_compare_consts);
+
+ /*
+  * Create an array to track the marked choices...
+  */
+
+  ppd->marked = cupsArrayNew((cups_array_func_t)ppd_compare_choices, NULL);
+
  /*
   * Return the PPD file structure...
   */
@@ -2130,6 +2241,40 @@ ppd_compare_attrs(ppd_attr_t *a, /* I - First attribute */
 }
 
 
+/*
+ * 'ppd_compare_choices()' - Compare two choices...
+ */
+
+static int                             /* O - Result of comparison */
+ppd_compare_choices(ppd_choice_t *a,   /* I - First choice */
+                    ppd_choice_t *b)   /* I - Second choice */
+{
+  return (a->option - b->option);
+}
+
+
+/*
+ * 'ppd_compare_consts()' - Compare two constraints.
+ */
+
+static int                             /* O - Result of comparison */
+ppd_compare_consts(ppd_const_t *a,     /* I - First constraint */
+                   ppd_const_t *b)     /* I - Second constraint */
+{
+  int  ret;                            /* Result of comparison */
+
+
+  if ((ret = strcmp(a->option1, b->option1)) != 0)
+    return (ret);
+  else if ((ret = strcmp(a->choice1, b->choice1)) != 0)
+    return (ret);
+  else if ((ret = strcmp(a->option2, b->option2)) != 0)
+    return (ret);
+  else
+    return (strcmp(a->choice2, b->choice2));
+}
+
+
 /*
  * 'ppd_compare_coptions()' - Compare two custom options.
  */
@@ -2348,7 +2493,7 @@ ppd_get_cparam(ppd_coption_t *opt,        /* I - PPD file */
     return (NULL);
 
   strlcpy(cparam->name, param, sizeof(cparam->name));
-  strlcpy(cparam->text, text, sizeof(cparam->text));
+  strlcpy(cparam->text, text[0] ? text : param, sizeof(cparam->text));
 
  /*
   * Add this record to the array...
@@ -2467,6 +2612,24 @@ ppd_get_option(ppd_group_t *group,       /* I - Group */
 }
 
 
+/*
+ * 'ppd_hash_option()' - Generate a hash of the option name...
+ */
+
+static int                             /* O - Hash index */
+ppd_hash_option(ppd_option_t *option)  /* I - Option */
+{
+  int          hash = 0;               /* Hash index */
+  const char   *k;                     /* Pointer into keyword */
+
+
+  for (hash = option->keyword[0], k = option->keyword + 1; *k;)
+    hash = 33 * hash + *k++;
+
+  return (hash & 511);
+}
+
+
 /*
  * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
  *                necessary.
@@ -2775,7 +2938,7 @@ ppd_read(cups_file_t    *fp,              /* I - File to read from */
 
     *lineptr = '\0';
 
-    DEBUG_printf(("LINE = \"%s\"\n", line));
+/*    DEBUG_printf(("LINE = \"%s\"\n", line));*/
 
    /*
     * The dynamically created PPDs for older style Mac OS X