]> Pileus Git - ~andy/gtk/blobdiff - modules/printbackends/cups/gtkprintbackendcups.c
Replace a lot of idle and timeout calls by the new gdk_threads api.
[~andy/gtk] / modules / printbackends / cups / gtkprintbackendcups.c
index a9eb39a12bfe77d6470c48ddbe19d7437807f609..5aab327f47f02c4ce39b76e7e938d5db39c22d58 100644 (file)
@@ -47,6 +47,7 @@
 #include "gtkprintercups.h"
 
 #include "gtkcupsutils.h"
+#include "gtkdebug.h"
 
 
 typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass;
@@ -147,16 +148,15 @@ static void                 cups_begin_polling_info                (GtkPrintBack
 static gboolean             cups_job_info_poll_timeout             (gpointer                           user_data);
 static void                 gtk_print_backend_cups_print_stream    (GtkPrintBackend                   *backend,
                                                                    GtkPrintJob                       *job,
-                                                                   gint                               data_fd,
+                                                                   GIOChannel                        *data_io,
                                                                    GtkPrintJobCompleteFunc            callback,
                                                                    gpointer                           user_data,
-                                                                   GDestroyNotify                     dnotify,
-                                                                   GError                           **error);
+                                                                   GDestroyNotify                     dnotify);
 static cairo_surface_t *    cups_printer_create_cairo_surface      (GtkPrinter                        *printer,
                                                                    GtkPrintSettings                  *settings,
                                                                    gdouble                            width,
                                                                    gdouble                            height,
-                                                                   gint                               cache_fd);
+                                                                   GIOChannel                        *cache_io);
 
 
 static void
@@ -184,6 +184,9 @@ gtk_print_backend_cups_register_type (GTypeModule *module)
 G_MODULE_EXPORT void 
 pb_module_init (GTypeModule *module)
 {
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: Initializing the CUPS print backend module\n")); 
+
   gtk_print_backend_cups_register_type (module);
   gtk_printer_cups_register_type (module);
 }
@@ -221,6 +224,9 @@ gtk_print_backend_cups_get_type (void)
 GtkPrintBackend *
 gtk_print_backend_cups_new (void)
 {
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: Creating a new CUPS print backend object\n"));
+
   return g_object_new (GTK_TYPE_PRINT_BACKEND_CUPS, NULL);
 }
 
