mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-01 16:30:15 +00:00
41b60bbd6c
The Common Print Dialog Backends (CPDB) concept has GUI-toolkit-independent backends for each print technology (CUPS, Print to File, cloud printing services, ...) and each print dialog (GTK, Qt, Chromium, ...) is supposed to use this backend, so that changes in print technologies can be centrally and quickly covered by changing the backends and everything new gets available in all print dialogs. This commit provides a GTK print dialog backend to add support for the CPDB concept. It communicates with all installed CPDB backends and so gives support for all these print technologies to the GTK print dialog. To make use of CPDB the GTK print dialog is supposed to be installed with this backend and the 'Print To File' backend, and not any others to prevent printer duplication.
1693 lines
61 KiB
C
1693 lines
61 KiB
C
/* GTK - The GIMP Toolkit
|
|
* gtkprintbackendcpdb.h: Default implementation of GtkPrintBackend
|
|
* for the Common Print Dialog Backends (CPDB)
|
|
* Copyright (C) 2022, 2023 TinyTrebuchet <tinytrebuchet@protonmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include <config.h>
|
|
#include <cpdb/frontend.h>
|
|
|
|
#include <gtk/gtkprivate.h>
|
|
#include "gtkprintbackendcpdb.h"
|
|
#include "gtkprintbackendutils.h"
|
|
|
|
#include <cairo.h>
|
|
#include <cairo-pdf.h>
|
|
|
|
#include <glib/gi18n-lib.h>
|
|
#include <gtkprintercpdb.h>
|
|
|
|
#define GTK_PRINT_BACKEND_CPDB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_CPDB, GtkPrintBackendCpdbClass))
|
|
#define GTK_IS_PRINT_BACKEND_CPDB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_CPDB))
|
|
#define GTK_PRINT_BACKEND_CPDB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_CPDB, GtkPrintBackendCpdbClass))
|
|
|
|
/*
|
|
* Multiplier for converting points to mm
|
|
*/
|
|
#define points_multiplier 2.83464567
|
|
|
|
#define _CPDB_MAX_CHUNK_SIZE 8192
|
|
|
|
|
|
|
|
static void gtk_print_backend_cpdb_finalize (GObject *object);
|
|
|
|
static void cpdb_request_printer_list (GtkPrintBackend *backend);
|
|
|
|
static void cpdb_printer_request_details (GtkPrinter *printer);
|
|
|
|
static void cpdb_acquire_details_cb (cpdb_printer_obj_t *cpdb_printer_obj,
|
|
int success,
|
|
gpointer user_data);
|
|
|
|
static GtkPrintCapabilities cpdb_printer_get_capabilities (GtkPrinter *printer);
|
|
|
|
static GtkPrinterOptionSet *cpdb_printer_get_options (GtkPrinter *printer,
|
|
GtkPrintSettings *settings,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintCapabilities capabilities);
|
|
|
|
static GtkPageSetup *cpdb_get_gtk_page_setup (cpdb_printer_obj_t *printer_obj,
|
|
const char *media);
|
|
static GList *cpdb_printer_list_papers (GtkPrinter *printer);
|
|
static GtkPageSetup *cpdb_printer_get_default_page_size (GtkPrinter *printer);
|
|
|
|
static gboolean cpdb_printer_get_hard_margins (GtkPrinter *printer,
|
|
double *top,
|
|
double *bottom,
|
|
double *left,
|
|
double *right);
|
|
static gboolean cpdb_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
|
|
GtkPaperSize *paper_size,
|
|
double *top,
|
|
double *bottom,
|
|
double *left,
|
|
double *right);
|
|
|
|
static void cpdb_printer_get_settings_from_options (GtkPrinter *printer,
|
|
GtkPrinterOptionSet *options,
|
|
GtkPrintSettings *settings);
|
|
|
|
static void cpdb_printer_prepare_for_print (GtkPrinter *printer,
|
|
GtkPrintJob *print_job,
|
|
GtkPrintSettings *settings,
|
|
GtkPageSetup *page_setup);
|
|
|
|
static void cpdb_print_cb (GtkPrintBackendCpdb *cpdb_backend,
|
|
GError *error,
|
|
gpointer user_data);
|
|
|
|
static gboolean cpdb_write (GIOChannel *source,
|
|
GIOCondition con,
|
|
gpointer user_data);
|
|
|
|
static void cpdb_print_stream (GtkPrintBackend *backend,
|
|
GtkPrintJob *job,
|
|
GIOChannel *data_io,
|
|
GtkPrintJobCompleteFunc callback,
|
|
gpointer user_data,
|
|
GDestroyNotify dnotify);
|
|
|
|
static void gtk_printer_cpdb_configure_page_setup (GtkPrinter *printer,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintSettings *settings);
|
|
|
|
static void gtk_printer_cpdb_configure_settings (const char *key,
|
|
const char *value,
|
|
gpointer user_data);
|
|
|
|
static cairo_surface_t *cpdb_printer_create_cairo_surface (GtkPrinter *printer,
|
|
GtkPrintSettings *settings,
|
|
double width,
|
|
double height,
|
|
GIOChannel *cache_io);
|
|
|
|
static void cpdb_fill_gtk_option (GtkPrinterOption *gtk_option,
|
|
cpdb_option_t *cpdb_option,
|
|
cpdb_printer_obj_t *printer_obj);
|
|
|
|
static void printer_updates_callback (cpdb_frontend_obj_t *frontend_obj,
|
|
cpdb_printer_obj_t *printer_obj,
|
|
cpdb_printer_update_t change);
|
|
|
|
static void add_option_to_settings (GtkPrinterOption *option,
|
|
gpointer user_data);
|
|
|
|
static void cpdb_printer_add_hash_table (gpointer key,
|
|
gpointer value,
|
|
gpointer user_data);
|
|
|
|
static void cpdb_add_gtk_printer (GtkPrintBackend *backend,
|
|
cpdb_printer_obj_t *printer_obj);
|
|
|
|
static void cpdb_remove_gtk_printer (GtkPrintBackend *backend,
|
|
cpdb_printer_obj_t *printer_obj);
|
|
|
|
static void set_state_message (GtkPrinter *printer);
|
|
|
|
static char *cpdb_option_translation (cpdb_printer_obj_t *printer_obj,
|
|
const char *option_name);
|
|
static char *cpdb_choice_translation (cpdb_printer_obj_t *printer_obj,
|
|
const char *option_name,
|
|
const char *choice_name);
|
|
|
|
static void initialize (void);
|
|
static gchar *get_gtk_group (cpdb_printer_obj_t *printer_obj,
|
|
const char *group_name);
|
|
|
|
|
|
/*
|
|
* List of locales for text translation
|
|
*/
|
|
static const gchar* const* locales = NULL;
|
|
|
|
/*
|
|
* Mark the options which have already been displayed in other tabs,
|
|
* and exclude them from the "Advanced" tab, while getting printer options
|
|
*/
|
|
static GHashTable *already_used_options = NULL;
|
|
|
|
|
|
struct _GtkPrintBackendCpdbClass
|
|
{
|
|
GtkPrintBackendClass parent_class;
|
|
};
|
|
|
|
struct _GtkPrintBackendCpdb
|
|
{
|
|
GtkPrintBackend parent_instance;
|
|
cpdb_frontend_obj_t *frontend_obj;
|
|
};
|
|
|
|
typedef struct {
|
|
GtkPrintBackend *backend;
|
|
GtkPrintJobCompleteFunc callback;
|
|
GtkPrintJob *job;
|
|
char *path;
|
|
GIOStream *target_io_stream;
|
|
gpointer user_data;
|
|
GDestroyNotify dnotify;
|
|
} _PrintStreamData;
|
|
|
|
|
|
G_DEFINE_DYNAMIC_TYPE (GtkPrintBackendCpdb, gtk_print_backend_cpdb, GTK_TYPE_PRINT_BACKEND)
|
|
|
|
/*
|
|
* GtkPrintBackend object for currently opened print dialog
|
|
*/
|
|
static GtkPrintBackend *gtk_print_backend = NULL;
|
|
|
|
|
|
G_MODULE_EXPORT
|
|
void
|
|
g_io_module_load (GIOModule *module)
|
|
{
|
|
g_type_module_use (G_TYPE_MODULE (module));
|
|
|
|
gtk_print_backend_cpdb_register_type (G_TYPE_MODULE (module));
|
|
gtk_printer_cpdb_register_type (G_TYPE_MODULE (module));
|
|
|
|
g_io_extension_point_implement (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME,
|
|
GTK_TYPE_PRINT_BACKEND_CPDB,
|
|
"cpdb",
|
|
10);
|
|
}
|
|
|
|
G_MODULE_EXPORT
|
|
void
|
|
g_io_module_unload (GIOModule *module)
|
|
{
|
|
}
|
|
|
|
G_MODULE_EXPORT
|
|
char **
|
|
g_io_module_query (void)
|
|
{
|
|
char *eps[] = {
|
|
(char *)GTK_PRINT_BACKEND_EXTENSION_POINT_NAME,
|
|
NULL
|
|
};
|
|
|
|
return g_strdupv (eps);
|
|
}
|
|
|
|
/*
|
|
* GtkPrintBackendCpdb
|
|
*/
|
|
|
|
/*
|
|
* gtk_print_backend_cpdb_new:
|
|
*
|
|
* Creates a new #GtkPrintBackendCpdb object. #GtkPrintBackendCpdb
|
|
* implements the #GtkPrintBackend interface with direct access to
|
|
* the filesystem using Unix/Linux API calls
|
|
*
|
|
* Returns: the new #GtkPrintBackendCpdb object
|
|
*/
|
|
GtkPrintBackend *
|
|
gtk_print_backend_cpdb_new (void)
|
|
{
|
|
GTK_DEBUG (PRINTING, "CPDB Backend: Creating a new CPDB print backend object");
|
|
|
|
return g_object_new (GTK_TYPE_PRINT_BACKEND_CPDB, NULL);
|
|
}
|
|
|
|
|
|
static void
|
|
gtk_print_backend_cpdb_class_init (GtkPrintBackendCpdbClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (klass);
|
|
|
|
gobject_class->finalize = gtk_print_backend_cpdb_finalize;
|
|
|
|
backend_class->request_printer_list = cpdb_request_printer_list;
|
|
backend_class->printer_request_details = cpdb_printer_request_details;
|
|
backend_class->printer_get_capabilities = cpdb_printer_get_capabilities;
|
|
backend_class->printer_get_options = cpdb_printer_get_options;
|
|
backend_class->printer_list_papers = cpdb_printer_list_papers;
|
|
backend_class->printer_get_default_page_size = cpdb_printer_get_default_page_size;
|
|
backend_class->printer_get_hard_margins = cpdb_printer_get_hard_margins;
|
|
backend_class->printer_get_hard_margins_for_paper_size = cpdb_printer_get_hard_margins_for_paper_size;
|
|
backend_class->printer_get_settings_from_options = cpdb_printer_get_settings_from_options;
|
|
backend_class->printer_prepare_for_print = cpdb_printer_prepare_for_print;
|
|
backend_class->printer_create_cairo_surface = cpdb_printer_create_cairo_surface;
|
|
backend_class->print_stream = cpdb_print_stream;
|
|
}
|
|
|
|
static void
|
|
gtk_print_backend_cpdb_class_finalize (GtkPrintBackendCpdbClass *class)
|
|
{
|
|
}
|
|
|
|
static void
|
|
gtk_print_backend_cpdb_init (GtkPrintBackendCpdb *backend_cpdb)
|
|
{
|
|
char *tmp, *instance_name;
|
|
|
|
initialize ();
|
|
|
|
/*
|
|
* Initialize the FrontendObj with a random instance name to
|
|
* prevent conflicts with print dialogs opened from other programs
|
|
*/
|
|
tmp = random_string (4);
|
|
instance_name = g_strdup_printf ("Gtk_%s", tmp);
|
|
GTK_DEBUG (PRINTING, "Creating frontendObj for CPDB backend: %s", instance_name);
|
|
backend_cpdb->frontend_obj = cpdbGetNewFrontendObj (instance_name,
|
|
(cpdb_printer_callback) printer_updates_callback);
|
|
cpdbIgnoreLastSavedSettings (backend_cpdb->frontend_obj);
|
|
gtk_print_backend = GTK_PRINT_BACKEND (backend_cpdb);
|
|
g_free (tmp);
|
|
g_free (instance_name);
|
|
}
|
|
|
|
static void
|
|
gtk_print_backend_cpdb_finalize (GObject *object)
|
|
{
|
|
GtkPrintBackendCpdb *backend_cpdb;
|
|
GObjectClass *backend_parent_class;
|
|
|
|
GTK_DEBUG (PRINTING, "Finalizing CPDB backend object");
|
|
|
|
backend_cpdb = GTK_PRINT_BACKEND_CPDB (object);
|
|
backend_parent_class = G_OBJECT_CLASS (gtk_print_backend_cpdb_parent_class);
|
|
cpdbDeleteFrontendObj (backend_cpdb->frontend_obj);
|
|
gtk_print_backend = NULL;
|
|
|
|
backend_parent_class->finalize (object);
|
|
}
|
|
|
|
/*
|
|
* This function is responsible for displaying the printer
|
|
* list obtained from CPDB backend on the print dialog.
|
|
*/
|
|
static void
|
|
cpdb_request_printer_list (GtkPrintBackend *backend)
|
|
{
|
|
GtkPrintBackendCpdb *backend_cpdb = GTK_PRINT_BACKEND_CPDB (backend);
|
|
|
|
cpdbConnectToDBus (backend_cpdb->frontend_obj);
|
|
g_hash_table_foreach (backend_cpdb->frontend_obj->printer,
|
|
cpdb_printer_add_hash_table,
|
|
backend);
|
|
gtk_print_backend_set_list_done (backend);
|
|
}
|
|
|
|
/*
|
|
* This function is responsible for making a printer acquire all
|
|
* the details and supported options list, which need not be queried
|
|
* until the user clicks on the printer in the printer list in the dialog.
|
|
* The print dialog runs this function asynchronously and displays
|
|
* "Getting printer attributes..." as the printer status meanwhile.
|
|
* This function is needed as some printers (like temporary CUPS queue)
|
|
* can take a couple of seconds to materialize and acquire all the details,
|
|
* and it's important the dialog doesn't block during that time.
|
|
*/
|
|
static void
|
|
cpdb_printer_request_details (GtkPrinter *printer)
|
|
{
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
cpdbAcquireDetails (printer_obj, cpdb_acquire_details_cb, printer);
|
|
}
|
|
|
|
static void
|
|
cpdb_acquire_details_cb (cpdb_printer_obj_t *printer_obj,
|
|
int success,
|
|
gpointer user_data)
|
|
{
|
|
GtkPrinter *printer = GTK_PRINTER (user_data);
|
|
GtkPrintBackend *backend = gtk_printer_get_backend (printer);
|
|
gboolean accepting_jobs, paused, status_changed;
|
|
|
|
if (success == 0)
|
|
{
|
|
GTK_DEBUG (PRINTING, "Error acquiring printer details");
|
|
g_signal_emit_by_name (printer, "details-acquired", FALSE);
|
|
return;
|
|
}
|
|
|
|
accepting_jobs = cpdbIsAcceptingJobs (printer_obj);
|
|
paused = g_strcmp0 (cpdbGetState (printer_obj), "stopped") == 0;
|
|
status_changed = paused ^ gtk_printer_is_paused (printer);
|
|
|
|
gtk_printer_set_is_accepting_jobs (printer, accepting_jobs);
|
|
gtk_printer_set_is_paused (printer, paused);
|
|
set_state_message (printer);
|
|
|
|
gtk_printer_set_has_details (printer, TRUE);
|
|
g_signal_emit_by_name (printer, "details-acquired", TRUE);
|
|
|
|
if (status_changed)
|
|
g_signal_emit_by_name (backend, "printer-status-changed", printer);
|
|
}
|
|
|
|
|
|
/*
|
|
* This function is responsible for specifying which features the
|
|
* print dialog should offer for the given printer.
|
|
*/
|
|
static GtkPrintCapabilities
|
|
cpdb_printer_get_capabilities (GtkPrinter *printer)
|
|
{
|
|
GtkPrintCapabilities capabilities = 0;
|
|
cpdb_option_t *cpdb_option;
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_PAGE_SET);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported >= 3)
|
|
capabilities |= GTK_PRINT_CAPABILITY_PAGE_SET;
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_COPIES);
|
|
if (cpdb_option != NULL &&
|
|
g_strcmp0 (cpdb_option->supported_values[0], "1") != 0 &&
|
|
g_strcmp0 (cpdb_option->supported_values[0], "1-1") != 0)
|
|
capabilities |= GTK_PRINT_CAPABILITY_COPIES;
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_COLLATE);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
capabilities |= GTK_PRINT_CAPABILITY_COLLATE;
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_PAGE_DELIVERY);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
capabilities |= GTK_PRINT_CAPABILITY_REVERSE;
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_PRINT_SCALING);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
capabilities |= GTK_PRINT_CAPABILITY_SCALE;
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_NUMBER_UP);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
capabilities |= GTK_PRINT_CAPABILITY_NUMBER_UP;
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_NUMBER_UP_LAYOUT);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
capabilities |= GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT;
|
|
|
|
return capabilities;
|
|
}
|
|
|
|
|
|
/*
|
|
* This function is responsible for getting all the options
|
|
* that the printer supports and display them into the
|
|
* GUI template of GTK+ print dialog box.
|
|
* The backend should obtain whatever options it supports,
|
|
* from either its print server or PPDs.
|
|
*/
|
|
static GtkPrinterOptionSet *
|
|
cpdb_printer_get_options (GtkPrinter *printer,
|
|
GtkPrintSettings *settings,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintCapabilities capabilities)
|
|
{
|
|
char *option_name;
|
|
char *display_name;
|
|
gpointer key, value;
|
|
GHashTableIter iter;
|
|
GtkPrinterCpdb *printer_cpdb;
|
|
cpdb_printer_obj_t *printer_obj;
|
|
cpdb_option_t *cpdb_option;
|
|
GtkPrinterOption *gtk_option;
|
|
GtkPrinterOptionSet *gtk_option_set;
|
|
|
|
gtk_option_set = gtk_printer_option_set_new ();
|
|
printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
/** Page-Setup **/
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_NUMBER_UP);
|
|
if ((capabilities & GTK_PRINT_CAPABILITY_NUMBER_UP) && cpdb_option != NULL)
|
|
{
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-n-up",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_NUMBER_UP_LAYOUT);
|
|
if ((capabilities & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) && cpdb_option != NULL)
|
|
{
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-n-up-layout",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_SIDES);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
{
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-duplex",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_MEDIA_SOURCE);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
{
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-paper-source",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_MEDIA_TYPE);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
{
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-paper-type",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_OUTPUT_BIN);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
{
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-output-tray",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
|
|
/** Jobs **/
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_JOB_PRIORITY);
|
|
if (cpdb_option != NULL)
|
|
{
|
|
/* job-priority is represented as a number from 1-100 */
|
|
const char *prio[] = {"100", "80", "50", "30"};
|
|
const char *prio_display[] = {N_("Urgent"), N_("High"), N_("Medium"), N_("Low")};
|
|
|
|
for (int i = 0; i < G_N_ELEMENTS(prio_display); i++)
|
|
prio_display[i] = _(prio_display[i]);
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-job-prio",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
gtk_printer_option_choices_from_array (gtk_option,
|
|
G_N_ELEMENTS (prio),
|
|
prio, prio_display);
|
|
gtk_printer_option_set (gtk_option, "50");
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_JOB_SHEETS);
|
|
if (cpdb_option != NULL && cpdb_option->num_supported > 1)
|
|
{
|
|
gtk_option = gtk_printer_option_new ("gtk-cover-before",
|
|
C_("printer option", "Before"),
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
|
|
gtk_option = gtk_printer_option_new ("gtk-cover-after",
|
|
C_("printer option", "After"),
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
cpdb_option = cpdbGetOption (printer_obj, CPDB_OPTION_BILLING_INFO);
|
|
if (cpdb_option != NULL)
|
|
{
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new ("gtk-billing-info",
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_STRING);
|
|
gtk_printer_option_set (gtk_option, "");
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
const char *print_at[] = {"now", "at", "on-hold"};
|
|
gtk_option = gtk_printer_option_new ("gtk-print-time",
|
|
_("Print at"),
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
gtk_printer_option_choices_from_array (gtk_option,
|
|
G_N_ELEMENTS (print_at),
|
|
print_at, print_at);
|
|
gtk_printer_option_set (gtk_option, "now");
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
|
|
gtk_option = gtk_printer_option_new ("gtk-print-time-text",
|
|
_("Print at time"),
|
|
GTK_PRINTER_OPTION_TYPE_STRING);
|
|
gtk_printer_option_set (gtk_option, "");
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
|
|
/** Other options **/
|
|
g_hash_table_iter_init (&iter, printer_obj->options->table);
|
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
{
|
|
option_name = (char *) key;
|
|
if (g_hash_table_contains (already_used_options, option_name))
|
|
continue;
|
|
|
|
cpdb_option = (cpdb_option_t *) value;
|
|
if (cpdb_option->num_supported <= 1)
|
|
continue;
|
|
|
|
display_name = cpdb_option_translation (printer_obj,
|
|
cpdb_option->option_name);
|
|
gtk_option = gtk_printer_option_new (cpdb_option->option_name,
|
|
display_name,
|
|
GTK_PRINTER_OPTION_TYPE_PICKONE);
|
|
cpdb_fill_gtk_option (gtk_option, cpdb_option, printer_obj);
|
|
gtk_option->group = get_gtk_group (printer_obj,
|
|
cpdb_option->group_name);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
/*
|
|
* Check if borderles printing is supported
|
|
*/
|
|
gboolean borderless = TRUE;
|
|
const char *attrs[] = {CPDB_OPTION_MARGIN_TOP, CPDB_OPTION_MARGIN_BOTTOM,
|
|
CPDB_OPTION_MARGIN_LEFT, CPDB_OPTION_MARGIN_RIGHT};
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
cpdb_option = cpdbGetOption (printer_obj, (gchar *) attrs[i]);
|
|
gboolean found = FALSE;
|
|
|
|
if (cpdb_option != NULL)
|
|
{
|
|
for (int j = 0; j < cpdb_option->num_supported; j++)
|
|
{
|
|
if (g_strcmp0 (cpdb_option->supported_values[j], "0") == 0)
|
|
{
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
borderless = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (borderless)
|
|
{
|
|
gtk_option = gtk_printer_option_new ("borderless",
|
|
C_("print option", "Borderless"),
|
|
GTK_PRINTER_OPTION_TYPE_BOOLEAN);
|
|
gtk_option->group = get_gtk_group (printer_obj, CPDB_GROUP_MEDIA);
|
|
gtk_printer_option_set_add (gtk_option_set, gtk_option);
|
|
g_object_unref (gtk_option);
|
|
}
|
|
|
|
return gtk_option_set;
|
|
}
|
|
|
|
/*
|
|
* Helper function to create GtkPageSetup from given "media" size
|
|
*/
|
|
static GtkPageSetup *
|
|
cpdb_get_gtk_page_setup (cpdb_printer_obj_t *printer_obj,
|
|
const char *media)
|
|
{
|
|
char *display_name;
|
|
int width, height, num_margins, ok;
|
|
cpdb_margin_t *margins;
|
|
GtkPaperSize *paper_size;
|
|
GtkPageSetup *page_setup;
|
|
|
|
page_setup = gtk_page_setup_new ();
|
|
display_name = cpdb_choice_translation (printer_obj,
|
|
CPDB_OPTION_MEDIA,
|
|
media);
|
|
ok = cpdbGetMediaSize (printer_obj,
|
|
media,
|
|
&width,
|
|
&height);
|
|
if (ok == 1)
|
|
{
|
|
paper_size = gtk_paper_size_new_custom (media,
|
|
display_name,
|
|
width / 100.0,
|
|
height / 100.0,
|
|
GTK_UNIT_MM);
|
|
gtk_page_setup_set_paper_size (page_setup, paper_size);
|
|
gtk_paper_size_free (paper_size);
|
|
}
|
|
num_margins = cpdbGetMediaMargins (printer_obj,
|
|
media,
|
|
&margins);
|
|
if (num_margins > 0)
|
|
{
|
|
gtk_page_setup_set_left_margin (page_setup,
|
|
margins[0].left / 100.0,
|
|
GTK_UNIT_MM);
|
|
gtk_page_setup_set_right_margin (page_setup,
|
|
margins[0].right / 100.0,
|
|
GTK_UNIT_MM);
|
|
gtk_page_setup_set_top_margin (page_setup,
|
|
margins[0].top / 100.0,
|
|
GTK_UNIT_MM);
|
|
gtk_page_setup_set_bottom_margin (page_setup,
|
|
margins[0].bottom / 100.0,
|
|
GTK_UNIT_MM);
|
|
}
|
|
return page_setup;
|
|
}
|
|
|
|
/*
|
|
* This function is responsible for listing all the page sizes supported by a printer
|
|
*/
|
|
static GList *
|
|
cpdb_printer_list_papers (GtkPrinter *printer)
|
|
{
|
|
cpdb_option_t *media;
|
|
GList *result = NULL;
|
|
GtkPageSetup *page_setup;
|
|
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
media = cpdbGetOption (printer_obj, CPDB_OPTION_MEDIA);
|
|
if (media == NULL)
|
|
return NULL;
|
|
|
|
for (int i = 0; i < media->num_supported; i++)
|
|
{
|
|
if (g_str_has_prefix (media->supported_values[i], "custom_min") ||
|
|
g_str_has_prefix (media->supported_values[i], "custom_max"))
|
|
continue;
|
|
|
|
page_setup = cpdb_get_gtk_page_setup (printer_obj,
|
|
media->supported_values[i]);
|
|
result = g_list_prepend (result, page_setup);
|
|
}
|
|
result = g_list_reverse (result);
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* This function is responsible for getting the default page size for a printer
|
|
*/
|
|
static GtkPageSetup *
|
|
cpdb_printer_get_default_page_size (GtkPrinter *printer)
|
|
{
|
|
char *default_media;
|
|
GtkPageSetup *page_setup = NULL;
|
|
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
default_media = cpdbGetDefault (printer_obj, CPDB_OPTION_MEDIA);
|
|
if (default_media != NULL)
|
|
{
|
|
page_setup = cpdb_get_gtk_page_setup (printer_obj, default_media);
|
|
}
|
|
|
|
return page_setup;
|
|
}
|
|
|
|
/*
|
|
* This function is responsible for getting the
|
|
* default page size margins supported by a printer
|
|
*/
|
|
static gboolean
|
|
cpdb_printer_get_hard_margins (GtkPrinter *printer,
|
|
double *top,
|
|
double *bottom,
|
|
double *left,
|
|
double *right)
|
|
{
|
|
char *left_margin, *right_margin, *top_margin, *bottom_margin;
|
|
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
top_margin = cpdbGetDefault (printer_obj, CPDB_OPTION_MARGIN_TOP);
|
|
left_margin = cpdbGetDefault (printer_obj, CPDB_OPTION_MARGIN_LEFT);
|
|
right_margin = cpdbGetDefault (printer_obj, CPDB_OPTION_MARGIN_RIGHT);
|
|
bottom_margin = cpdbGetDefault (printer_obj, CPDB_OPTION_MARGIN_BOTTOM);
|
|
|
|
if (top_margin != NULL &&
|
|
left_margin != NULL &&
|
|
right_margin != NULL &&
|
|
bottom_margin != NULL)
|
|
{
|
|
*top = g_ascii_strtod (top_margin, NULL) * points_multiplier / 100.0;
|
|
*left = g_ascii_strtod (left_margin, NULL) * points_multiplier / 100.0;
|
|
*right = g_ascii_strtod (right_margin, NULL) * points_multiplier / 100.0;
|
|
*bottom = g_ascii_strtod (bottom_margin, NULL) * points_multiplier / 100.0;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* This function is responsible for getting the
|
|
* default page size margins for give paper size
|
|
*/
|
|
static gboolean
|
|
cpdb_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
|
|
GtkPaperSize *paper_size,
|
|
double *top,
|
|
double *bottom,
|
|
double *left,
|
|
double *right)
|
|
{
|
|
int num_margins;
|
|
const char *media;
|
|
cpdb_margin_t *margins;
|
|
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
media = gtk_paper_size_get_name (paper_size);
|
|
if (media != NULL)
|
|
{
|
|
num_margins = cpdbGetMediaMargins (printer_obj, media, &margins);
|
|
if (num_margins > 0)
|
|
{
|
|
*top = margins[0].top * points_multiplier / 100.0;
|
|
*left = margins[0].left * points_multiplier / 100.0;
|
|
*right = margins[0].right * points_multiplier / 100.0;
|
|
*bottom = margins[0].bottom * points_multiplier / 100.0;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* @user_data: GtkPrintSettings
|
|
*/
|
|
static void
|
|
add_option_to_settings (GtkPrinterOption *option,
|
|
gpointer user_data)
|
|
{
|
|
GtkPrintSettings *settings = (GtkPrintSettings *) user_data;
|
|
gtk_print_settings_set (settings, option->name, option->value);
|
|
}
|
|
|
|
/*
|
|
* This method is invoked when the print button on the print dialog is pressed.
|
|
* It's responsible for gathering all the settings from the print dialog that the
|
|
* user may have selected before pressing the print button.
|
|
*/
|
|
static void
|
|
cpdb_printer_get_settings_from_options (GtkPrinter *printer,
|
|
GtkPrinterOptionSet *options,
|
|
GtkPrintSettings *settings)
|
|
{
|
|
char *value;
|
|
GtkPrinterOption *option, *cover_before, *cover_after;
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-n-up");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_NUMBER_UP,
|
|
option->value);
|
|
}
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-n-up-layout");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_NUMBER_UP_LAYOUT,
|
|
option->value);
|
|
}
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-duplex");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_SIDES,
|
|
option->value);
|
|
}
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-paper-source");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_MEDIA_SOURCE,
|
|
option->value);
|
|
}
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-paper-type");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_MEDIA_TYPE,
|
|
option->value);
|
|
}
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-output-tray");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_OUTPUT_BIN,
|
|
option->value);
|
|
}
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-job-prio");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_JOB_PRIORITY,
|
|
option->value);
|
|
}
|
|
|
|
cover_before = gtk_printer_option_set_lookup (options, "gtk-cover-before");
|
|
cover_after = gtk_printer_option_set_lookup (options, "gtk-cover-after");
|
|
if (cover_before != NULL && cover_after != NULL)
|
|
{
|
|
value = g_strdup_printf ("%s,%s",
|
|
cover_before->value,
|
|
cover_after->value);
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_JOB_SHEETS,
|
|
value);
|
|
g_free (value);
|
|
}
|
|
|
|
option = gtk_printer_option_set_lookup (options, "gtk-billing-info");
|
|
if (option != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_BILLING_INFO,
|
|
option->value);
|
|
}
|
|
|
|
char *print_at = NULL;
|
|
option = gtk_printer_option_set_lookup (options, "gtk-print-time");
|
|
if (option != NULL)
|
|
print_at = g_strdup (option->value);
|
|
|
|
char *print_at_time = NULL;
|
|
option = gtk_printer_option_set_lookup (options, "gtk-print-time-text");
|
|
if (option != NULL)
|
|
print_at_time = g_strdup (option->value);
|
|
|
|
if (print_at != NULL && print_at_time != NULL)
|
|
{
|
|
if (g_strcmp0 (print_at, "at") == 0)
|
|
{
|
|
char *utc_time = NULL;
|
|
|
|
utc_time = localtime_to_utctime (print_at_time);
|
|
if (utc_time != NULL)
|
|
{
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_JOB_HOLD_UNTIL,
|
|
utc_time);
|
|
g_free (utc_time);
|
|
}
|
|
else
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_JOB_HOLD_UNTIL,
|
|
print_at_time);
|
|
}
|
|
else if (g_strcmp0 (print_at, "on-hold") == 0)
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_JOB_HOLD_UNTIL,
|
|
CPDB_JOB_HOLD_INDEFINITE);
|
|
}
|
|
if (print_at != NULL)
|
|
g_free (print_at);
|
|
if (print_at_time != NULL)
|
|
g_free (print_at_time);
|
|
|
|
gtk_printer_option_set_foreach (options, add_option_to_settings, settings);
|
|
}
|
|
|
|
static cairo_status_t
|
|
_cairo_write (void *closure,
|
|
const unsigned char *data,
|
|
unsigned int length)
|
|
{
|
|
GIOChannel *io = (GIOChannel *)closure;
|
|
gsize written;
|
|
GError *error;
|
|
|
|
error = NULL;
|
|
|
|
GTK_DEBUG (PRINTING, "CPDB Backend: Writing %i byte chunk to temp file", length);
|
|
|
|
while (length > 0)
|
|
{
|
|
g_io_channel_write_chars (io, (const char *)data, length, &written, &error);
|
|
|
|
if (error != NULL)
|
|
{
|
|
GTK_DEBUG (PRINTING, "CPDB Backend: Error writing to temp file, %s", error->message);
|
|
|
|
g_error_free (error);
|
|
return CAIRO_STATUS_WRITE_ERROR;
|
|
}
|
|
|
|
GTK_DEBUG (PRINTING, "CPDB Backend: Wrote %" G_GSIZE_FORMAT " bytes to temp file\n", written);
|
|
|
|
data += written;
|
|
length -= written;
|
|
}
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* called after prepare_for_print ()
|
|
*/
|
|
static cairo_surface_t *
|
|
cpdb_printer_create_cairo_surface (GtkPrinter *printer,
|
|
GtkPrintSettings *settings,
|
|
double width,
|
|
double height,
|
|
GIOChannel *cache_io)
|
|
{
|
|
cairo_surface_t *surface;
|
|
|
|
surface = cairo_pdf_surface_create_for_stream (_cairo_write, cache_io, width, height);
|
|
|
|
cairo_surface_set_fallback_resolution (surface,
|
|
2.0 * gtk_print_settings_get_printer_lpi (settings),
|
|
2.0 * gtk_print_settings_get_printer_lpi (settings));
|
|
|
|
return surface;
|
|
}
|
|
|
|
static void
|
|
gtk_printer_cpdb_configure_settings (const char *key,
|
|
const char *value,
|
|
gpointer user_data)
|
|
{
|
|
const char *option_name, *option_value;
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (user_data);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
option_name = key;
|
|
option_value = value;
|
|
if (g_str_has_prefix (option_name, "gtk") ||
|
|
g_strcmp0 (option_value, "") == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
cpdbAddSettingToPrinter (printer_obj, option_name, option_value);
|
|
}
|
|
|
|
static void
|
|
gtk_printer_cpdb_configure_page_setup (GtkPrinter *printer,
|
|
GtkPageSetup *page_setup,
|
|
GtkPrintSettings *settings)
|
|
{
|
|
char *value, *orientation, *default_orientation;
|
|
const char *borderless;
|
|
double width, height, left, top, right, bottom;
|
|
GtkPageOrientation page_orientation;
|
|
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM) * 100.0;
|
|
height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM) * 100.0;
|
|
left = gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM) * 100.0;
|
|
right = gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM) * 100.0;
|
|
top = gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM) * 100.0;
|
|
bottom = gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM) * 100.0;
|
|
|
|
borderless = gtk_print_settings_get (settings, "borderless");
|
|
if (g_ascii_strcasecmp (borderless, "True") == 0)
|
|
left = right = top = bottom = 0;
|
|
|
|
value = g_strdup_printf ("{media-size={x-dimension=%.0f y-dimension=%.0f} "
|
|
"media-bottom-margin=%.0f "
|
|
"media-left-margin=%.0f "
|
|
"media-right-margin=%.0f "
|
|
"media-top-margin=%.0f}",
|
|
width, height, bottom, left, right, top);
|
|
gtk_print_settings_set (settings, CPDB_OPTION_MEDIA_COL, value);
|
|
g_free (value);
|
|
|
|
page_orientation = gtk_page_setup_get_orientation (page_setup);
|
|
default_orientation = cpdbGetDefault (printer_obj, CPDB_OPTION_ORIENTATION);
|
|
|
|
switch (page_orientation)
|
|
{
|
|
case GTK_PAGE_ORIENTATION_PORTRAIT:
|
|
orientation = g_strdup_printf (CPDB_ORIENTATION_PORTRAIT);
|
|
break;
|
|
|
|
case GTK_PAGE_ORIENTATION_LANDSCAPE:
|
|
orientation = g_strdup_printf (CPDB_ORIENTATION_LANDSCAPE);
|
|
break;
|
|
|
|
case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
|
|
orientation = g_strdup_printf (CPDB_ORIENTATION_RLANDSCAPE);
|
|
break;
|
|
|
|
case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
|
|
orientation = g_strdup_printf (CPDB_ORIENTATION_RPORTRAIT);
|
|
break;
|
|
|
|
default:
|
|
orientation = default_orientation;
|
|
}
|
|
|
|
gtk_print_settings_set (settings, CPDB_OPTION_ORIENTATION, orientation);
|
|
g_free (orientation);
|
|
}
|
|
|
|
static void
|
|
cpdb_printer_prepare_for_print (GtkPrinter *printer,
|
|
GtkPrintJob *print_job,
|
|
GtkPrintSettings *settings,
|
|
GtkPageSetup *page_setup)
|
|
{
|
|
int n_ranges;
|
|
double scale;
|
|
|
|
GtkPrintPages pages;
|
|
GtkPageRange *ranges;
|
|
GtkPageSet page_set;
|
|
GtkPrintCapabilities capabilities;
|
|
|
|
capabilities = cpdb_printer_get_capabilities (printer);
|
|
|
|
pages = gtk_print_settings_get_print_pages (settings);
|
|
gtk_print_job_set_pages (print_job, pages);
|
|
gtk_print_settings_unset (settings, GTK_PRINT_SETTINGS_PRINT_PAGES);
|
|
|
|
if (pages == GTK_PRINT_PAGES_RANGES)
|
|
ranges = gtk_print_settings_get_page_ranges (settings, &n_ranges);
|
|
else
|
|
{
|
|
ranges = NULL;
|
|
n_ranges = 0;
|
|
}
|
|
gtk_print_job_set_page_ranges (print_job, ranges, n_ranges);
|
|
gtk_print_settings_unset (settings, GTK_PRINT_SETTINGS_PAGE_RANGES);
|
|
|
|
scale = gtk_print_settings_get_scale (settings);
|
|
if (scale != 100.0)
|
|
gtk_print_job_set_scale (print_job, scale / 100.0);
|
|
gtk_print_settings_unset (settings, GTK_PRINT_SETTINGS_SCALE);
|
|
|
|
if (capabilities & GTK_PRINT_CAPABILITY_COLLATE)
|
|
{
|
|
if (gtk_print_settings_get_collate (settings))
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_COLLATE,
|
|
CPDB_COLLATE_ENABLED);
|
|
}
|
|
gtk_print_job_set_collate (print_job, FALSE);
|
|
gtk_print_settings_unset (settings, GTK_PRINT_SETTINGS_COLLATE);
|
|
|
|
if (capabilities & GTK_PRINT_CAPABILITY_REVERSE)
|
|
{
|
|
if (gtk_print_settings_get_reverse (settings))
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_PAGE_DELIVERY,
|
|
CPDB_PAGE_DELIVERY_REVERSE);
|
|
}
|
|
gtk_print_job_set_reverse (print_job, FALSE);
|
|
gtk_print_settings_unset (settings, GTK_PRINT_SETTINGS_REVERSE);
|
|
|
|
if (capabilities & GTK_PRINT_CAPABILITY_COPIES)
|
|
{
|
|
int copies = gtk_print_settings_get_n_copies (settings);
|
|
if (copies > 1)
|
|
{
|
|
char *value = g_strdup_printf ("%d", copies);
|
|
gtk_print_settings_set (settings, CPDB_OPTION_COPIES, value);
|
|
g_free (value);
|
|
}
|
|
}
|
|
gtk_print_job_set_num_copies (print_job, 1);
|
|
gtk_print_settings_unset (settings, GTK_PRINT_SETTINGS_N_COPIES);
|
|
|
|
page_set = gtk_print_settings_get_page_set (settings);
|
|
switch (page_set)
|
|
{
|
|
case GTK_PAGE_SET_EVEN :
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_PAGE_SET,
|
|
CPDB_PAGE_SET_EVEN);
|
|
break;
|
|
|
|
case GTK_PAGE_SET_ODD :
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_PAGE_SET,
|
|
CPDB_PAGE_SET_ODD);
|
|
break;
|
|
|
|
case GTK_PAGE_SET_ALL :
|
|
default :
|
|
gtk_print_settings_set (settings,
|
|
CPDB_OPTION_PAGE_SET,
|
|
CPDB_PAGE_SET_ALL);
|
|
}
|
|
gtk_print_job_set_page_set (print_job, GTK_PAGE_SET_ALL);
|
|
gtk_print_settings_unset (settings, GTK_PRINT_SETTINGS_PAGE_SET);
|
|
|
|
gtk_print_settings_unset (settings, "printer");
|
|
|
|
gtk_printer_cpdb_configure_page_setup (printer, page_setup, settings);
|
|
gtk_print_settings_unset (settings, "borderless");
|
|
|
|
gtk_print_settings_foreach (settings,
|
|
gtk_printer_cpdb_configure_settings,
|
|
printer);
|
|
}
|
|
|
|
|
|
static void
|
|
cpdb_print_cb (GtkPrintBackendCpdb *backend_cpdb,
|
|
GError *error,
|
|
gpointer user_data)
|
|
{;
|
|
GtkPrinterCpdb *printer_cpdb;
|
|
cpdb_printer_obj_t *printer_obj;
|
|
_PrintStreamData *ps = (_PrintStreamData *) user_data;
|
|
|
|
if (ps->target_io_stream != NULL)
|
|
g_io_stream_close (G_IO_STREAM (ps->target_io_stream), NULL, NULL);
|
|
|
|
if (ps->callback)
|
|
ps->callback (ps->job, ps->user_data, error);
|
|
|
|
if (ps->dnotify)
|
|
ps->dnotify (ps->user_data);
|
|
|
|
gtk_print_job_set_status (ps->job,
|
|
error ? GTK_PRINT_STATUS_FINISHED_ABORTED
|
|
: GTK_PRINT_STATUS_FINISHED);
|
|
|
|
if (!error)
|
|
{
|
|
printer_cpdb = GTK_PRINTER_CPDB (gtk_print_job_get_printer (ps->job));
|
|
printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
GTK_DEBUG (PRINTING, "CPDB Backend: Sending file to CPDB for printing - %s\n", ps->path);
|
|
|
|
cpdbPrintFile (printer_obj, ps->path);
|
|
|
|
g_free (ps->path);
|
|
}
|
|
|
|
if (ps->job)
|
|
g_object_unref (ps->job);
|
|
|
|
g_free (ps);
|
|
}
|
|
|
|
static gboolean
|
|
cpdb_write (GIOChannel *source,
|
|
GIOCondition con,
|
|
gpointer user_data)
|
|
{
|
|
char buf[_CPDB_MAX_CHUNK_SIZE];
|
|
gsize bytes_read;
|
|
GError *error;
|
|
GIOStatus status;
|
|
GOutputStream *out_stream;
|
|
_PrintStreamData *ps = (_PrintStreamData *) user_data;
|
|
|
|
error = NULL;
|
|
|
|
status = g_io_channel_read_chars (source,
|
|
buf,
|
|
_CPDB_MAX_CHUNK_SIZE,
|
|
&bytes_read,
|
|
&error);
|
|
|
|
if (status != G_IO_STATUS_ERROR)
|
|
{
|
|
gsize bytes_written;
|
|
|
|
out_stream = g_io_stream_get_output_stream (ps->target_io_stream);
|
|
g_output_stream_write_all (out_stream,
|
|
buf,
|
|
bytes_read,
|
|
&bytes_written,
|
|
NULL,
|
|
&error);
|
|
}
|
|
|
|
if (error != NULL || status == G_IO_STATUS_EOF)
|
|
{
|
|
cpdb_print_cb (GTK_PRINT_BACKEND_CPDB (ps->backend),
|
|
error,
|
|
user_data);
|
|
|
|
if (error != NULL)
|
|
{
|
|
GTK_DEBUG (PRINTING, "CPDB Backend: Error writing to file - %s\n", error->message);
|
|
|
|
g_error_free (error);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
GTK_DEBUG (PRINTING, "CPDB Backend: Writing %" G_GSIZE_FORMAT " byte chunk to cpdb pipe\n", bytes_read);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
cpdb_print_stream (GtkPrintBackend *backend,
|
|
GtkPrintJob *job,
|
|
GIOChannel *data_io,
|
|
GtkPrintJobCompleteFunc callback,
|
|
gpointer user_data,
|
|
GDestroyNotify dnotify)
|
|
{
|
|
GError *error;
|
|
GFile *file;
|
|
_PrintStreamData *ps;
|
|
GFileIOStream *iostream;
|
|
|
|
ps = g_new0 (_PrintStreamData, 1);
|
|
ps->callback = callback;
|
|
ps->user_data = user_data;
|
|
ps->dnotify = dnotify;
|
|
ps->job = g_object_ref (job);
|
|
ps->backend = backend;
|
|
|
|
error = NULL;
|
|
file = g_file_new_tmp (NULL, &iostream, &error);
|
|
if (file == NULL)
|
|
goto error;
|
|
|
|
ps->path = g_file_get_path (file);
|
|
ps->target_io_stream = G_IO_STREAM (iostream);
|
|
|
|
g_object_unref (file);
|
|
|
|
error:
|
|
if (error != NULL)
|
|
{
|
|
GTK_DEBUG (PRINTING, "Error: %s\n", error->message);
|
|
|
|
cpdb_print_cb (GTK_PRINT_BACKEND_CPDB (backend), error, ps);
|
|
|
|
g_error_free (error);
|
|
return;
|
|
}
|
|
|
|
g_io_add_watch (data_io,
|
|
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
|
|
(GIOFunc) cpdb_write,
|
|
ps);
|
|
|
|
}
|
|
|
|
/*
|
|
* Reflect changes in printers to the GTK print dialog.
|
|
*/
|
|
static void
|
|
printer_updates_callback (cpdb_frontend_obj_t *frontend_obj,
|
|
cpdb_printer_obj_t *printer_obj,
|
|
cpdb_printer_update_t change)
|
|
{
|
|
GtkPrinter *printer;
|
|
|
|
if (gtk_print_backend == NULL)
|
|
return;
|
|
|
|
switch (change)
|
|
{
|
|
case CPDB_CHANGE_PRINTER_ADDED:
|
|
cpdb_add_gtk_printer (gtk_print_backend, printer_obj);
|
|
break;
|
|
|
|
case CPDB_CHANGE_PRINTER_REMOVED:
|
|
cpdb_remove_gtk_printer (gtk_print_backend, printer_obj);
|
|
cpdbDeletePrinterObj (printer_obj);
|
|
break;
|
|
|
|
case CPDB_CHANGE_PRINTER_STATE_CHANGED:
|
|
printer = gtk_print_backend_find_printer (gtk_print_backend, printer_obj->name);
|
|
set_state_message (printer);
|
|
g_signal_emit_by_name (gtk_print_backend, "printer-status-changed", printer);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @key: printer name
|
|
* @value: cpdb_printer_obj_t
|
|
* @user_data: GtkPrintBackend
|
|
*/
|
|
static void
|
|
cpdb_printer_add_hash_table (gpointer key,
|
|
gpointer value,
|
|
gpointer user_data)
|
|
{
|
|
cpdb_add_gtk_printer (user_data, value);
|
|
}
|
|
|
|
/*
|
|
* Adds given printer to given GtkPrintBackend
|
|
*/
|
|
static void
|
|
cpdb_add_gtk_printer (GtkPrintBackend *backend,
|
|
cpdb_printer_obj_t *printer_obj)
|
|
{
|
|
GtkPrinter *printer;
|
|
GtkPrinterCpdb *printer_cpdb;
|
|
cpdb_printer_obj_t *default_printer;
|
|
|
|
GtkPrintBackendCpdb *backend_cpdb = GTK_PRINT_BACKEND_CPDB (backend);
|
|
|
|
/*
|
|
* Ignore printers from FILE backend,
|
|
* since we are using "Print To File" GTK print backend.
|
|
*/
|
|
if (g_strcmp0 (printer_obj->backend_name, "FILE") == 0)
|
|
return;
|
|
|
|
printer_cpdb = g_object_new (GTK_TYPE_PRINTER_CPDB,
|
|
"name", printer_obj->name,
|
|
"backend", backend,
|
|
NULL);
|
|
gtk_printer_cpdb_set_printer_obj (printer_cpdb, printer_obj);
|
|
|
|
printer = GTK_PRINTER (printer_cpdb);
|
|
gtk_printer_set_icon_name (printer, "printer");
|
|
gtk_printer_set_location (printer, printer_obj->location);
|
|
gtk_printer_set_description (printer, printer_obj->info);
|
|
gtk_printer_set_accepts_pdf (printer, TRUE);
|
|
gtk_printer_set_accepts_ps (printer, TRUE);
|
|
gtk_printer_set_is_active (printer, TRUE);
|
|
gtk_printer_set_has_details (printer, FALSE);
|
|
|
|
default_printer = cpdbGetDefaultPrinter (backend_cpdb->frontend_obj);
|
|
if (default_printer == printer_obj)
|
|
gtk_printer_set_is_default (printer, TRUE);
|
|
|
|
/*
|
|
* If printer state is not available, wait till cpdbAcquireDetails ()
|
|
* is called when the printer is clicked on in the print dialog
|
|
*/
|
|
if (g_strcmp0 (printer_obj->state, "NA") == 0)
|
|
{
|
|
gtk_printer_set_is_accepting_jobs (printer, TRUE);
|
|
gtk_printer_set_is_paused (printer, FALSE);
|
|
gtk_printer_set_state_message (printer, "");
|
|
}
|
|
else
|
|
{
|
|
gtk_printer_set_is_accepting_jobs (printer,
|
|
cpdbIsAcceptingJobs (printer_obj));
|
|
gtk_printer_set_is_paused (printer,
|
|
g_strcmp0 (cpdbGetState (printer_obj),
|
|
CPDB_STATE_STOPPED) == 0);
|
|
set_state_message (printer);
|
|
}
|
|
|
|
gtk_print_backend_add_printer (backend, printer);
|
|
if (gtk_print_backend_printer_list_is_done (backend))
|
|
{
|
|
g_signal_emit_by_name (backend, "printer-added", printer);
|
|
g_signal_emit_by_name (backend, "printer-list-changed");
|
|
}
|
|
g_object_unref (printer);
|
|
}
|
|
|
|
/*
|
|
* Removes given printer from given GtkPrintBackend
|
|
*/
|
|
static void
|
|
cpdb_remove_gtk_printer (GtkPrintBackend *backend,
|
|
cpdb_printer_obj_t *printer_obj)
|
|
{
|
|
GtkPrinter *printer = gtk_print_backend_find_printer (backend, printer_obj->name);
|
|
|
|
gtk_print_backend_remove_printer (backend, printer);
|
|
g_signal_emit_by_name (backend, "printer-removed", printer);
|
|
g_signal_emit_by_name (backend, "printer-list-changed");
|
|
}
|
|
|
|
/*
|
|
* Sets printer status
|
|
*/
|
|
static void
|
|
set_state_message (GtkPrinter *printer)
|
|
{
|
|
gboolean stopped, accepting_jobs;
|
|
GtkPrinterCpdb *printer_cpdb = GTK_PRINTER_CPDB (printer);
|
|
cpdb_printer_obj_t *printer_obj = gtk_printer_cpdb_get_printer_obj (printer_cpdb);
|
|
|
|
stopped = g_strcmp0 (cpdbGetState (printer_obj), CPDB_STATE_STOPPED) == 0;
|
|
accepting_jobs = cpdbIsAcceptingJobs (printer_obj);
|
|
|
|
if (stopped && !accepting_jobs)
|
|
/* Translators: this is a printer status. */
|
|
gtk_printer_set_state_message (printer, _("Paused; Rejecting Jobs"));
|
|
else if (stopped && accepting_jobs)
|
|
/* Translators: this is a printer status. */
|
|
gtk_printer_set_state_message (printer, _("Paused"));
|
|
else if (!accepting_jobs)
|
|
/* Translators: this is a printer status. */
|
|
gtk_printer_set_state_message (printer, _("Rejecting Jobs"));
|
|
else
|
|
gtk_printer_set_state_message (printer, "");
|
|
}
|
|
|
|
/*
|
|
* Fills option choices & sets default in gtk_option from cpdb_option
|
|
*/
|
|
static void
|
|
cpdb_fill_gtk_option (GtkPrinterOption *gtk_option,
|
|
cpdb_option_t *cpdb_option,
|
|
cpdb_printer_obj_t *printer_obj)
|
|
{
|
|
char *display_val;
|
|
char **default_val;
|
|
|
|
gtk_printer_option_allocate_choices (gtk_option, cpdb_option->num_supported);
|
|
for (int i = 0; i < cpdb_option->num_supported; i++)
|
|
{
|
|
gtk_option->choices[i] = g_strdup (cpdb_option->supported_values[i]);
|
|
display_val = cpdb_choice_translation (printer_obj,
|
|
cpdb_option->option_name,
|
|
cpdb_option->supported_values[i]);
|
|
gtk_option->choices_display[i] = g_strdup (display_val);
|
|
}
|
|
|
|
if (g_strcmp0 (cpdb_option->default_value, "NA") != 0)
|
|
{
|
|
if (g_strcmp0 (cpdb_option->option_name, CPDB_OPTION_JOB_SHEETS) == 0)
|
|
{
|
|
default_val = g_strsplit (cpdb_option->default_value, ",", 2);
|
|
if (g_strcmp0 (gtk_option->name, "gtk-cover-before") == 0)
|
|
gtk_printer_option_set (gtk_option, default_val[0]);
|
|
else if (g_strcmp0 (gtk_option->name, "gtk-cover-after") == 0)
|
|
gtk_printer_option_set (gtk_option, default_val[1]);
|
|
}
|
|
else
|
|
{
|
|
gtk_printer_option_set (gtk_option, g_strdup (cpdb_option->default_value));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Wrapper for getting translation of an option name
|
|
*/
|
|
static char *
|
|
cpdb_option_translation (cpdb_printer_obj_t *printer_obj,
|
|
const char *option_name)
|
|
{
|
|
int i;
|
|
char *translation = NULL;
|
|
|
|
for (i = 0; locales[i] != NULL; i++)
|
|
{
|
|
translation = cpdbGetOptionTranslation (printer_obj,
|
|
option_name,
|
|
locales[i]);
|
|
if (translation != NULL)
|
|
break;
|
|
}
|
|
return translation;
|
|
}
|
|
|
|
/*
|
|
* Wrapper for getting translation of a choice name
|
|
*/
|
|
static char *
|
|
cpdb_choice_translation (cpdb_printer_obj_t *printer_obj,
|
|
const char *option_name,
|
|
const char *choice_name)
|
|
{
|
|
int i;
|
|
char *translation = NULL;
|
|
|
|
for (i = 0; locales[i] != NULL; i++)
|
|
{
|
|
translation = cpdbGetChoiceTranslation (printer_obj,
|
|
option_name,
|
|
choice_name,
|
|
locales[i]);
|
|
if (translation != NULL)
|
|
break;
|
|
}
|
|
return translation;
|
|
}
|
|
|
|
/*
|
|
* Wrapper for getting translation of a group name
|
|
*/
|
|
static char *
|
|
cpdb_group_translation (cpdb_printer_obj_t *printer_obj,
|
|
const char *group_name)
|
|
{
|
|
int i;
|
|
char *translation = NULL;
|
|
|
|
for (i = 0; locales[i] != NULL; i++)
|
|
{
|
|
translation = cpdbGetGroupTranslation (printer_obj,
|
|
group_name,
|
|
locales[i]);
|
|
if (translation != NULL)
|
|
break;
|
|
}
|
|
return translation;
|
|
}
|
|
|
|
/*
|
|
* Convert CPDB groups explicitly supported by GTK print dialog
|
|
*/
|
|
static gchar *
|
|
get_gtk_group (cpdb_printer_obj_t *printer_obj,
|
|
const char *group_name)
|
|
{
|
|
if (g_strcmp0 (group_name, CPDB_GROUP_COLOR) == 0)
|
|
return g_strdup ("ColorPage");
|
|
if (g_strcmp0 (group_name, CPDB_GROUP_QUALITY) == 0)
|
|
return g_strdup ("ImageQualityPage");
|
|
if (g_strcmp0 (group_name, CPDB_GROUP_FINISHINGS) == 0)
|
|
return g_strdup ("FinishingPage");
|
|
return cpdb_group_translation (printer_obj, group_name);
|
|
}
|
|
|
|
/*
|
|
* Do initial setup
|
|
*/
|
|
static void
|
|
initialize (void)
|
|
{
|
|
cpdbInit ();
|
|
|
|
if (locales == NULL)
|
|
locales = g_get_language_names ();
|
|
|
|
if (already_used_options == NULL)
|
|
{
|
|
already_used_options = g_hash_table_new (g_str_hash, g_str_equal);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_COPIES);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_PAGE_RANGES);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_ORIENTATION);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_PAGE_DELIVERY);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_COLLATE);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_NUMBER_UP);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_NUMBER_UP_LAYOUT);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_PAGE_SET);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_MEDIA);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_MARGIN_TOP);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_MARGIN_BOTTOM);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_MARGIN_LEFT);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_MARGIN_RIGHT);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_SIDES);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_MEDIA_SOURCE);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_MEDIA_TYPE);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_OUTPUT_BIN);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_JOB_PRIORITY);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_JOB_SHEETS);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_JOB_HOLD_UNTIL);
|
|
g_hash_table_add (already_used_options, (gpointer) CPDB_OPTION_BILLING_INFO);
|
|
g_hash_table_add (already_used_options, (gpointer) "borderless");
|
|
}
|
|
}
|