Blame gtk/gtkprintbackend.c

Packit 98cdb6
/* GTK - The GIMP Toolkit
Packit 98cdb6
 * gtkprintbackend.h: Abstract printer backend interfaces
Packit 98cdb6
 * Copyright (C) 2003, Red Hat, Inc.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is free software; you can redistribute it and/or
Packit 98cdb6
 * modify it under the terms of the GNU Lesser General Public
Packit 98cdb6
 * License as published by the Free Software Foundation; either
Packit 98cdb6
 * version 2 of the License, or (at your option) any later version.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is distributed in the hope that it will be useful,
Packit 98cdb6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 98cdb6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 98cdb6
 * Lesser General Public License for more details.
Packit 98cdb6
 *
Packit 98cdb6
 * You should have received a copy of the GNU Lesser General Public
Packit 98cdb6
 * License along with this library; if not, write to the
Packit 98cdb6
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 98cdb6
 * Boston, MA 02111-1307, USA.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
#include "config.h"
Packit 98cdb6
#include <string.h>
Packit 98cdb6
Packit 98cdb6
#include <gmodule.h>
Packit 98cdb6
Packit 98cdb6
#include "gtkintl.h"
Packit 98cdb6
#include "gtkmodules.h"
Packit 98cdb6
#include "gtkmarshalers.h"
Packit 98cdb6
#include "gtkprivate.h"
Packit 98cdb6
#include "gtkprintbackend.h"
Packit 98cdb6
#include "gtkalias.h"
Packit 98cdb6
Packit 98cdb6
#define GTK_PRINT_BACKEND_GET_PRIVATE(o)  \
Packit 98cdb6
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendPrivate))
Packit 98cdb6
Packit 98cdb6
static void gtk_print_backend_dispose      (GObject      *object);
Packit 98cdb6
static void gtk_print_backend_set_property (GObject      *object,
Packit 98cdb6
                                            guint         prop_id,
Packit 98cdb6
                                            const GValue *value,
Packit 98cdb6
                                            GParamSpec   *pspec);
Packit 98cdb6
static void gtk_print_backend_get_property (GObject      *object,
Packit 98cdb6
                                            guint         prop_id,
Packit 98cdb6
                                            GValue       *value,
Packit 98cdb6
                                            GParamSpec   *pspec);
Packit 98cdb6
Packit 98cdb6
struct _GtkPrintBackendPrivate
Packit 98cdb6
{
Packit 98cdb6
  GHashTable *printers;
Packit 98cdb6
  guint printer_list_requested : 1;
Packit 98cdb6
  guint printer_list_done : 1;
Packit 98cdb6
  GtkPrintBackendStatus status;
Packit 98cdb6
  char **auth_info_required;
Packit 98cdb6
  char **auth_info;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
enum {
Packit 98cdb6
  PRINTER_LIST_CHANGED,
Packit 98cdb6
  PRINTER_LIST_DONE,
Packit 98cdb6
  PRINTER_ADDED,
Packit 98cdb6
  PRINTER_REMOVED,
Packit 98cdb6
  PRINTER_STATUS_CHANGED,
Packit 98cdb6
  REQUEST_PASSWORD,
Packit 98cdb6
  LAST_SIGNAL
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static guint signals[LAST_SIGNAL] = { 0 };
Packit 98cdb6
Packit 98cdb6
enum 
Packit 98cdb6
{ 
Packit 98cdb6
  PROP_ZERO,
Packit 98cdb6
  PROP_STATUS
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static GObjectClass *backend_parent_class;
Packit 98cdb6
Packit 98cdb6
GQuark
Packit 98cdb6
gtk_print_backend_error_quark (void)
Packit 98cdb6
{
Packit 98cdb6
  static GQuark quark = 0;
Packit 98cdb6
  if (quark == 0)
Packit 98cdb6
    quark = g_quark_from_static_string ("gtk-print-backend-error-quark");
Packit 98cdb6
  return quark;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/*****************************************
Packit 98cdb6
 *     GtkPrintBackendModule modules     *
Packit 98cdb6
 *****************************************/