@@ -253,21 +259,31 @@ _cairo_write_to_cups (void                *closure,
                       const unsigned char *data,
                       unsigned int         length)
 {
-  gint fd = GPOINTER_TO_INT (closure);
-  gssize written;
-  
+  GIOChannel *io = (GIOChannel *)closure;
+  gsize written;
+  GError *error;
+
+  error = NULL;
+
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: Writting %i byte chunk to temp file\n", length));
+
   while (length > 0) 
     {
-      written = write (fd, data, length);
+      g_io_channel_write_chars (io, data, length, &written, &error);
 
-      if (written == -1)
+      if (error != NULL)
        {
-         if (errno == EAGAIN || errno == EINTR)
-           continue;
-         
+         GTK_NOTE (PRINTING,
+                    g_print ("CUPS Backend: Error writting to temp file, %s\n", error->message));
+
+          g_error_free (error);
          return CAIRO_STATUS_WRITE_ERROR;
        }    
 
+      GTK_NOTE (PRINTING,
+                g_print ("CUPS Backend: Wrote %i bytes to temp file\n", written));
+
       data += written;
       length -= written;
     }
@@ -280,13 +296,13 @@ cups_printer_create_cairo_surface (GtkPrinter       *printer,
                                   GtkPrintSettings *settings,
                                   gdouble           width, 
                                   gdouble           height,
-                                  gint              cache_fd)
+                                  GIOChannel       *cache_io)
 {
   cairo_surface_t *surface; 
  
   /* TODO: check if it is a ps or pdf printer */
   
-  surface = cairo_ps_surface_create_for_stream  (_cairo_write_to_cups, GINT_TO_POINTER (cache_fd), width, height);
+  surface = cairo_ps_surface_create_for_stream  (_cairo_write_to_cups, cache_io, width, height);
 
   /* TODO: DPI from settings object? */
   cairo_surface_set_fallback_resolution (surface, 300, 300);
@@ -304,6 +320,9 @@ typedef struct {
 static void
 cups_free_print_stream_data (CupsPrintStreamData *data)
 {
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
   if (data->dnotify)
     data->dnotify (data->user_data);
   g_object_unref (data->job);
@@ -318,6 +337,9 @@ cups_print_cb (GtkPrintBackendCups *print_backend,
   GError *error = NULL;
   CupsPrintStreamData *ps = user_data;
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC)); 
+
   if (gtk_cups_result_is_error (result))
     error = g_error_new_literal (gtk_print_error_quark (),
                                  GTK_PRINT_ERROR_INTERNAL_ERROR,
@@ -373,11 +395,10 @@ add_cups_options (const gchar *key,
 static void
 gtk_print_backend_cups_print_stream (GtkPrintBackend         *print_backend,
                                      GtkPrintJob             *job,
-                                    gint                     data_fd,
+                                    GIOChannel              *data_io,
                                     GtkPrintJobCompleteFunc  callback,
                                     gpointer                 user_data,
-                                    GDestroyNotify           dnotify,
-                                    GError                 **error)
+                                    GDestroyNotify           dnotify)
 {
   GtkPrinterCups *cups_printer;
   CupsPrintStreamData *ps;
@@ -385,13 +406,16 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend         *print_backend,
   GtkPrintSettings *settings;
   const gchar *title;
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));   
+
   cups_printer = GTK_PRINTER_CUPS (gtk_print_job_get_printer (job));
   settings = gtk_print_job_get_settings (job);
 
   request = gtk_cups_request_new (NULL,
                                   GTK_CUPS_POST,
                                   IPP_PRINT_JOB,
-                                 data_fd,
+                                 data_io,
                                  NULL,
                                  cups_printer->device_uri);
 
@@ -425,7 +449,8 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend         *print_backend,
 static void
 gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
 {
-  backend_cups->list_printers_poll = 0;  
+  backend_cups->list_printers_poll = FALSE;  
+  backend_cups->got_default_printer = FALSE;  
   backend_cups->list_printers_pending = FALSE;
 
   cups_request_default_printer (backend_cups);
@@ -435,6 +460,9 @@ static void
 gtk_print_backend_cups_finalize (GObject *object)
 {
   GtkPrintBackendCups *backend_cups;
+  
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: finalizing CUPS backend module\n"));
 
   backend_cups = GTK_PRINT_BACKEND_CUPS (object);
 
@@ -449,6 +477,9 @@ gtk_print_backend_cups_dispose (GObject *object)
 {
   GtkPrintBackendCups *backend_cups;
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
   backend_cups = GTK_PRINT_BACKEND_CUPS (object);
 
   if (backend_cups->list_printers_poll > 0)
@@ -466,6 +497,9 @@ cups_dispatch_watch_check (GSource *source)
   GtkCupsPollState poll_state;
   gboolean result;
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source)); 
+
   dispatch = (GtkPrintCupsDispatchWatch *) source;
 
   poll_state = gtk_cups_request_get_poll_state (dispatch->request);
@@ -514,7 +548,10 @@ cups_dispatch_watch_prepare (GSource *source,
   GtkPrintCupsDispatchWatch *dispatch;
 
   dispatch = (GtkPrintCupsDispatchWatch *) source;
+
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source));
+
   *timeout_ = -1;
   
   return gtk_cups_request_read_write (dispatch->request);
@@ -537,8 +574,11 @@ cups_dispatch_watch_dispatch (GSource     *source,
 
   result = gtk_cups_request_get_result (dispatch->request);
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source));
+
   if (gtk_cups_result_is_error (result))
-    g_warning (gtk_cups_result_get_error_string (result));
+    g_warning ("Error result: %s", gtk_cups_result_get_error_string (result));
 
   ep_callback (GTK_PRINT_BACKEND (dispatch->backend), result, user_data);
 
@@ -550,6 +590,9 @@ cups_dispatch_watch_finalize (GSource *source)
 {
   GtkPrintCupsDispatchWatch *dispatch;
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s <source %p>\n", G_STRFUNC, source));
+
   dispatch = (GtkPrintCupsDispatchWatch *) source;
 
   gtk_cups_request_free (dispatch->request);
@@ -593,6 +636,9 @@ cups_request_execute (GtkPrintBackendCups              *print_backend,
   dispatch = (GtkPrintCupsDispatchWatch *) g_source_new (&_cups_dispatch_watch_funcs, 
                                                          sizeof (GtkPrintCupsDispatchWatch));
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s <source %p> - Executing cups request on server '%s' and resource '%s'\n", G_STRFUNC, dispatch, request->server, request->resource));
+
   dispatch->request = request;
   dispatch->backend = g_object_ref (print_backend);
   dispatch->data_poll = NULL;
@@ -625,8 +671,15 @@ cups_request_printer_info_cb (GtkPrintBackendCups *backend,
   printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (backend),
                                            printer_name);
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s - Got printer info for printer '%s'\n", G_STRFUNC, printer_name));
+
   if (!printer)
-    return;
+    {
+      GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: Could not find printer called '%s'\n", printer_name));
+      return;
+    }
 
   cups_printer = GTK_PRINTER_CUPS (printer);
   
@@ -692,7 +745,7 @@ cups_request_printer_info (GtkPrintBackendCups *print_backend,
   request = gtk_cups_request_new (NULL,
                                   GTK_CUPS_POST,
                                   IPP_GET_PRINTER_ATTRIBUTES,
-                                 0,
+                                 NULL,
                                  NULL,
                                  NULL);
 
@@ -701,6 +754,9 @@ cups_request_printer_info (GtkPrintBackendCups *print_backend,
   gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI,
                                    "printer-uri", NULL, printer_uri);
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s - Requesting printer info for URI '%s'\n", G_STRFUNC, printer_uri));
+
   g_free (printer_uri);
 
   gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
@@ -823,7 +879,7 @@ cups_request_job_info (CupsJobPollData *data)
   request = gtk_cups_request_new (NULL,
                                   GTK_CUPS_POST,
                                   IPP_GET_JOB_ATTRIBUTES,
-                                 0,
+                                 NULL,
                                  NULL,
                                  NULL);
 
@@ -902,12 +958,16 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
 
   list_has_changed = FALSE;
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
   cups_backend->list_printers_pending = FALSE;
 
   if (gtk_cups_result_is_error (result))
     {
       g_warning ("Error getting printer list: %s", gtk_cups_result_get_error_string (result));
-      return;
+
+      goto done;
     }
   
   /* Gather the names of the printers in the current queue
@@ -947,6 +1007,11 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
        else if (!strcmp (attr->name, "member-uris") &&
                 attr->value_tag == IPP_TAG_URI)
          member_uris = attr->values[0].string.text;
+        else
+         {
+           GTK_NOTE (PRINTING,
+                      g_print ("CUPS Backend: Attribute %s ignored", attr->name));
+         }
 
         attr = attr->next;
       }
@@ -980,10 +1045,20 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
 
          cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name);
 
+          /* Check to see if we are looking at a class */
          if (member_uris)
-           cups_printer->printer_uri = g_strdup (member_uris);
+           {
+             cups_printer->printer_uri = g_strdup (member_uris);
+             /* TODO if member_uris is a class we need to recursivly find a printer */
+             GTK_NOTE (PRINTING,
+                        g_print ("CUPS Backend: Found class with printer %s\n", member_uris));
+           }
          else
-           cups_printer->printer_uri = g_strdup (printer_uri);
+           {
+             cups_printer->printer_uri = g_strdup (printer_uri);
+              GTK_NOTE (PRINTING,
+                        g_print ("CUPS Backend: Found printer %s\n", printer_uri));
+            }
 
 #if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) || CUPS_VERSION_MAJOR > 1
          httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri, 
@@ -1002,6 +1077,13 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
                        resource);
 #endif
 
+          if (!strncmp (resource, "/printers/", 10))
+           {
+             cups_printer->ppd_name = g_strdup (resource + 10);
+              GTK_NOTE (PRINTING,
+                        g_print ("CUPS Backend: Setting ppd name '%s' for printer/class '%s'\n", cups_printer->ppd_name, printer_name));
+            }
+
          gethostname (uri, sizeof(uri));
          if (strcasecmp (uri, hostname) == 0)
            strcpy (hostname, "localhost");
@@ -1054,6 +1136,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
       list_has_changed = TRUE;
     }
   
+done:
   if (list_has_changed)
     g_signal_emit_by_name (backend, "printer-list-changed");
   
@@ -1075,12 +1158,15 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
       !cups_backend->got_default_printer)
     return TRUE;
 
+  g_object_ref (cups_backend);
+  GDK_THREADS_LEAVE ();
+
   cups_backend->list_printers_pending = TRUE;
 
   request = gtk_cups_request_new (NULL,
                                   GTK_CUPS_POST,
                                   CUPS_GET_PRINTERS,
-                                 0,
+                                 NULL,
                                  NULL,
                                  NULL);
 
@@ -1093,6 +1179,8 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
                         (GtkPrintCupsResponseCallbackFunc) cups_request_printer_list_cb,
                        request,
                        NULL);
+  GDK_THREADS_ENTER ();
+  g_object_unref (cups_backend);
 
   return TRUE;
 }
@@ -1106,7 +1194,7 @@ cups_get_printer_list (GtkPrintBackend *backend)
   if (cups_backend->list_printers_poll == 0)
     {
       cups_request_printer_list (cups_backend);
-      cups_backend->list_printers_poll = g_timeout_add (3000 * 100000,
+      cups_backend->list_printers_poll = gdk_threads_add_timeout (3000,
                                                         (GSourceFunc) cups_request_printer_list,
                                                         backend);
     }
@@ -1114,16 +1202,16 @@ cups_get_printer_list (GtkPrintBackend *backend)
 
 typedef struct {
   GtkPrinterCups *printer;
-  gint ppd_fd;
-  gchar *ppd_filename;
+  GIOChannel *ppd_io;
 } GetPPDData;
 
 static void
 get_ppd_data_free (GetPPDData *data)
 {
-  close (data->ppd_fd);
-  unlink (data->ppd_filename);
-  g_free (data->ppd_filename);
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
+  g_io_channel_unref (data->ppd_io);
   g_object_unref (data->printer);
   g_free (data);
 }
@@ -1136,20 +1224,26 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
   ipp_t *response;
   GtkPrinter *printer;
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
   printer = GTK_PRINTER (data->printer);
   GTK_PRINTER_CUPS (printer)->reading_ppd = FALSE;
 
   if (gtk_cups_result_is_error (result))
     {
-      g_signal_emit_by_name (printer, "details-acquired", printer, FALSE);
+      g_signal_emit_by_name (printer, "details-acquired", FALSE);
       return;
     }
 
   response = gtk_cups_result_get_response (result);
 
-  data->printer->ppd_file = ppdOpenFile (data->ppd_filename);
+  /* let ppdOpenFd take over the ownership of the open file */
+  g_io_channel_seek_position (data->ppd_io, 0, G_SEEK_SET, NULL);
+  data->printer->ppd_file = ppdOpenFd (dup (g_io_channel_unix_get_fd (data->ppd_io)));
+  
   gtk_printer_set_has_details (printer, TRUE);
-  g_signal_emit_by_name (printer, "details-acquired", printer, TRUE);
+  g_signal_emit_by_name (printer, "details-acquired", TRUE);
 }
 
 static void