Packit 98cdb6
Packit 98cdb6
typedef struct _GtkPrintBackendModule GtkPrintBackendModule;
Packit 98cdb6
typedef struct _GtkPrintBackendModuleClass GtkPrintBackendModuleClass;
Packit 98cdb6
Packit 98cdb6
struct _GtkPrintBackendModule
Packit 98cdb6
{
Packit 98cdb6
  GTypeModule parent_instance;
Packit 98cdb6
  
Packit 98cdb6
  GModule *library;
Packit 98cdb6
Packit 98cdb6
  void             (*init)     (GTypeModule    *module);
Packit 98cdb6
  void             (*exit)     (void);
Packit 98cdb6
  GtkPrintBackend* (*create)   (void);
Packit 98cdb6
Packit 98cdb6
  gchar *path;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
struct _GtkPrintBackendModuleClass
Packit 98cdb6
{
Packit 98cdb6
  GTypeModuleClass parent_class;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
G_DEFINE_TYPE (GtkPrintBackendModule, _gtk_print_backend_module, G_TYPE_TYPE_MODULE)
Packit 98cdb6
#define GTK_TYPE_PRINT_BACKEND_MODULE      (_gtk_print_backend_module_get_type ())
Packit 98cdb6
#define GTK_PRINT_BACKEND_MODULE(module)   (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_PRINT_BACKEND_MODULE, GtkPrintBackendModule))
Packit 98cdb6
Packit 98cdb6
static GSList *loaded_backends;
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
gtk_print_backend_module_load (GTypeModule *module)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendModule *pb_module = GTK_PRINT_BACKEND_MODULE (module); 
Packit 98cdb6
  gpointer initp, exitp, createp;
Packit 98cdb6
 
Packit 98cdb6
  pb_module->library = g_module_open (pb_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
Packit 98cdb6
  if (!pb_module->library)
Packit 98cdb6
    {
Packit 98cdb6
      g_warning ("%s", g_module_error());
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  /* extract symbols from the lib */
Packit 98cdb6
  if (!g_module_symbol (pb_module->library, "pb_module_init",
Packit 98cdb6
			&initp) ||
Packit 98cdb6
      !g_module_symbol (pb_module->library, "pb_module_exit", 
Packit 98cdb6
			&exitp) ||
Packit 98cdb6
      !g_module_symbol (pb_module->library, "pb_module_create", 
Packit 98cdb6
			&createp))
Packit 98cdb6
    {
Packit 98cdb6
      g_warning ("%s", g_module_error());
Packit 98cdb6
      g_module_close (pb_module->library);
Packit 98cdb6
      
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  pb_module->init = initp;
Packit 98cdb6
  pb_module->exit = exitp;
Packit 98cdb6
  pb_module->create = createp;
Packit 98cdb6
Packit 98cdb6
  /* call the printbackend's init function to let it */
Packit 98cdb6
  /* setup anything it needs to set up. */
Packit 98cdb6
  pb_module->init (module);
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_print_backend_module_unload (GTypeModule *module)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendModule *pb_module = GTK_PRINT_BACKEND_MODULE (module);
Packit 98cdb6
  
Packit 98cdb6
  pb_module->exit();
Packit 98cdb6
Packit 98cdb6
  g_module_close (pb_module->library);
Packit 98cdb6
  pb_module->library = NULL;
Packit 98cdb6
Packit 98cdb6
  pb_module->init = NULL;
Packit 98cdb6
  pb_module->exit = NULL;
Packit 98cdb6
  pb_module->create = NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* This only will ever be called if an error occurs during
Packit 98cdb6
 * initialization
Packit 98cdb6
 */
Packit 98cdb6
static void
Packit 98cdb6
gtk_print_backend_module_finalize (GObject *object)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendModule *module = GTK_PRINT_BACKEND_MODULE (object);
Packit 98cdb6
Packit 98cdb6
  g_free (module->path);
Packit 98cdb6
Packit 98cdb6
  G_OBJECT_CLASS (_gtk_print_backend_module_parent_class)->finalize (object);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
_gtk_print_backend_module_class_init (GtkPrintBackendModuleClass *class)
Packit 98cdb6
{
Packit 98cdb6
  GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
Packit 98cdb6
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Packit 98cdb6
Packit 98cdb6
  module_class->load = gtk_print_backend_module_load;
Packit 98cdb6
  module_class->unload = gtk_print_backend_module_unload;
Packit 98cdb6
Packit 98cdb6
  gobject_class->finalize = gtk_print_backend_module_finalize;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void 
Packit 98cdb6
gtk_print_backend_set_property (GObject      *object,
Packit 98cdb6
                                guint         prop_id,
Packit 98cdb6
                                const GValue *value,
Packit 98cdb6
                                GParamSpec   *pspec)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
Packit 98cdb6
  priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend); 
Packit 98cdb6
Packit 98cdb6
  switch (prop_id)
Packit 98cdb6
    {
Packit 98cdb6
    case PROP_STATUS:
Packit 98cdb6
      priv->status = g_value_get_int (value);
Packit 98cdb6
      break;
Packit 98cdb6
    default:
Packit 98cdb6
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void 
Packit 98cdb6
gtk_print_backend_get_property (GObject    *object,
Packit 98cdb6
                                guint       prop_id,
Packit 98cdb6
                                GValue     *value,
Packit 98cdb6
                                GParamSpec *pspec)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
Packit 98cdb6
  priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend); 
Packit 98cdb6
Packit 98cdb6
  switch (prop_id)
Packit 98cdb6
    {
Packit 98cdb6
    case PROP_STATUS:
Packit 98cdb6
      g_value_set_int (value, priv->status);
Packit 98cdb6
      break;
Packit 98cdb6
    default:
Packit 98cdb6
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
_gtk_print_backend_module_init (GtkPrintBackendModule *pb_module)
Packit 98cdb6
{
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GtkPrintBackend *
Packit 98cdb6
_gtk_print_backend_module_create (GtkPrintBackendModule *pb_module)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackend *pb;
Packit 98cdb6
  
Packit 98cdb6
  if (g_type_module_use (G_TYPE_MODULE (pb_module)))
Packit 98cdb6
    {
Packit 98cdb6
      pb = pb_module->create ();
Packit 98cdb6
      g_type_module_unuse (G_TYPE_MODULE (pb_module));
Packit 98cdb6
      return pb;
Packit 98cdb6
    }
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GtkPrintBackend *
Packit 98cdb6
_gtk_print_backend_create (const gchar *backend_name)
Packit 98cdb6
{
Packit 98cdb6
  GSList *l;
Packit 98cdb6
  gchar *module_path;
Packit 98cdb6
  gchar *full_name;
Packit 98cdb6
  GtkPrintBackendModule *pb_module;
Packit 98cdb6
  GtkPrintBackend *pb;
Packit 98cdb6
Packit 98cdb6
  for (l = loaded_backends; l != NULL; l = l->next)
Packit 98cdb6
    {
Packit 98cdb6
      pb_module = l->data;
Packit 98cdb6
      
Packit 98cdb6
      if (strcmp (G_TYPE_MODULE (pb_module)->name, backend_name) == 0)
Packit 98cdb6
	return _gtk_print_backend_module_create (pb_module);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  pb = NULL;
Packit 98cdb6
  if (g_module_supported ())
Packit 98cdb6
    {
Packit 98cdb6
      full_name = g_strconcat ("printbackend-", backend_name, NULL);
Packit 98cdb6
      module_path = _gtk_find_module (full_name, "printbackends");
Packit 98cdb6
      g_free (full_name);
Packit 98cdb6
Packit 98cdb6
      if (module_path)
Packit 98cdb6
	{
Packit 98cdb6
	  pb_module = g_object_new (GTK_TYPE_PRINT_BACKEND_MODULE, NULL);
Packit 98cdb6
Packit 98cdb6
	  g_type_module_set_name (G_TYPE_MODULE (pb_module), backend_name);
Packit 98cdb6
	  pb_module->path = g_strdup (module_path);
Packit 98cdb6
Packit 98cdb6
	  loaded_backends = g_slist_prepend (loaded_backends,
Packit 98cdb6
		   		             pb_module);
Packit 98cdb6
Packit 98cdb6
	  pb = _gtk_print_backend_module_create (pb_module);
Packit 98cdb6
Packit 98cdb6
	  /* Increase use-count so that we don't unload print backends.
Packit 98cdb6
	   * There is a problem with module unloading in the cups module,
Packit 98cdb6
	   * see cups_dispatch_watch_finalize for details. 
Packit 98cdb6
	   */
Packit 98cdb6
	  g_type_module_use (G_TYPE_MODULE (pb_module));
Packit 98cdb6
	}
Packit 98cdb6
      
Packit 98cdb6
      g_free (module_path);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return pb;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_printer_backend_load_modules:
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: (element-type GtkPrintBackend) (transfer container):
Packit 98cdb6
 */
Packit 98cdb6
GList *
Packit 98cdb6
gtk_print_backend_load_modules (void)
Packit 98cdb6
{
Packit 98cdb6
  GList *result;
Packit 98cdb6
  GtkPrintBackend *backend;
Packit 98cdb6
  gchar *setting;
Packit 98cdb6
  gchar **backends;
Packit 98cdb6
  gint i;
Packit 98cdb6
  GtkSettings *settings;
Packit 98cdb6
Packit 98cdb6
  result = NULL;
Packit 98cdb6
Packit 98cdb6
  settings = gtk_settings_get_default ();
Packit 98cdb6
  if (settings)
Packit 98cdb6
    g_object_get (settings, "gtk-print-backends", &setting, NULL);
Packit 98cdb6
  else
Packit 98cdb6
    setting = g_strdup (GTK_PRINT_BACKENDS);
Packit 98cdb6
Packit 98cdb6
  backends = g_strsplit (setting, ",", -1);
Packit 98cdb6
Packit 98cdb6
  for (i = 0; backends[i]; i++)
Packit 98cdb6
    {
Packit 98cdb6
      g_strchug (backends[i]);
Packit 98cdb6
      g_strchomp (backends[i]);
Packit 98cdb6
      backend = _gtk_print_backend_create (backends[i]);
Packit 98cdb6
      
Packit 98cdb6
      if (backend)
Packit 98cdb6
        result = g_list_append (result, backend);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_strfreev (backends);
Packit 98cdb6
  g_free (setting);
Packit 98cdb6
Packit 98cdb6
  return result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/*****************************************
Packit 98cdb6
 *             GtkPrintBackend           *
Packit 98cdb6
 *****************************************/
Packit 98cdb6
Packit 98cdb6
G_DEFINE_TYPE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
Packit 98cdb6
Packit 98cdb6
static void                 fallback_printer_request_details       (GtkPrinter          *printer);
Packit 98cdb6
static gboolean             fallback_printer_mark_conflicts        (GtkPrinter          *printer,
Packit 98cdb6
								    GtkPrinterOptionSet *options);
Packit 98cdb6
static gboolean             fallback_printer_get_hard_margins      (GtkPrinter          *printer,
Packit 98cdb6
                                                                    gdouble             *top,
Packit 98cdb6
                                                                    gdouble             *bottom,
Packit 98cdb6
                                                                    gdouble             *left,
Packit 98cdb6
                                                                    gdouble             *right);
Packit 98cdb6
static GList *              fallback_printer_list_papers           (GtkPrinter          *printer);
Packit 98cdb6
static GtkPageSetup *       fallback_printer_get_default_page_size (GtkPrinter          *printer);
Packit 98cdb6
static GtkPrintCapabilities fallback_printer_get_capabilities      (GtkPrinter          *printer);
Packit 98cdb6
static void                 request_password                       (GtkPrintBackend     *backend,
Packit 98cdb6
                                                                    gpointer             auth_info_required,
Packit 98cdb6
                                                                    gpointer             auth_info_default,
Packit 98cdb6
                                                                    gpointer             auth_info_display,
Packit 98cdb6
                                                                    gpointer             auth_info_visible,
Packit 98cdb6
                                                                    const gchar         *prompt);
Packit 98cdb6
  
Packit 98cdb6
static void
Packit 98cdb6
gtk_print_backend_class_init (GtkPrintBackendClass *class)
Packit 98cdb6
{
Packit 98cdb6
  GObjectClass *object_class;
Packit 98cdb6
  object_class = (GObjectClass *) class;
Packit 98cdb6
Packit 98cdb6
  backend_parent_class = g_type_class_peek_parent (class);
Packit 98cdb6
  
Packit 98cdb6
  object_class->dispose = gtk_print_backend_dispose;
Packit 98cdb6
  object_class->set_property = gtk_print_backend_set_property;
Packit 98cdb6
  object_class->get_property = gtk_print_backend_get_property;
Packit 98cdb6
Packit 98cdb6
  class->printer_request_details = fallback_printer_request_details;
Packit 98cdb6
  class->printer_mark_conflicts = fallback_printer_mark_conflicts;
Packit 98cdb6
  class->printer_get_hard_margins = fallback_printer_get_hard_margins;
Packit 98cdb6
  class->printer_list_papers = fallback_printer_list_papers;
Packit 98cdb6
  class->printer_get_default_page_size = fallback_printer_get_default_page_size;
Packit 98cdb6
  class->printer_get_capabilities = fallback_printer_get_capabilities;
Packit 98cdb6
  class->request_password = request_password;
Packit 98cdb6
  
Packit 98cdb6
  g_object_class_install_property (object_class, 
Packit 98cdb6
                                   PROP_STATUS,
Packit 98cdb6
                                   g_param_spec_int ("status",
Packit 98cdb6
                                                     "Status",
Packit 98cdb6
                                                     "The status of the print backend",
Packit 98cdb6
                                                     GTK_PRINT_BACKEND_STATUS_UNKNOWN,
Packit 98cdb6
                                                     GTK_PRINT_BACKEND_STATUS_UNAVAILABLE,
Packit 98cdb6
                                                     GTK_PRINT_BACKEND_STATUS_UNKNOWN,
Packit 98cdb6
                                                     GTK_PARAM_READWRITE)); 
Packit 98cdb6
Packit 98cdb6
  g_type_class_add_private (class, sizeof (GtkPrintBackendPrivate));
Packit 98cdb6
  
Packit 98cdb6
  signals[PRINTER_LIST_CHANGED] =
Packit 98cdb6
    g_signal_new (I_("printer-list-changed"),
Packit 98cdb6
		  G_TYPE_FROM_CLASS (class),
Packit 98cdb6
		  G_SIGNAL_RUN_LAST,
Packit 98cdb6
		  G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
Packit 98cdb6
		  NULL, NULL,
Packit 98cdb6
		  g_cclosure_marshal_VOID__VOID,
Packit 98cdb6
		  G_TYPE_NONE, 0);
Packit 98cdb6
  signals[PRINTER_LIST_DONE] =
Packit 98cdb6
    g_signal_new (I_("printer-list-done"),
Packit 98cdb6
		    G_TYPE_FROM_CLASS (class),
Packit 98cdb6
		    G_SIGNAL_RUN_LAST,
Packit 98cdb6
		    G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
Packit 98cdb6
		    NULL, NULL,
Packit 98cdb6
		    g_cclosure_marshal_VOID__VOID,
Packit 98cdb6
		    G_TYPE_NONE, 0);
Packit 98cdb6
  signals[PRINTER_ADDED] =
Packit 98cdb6
    g_signal_new (I_("printer-added"),
Packit 98cdb6
		  G_TYPE_FROM_CLASS (class),
Packit 98cdb6
		  G_SIGNAL_RUN_LAST,
Packit 98cdb6
		  G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
Packit 98cdb6
		  NULL, NULL,
Packit 98cdb6
		  g_cclosure_marshal_VOID__OBJECT,
Packit 98cdb6
		  G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
Packit 98cdb6
  signals[PRINTER_REMOVED] =
Packit 98cdb6
    g_signal_new (I_("printer-removed"),
Packit 98cdb6
		  G_TYPE_FROM_CLASS (class),
Packit 98cdb6
		  G_SIGNAL_RUN_LAST,
Packit 98cdb6
		  G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
Packit 98cdb6
		  NULL, NULL,
Packit 98cdb6
		  g_cclosure_marshal_VOID__OBJECT,
Packit 98cdb6
		  G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
Packit 98cdb6
  signals[PRINTER_STATUS_CHANGED] =
Packit 98cdb6
    g_signal_new (I_("printer-status-changed"),
Packit 98cdb6
		  G_TYPE_FROM_CLASS (class),
Packit 98cdb6
		  G_SIGNAL_RUN_LAST,
Packit 98cdb6
		  G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
Packit 98cdb6
		  NULL, NULL,
Packit 98cdb6
		  g_cclosure_marshal_VOID__OBJECT,
Packit 98cdb6
		  G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
Packit 98cdb6
  signals[REQUEST_PASSWORD] =
Packit 98cdb6
    g_signal_new (I_("request-password"),
Packit 98cdb6
		  G_TYPE_FROM_CLASS (class),
Packit 98cdb6
		  G_SIGNAL_RUN_LAST,
Packit 98cdb6
		  G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
Packit 98cdb6
		  NULL, NULL,
Packit 98cdb6
		  _gtk_marshal_VOID__POINTER_POINTER_POINTER_POINTER_STRING,
Packit 98cdb6
		  G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_print_backend_init (GtkPrintBackend *backend)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
Packit 98cdb6
  priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend); 
Packit 98cdb6
Packit 98cdb6
  priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal, 
Packit 98cdb6
					  (GDestroyNotify) g_free,
Packit 98cdb6
					  (GDestroyNotify) g_object_unref);
Packit 98cdb6
  priv->auth_info_required = NULL;
Packit 98cdb6
  priv->auth_info = NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_print_backend_dispose (GObject *object)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackend *backend;
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
Packit 98cdb6
  backend = GTK_PRINT_BACKEND (object);
Packit 98cdb6
  priv = backend->priv;
Packit 98cdb6
Packit 98cdb6
  /* We unref the printers in dispose, not in finalize so that
Packit 98cdb6
   * we can break refcount cycles with gtk_print_backend_destroy 
Packit 98cdb6
   */
Packit 98cdb6
  if (priv->printers)
Packit 98cdb6
    {
Packit 98cdb6
      g_hash_table_destroy (priv->printers);
Packit 98cdb6
      priv->printers = NULL;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  backend_parent_class->dispose (object);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
fallback_printer_request_details (GtkPrinter *printer)
Packit 98cdb6
{
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
fallback_printer_mark_conflicts (GtkPrinter          *printer,
Packit 98cdb6
				 GtkPrinterOptionSet *options)
Packit 98cdb6
{
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
fallback_printer_get_hard_margins (GtkPrinter *printer,
Packit 98cdb6
				   gdouble    *top,
Packit 98cdb6
				   gdouble    *bottom,
Packit 98cdb6
				   gdouble    *left,
Packit 98cdb6
				   gdouble    *right)
Packit 98cdb6
{
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GList *
Packit 98cdb6
fallback_printer_list_papers (GtkPrinter *printer)
Packit 98cdb6
{
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GtkPageSetup *
Packit 98cdb6
fallback_printer_get_default_page_size (GtkPrinter *printer)
Packit 98cdb6
{
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GtkPrintCapabilities
Packit 98cdb6
fallback_printer_get_capabilities (GtkPrinter *printer)
Packit 98cdb6
{
Packit 98cdb6
  return 0;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
printer_hash_to_sorted_active_list (const gchar  *key,
Packit 98cdb6
                                    gpointer      value,
Packit 98cdb6
                                    GList       **out_list)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrinter *printer;
Packit 98cdb6
Packit 98cdb6
  printer = GTK_PRINTER (value);
Packit 98cdb6
Packit 98cdb6
  if (gtk_printer_get_name (printer) == NULL)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  if (!gtk_printer_is_active (printer))
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_print_backend_add_printer (GtkPrintBackend *backend,
Packit 98cdb6
			       GtkPrinter      *printer)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
Packit 98cdb6
Packit 98cdb6
  priv = backend->priv;
Packit 98cdb6
Packit 98cdb6
  if (!priv->printers)
Packit 98cdb6
    return;
Packit 98cdb6
  
Packit 98cdb6
  g_hash_table_insert (priv->printers,
Packit 98cdb6
		       g_strdup (gtk_printer_get_name (printer)), 
Packit 98cdb6
		       g_object_ref (printer));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_print_backend_remove_printer (GtkPrintBackend *backend,
Packit 98cdb6
				  GtkPrinter      *printer)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
Packit 98cdb6
  priv = backend->priv;
Packit 98cdb6
Packit 98cdb6
  if (!priv->printers)
Packit 98cdb6
    return;
Packit 98cdb6
  
Packit 98cdb6
  g_hash_table_remove (priv->printers,
Packit 98cdb6
		       gtk_printer_get_name (printer));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_print_backend_set_list_done (GtkPrintBackend *backend)
Packit 98cdb6
{
Packit 98cdb6
  if (!backend->priv->printer_list_done)
Packit 98cdb6
    {
Packit 98cdb6
      backend->priv->printer_list_done = TRUE;
Packit 98cdb6
      g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_print_backend_get_printer_list:
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: (element-type GtkPrinter) (transfer container):
Packit 98cdb6
 */
Packit 98cdb6
GList *
Packit 98cdb6
gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
  GList *result;
Packit 98cdb6
  
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
Packit 98cdb6
Packit 98cdb6
  priv = backend->priv;
Packit 98cdb6
Packit 98cdb6
  result = NULL;
Packit 98cdb6
  if (priv->printers != NULL)
Packit 98cdb6
    g_hash_table_foreach (priv->printers,
Packit 98cdb6
                          (GHFunc) printer_hash_to_sorted_active_list,
Packit 98cdb6
                          &result);
Packit 98cdb6
Packit 98cdb6
  if (!priv->printer_list_requested && priv->printers != NULL)
Packit 98cdb6
    {
Packit 98cdb6
      if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
Packit 98cdb6
	GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
Packit 98cdb6
      priv->printer_list_requested = TRUE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
Packit 98cdb6
Packit 98cdb6
  return print_backend->priv->printer_list_done;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
GtkPrinter *
Packit 98cdb6
gtk_print_backend_find_printer (GtkPrintBackend *backend,
Packit 98cdb6
                                const gchar     *printer_name)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendPrivate *priv;
Packit 98cdb6
  GtkPrinter *printer;
Packit 98cdb6
  
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
Packit 98cdb6
Packit 98cdb6
  priv = backend->priv;
Packit 98cdb6
Packit 98cdb6
  if (priv->printers)
Packit 98cdb6
    printer = g_hash_table_lookup (priv->printers, printer_name);
Packit 98cdb6
  else
Packit 98cdb6
    printer = NULL;
Packit 98cdb6
Packit 98cdb6
  return printer;  
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_print_backend_print_stream (GtkPrintBackend        *backend,
Packit 98cdb6
                                GtkPrintJob            *job,
Packit 98cdb6
                                GIOChannel             *data_io,
Packit 98cdb6
                                GtkPrintJobCompleteFunc callback,
Packit 98cdb6
                                gpointer                user_data,
Packit 98cdb6
				GDestroyNotify          dnotify)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
Packit 98cdb6
Packit 98cdb6
  GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
Packit 98cdb6
						       job,
Packit 98cdb6
						       data_io,
Packit 98cdb6
						       callback,
Packit 98cdb6
						       user_data,
Packit 98cdb6
						       dnotify);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void 
Packit 98cdb6
gtk_print_backend_set_password (GtkPrintBackend  *backend,
Packit 98cdb6
                                gchar           **auth_info_required,
Packit 98cdb6
                                gchar           **auth_info)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
Packit 98cdb6
Packit 98cdb6
  if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
Packit 98cdb6
    GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend, auth_info_required, auth_info);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
store_entry (GtkEntry  *entry,
Packit 98cdb6
             gpointer   user_data)
Packit 98cdb6
{
Packit 98cdb6
  gchar **data = (gchar **) user_data;
Packit 98cdb6
Packit 98cdb6
  if (*data != NULL)
Packit 98cdb6
    {
Packit 98cdb6
      memset (*data, 0, strlen (*data));
Packit 98cdb6
      g_free (*data);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  *data = g_strdup (gtk_entry_get_text (entry));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
password_dialog_response (GtkWidget       *dialog,
Packit 98cdb6
                          gint             response_id,
Packit 98cdb6
                          GtkPrintBackend *backend)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendPrivate *priv = backend->priv;
Packit 98cdb6
  gint i;
Packit 98cdb6
Packit 98cdb6
  if (response_id == GTK_RESPONSE_OK)
Packit 98cdb6
    gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info);
Packit 98cdb6
  else
Packit 98cdb6
    gtk_print_backend_set_password (backend, priv->auth_info_required, NULL);
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < g_strv_length (priv->auth_info_required); i++)
Packit 98cdb6
    if (priv->auth_info[i] != NULL)
Packit 98cdb6
      {
Packit 98cdb6
        memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
Packit 98cdb6
        g_free (priv->auth_info[i]);
Packit 98cdb6
        priv->auth_info[i] = NULL;
Packit 98cdb6
      }
Packit 98cdb6
  g_free (priv->auth_info);
Packit 98cdb6
  priv->auth_info = NULL;
Packit 98cdb6
Packit 98cdb6
  g_strfreev (priv->auth_info_required);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_destroy (dialog);
Packit 98cdb6
Packit 98cdb6
  g_object_unref (backend);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
request_password (GtkPrintBackend  *backend,
Packit 98cdb6
                  gpointer          auth_info_required,
Packit 98cdb6
                  gpointer          auth_info_default,
Packit 98cdb6
                  gpointer          auth_info_display,
Packit 98cdb6
                  gpointer          auth_info_visible,
Packit 98cdb6
                  const gchar      *prompt)
Packit 98cdb6
{
Packit 98cdb6
  GtkPrintBackendPrivate *priv = backend->priv;
Packit 98cdb6
  GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry;
Packit 98cdb6
  GtkWidget *focus = NULL;
Packit 98cdb6
  gchar     *markup;
Packit 98cdb6
  gint       length;
Packit 98cdb6
  gint       i;
Packit 98cdb6
  gchar    **ai_required = (gchar **) auth_info_required;
Packit 98cdb6
  gchar    **ai_default = (gchar **) auth_info_default;
Packit 98cdb6
  gchar    **ai_display = (gchar **) auth_info_display;
Packit 98cdb6
  gboolean  *ai_visible = (gboolean *) auth_info_visible;
Packit 98cdb6
Packit 98cdb6
  priv->auth_info_required = g_strdupv (ai_required);
Packit 98cdb6
  length = g_strv_length (ai_required);
Packit 98cdb6
  priv->auth_info = g_new0 (gchar *, length + 1);
Packit 98cdb6
Packit 98cdb6
  dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL, 
Packit 98cdb6
                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
Packit 98cdb6
                                         GTK_STOCK_OK, GTK_RESPONSE_OK,
Packit 98cdb6
                                         NULL);
Packit 98cdb6
Packit 98cdb6
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
Packit 98cdb6
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
Packit 98cdb6
Packit 98cdb6
  main_box = gtk_hbox_new (FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  /* Left */
Packit 98cdb6
  icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
Packit 98cdb6
  gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
Packit 98cdb6
  gtk_misc_set_padding (GTK_MISC (icon), 6, 6);
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
  /* Right */
Packit 98cdb6
  vbox = gtk_vbox_new (FALSE, 0);
Packit 98cdb6
  gtk_widget_set_size_request (GTK_WIDGET (vbox), 320, -1);
Packit 98cdb6
Packit 98cdb6
  /* Right - 1. */
Packit 98cdb6
  label = gtk_label_new (NULL);
Packit 98cdb6
  markup = g_markup_printf_escaped ("%s", prompt);
Packit 98cdb6
  gtk_label_set_markup (GTK_LABEL (label), markup);
Packit 98cdb6
  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
Packit 98cdb6
  gtk_widget_set_size_request (GTK_WIDGET (label), 320, -1);
Packit 98cdb6
  g_free (markup);
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
  /* Packing */
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_box, TRUE, FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (main_box), icon, FALSE, FALSE, 6);
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (main_box), vbox, FALSE, FALSE, 6);
Packit 98cdb6
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 6);
Packit 98cdb6
  
Packit 98cdb6
  /* Right - 2. */
Packit 98cdb6
  for (i = 0; i < length; i++)
Packit 98cdb6
    {
Packit 98cdb6
      priv->auth_info[i] = g_strdup (ai_default[i]);
Packit 98cdb6
      if (ai_display[i] != NULL)
Packit 98cdb6
        {
Packit 98cdb6
          box = gtk_hbox_new (TRUE, 0);
Packit 98cdb6
Packit 98cdb6
          label = gtk_label_new (ai_display[i]);
Packit 98cdb6
          gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
Packit 98cdb6
Packit 98cdb6
          entry = gtk_entry_new ();
Packit 98cdb6
          focus = entry;
Packit 98cdb6
Packit 98cdb6
          if (ai_default[i] != NULL)
Packit 98cdb6
            gtk_entry_set_text (GTK_ENTRY (entry), ai_default[i]);
Packit 98cdb6
Packit 98cdb6
          gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
Packit 98cdb6
          gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
Packit 98cdb6
Packit 98cdb6
          gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 6);
Packit 98cdb6
Packit 98cdb6
          gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
Packit 98cdb6
          gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0);
Packit 98cdb6
Packit 98cdb6
          g_signal_connect (entry, "changed",
Packit 98cdb6
                            G_CALLBACK (store_entry), &(priv->auth_info[i]));
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (focus != NULL)
Packit 98cdb6
    {
Packit 98cdb6
      gtk_widget_grab_focus (focus);
Packit 98cdb6
      focus = NULL;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_object_ref (backend);
Packit 98cdb6
  g_signal_connect (G_OBJECT (dialog), "response",
Packit 98cdb6
                    G_CALLBACK (password_dialog_response), backend);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_show_all (dialog);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gtk_print_backend_destroy (GtkPrintBackend *print_backend)
Packit 98cdb6
{
Packit 98cdb6
  /* The lifecycle of print backends and printers are tied, such that
Packit 98cdb6
   * the backend owns the printers, but the printers also ref the backend.
Packit 98cdb6
   * This is so that if the app has a reference to a printer its backend
Packit 98cdb6
   * will be around. However, this results in a cycle, which we break
Packit 98cdb6
   * with this call, which causes the print backend to release its printers.
Packit 98cdb6
   */
Packit 98cdb6
  g_object_run_dispose (G_OBJECT (print_backend));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
#define __GTK_PRINT_BACKEND_C__
Packit 98cdb6
#include "gtkaliasdef.c"