@@ -1159,13 +1253,19 @@ cups_request_ppd (GtkPrinter *printer)
   GtkPrintBackend *print_backend;
   GtkPrinterCups *cups_printer;
   GtkCupsRequest *request;
+  char *ppd_filename;
   gchar *resource;
   http_t *http;
   GetPPDData *data;
-  
+  int fd;
+
   cups_printer = GTK_PRINTER_CUPS (printer);
 
   error = NULL;
+
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
   /* FIXME this can return NULL! */
   http = httpConnectEncrypt (cups_printer->hostname, 
                             cups_printer->port,
@@ -1173,35 +1273,52 @@ cups_request_ppd (GtkPrinter *printer)
 
   data = g_new0 (GetPPDData, 1);
 
-  data->ppd_fd = g_file_open_tmp ("gtkprint_ppd_XXXXXX", 
-                                  &data->ppd_filename, 
-                                  &error);
+  fd = g_file_open_tmp ("gtkprint_ppd_XXXXXX", 
+                        &ppd_filename, 
+                        &error);
+
+#ifdef G_ENABLE_DEBUG 
+  /* If we are debugging printing don't delete the tmp files */
+  if (!(gtk_debug_flags & GTK_DEBUG_PRINTING))
+    unlink (ppd_filename);
+#else
+  unlink (ppd_filename);
+#endif /* G_ENABLE_DEBUG */
 
   if (error != NULL)
     {
       g_warning ("%s", error->message);
       g_error_free (error);
       httpClose (http);
+      g_free (ppd_filename);
       g_free (data);
 
-      g_signal_emit_by_name (printer, "details-acquired", printer, FALSE);
+      g_signal_emit_by_name (printer, "details-acquired", FALSE);
       return;
     }
     
-  fchmod (data->ppd_fd, S_IRUSR | S_IWUSR);
+  fchmod (fd, S_IRUSR | S_IWUSR);
+  data->ppd_io = g_io_channel_unix_new (fd);
+  g_io_channel_set_encoding (data->ppd_io, NULL, NULL);
+  g_io_channel_set_close_on_unref (data->ppd_io, TRUE);
 
   data->printer = g_object_ref (printer);
 
-  resource = g_strdup_printf ("/printers/%s.ppd", gtk_printer_get_name (printer));
+  resource = g_strdup_printf ("/printers/%s.ppd", 
+                              gtk_printer_cups_get_ppd_name (GTK_PRINTER_CUPS(printer)));
   request = gtk_cups_request_new (http,
                                   GTK_CUPS_GET,
                                  0,
-                                  data->ppd_fd,
+                                  data->ppd_io,
                                  cups_printer->hostname,
                                  resource);
 
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: Requesting resource %s to be written to temp file %s\n", resource, ppd_filename));
+
   g_free (resource);
+  g_free (ppd_filename);
+
   cups_printer->reading_ppd = TRUE;
 
   print_backend = gtk_printer_get_backend (printer);
@@ -1259,7 +1376,7 @@ cups_request_default_printer (GtkPrintBackendCups *print_backend)
   request = gtk_cups_request_new (NULL,
                                   GTK_CUPS_POST,
                                   CUPS_GET_DEFAULT,
-                                 0,
+                                 NULL,
                                  NULL,
                                  NULL);
   
@@ -1553,6 +1670,16 @@ value_is_off (const char *value)
           strcasecmp (value, "False") == 0);
 }
 
+static char *
+ppd_group_name (ppd_group_t *group)
+{
+#if CUPS_VERSION_MAJOR > 1 || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR > 1) || (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR == 1 && CUPS_VERSION_PATCH >= 18) 
+  return group->name;
+#else
+  return group->text;
+#endif
+}
+
 static int
 available_choices (ppd_file_t     *ppd,
                   ppd_option_t   *option,
@@ -1578,7 +1705,10 @@ available_choices (ppd_file_t     *ppd,
   installed_options = NULL;
   for (i = 0; i < ppd->num_groups; i++)
     {
-      if (strcmp (ppd->groups[i].name, "InstallableOptions") == 0)
+      char *name; 
+
+      name = ppd_group_name (&ppd->groups[i]);
+      if (strcmp (name, "InstallableOptions") == 0)
        {
          installed_options = &ppd->groups[i];
          break;
@@ -1726,6 +1856,9 @@ create_pickone_option (ppd_file_t   *ppd_file,
   char *label;
   int n_choices;
   int i;
+#ifdef HAVE_CUPS_API_1_2
+  ppd_coption_t *coption;
+#endif
 
   g_assert (ppd_option->ui == PPD_UI_PICKONE);
   
@@ -1734,9 +1867,65 @@ create_pickone_option (ppd_file_t   *ppd_file,
   n_choices = available_choices (ppd_file, ppd_option, &available, g_str_has_prefix (gtk_name, "gtk-"));
   if (n_choices > 0)
     {
+      
+      /* right now only support one parameter per custom option 
+       * if more than one print warning and only offer the default choices
+       */
+
       label = get_option_text (ppd_file, ppd_option);
-      option = gtk_printer_option_new (gtk_name, label,
-                                      GTK_PRINTER_OPTION_TYPE_PICKONE);
+
+#ifdef HAVE_CUPS_API_1_2
+      coption = ppdFindCustomOption (ppd_file, ppd_option->keyword);
+
+      if (coption)
+        {
+         ppd_cparam_t *cparam;
+
+          cparam = ppdFirstCustomParam (coption);
+
+          if (ppdNextCustomParam (coption) == NULL)
+           {
+              switch (cparam->type)
+               {
+                case PPD_CUSTOM_INT:
+                 option = gtk_printer_option_new (gtk_name, label,
+                                        GTK_PRINTER_OPTION_TYPE_PICKONE_INT);
+                 break;
+                case PPD_CUSTOM_PASSCODE:
+                 option = gtk_printer_option_new (gtk_name, label,
+                                        GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE);
+                 break;
+                case PPD_CUSTOM_PASSWORD:
+                   option = gtk_printer_option_new (gtk_name, label,
+                                        GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD);
+                 break;
+               case PPD_CUSTOM_REAL:
+                   option = gtk_printer_option_new (gtk_name, label,
+                                        GTK_PRINTER_OPTION_TYPE_PICKONE_REAL);
+                 break;
+                case PPD_CUSTOM_STRING:
+                 option = gtk_printer_option_new (gtk_name, label,
+                                        GTK_PRINTER_OPTION_TYPE_PICKONE_STRING);
+                 break;
+                case PPD_CUSTOM_POINTS: 
+                 g_warning ("Not Supported: PPD Custom Points Option");
+                 break;
+                case PPD_CUSTOM_CURVE:
+                  g_warning ("Not Supported: PPD Custom Curve Option");
+                 break;
+                case PPD_CUSTOM_INVCURVE:      
+                 g_warning ("Not Supported: PPD Custom Inverse Curve Option");
+                 break;
+               }
+           }
+         else
+           g_warning ("Not Supported: PPD Custom Option has more than one parameter");
+       }
+#endif /* HAVE_CUPS_API_1_2 */
+
+      if (!option)
+        option = gtk_printer_option_new (gtk_name, label,
+                                        GTK_PRINTER_OPTION_TYPE_PICKONE);
       g_free (label);
       
       gtk_printer_option_allocate_choices (option, n_choices);
@@ -1848,7 +2037,7 @@ handle_option (GtkPrinterOptionSet *set,
 
   if (STRING_IN_TABLE (ppd_option->keyword, cups_option_blacklist))
     return;
-  
+
   name = get_option_name (ppd_option->keyword);
 
   option = NULL;
@@ -1866,21 +2055,24 @@ handle_option (GtkPrinterOptionSet *set,
   
   if (option)
     {
-      if (STRING_IN_TABLE (toplevel_group->name,
+      char *name;
+
+      name = ppd_group_name (toplevel_group);
+      if (STRING_IN_TABLE (name,
                           color_group_whitelist) ||
          STRING_IN_TABLE (ppd_option->keyword,
                           color_option_whitelist))
        {
          option->group = g_strdup ("ColorPage");
        }
-      else if (STRING_IN_TABLE (toplevel_group->name,
+      else if (STRING_IN_TABLE (name,
                                image_quality_group_whitelist) ||
               STRING_IN_TABLE (ppd_option->keyword,
                                image_quality_option_whitelist))
        {
          option->group = g_strdup ("ImageQualityPage");
        }
-      else if (STRING_IN_TABLE (toplevel_group->name,
+      else if (STRING_IN_TABLE (name,
                                finishing_group_whitelist) ||
               STRING_IN_TABLE (ppd_option->keyword,
                                finishing_option_whitelist))
@@ -1908,9 +2100,11 @@ handle_group (GtkPrinterOptionSet *set,
              GtkPrintSettings    *settings)
 {
   gint i;
-
+  gchar *name;
+  
   /* Ignore installable options */
-  if (strcmp (toplevel_group->name, "InstallableOptions") == 0)
+  name = ppd_group_name (toplevel_group);
+  if (strcmp (name, "InstallableOptions") == 0)
     return;
   
   for (i = 0; i < group->num_options; i++)
@@ -2007,14 +2201,27 @@ cups_printer_get_options (GtkPrinter           *printer,
     {
       GtkPaperSize *paper_size;
       ppd_option_t *option;
-      
+      const gchar  *ppd_name;
+
       ppdMarkDefaults (ppd_file);
 
       paper_size = gtk_page_setup_get_paper_size (page_setup);
 
       option = ppdFindOption (ppd_file, "PageSize");
-      strncpy (option->defchoice, gtk_paper_size_get_ppd_name (paper_size),
-              PPD_MAX_NAME);
+      ppd_name = gtk_paper_size_get_ppd_name (paper_size);
+      
+      if (ppd_name)
+       strncpy (option->defchoice, ppd_name, PPD_MAX_NAME);
+      else
+        {
+          gchar *custom_name;
+
+         custom_name = g_strdup_printf (_("Custom.%2fx%.2f"),
+                                        gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS),
+                                        gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS));
+          strncpy (option->defchoice, custom_name, PPD_MAX_NAME);
+          g_free (custom_name);
+        }
 
       for (i = 0; i < ppd_file->num_groups; i++)
         handle_group (set, ppd_file, &ppd_file->groups[i], &ppd_file->groups[i], settings);