+++ /dev/null
-/* GtkCustomPaperUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- * Copyright © 2006, 2007, 2008 Christian Persch
- *
- * 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 <string.h>
-#include <locale.h>
-
-#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
-#include <langinfo.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-#include "gtkprivate.h"
-
-#include "deprecated/gtkliststore.h"
-
-#include "gtksignallistitemfactory.h"
-#include "gtklabel.h"
-#include "gtkspinbutton.h"
-
-#include "gtkcustompaperunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprintutilsprivate.h"
-#include "deprecated/gtkdialogprivate.h"
-
-#define LEGACY_CUSTOM_PAPER_FILENAME ".gtk-custom-papers"
-#define CUSTOM_PAPER_FILENAME "custom-papers"
-
-
-typedef struct
-{
- GtkUnit display_unit;
- GtkWidget *spin_button;
-} UnitWidget;
-
-struct _GtkCustomPaperUnixDialog
-{
- GtkDialog parent_instance;
-
- GtkWidget *listview;
- GtkWidget *values_box;
- GtkWidget *printer_combo;
- GtkWidget *width_widget;
- GtkWidget *height_widget;
- GtkWidget *top_widget;
- GtkWidget *bottom_widget;
- GtkWidget *left_widget;
- GtkWidget *right_widget;
-
- gulong printer_inserted_tag;
-
- guint request_details_tag;
- GtkPrinter *request_details_printer;
-
- guint non_user_change : 1;
-
- GListStore *custom_paper_list;
- GListModel *printer_list;
-
- GList *print_backends;
-};
-
-typedef struct _GtkCustomPaperUnixDialogClass GtkCustomPaperUnixDialogClass;
-
-struct _GtkCustomPaperUnixDialogClass
-{
- GtkDialogClass parent_class;
-};
-
-
-enum {
- PRINTER_LIST_COL_NAME,
- PRINTER_LIST_COL_PRINTER,
- PRINTER_LIST_N_COLS
-};
-
-
-G_DEFINE_TYPE (GtkCustomPaperUnixDialog, gtk_custom_paper_unix_dialog, GTK_TYPE_DIALOG)
-
-
-static void gtk_custom_paper_unix_dialog_constructed (GObject *object);
-static void gtk_custom_paper_unix_dialog_finalize (GObject *object);
-static void populate_dialog (GtkCustomPaperUnixDialog *dialog);
-
-
-
-GtkUnit
-_gtk_print_get_default_user_units (void)
-{
- /* Translate to the default units to use for presenting
- * lengths to the user. Translate to default:inch if you
- * want inches, otherwise translate to default:mm.
- * Do *not* translate it to "predefinito:mm", if it
- * it isn't default:mm or default:inch it will not work
- */
- char *e = _("default:mm");
-
-#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
- char *imperial = NULL;
-
- imperial = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
- if (imperial && imperial[0] == 2 )
- return GTK_UNIT_INCH; /* imperial */
- if (imperial && imperial[0] == 1 )
- return GTK_UNIT_MM; /* metric */
-#endif
-
- if (strcmp (e, "default:inch")==0)
- return GTK_UNIT_INCH;
- else if (strcmp (e, "default:mm"))
- g_warning ("Whoever translated default:mm did so wrongly.");
- return GTK_UNIT_MM;
-}
-
-static char *
-custom_paper_get_legacy_filename (void)
-{
- char *filename;
-
- filename = g_build_filename (g_get_home_dir (),
- LEGACY_CUSTOM_PAPER_FILENAME, NULL);
- g_assert (filename != NULL);
- return filename;
-}
-
-static char *
-custom_paper_get_filename (void)
-{
- char *filename;
-
- filename = g_build_filename (g_get_user_config_dir (),
- "gtk-4.0",
- CUSTOM_PAPER_FILENAME, NULL);
- g_assert (filename != NULL);
- return filename;
-}
-
-GList *
-_gtk_load_custom_papers (void)
-{
- GKeyFile *keyfile;
- char *filename;
- char **groups;
- gsize n_groups, i;
- gboolean load_ok;
- GList *result = NULL;
-
- filename = custom_paper_get_filename ();
-
- keyfile = g_key_file_new ();
- load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
- g_free (filename);
- if (!load_ok)
- {
- /* try legacy file */
- filename = custom_paper_get_legacy_filename ();
- load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
- g_free (filename);
- }
- if (!load_ok)
- {
- g_key_file_free (keyfile);
- return NULL;
- }
-
- groups = g_key_file_get_groups (keyfile, &n_groups);
- for (i = 0; i < n_groups; ++i)
- {
- GtkPageSetup *page_setup;
-
- page_setup = gtk_page_setup_new_from_key_file (keyfile, groups[i], NULL);
- if (!page_setup)
- continue;
-
- result = g_list_prepend (result, page_setup);
- }
-
- g_strfreev (groups);
- g_key_file_free (keyfile);
-
- return g_list_reverse (result);
-}
-
-void
-gtk_print_load_custom_papers (GListStore *store)
-{
- GList *papers, *p;
- GtkPageSetup *page_setup;
-
- g_list_store_remove_all (store);
-
- papers = _gtk_load_custom_papers ();
- for (p = papers; p; p = p->next)
- {
- page_setup = p->data;
- g_list_store_append (store, page_setup);
- g_object_unref (page_setup);
- }
-
- g_list_free (papers);
-}
-
-static void
-gtk_print_save_custom_papers (GListStore *store)
-{
- GKeyFile *keyfile;
- char *filename, *data, *parentdir;
- gsize len;
- int i = 0;
-
- keyfile = g_key_file_new ();
-
- for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
- {
- GtkPageSetup *page_setup;
- char group[32];
-
- page_setup = g_list_model_get_item (G_LIST_MODEL (store), i);
- g_snprintf (group, sizeof (group), "Paper%u", i);
- gtk_page_setup_to_key_file (page_setup, keyfile, group);
- g_object_unref (page_setup);
- }
-
- filename = custom_paper_get_filename ();
- parentdir = g_build_filename (g_get_user_config_dir (),
- "gtk-4.0",
- NULL);
- if (g_mkdir_with_parents (parentdir, 0700) == 0)
- {
- data = g_key_file_to_data (keyfile, &len, NULL);
- g_file_set_contents (filename, data, len, NULL);
- g_free (data);
- }
- g_free (parentdir);
- g_free (filename);
-}
-
-static void
-gtk_custom_paper_unix_dialog_class_init (GtkCustomPaperUnixDialogClass *class)
-{
- G_OBJECT_CLASS (class)->constructed = gtk_custom_paper_unix_dialog_constructed;
- G_OBJECT_CLASS (class)->finalize = gtk_custom_paper_unix_dialog_finalize;
-}
-
-static void
-custom_paper_dialog_response_cb (GtkDialog *dialog,
- int response,
- gpointer user_data)
-{
- GtkCustomPaperUnixDialog *self = GTK_CUSTOM_PAPER_UNIX_DIALOG (dialog);
-
- gtk_print_save_custom_papers (self->custom_paper_list);
-}
-
-static gboolean
-match_func (gpointer item, gpointer user_data)
-{
- return !gtk_printer_is_virtual (GTK_PRINTER (item));
-}
-
-static void
-gtk_custom_paper_unix_dialog_init (GtkCustomPaperUnixDialog *dialog)
-{
- GtkPrinter *printer;
- GListStore *printer_list;
- GListStore *printer_list_list;
- GListModel *full_list;
- GtkFilter *filter;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- dialog->print_backends = NULL;
-
- dialog->request_details_printer = NULL;
- dialog->request_details_tag = 0;
-
- printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
- printer_list = g_list_store_new (GTK_TYPE_PRINTER);
- printer = gtk_printer_new (_("Margins from Printer…"), NULL, FALSE);
- g_list_store_append (printer_list, printer);
- g_object_unref (printer);
- g_list_store_append (printer_list_list, printer_list);
- g_object_unref (printer_list);
-
- full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
-
- filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
- dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
-
- dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
- gtk_print_load_custom_papers (dialog->custom_paper_list);
-
- populate_dialog (dialog);
-
- g_signal_connect (dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), NULL);
-}
-
-static void
-gtk_custom_paper_unix_dialog_constructed (GObject *object)
-{
- gboolean use_header;
-
- G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->constructed (object);
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- g_object_get (object, "use-header-bar", &use_header, NULL);
- if (!use_header)
- {
- gtk_dialog_add_buttons (GTK_DIALOG (object),
- _("_Close"), GTK_RESPONSE_CLOSE,
- NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_CLOSE);
- }
-G_GNUC_END_IGNORE_DEPRECATIONS
-}
-
-static void
-gtk_custom_paper_unix_dialog_finalize (GObject *object)
-{
- GtkCustomPaperUnixDialog *dialog = GTK_CUSTOM_PAPER_UNIX_DIALOG (object);
- GList *node;
-
- if (dialog->printer_list)
- {
- g_signal_handler_disconnect (dialog->printer_list, dialog->printer_inserted_tag);
- g_object_unref (dialog->printer_list);
- dialog->printer_list = NULL;
- }
-
- if (dialog->request_details_tag)
- {
- g_signal_handler_disconnect (dialog->request_details_printer,
- dialog->request_details_tag);
- g_object_unref (dialog->request_details_printer);
- dialog->request_details_printer = NULL;
- dialog->request_details_tag = 0;
- }
-
- g_clear_object (&dialog->custom_paper_list);
-
- for (node = dialog->print_backends; node; node = node->next)
- gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
- g_list_free_full (dialog->print_backends, g_object_unref);
- dialog->print_backends = NULL;
-
- G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->finalize (object);
-}
-
-/**
- * gtk_custom_paper_unix_dialog_new:
- * @title: (nullable): the title of the dialog
- * @parent: (nullable): transient parent of the dialog
- *
- * Creates a new custom paper dialog.
- *
- * Returns: the new `GtkCustomPaperUnixDialog`
- */
-GtkWidget *
-_gtk_custom_paper_unix_dialog_new (GtkWindow *parent,
- const char *title)
-{
- GtkWidget *result;
-
- if (title == NULL)
- title = _("Manage Custom Sizes");
-
- result = g_object_new (GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG,
- "title", title,
- "transient-for", parent,
- "modal", parent != NULL,
- "destroy-with-parent", TRUE,
- "resizable", FALSE,
- NULL);
-
- return result;
-}
-
-static void
-load_print_backends (GtkCustomPaperUnixDialog *dialog)
-{
- GListModel *full_list;
- GListStore *printer_list_list;
- GList *node;
-
- full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
- printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
-
- if (g_module_supported ())
- dialog->print_backends = gtk_print_backend_load_modules ();
-
- for (node = dialog->print_backends; node != NULL; node = node->next)
- {
- GtkPrintBackend *backend = GTK_PRINT_BACKEND (node->data);
- g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
- }
-}
-
-static void unit_widget_changed (GtkCustomPaperUnixDialog *dialog);
-
-static GtkWidget *
-new_unit_widget (GtkCustomPaperUnixDialog *dialog,
- GtkUnit unit,
- GtkWidget *mnemonic_label)
-{
- GtkWidget *hbox, *button, *label;
- UnitWidget *data;
-
- data = g_new0 (UnitWidget, 1);
- data->display_unit = unit;
-
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-
- button = gtk_spin_button_new_with_range (0.0, 9999.0, 1);
- gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
- if (unit == GTK_UNIT_INCH)
- gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 2);
- else
- gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 1);
-
- gtk_box_append (GTK_BOX (hbox), button);
-
- data->spin_button = button;
-
- g_signal_connect_swapped (button, "value-changed",
- G_CALLBACK (unit_widget_changed), dialog);
-
- if (unit == GTK_UNIT_INCH)
- label = gtk_label_new (_("inch"));
- else
- label = gtk_label_new (_("mm"));
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-
- gtk_box_append (GTK_BOX (hbox), label);
- gtk_label_set_mnemonic_widget (GTK_LABEL (mnemonic_label), button);
-
- g_object_set_data_full (G_OBJECT (hbox), "unit-data", data, g_free);
-
- return hbox;
-}
-
-static double
-unit_widget_get (GtkWidget *unit_widget)
-{
- UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
- return _gtk_print_convert_to_mm (gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->spin_button)),
- data->display_unit);
-}
-
-static void
-unit_widget_set (GtkWidget *unit_widget,
- double value)
-{
- UnitWidget *data;
-
- data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->spin_button),
- _gtk_print_convert_from_mm (value, data->display_unit));
-}
-
-static void
-update_combo_sensitivity_from_printers (GtkCustomPaperUnixDialog *dialog)
-{
- gboolean sensitive = FALSE;
-
- if (g_list_model_get_n_items (dialog->printer_list) > 1)
- sensitive = TRUE;
-
- gtk_widget_set_sensitive (dialog->printer_combo, sensitive);
-}
-
-static void
-update_custom_widgets_from_list (GtkCustomPaperUnixDialog *dialog)
-{
- GListModel *model;
- GtkPageSetup *page_setup;
-
- model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
- page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
-
- dialog->non_user_change = TRUE;
- if (page_setup != NULL)
- {
- unit_widget_set (dialog->width_widget,
- gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM));
- unit_widget_set (dialog->height_widget,
- gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM));
- unit_widget_set (dialog->top_widget,
- gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
- unit_widget_set (dialog->bottom_widget,
- gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
- unit_widget_set (dialog->left_widget,
- gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
- unit_widget_set (dialog->right_widget,
- gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
-
- gtk_widget_set_sensitive (dialog->values_box, TRUE);
- }
- else
- {
- gtk_widget_set_sensitive (dialog->values_box, FALSE);
- }
-
- if (dialog->printer_list)
- update_combo_sensitivity_from_printers (dialog);
- dialog->non_user_change = FALSE;
-}
-
-static void
-selected_custom_paper_changed (GObject *list,
- GParamSpec *pspec,
- GtkCustomPaperUnixDialog *dialog)
-{
- update_custom_widgets_from_list (dialog);
-}
-
-static void
-unit_widget_changed (GtkCustomPaperUnixDialog *dialog)
-{
- double w, h, top, bottom, left, right;
- GListModel *model;
- GtkPageSetup *page_setup;
- GtkPaperSize *paper_size;
-
- if (dialog->non_user_change)
- return;
-
- model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
- page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
-
- if (page_setup != NULL)
- {
- w = unit_widget_get (dialog->width_widget);
- h = unit_widget_get (dialog->height_widget);
-
- paper_size = gtk_page_setup_get_paper_size (page_setup);
- gtk_paper_size_set_size (paper_size, w, h, GTK_UNIT_MM);
-
- top = unit_widget_get (dialog->top_widget);
- bottom = unit_widget_get (dialog->bottom_widget);
- left = unit_widget_get (dialog->left_widget);
- right = unit_widget_get (dialog->right_widget);
-
- gtk_page_setup_set_top_margin (page_setup, top, GTK_UNIT_MM);
- gtk_page_setup_set_bottom_margin (page_setup, bottom, GTK_UNIT_MM);
- gtk_page_setup_set_left_margin (page_setup, left, GTK_UNIT_MM);
- gtk_page_setup_set_right_margin (page_setup, right, GTK_UNIT_MM);
- }
-}
-
-static gboolean
-custom_paper_name_used (GtkCustomPaperUnixDialog *dialog,
- const char *name)
-{
- GtkPageSetup *page_setup;
- GtkPaperSize *paper_size;
- guint i;
-
- for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)); i++)
- {
- page_setup = g_list_model_get_item (G_LIST_MODEL (dialog->custom_paper_list), i);
- paper_size = gtk_page_setup_get_paper_size (page_setup);
- if (strcmp (name, gtk_paper_size_get_name (paper_size)) == 0)
- {
- g_object_unref (page_setup);
- return TRUE;
- }
- g_object_unref (page_setup);
- }
-
- return FALSE;
-}
-
-static void
-add_custom_paper (GtkCustomPaperUnixDialog *dialog)
-{
- GtkPageSetup *page_setup;
- GtkPaperSize *paper_size;
- char *name;
- int i;
-
- i = 1;
- name = NULL;
- do
- {
- g_free (name);
- name = g_strdup_printf (_("Custom Size %d"), i);
- i++;
- } while (custom_paper_name_used (dialog, name));
-
- page_setup = gtk_page_setup_new ();
- paper_size = gtk_paper_size_new_custom (name, name,
- gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
- gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
- GTK_UNIT_MM);
- gtk_page_setup_set_paper_size (page_setup, paper_size);
- gtk_paper_size_free (paper_size);
-
- g_list_store_append (dialog->custom_paper_list, page_setup);
- g_object_unref (page_setup);
-
- /* FIXME start editing */
-
- g_free (name);
-}
-
-static void
-remove_custom_paper (GtkCustomPaperUnixDialog *dialog)
-{
- GListModel *model;
- guint selected;
-
- model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
- selected = gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model));
- if (selected != GTK_INVALID_LIST_POSITION)
- g_list_store_remove (dialog->custom_paper_list, selected);
-}
-
-static void
-set_margins_from_printer (GtkCustomPaperUnixDialog *dialog,
- GtkPrinter *printer)
-{
- double top, bottom, left, right;
-
- top = bottom = left = right = 0;
- if (!gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right))
- return;
-
- dialog->non_user_change = TRUE;
- unit_widget_set (dialog->top_widget, _gtk_print_convert_to_mm (top, GTK_UNIT_POINTS));
- unit_widget_set (dialog->bottom_widget, _gtk_print_convert_to_mm (bottom, GTK_UNIT_POINTS));
- unit_widget_set (dialog->left_widget, _gtk_print_convert_to_mm (left, GTK_UNIT_POINTS));
- unit_widget_set (dialog->right_widget, _gtk_print_convert_to_mm (right, GTK_UNIT_POINTS));
- dialog->non_user_change = FALSE;
-
- /* Only send one change */
- unit_widget_changed (dialog);
-}
-
-static void
-get_margins_finished_callback (GtkPrinter *printer,
- gboolean success,
- GtkCustomPaperUnixDialog *dialog)
-{
- g_signal_handler_disconnect (dialog->request_details_printer,
- dialog->request_details_tag);
- g_object_unref (dialog->request_details_printer);
- dialog->request_details_tag = 0;
- dialog->request_details_printer = NULL;
-
- if (success)
- set_margins_from_printer (dialog, printer);
-
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
-}
-
-static void
-margins_from_printer_changed (GtkCustomPaperUnixDialog *dialog)
-{
- guint selected;
- GtkPrinter *printer;
-
- if (dialog->request_details_tag)
- {
- g_signal_handler_disconnect (dialog->request_details_printer,
- dialog->request_details_tag);
- g_object_unref (dialog->request_details_printer);
- dialog->request_details_printer = NULL;
- dialog->request_details_tag = 0;
- }
-
- selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
- if (selected != 0)
- {
- GListModel *model;
-
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
- printer = g_list_model_get_item (model, selected);
-
- if (printer)
- {
- if (gtk_printer_has_details (printer))
- {
- set_margins_from_printer (dialog, printer);
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
- }
- else
- {
- dialog->request_details_printer = g_object_ref (printer);
- dialog->request_details_tag =
- g_signal_connect (printer, "details-acquired",
- G_CALLBACK (get_margins_finished_callback), dialog);
- gtk_printer_request_details (printer);
- }
-
- g_object_unref (printer);
- }
- }
-}
-
-static GtkWidget *
-wrap_in_frame (const char *label,
- GtkWidget *child)
-{
- GtkWidget *frame, *label_widget;
- char *bold_text;
-
- label_widget = gtk_label_new (NULL);
- gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
- gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
-
- bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
- gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
- g_free (bold_text);
-
- frame = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
- gtk_box_append (GTK_BOX (frame), label_widget);
-
- gtk_widget_set_margin_start (child, 12);
- gtk_widget_set_halign (child, GTK_ALIGN_FILL);
- gtk_widget_set_valign (child, GTK_ALIGN_FILL);
-
- gtk_box_append (GTK_BOX (frame), child);
-
- return frame;
-}
-
-static void
-setup_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- gtk_list_item_set_child (item, gtk_editable_label_new (""));
-}
-
-static void
-label_changed (GObject *object,
- GParamSpec *pspec,
- GtkListItem *item)
-{
- GtkPageSetup *page_setup;
- GtkPaperSize *paper_size;
- const char *new_text;
-
- page_setup = gtk_list_item_get_item (item);
-
- new_text = gtk_editable_get_text (GTK_EDITABLE (object));
-
- paper_size = gtk_paper_size_new_custom (new_text, new_text,
- gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
- gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM), GTK_UNIT_MM);
- gtk_page_setup_set_paper_size (page_setup, paper_size);
- gtk_paper_size_free (paper_size);
-}
-
-static void
-state_changed (GtkWidget *item,
- GtkStateFlags old_state,
- GtkWidget *label)
-{
- gboolean selected;
-
- selected = (gtk_widget_get_state_flags (item) & GTK_STATE_FLAG_SELECTED) != 0;
- gtk_editable_set_editable (GTK_EDITABLE (label), selected);
-}
-
-static void
-bind_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkPageSetup *page_setup;
- GtkPaperSize *paper_size;
- GtkWidget *label;
-
- page_setup = gtk_list_item_get_item (item);
- label = gtk_list_item_get_child (item);
-
- paper_size = gtk_page_setup_get_paper_size (page_setup);
- gtk_editable_set_text (GTK_EDITABLE (label),
- gtk_paper_size_get_display_name (paper_size));
- g_signal_connect (label, "notify::text",
- G_CALLBACK (label_changed), item);
- g_signal_connect (gtk_widget_get_parent (label), "state-flags-changed",
- G_CALLBACK (state_changed), label);
-}
-
-static void
-unbind_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkWidget *label;
-
- label = gtk_list_item_get_child (item);
- g_signal_handlers_disconnect_by_func (label, label_changed, item);
- g_signal_handlers_disconnect_by_func (gtk_widget_get_parent (label), state_changed, label);
-}
-
-static void
-setup_printer_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkWidget *label;
-
- label = gtk_label_new ("");
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_printer_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkPrinter *printer;
- GtkWidget *label;
-
- printer = gtk_list_item_get_item (item);
- label = gtk_list_item_get_child (item);
-
- gtk_label_set_label (GTK_LABEL (label), gtk_printer_get_name (printer));
-}
-
-static void
-populate_dialog (GtkCustomPaperUnixDialog *dialog)
-{
- GtkDialog *cpu_dialog = GTK_DIALOG (dialog);
- GtkWidget *content_area;
- GtkWidget *grid, *label, *widget, *frame, *combo;
- GtkWidget *hbox, *vbox, *listview, *scrolled, *toolbar, *button;
- GtkUnit user_units;
- GtkSelectionModel *model;
- GtkListItemFactory *factory;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- content_area = gtk_dialog_get_content_area (cpu_dialog);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
-
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18);
- gtk_widget_set_margin_start (hbox, 20);
- gtk_widget_set_margin_end (hbox, 20);
- gtk_widget_set_margin_top (hbox, 20);
- gtk_widget_set_margin_bottom (hbox, 20);
- gtk_box_append (GTK_BOX (content_area), hbox);
-
- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_append (GTK_BOX (hbox), vbox);
-
- scrolled = gtk_scrolled_window_new ();
- gtk_widget_set_vexpand (scrolled, TRUE);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled), TRUE);
- gtk_box_append (GTK_BOX (vbox), scrolled);
-
- model = GTK_SELECTION_MODEL (gtk_single_selection_new (g_object_ref (G_LIST_MODEL (dialog->custom_paper_list))));
- g_signal_connect (model, "notify::selected", G_CALLBACK (selected_custom_paper_changed), dialog);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
- g_signal_connect (factory, "unbind", G_CALLBACK (unbind_item), NULL);
-
- listview = gtk_list_view_new (model, factory);
- gtk_widget_set_size_request (listview, 140, -1);
-
- dialog->listview = listview;
-
- gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), listview);
-
- toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
- gtk_widget_add_css_class (toolbar, "linked");
-
- gtk_box_append (GTK_BOX (vbox), toolbar);
-
- button = gtk_button_new_from_icon_name ("list-add-symbolic");
- g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_custom_paper), dialog);
-
- gtk_box_append (GTK_BOX (toolbar), button);
-
- button = gtk_button_new_from_icon_name ("list-remove-symbolic");
- g_signal_connect_swapped (button, "clicked", G_CALLBACK (remove_custom_paper), dialog);
-
- gtk_box_append (GTK_BOX (toolbar), button);
-
- user_units = _gtk_print_get_default_user_units ();
-
- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18);
- dialog->values_box = vbox;
- gtk_box_append (GTK_BOX (hbox), vbox);
-
- grid = gtk_grid_new ();
-
- gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
- gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
-
- label = gtk_label_new_with_mnemonic (_("_Width:"));
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
- gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
- widget = new_unit_widget (dialog, user_units, label);
- dialog->width_widget = widget;
- gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
-
- label = gtk_label_new_with_mnemonic (_("_Height:"));
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
- gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
-
- widget = new_unit_widget (dialog, user_units, label);
- dialog->height_widget = widget;
- gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
-
- frame = wrap_in_frame (_("Paper Size"), grid);
- gtk_box_append (GTK_BOX (vbox), frame);
-
- grid = gtk_grid_new ();
- gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
- gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
-
- label = gtk_label_new_with_mnemonic (_("_Top:"));
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
- gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
- widget = new_unit_widget (dialog, user_units, label);
- dialog->top_widget = widget;
- gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
-
- label = gtk_label_new_with_mnemonic (_("_Bottom:"));
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
- gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
-
- widget = new_unit_widget (dialog, user_units, label);
- dialog->bottom_widget = widget;
- gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
-
- label = gtk_label_new_with_mnemonic (_("_Left:"));
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
- gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
-
- widget = new_unit_widget (dialog, user_units, label);
- dialog->left_widget = widget;
- gtk_grid_attach (GTK_GRID (grid), widget, 1, 2, 1, 1);
-
- label = gtk_label_new_with_mnemonic (_("_Right:"));
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
- gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
-
- widget = new_unit_widget (dialog, user_units, label);
- dialog->right_widget = widget;
- gtk_grid_attach (GTK_GRID (grid), widget, 1, 3, 1, 1);
-
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_grid_attach (GTK_GRID (grid), hbox, 0, 4, 2, 1);
-
- combo = gtk_drop_down_new (g_object_ref (dialog->printer_list), NULL);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
- gtk_drop_down_set_factory (GTK_DROP_DOWN (combo), factory);
- g_object_unref (factory);
-
- dialog->printer_combo = combo;
-
- dialog->printer_inserted_tag =
- g_signal_connect_swapped (dialog->printer_list, "items-changed",
- G_CALLBACK (update_combo_sensitivity_from_printers), dialog);
- update_combo_sensitivity_from_printers (dialog);
-
- gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), 0);
- gtk_box_append (GTK_BOX (hbox), combo);
-
- g_signal_connect_swapped (combo, "notify::selected",
- G_CALLBACK (margins_from_printer_changed), dialog);
-
- frame = wrap_in_frame (_("Paper Margins"), grid);
- gtk_box_append (GTK_BOX (vbox), frame);
-
- update_custom_widgets_from_list (dialog);
-
- if (g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)) == 0)
- add_custom_paper (dialog);
-
- load_print_backends (dialog);
-}
+++ /dev/null
-/* GtkCustomPaperUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.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/>.
- */
-
-#pragma once
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG (gtk_custom_paper_unix_dialog_get_type ())
-#define GTK_CUSTOM_PAPER_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG, GtkCustomPaperUnixDialog))
-#define GTK_IS_CUSTOM_PAPER_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG))
-
-typedef struct _GtkCustomPaperUnixDialog GtkCustomPaperUnixDialog;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_custom_paper_unix_dialog_get_type (void) G_GNUC_CONST;
-GtkWidget * _gtk_custom_paper_unix_dialog_new (GtkWindow *parent,
- const char *title);
-GtkUnit _gtk_print_get_default_user_units (void);
-void gtk_print_load_custom_papers (GListStore *store);
-GList * _gtk_load_custom_papers (void);
-
-
-G_END_DECLS
-
#include "gtkwidgetprivate.h"
#include "gtkwindowprivate.h"
#include "gtkwindowgroup.h"
-#include "gtkprintbackendprivate.h"
+#include "print/gtkprintbackendprivate.h"
#include "gtkimmoduleprivate.h"
#include "gtkroot.h"
#include "gtknative.h"
+++ /dev/null
-/* GtkPageSetupUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- * Copyright © 2006, 2007, 2008 Christian Persch
- *
- * 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 <string.h>
-#include <locale.h>
-
-#include <glib/gi18n-lib.h>
-#include "gtkprivate.h"
-
-#include "gtkbutton.h"
-#include "gtkscrolledwindow.h"
-#include "gtkcheckbutton.h"
-#include "gtklabel.h"
-#include "gtkgrid.h"
-
-#include "gtkpagesetupunixdialog.h"
-#include "gtkcustompaperunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "print/gtkpapersize.h"
-#include "gtkprintutilsprivate.h"
-#include "deprecated/gtkdialogprivate.h"
-
-/**
- * GtkPageSetupUnixDialog:
- *
- * `GtkPageSetupUnixDialog` implements a page setup dialog for platforms
- * which don’t provide a native page setup dialog, like Unix.
- *
- * 
- *
- * It can be used very much like any other GTK dialog, at the
- * cost of the portability offered by the high-level printing
- * API in [class@Gtk.PrintOperation].
- *
- * ## CSS nodes
- *
- * `GtkPageSetupUnixDialog` has a single CSS node with the name `window` and
- * style class `.pagesetup`.
- */
-
-typedef struct _GtkPageSetupUnixDialogClass GtkPageSetupUnixDialogClass;
-
-struct _GtkPageSetupUnixDialog
-{
- GtkDialog parent_instance;
-
- GListModel *printer_list;
- GListStore *page_setup_list;
- GListStore *custom_paper_list;
- GListStore *manage_papers_list;
- GListStore *paper_size_list;
-
- GList *print_backends;
-
- GtkWidget *printer_combo;
- GtkWidget *paper_size_combo;
- GtkWidget *paper_size_label;
-
- GtkWidget *portrait_radio;
- GtkWidget *reverse_portrait_radio;
- GtkWidget *landscape_radio;
- GtkWidget *reverse_landscape_radio;
-
- gulong request_details_tag;
- GtkPrinter *request_details_printer;
-
- GtkPrintSettings *print_settings;
-
- gboolean internal_change;
-
- /* Save last setup so we can re-set it after selecting manage custom sizes */
- GtkPageSetup *last_setup;
-};
-
-struct _GtkPageSetupUnixDialogClass
-{
- GtkDialogClass parent_class;
-};
-
-
-/* Keep these in line with GtkListStores defined in gtkpagesetupunixprintdialog.ui */
-enum {
- PRINTER_LIST_COL_NAME,
- PRINTER_LIST_COL_PRINTER,
- PRINTER_LIST_N_COLS
-};
-
-enum {
- PAGE_SETUP_LIST_COL_PAGE_SETUP,
- PAGE_SETUP_LIST_COL_IS_SEPARATOR,
- PAGE_SETUP_LIST_N_COLS
-};
-
-G_DEFINE_TYPE (GtkPageSetupUnixDialog, gtk_page_setup_unix_dialog, GTK_TYPE_DIALOG)
-
-static void gtk_page_setup_unix_dialog_finalize (GObject *object);
-static void fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
- GtkPrinter *printer);
-static void printer_changed_callback (GtkDropDown *combo_box,
- GParamSpec *pspec,
- GtkPageSetupUnixDialog *dialog);
-static void paper_size_changed (GtkDropDown *combo_box,
- GParamSpec *pspec,
- GtkPageSetupUnixDialog *dialog);
-static void load_print_backends (GtkPageSetupUnixDialog *dialog);
-
-
-static const char common_paper_sizes[][16] = {
- "na_letter",
- "na_legal",
- "iso_a4",
- "iso_a5",
- "roc_16k",
- "iso_b5",
- "jis_b5",
- "na_number-10",
- "iso_dl",
- "jpn_chou3",
- "na_ledger",
- "iso_a3"
-};
-
-
-static void
-gtk_page_setup_unix_dialog_class_init (GtkPageSetupUnixDialogClass *class)
-{
- GObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- object_class = G_OBJECT_CLASS (class);
- widget_class = GTK_WIDGET_CLASS (class);
-
- object_class->finalize = gtk_page_setup_unix_dialog_finalize;
-
- /* Bind class to template
- */
- gtk_widget_class_set_template_from_resource (widget_class,
- "/org/gtk/libgtk/ui/gtkpagesetupunixdialog.ui");
-
- gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, printer_combo);
- gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, paper_size_combo);
- gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, paper_size_label);
- gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, portrait_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, reverse_portrait_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, landscape_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, reverse_landscape_radio);
-
- gtk_widget_class_bind_template_callback (widget_class, printer_changed_callback);
- gtk_widget_class_bind_template_callback (widget_class, paper_size_changed);
-}
-
-static void
-setup_paper_size_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkWidget *label;
-
- label = gtk_label_new ("");
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_paper_size_list_item (GtkSignalListItemFactory *factory,
- GtkListItem *item,
- GtkPageSetupUnixDialog *self)
-{
- GtkPageSetup *page_setup;
- GtkWidget *label;
- guint pos;
- GListModel *papers;
- GListModel *model;
- gpointer first;
-
- page_setup = gtk_list_item_get_item (item);
- label = gtk_list_item_get_child (item);
-
- pos = gtk_list_item_get_position (item);
- papers = gtk_drop_down_get_model (GTK_DROP_DOWN (self->paper_size_combo));
- model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), pos);
- if (model != G_LIST_MODEL (self->manage_papers_list))
- {
- GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
- gtk_label_set_text (GTK_LABEL (label), gtk_paper_size_get_display_name (paper_size));
- }
- else
- gtk_label_set_text (GTK_LABEL (label), _("Manage Custom Sizes…"));
-
- first = g_list_model_get_item (model, 0);
- g_object_unref (first);
- if (pos != 0 &&
- page_setup == GTK_PAGE_SETUP (first))
- gtk_widget_add_css_class (gtk_widget_get_parent (label), "separator");
- else
- gtk_widget_remove_css_class (gtk_widget_get_parent (label), "separator");
-}
-
-static void
-bind_paper_size_item (GtkSignalListItemFactory *factory,
- GtkListItem *item,
- GtkPageSetupUnixDialog *self)
-{
- GtkWidget *label;
-
- bind_paper_size_list_item (factory, item, self);
-
- label = gtk_list_item_get_child (item);
- gtk_widget_remove_css_class (label, "separator-before");
-}
-
-static gboolean
-match_func (gpointer item, gpointer user_data)
-{
- return !gtk_printer_is_virtual (GTK_PRINTER (item));
-}
-
-static void
-setup_printer_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkWidget *label;
-
- label = gtk_label_new ("");
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_printer_item (GtkSignalListItemFactory *factory,
- GtkListItem *item,
- GtkPageSetupUnixDialog *self)
-{
- GtkPrinter *printer;
- GtkWidget *label;
- const char *location;
- const char *name;
- char *str;
-
- printer = gtk_list_item_get_item (item);
- label = gtk_list_item_get_child (item);
-
- name = gtk_printer_get_name (printer);
- location = gtk_printer_get_location (printer);
- str = g_strdup_printf ("<b>%s</b>\n%s", name, location ? location : "");
- gtk_label_set_markup (GTK_LABEL (label), str);
- g_free (str);
-}
-
-static void
-gtk_page_setup_unix_dialog_init (GtkPageSetupUnixDialog *dialog)
-{
- GtkListItemFactory *factory;
- GListStore *store;
- GListModel *paper_size_list;
- GtkPrinter *printer;
- GListStore *printer_list;
- GListStore *printer_list_list;
- GListModel *full_list;
- GtkFilter *filter;
- GtkPageSetup *page_setup;
-
- dialog->internal_change = TRUE;
- dialog->print_backends = NULL;
-
- gtk_widget_init_template (GTK_WIDGET (dialog));
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
- gtk_dialog_add_buttons (GTK_DIALOG (dialog),
- _("_Cancel"), GTK_RESPONSE_CANCEL,
- _("_Apply"), GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
- dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
- dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
- page_setup = gtk_page_setup_new ();
- g_list_store_append (dialog->manage_papers_list, page_setup);
- g_object_unref (page_setup);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
- gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
- g_object_unref (factory);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
- gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
- g_object_unref (factory);
-
- store = g_list_store_new (G_TYPE_LIST_MODEL);
- g_list_store_append (store, dialog->page_setup_list);
- g_list_store_append (store, dialog->custom_paper_list);
- g_list_store_append (store, dialog->manage_papers_list);
- paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
- gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
- g_object_unref (paper_size_list);
-
- /* Do this in code, we want the translatable strings without the markup */
- printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
- printer_list = g_list_store_new (GTK_TYPE_PRINTER);
- printer = gtk_printer_new (_("Any Printer"), NULL, FALSE);
- gtk_printer_set_location (printer, _("For portable documents"));
- g_list_store_append (printer_list, printer);
- g_object_unref (printer);
- g_list_store_append (printer_list_list, printer_list);
- g_object_unref (printer_list);
-
- full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
-
- filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
- dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
- gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->printer_combo), factory);
- g_object_unref (factory);
-
- gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->printer_combo), dialog->printer_list);
- printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
-
- /* Load data */
- gtk_print_load_custom_papers (dialog->custom_paper_list);
- load_print_backends (dialog);
- dialog->internal_change = FALSE;
-}
-
-static void
-gtk_page_setup_unix_dialog_finalize (GObject *object)
-{
- GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
- GList *node;
-
- if (dialog->request_details_tag)
- {
- g_signal_handler_disconnect (dialog->request_details_printer,
- dialog->request_details_tag);
- g_object_unref (dialog->request_details_printer);
- dialog->request_details_printer = NULL;
- dialog->request_details_tag = 0;
- }
-
- g_clear_object (&dialog->printer_list);
- g_clear_object (&dialog->page_setup_list);
- g_clear_object (&dialog->custom_paper_list);
- g_clear_object (&dialog->manage_papers_list);
-
- if (dialog->print_settings)
- {
- g_object_unref (dialog->print_settings);
- dialog->print_settings = NULL;
- }
-
- for (node = dialog->print_backends; node != NULL; node = node->next)
- gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
- g_list_free_full (dialog->print_backends, g_object_unref);
- dialog->print_backends = NULL;
-
- G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
-}
-
-static void
-load_print_backends (GtkPageSetupUnixDialog *dialog)
-{
- GListModel *full_list;
- GListStore *printer_list_list;
- GList *node;
-
- full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
- printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
-
- if (g_module_supported ())
- dialog->print_backends = gtk_print_backend_load_modules ();
-
- for (node = dialog->print_backends; node != NULL; node = node->next)
- {
- GtkPrintBackend *backend = node->data;
- g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
- }
-}
-
-static GtkPageSetup *
-get_current_page_setup (GtkPageSetupUnixDialog *dialog)
-{
- guint selected;
- GListModel *model;
-
- selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->paper_size_combo));
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
- if (selected != GTK_INVALID_LIST_POSITION)
- return g_list_model_get_item (model, selected);
-
- return gtk_page_setup_new ();
-}
-
-static gboolean
-page_setup_is_equal (GtkPageSetup *a,
- GtkPageSetup *b)
-{
- return
- gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
- gtk_page_setup_get_paper_size (b)) &&
- gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
- gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
- gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
- gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
-}
-
-static gboolean
-page_setup_is_same_size (GtkPageSetup *a,
- GtkPageSetup *b)
-{
- return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
- gtk_page_setup_get_paper_size (b));
-}
-
-static gboolean
-set_paper_size (GtkPageSetupUnixDialog *dialog,
- GtkPageSetup *page_setup,
- gboolean size_only,
- gboolean add_item)
-{
- GListModel *model;
- GtkPageSetup *list_page_setup;
- guint i;
-
- if (page_setup == NULL)
- return FALSE;
-
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
- for (i = 0; i < g_list_model_get_n_items (model); i++)
- {
- list_page_setup = g_list_model_get_item (model, i);
- if (list_page_setup == NULL)
- continue;
-
- if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
- (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
- {
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
- g_object_unref (list_page_setup);
- return TRUE;
- }
-
- g_object_unref (list_page_setup);
- }
-
- if (add_item)
- {
- i = g_list_model_get_n_items (model);
- g_list_store_append (dialog->page_setup_list, page_setup);
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
- GtkPrinter *printer)
-{
- GList *list, *l;
- GtkPageSetup *current_page_setup, *page_setup;
- GtkPaperSize *paper_size;
- int i;
-
- g_list_store_remove_all (dialog->page_setup_list);
-
- if (printer == NULL)
- {
- for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
- {
- page_setup = gtk_page_setup_new ();
- paper_size = gtk_paper_size_new (common_paper_sizes[i]);
- gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
- gtk_paper_size_free (paper_size);
-
- g_list_store_append (dialog->page_setup_list, page_setup);
- g_object_unref (page_setup);
- }
- }
- else
- {
- list = gtk_printer_list_papers (printer);
- /* TODO: We should really sort this list so interesting size
- are at the top */
- for (l = list; l != NULL; l = l->next)
- {
- page_setup = l->data;
- g_list_store_append (dialog->page_setup_list, page_setup);
- g_object_unref (page_setup);
- }
- g_list_free (list);
- }
-
- current_page_setup = NULL;
-
- /* When selecting a different printer, select its default paper size */
- if (printer != NULL)
- current_page_setup = gtk_printer_get_default_page_size (printer);
-
- if (current_page_setup == NULL)
- current_page_setup = get_current_page_setup (dialog);
-
- if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
- set_paper_size (dialog, current_page_setup, TRUE, TRUE);
-
- if (current_page_setup)
- g_object_unref (current_page_setup);
-}
-
-static void
-printer_changed_finished_callback (GtkPrinter *printer,
- gboolean success,
- GtkPageSetupUnixDialog *dialog)
-{
- g_signal_handler_disconnect (dialog->request_details_printer,
- dialog->request_details_tag);
- g_object_unref (dialog->request_details_printer);
- dialog->request_details_tag = 0;
- dialog->request_details_printer = NULL;
-
- if (success)
- fill_paper_sizes_from_printer (dialog, printer);
-
-}
-
-static void
-printer_changed_callback (GtkDropDown *combo_box,
- GParamSpec *pspec,
- GtkPageSetupUnixDialog *dialog)
-{
- GtkPrinter *printer;
- guint selected;
-
- if (dialog->request_details_tag)
- {
- g_signal_handler_disconnect (dialog->request_details_printer,
- dialog->request_details_tag);
- g_object_unref (dialog->request_details_printer);
- dialog->request_details_printer = NULL;
- dialog->request_details_tag = 0;
- }
-
- selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
- if (selected != GTK_INVALID_LIST_POSITION)
- {
- GListModel *model;
-
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
- printer = g_list_model_get_item (model, selected);
- if (strcmp (gtk_printer_get_name (printer), _("Any Printer")) == 0)
- g_clear_object (&printer);
-
- if (printer == NULL ||
- gtk_printer_has_details (printer))
- fill_paper_sizes_from_printer (dialog, printer);
- else
- {
- dialog->request_details_printer = g_object_ref (printer);
- dialog->request_details_tag =
- g_signal_connect (printer, "details-acquired",
- G_CALLBACK (printer_changed_finished_callback), dialog);
- gtk_printer_request_details (printer);
- }
-
- if (printer)
- g_object_unref (printer);
-
- if (dialog->print_settings)
- {
- const char *name = NULL;
-
- if (printer)
- name = gtk_printer_get_name (printer);
-
- gtk_print_settings_set (dialog->print_settings,
- "format-for-printer", name);
- }
- }
-}
-
-/* We do this munging because we don't want to show zero digits
- after the decimal point, and not to many such digits if they
- are nonzero. I wish printf let you specify max precision for %f... */
-static char *
-double_to_string (double d,
- GtkUnit unit)
-{
- char *val, *p;
- struct lconv *locale_data;
- const char *decimal_point;
- int decimal_point_len;
-
- locale_data = localeconv ();
- decimal_point = locale_data->decimal_point;
- decimal_point_len = strlen (decimal_point);
-
- /* Max two decimal digits for inch, max one for mm */
- if (unit == GTK_UNIT_INCH)
- val = g_strdup_printf ("%.2f", d);
- else
- val = g_strdup_printf ("%.1f", d);
-
- if (strstr (val, decimal_point))
- {
- p = val + strlen (val) - 1;
- while (*p == '0')
- p--;
- if (p - val + 1 >= decimal_point_len &&
- strncmp (p - (decimal_point_len - 1), decimal_point, decimal_point_len) == 0)
- p -= decimal_point_len;
- p[1] = '\0';
- }
-
- return val;
-}
-
-
-static void
-custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
- int response_id,
- gpointer user_data)
-{
- GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (user_data);
- GtkPageSetup *last_page_setup;
-
- dialog->internal_change = TRUE;
- gtk_print_load_custom_papers (dialog->custom_paper_list);
- printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
- dialog->internal_change = FALSE;
-
- if (dialog->last_setup)
- last_page_setup = g_object_ref (dialog->last_setup);
- else
- last_page_setup = gtk_page_setup_new (); /* "good" default */
- set_paper_size (dialog, last_page_setup, FALSE, TRUE);
- g_object_unref (last_page_setup);
-
- gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
-}
-
-static void
-paper_size_changed (GtkDropDown *combo_box,
- GParamSpec *pspec,
- GtkPageSetupUnixDialog *dialog)
-{
- GtkPageSetup *page_setup, *last_page_setup;
- guint selected;
- GtkUnit unit;
- char *str, *w, *h;
- char *top, *bottom, *left, *right;
- GtkLabel *label;
- const char *unit_str;
-
- if (dialog->internal_change)
- return;
-
- label = GTK_LABEL (dialog->paper_size_label);
-
- selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
- if (selected != GTK_INVALID_LIST_POSITION)
- {
- GListModel *papers, *model;
-
- papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
- page_setup = g_list_model_get_item (papers, selected);
- model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
-
- if (model == G_LIST_MODEL (dialog->manage_papers_list))
- {
- GtkWidget *custom_paper_dialog;
-
- /* Change from "manage" menu item to last value */
- if (dialog->last_setup)
- last_page_setup = g_object_ref (dialog->last_setup);
- else
- last_page_setup = gtk_page_setup_new (); /* "good" default */
- set_paper_size (dialog, last_page_setup, FALSE, TRUE);
- g_object_unref (last_page_setup);
-
- /* And show the custom paper dialog */
- custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), NULL);
- g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
- gtk_window_present (GTK_WINDOW (custom_paper_dialog));
-
- g_object_unref (page_setup);
-
- return;
- }
-
- if (dialog->last_setup)
- g_object_unref (dialog->last_setup);
-
- dialog->last_setup = g_object_ref (page_setup);
-
- unit = _gtk_print_get_default_user_units ();
-
- if (unit == GTK_UNIT_MM)
- unit_str = _("mm");
- else
- unit_str = _("inch");
-
- w = double_to_string (gtk_page_setup_get_paper_width (page_setup, unit),
- unit);
- h = double_to_string (gtk_page_setup_get_paper_height (page_setup, unit),
- unit);
- str = g_strdup_printf ("%s × %s %s", w, h, unit_str);
- g_free (w);
- g_free (h);
-
- gtk_label_set_text (label, str);
- g_free (str);
-
- top = double_to_string (gtk_page_setup_get_top_margin (page_setup, unit), unit);
- bottom = double_to_string (gtk_page_setup_get_bottom_margin (page_setup, unit), unit);
- left = double_to_string (gtk_page_setup_get_left_margin (page_setup, unit), unit);
- right = double_to_string (gtk_page_setup_get_right_margin (page_setup, unit), unit);
-
- str = g_strdup_printf (_("Margins:\n"
- " Left: %s %s\n"
- " Right: %s %s\n"
- " Top: %s %s\n"
- " Bottom: %s %s"
- ),
- left, unit_str,
- right, unit_str,
- top, unit_str,
- bottom, unit_str);
- g_free (top);
- g_free (bottom);
- g_free (left);
- g_free (right);
-
- gtk_widget_set_tooltip_text (dialog->paper_size_label, str);
- g_free (str);
-
- g_object_unref (page_setup);
- }
- else
- {
- gtk_label_set_text (label, "");
- gtk_widget_set_tooltip_text (dialog->paper_size_label, NULL);
- if (dialog->last_setup)
- g_object_unref (dialog->last_setup);
- dialog->last_setup = NULL;
- }
-}
-
-/**
- * gtk_page_setup_unix_dialog_new:
- * @title: (nullable): the title of the dialog
- * @parent: (nullable): transient parent of the dialog
- *
- * Creates a new page setup dialog.
- *
- * Returns: the new `GtkPageSetupUnixDialog`
- */
-GtkWidget *
-gtk_page_setup_unix_dialog_new (const char *title,
- GtkWindow *parent)
-{
- GtkWidget *result;
-
- if (title == NULL)
- title = _("Page Setup");
-
- result = g_object_new (GTK_TYPE_PAGE_SETUP_UNIX_DIALOG,
- "title", title,
- NULL);
-
- if (parent)
- gtk_window_set_transient_for (GTK_WINDOW (result), parent);
-
- return result;
-}
-
-static GtkPageOrientation
-get_orientation (GtkPageSetupUnixDialog *dialog)
-{
- if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->portrait_radio)))
- return GTK_PAGE_ORIENTATION_PORTRAIT;
- if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->landscape_radio)))
- return GTK_PAGE_ORIENTATION_LANDSCAPE;
- if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio)))
- return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
- return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
-}
-
-static void
-set_orientation (GtkPageSetupUnixDialog *dialog,
- GtkPageOrientation orientation)
-{
- switch (orientation)
- {
- case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_portrait_radio), TRUE);
- break;
- case GTK_PAGE_ORIENTATION_PORTRAIT:
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->portrait_radio), TRUE);
- break;
- case GTK_PAGE_ORIENTATION_LANDSCAPE:
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->landscape_radio), TRUE);
- break;
- case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio), TRUE);
- break;
- default:
- break;
- }
-}
-
-/**
- * gtk_page_setup_unix_dialog_set_page_setup:
- * @dialog: a `GtkPageSetupUnixDialog`
- * @page_setup: a `GtkPageSetup`
- *
- * Sets the `GtkPageSetup` from which the page setup
- * dialog takes its values.
- */
-void
-gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
- GtkPageSetup *page_setup)
-{
- if (page_setup)
- {
- set_paper_size (dialog, page_setup, FALSE, TRUE);
- set_orientation (dialog, gtk_page_setup_get_orientation (page_setup));
- }
-}
-
-/**
- * gtk_page_setup_unix_dialog_get_page_setup:
- * @dialog: a `GtkPageSetupUnixDialog`
- *
- * Gets the currently selected page setup from the dialog.
- *
- * Returns: (transfer none): the current page setup
- */
-GtkPageSetup *
-gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog)
-{
- GtkPageSetup *page_setup;
-
- page_setup = get_current_page_setup (dialog);
-
- gtk_page_setup_set_orientation (page_setup, get_orientation (dialog));
-
- return page_setup;
-}
-
-static gboolean
-set_active_printer (GtkPageSetupUnixDialog *dialog,
- const char *printer_name)
-{
- guint i, n;
- GtkPrinter *printer;
-
- if (!printer_name)
- return FALSE;
-
- for (i = 0, n = g_list_model_get_n_items (dialog->printer_list); i < n; i++)
- {
- printer = g_list_model_get_item (dialog->printer_list, i);
-
- if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
- {
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), i);
- g_object_unref (printer);
-
- return TRUE;
- }
-
- g_object_unref (printer);
- }
-
- return FALSE;
-}
-
-/**
- * gtk_page_setup_unix_dialog_set_print_settings:
- * @dialog: a `GtkPageSetupUnixDialog`
- * @print_settings: (nullable): a `GtkPrintSettings`
- *
- * Sets the `GtkPrintSettings` from which the page setup dialog
- * takes its values.
- */
-void
-gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
- GtkPrintSettings *print_settings)
-{
- const char *format_for_printer;
-
- if (dialog->print_settings == print_settings) return;
-
- if (dialog->print_settings)
- g_object_unref (dialog->print_settings);
-
- dialog->print_settings = print_settings;
-
- if (print_settings)
- {
- g_object_ref (print_settings);
-
- format_for_printer = gtk_print_settings_get (print_settings, "format-for-printer");
-
- /* Set printer if in list, otherwise set when
- * that printer is added
- */
- set_active_printer (dialog, format_for_printer);
- }
-}
-
-/**
- * gtk_page_setup_unix_dialog_get_print_settings:
- * @dialog: a `GtkPageSetupUnixDialog`
- *
- * Gets the current print settings from the dialog.
- *
- * Returns: (transfer none) (nullable): the current print settings
- **/
-GtkPrintSettings *
-gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog)
-{
- return dialog->print_settings;
-}
+++ /dev/null
-/* GtkPageSetupUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.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/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PAGE_SETUP_UNIX_DIALOG (gtk_page_setup_unix_dialog_get_type ())
-#define GTK_PAGE_SETUP_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG, GtkPageSetupUnixDialog))
-#define GTK_IS_PAGE_SETUP_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG))
-
-
-typedef struct _GtkPageSetupUnixDialog GtkPageSetupUnixDialog;
-
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_page_setup_unix_dialog_get_type (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkWidget * gtk_page_setup_unix_dialog_new (const char *title,
- GtkWindow *parent);
-GDK_AVAILABLE_IN_ALL
-void gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
- GtkPageSetup *page_setup);
-GDK_AVAILABLE_IN_ALL
-GtkPageSetup * gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
- GtkPrintSettings *print_settings);
-GDK_AVAILABLE_IN_ALL
-GtkPrintSettings *gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog);
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintoperation.c: Print Operation
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#ifndef _MSC_VER
-#ifndef _WIN32_WINNT
-/* Vista or newer */
-#define _WIN32_WINNT 0x0600
-#endif
-#ifndef WINVER
-#define WINVER _WIN32_WINNT
-#endif
-#endif
-
-#include "config.h"
-#include "gtkprint-win32.h"
-
-void
-gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames)
-{
- g_free (devnames->driver);
- g_free (devnames->device);
- g_free (devnames->output);
- g_free (devnames);
-}
-
-GtkPrintWin32Devnames *
-gtk_print_win32_devnames_from_win32 (HGLOBAL global)
-{
- LPDEVNAMES win = GlobalLock (global);
- gunichar2 *data = (gunichar2 *)win;
- GtkPrintWin32Devnames *devnames = g_new (GtkPrintWin32Devnames, 1);
-
- devnames->driver = g_utf16_to_utf8 (data + win->wDriverOffset,
- -1, NULL, NULL, NULL);
- devnames->device = g_utf16_to_utf8 (data + win->wDeviceOffset,
- -1, NULL, NULL, NULL);
- devnames->output = g_utf16_to_utf8 (data + win->wOutputOffset,
- -1, NULL, NULL, NULL);
- devnames->flags = win->wDefault;
-
- GlobalUnlock (global);
-
- return devnames;
-}
-
-HGLOBAL
-gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames)
-{
- HGLOBAL global;
- LPDEVNAMES windevnames;
- gunichar2 *data;
- gunichar2 *driver, *device, *output;
- glong driver_len, device_len, output_len;
- int i;
-
- driver = g_utf8_to_utf16 (devnames->driver, -1, NULL, &driver_len, NULL);
- device = g_utf8_to_utf16 (devnames->device, -1, NULL, &device_len, NULL);
- output = g_utf8_to_utf16 (devnames->output, -1, NULL, &output_len, NULL);
-
- global = GlobalAlloc (GMEM_MOVEABLE,
- sizeof (DEVNAMES) +
- (driver_len + 1) * 2 +
- (device_len + 1) * 2 +
- (output_len + 1) * 2);
-
- windevnames = GlobalLock (global);
- data = (gunichar2 *)windevnames;
- i = sizeof(DEVNAMES) / sizeof (gunichar2);
-
- windevnames->wDriverOffset = i;
- memcpy (data + i, driver, (driver_len + 1) * sizeof (gunichar2));
- i += driver_len + 1;
- windevnames->wDeviceOffset = i;
- memcpy (data + i, device, (device_len + 1) * sizeof (gunichar2));
- i += device_len + 1;
- windevnames->wOutputOffset = i;
- memcpy (data + i, output, (output_len + 1) * sizeof (gunichar2));
- i += output_len + 1;
- windevnames->wDefault = devnames->flags;
- GlobalUnlock (global);
-
- g_free (driver);
- g_free (device);
- g_free (output);
-
- return global;
-}
-
-HGLOBAL
-gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer_name)
-{
- HGLOBAL global;
- GtkPrintWin32Devnames *devnames;
-
- devnames = gtk_print_win32_devnames_from_printer_name(printer_name);
- if (devnames)
- {
- global = gtk_print_win32_devnames_to_win32 (devnames);
- gtk_print_win32_devnames_free (devnames);
- }
- else
- global = NULL;
-
- return global;
-}
-
-/*
- * Used to get printer device information from a printer name. This
- * can fail if the user has no right to read printer properties, so
- * this function can return NULL.
- */
-GtkPrintWin32Devnames *
-gtk_print_win32_devnames_from_printer_name (const char *printer_name)
-{
- HANDLE hprinter;
- gunichar2* win32_printer_name;
- GtkPrintWin32Devnames *devnames;
-
- win32_printer_name = g_utf8_to_utf16 (printer_name, -1, NULL, NULL, NULL);
- if (OpenPrinterW (win32_printer_name, &hprinter, NULL))
- {
- DWORD needed;
- PRINTER_INFO_2W* printer_info;
-
- GetPrinterW (hprinter, 2, NULL, 0, &needed);
- printer_info = (PRINTER_INFO_2W* )g_malloc ((gsize) needed);
- GetPrinterW (hprinter, 2, (LPBYTE) printer_info, needed, &needed);
- devnames = g_new (GtkPrintWin32Devnames, 1);
- devnames->driver = g_utf16_to_utf8 (printer_info->pDriverName, -1, NULL, NULL, NULL);
- devnames->device = g_strdup (printer_name);
- devnames->output = g_utf16_to_utf8 (printer_info->pPortName, -1, NULL, NULL, NULL);
- devnames->flags = 0;
- ClosePrinter (hprinter);
- g_free (printer_info);
- }
- else
- {
- /* Could not open printer */
- devnames = NULL;
- }
- g_free (win32_printer_name);
-
- return devnames;
-}
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprint-win32.h: Win32 Print utils
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-#include "win32/gdkwin32.h"
-
-G_BEGIN_DECLS
-
-#ifndef START_PAGE_GENERAL
-#define START_PAGE_GENERAL 0xffffffff
-#endif
-
-#ifndef PD_RESULT_CANCEL
-#define PD_RESULT_CANCEL 0
-#define PD_RESULT_PRINT 1
-#define PD_RESULT_APPLY 2
-#endif
-
-#ifndef PD_NOCURRENTPAGE
-#define PD_NOCURRENTPAGE 0x00800000
-#endif
-
-#ifndef PD_CURRENTPAGE
-#define PD_CURRENTPAGE 0x00400000
-#endif
-
-typedef struct {
- char *driver;
- char *device;
- char *output;
- int flags;
-} GtkPrintWin32Devnames;
-
-GDK_AVAILABLE_IN_ALL
-void gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames);
-GDK_AVAILABLE_IN_ALL
-GtkPrintWin32Devnames *gtk_print_win32_devnames_from_win32 (HGLOBAL global);
-GDK_AVAILABLE_IN_ALL
-GtkPrintWin32Devnames *gtk_print_win32_devnames_from_printer_name (const char *printer);
-GDK_AVAILABLE_IN_ALL
-HGLOBAL gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames);
-GDK_AVAILABLE_IN_ALL
-HGLOBAL gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer);
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintbackendprivate.h: Abstract printer backend interfaces
- * Copyright (C) 2003, Red Hat, Inc.
- *
- * 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 <string.h>
-
-#include <gmodule.h>
-
-#include <glib/gi18n-lib.h>
-#include "gtkdebug.h"
-#include "gtkmodulesprivate.h"
-#include "gtkmarshalers.h"
-#include "gtkprivate.h"
-#include "gtkprintbackendprivate.h"
-
-
-static void gtk_print_backend_finalize (GObject *object);
-static void gtk_print_backend_dispose (GObject *object);
-static void gtk_print_backend_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_print_backend_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
-struct _GtkPrintBackendPrivate
-{
- GListStore *printers;
- guint printer_list_requested : 1;
- guint printer_list_done : 1;
- GtkPrintBackendStatus status;
- char **auth_info_required;
- char **auth_info;
- gboolean store_auth_info;
-};
-
-enum {
- PRINTER_LIST_CHANGED,
- PRINTER_LIST_DONE,
- PRINTER_ADDED,
- PRINTER_REMOVED,
- PRINTER_STATUS_CHANGED,
- REQUEST_PASSWORD,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-enum
-{
- PROP_ZERO,
- PROP_STATUS
-};
-
-static GObjectClass *backend_parent_class;
-
-GQuark
-gtk_print_backend_error_quark (void)
-{
- static GQuark quark = 0;
- if (quark == 0)
- quark = g_quark_from_static_string ("gtk-print-backend-error-quark");
- return quark;
-}
-
-void
-gtk_print_backends_init (void)
-{
- GIOExtensionPoint *ep;
- GIOModuleScope *scope;
- char **paths;
- int i;
-
- GTK_DEBUG (MODULES, "Registering extension point %s", GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
-
- ep = g_io_extension_point_register (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
- g_io_extension_point_set_required_type (ep, GTK_TYPE_PRINT_BACKEND);
-
- scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
-
- paths = _gtk_get_module_path ("printbackends");
- for (i = 0; paths[i]; i++)
- {
- GTK_DEBUG (MODULES, "Scanning io modules in %s", paths[i]);
- g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
- }
- g_strfreev (paths);
-
- g_io_module_scope_free (scope);
-
- if (GTK_DEBUG_CHECK (MODULES))
- {
- GList *list, *l;
-
- list = g_io_extension_point_get_extensions (ep);
- for (l = list; l; l = l->next)
- {
- GIOExtension *ext = l->data;
- g_print ("extension: %s: type %s\n",
- g_io_extension_get_name (ext),
- g_type_name (g_io_extension_get_type (ext)));
- }
- }
-}
-
-/**
- * gtk_print_backend_load_modules:
- *
- * Returns: (element-type GtkPrintBackend) (transfer container):
- */
-GList *
-gtk_print_backend_load_modules (void)
-{
- GList *result;
- GtkPrintBackend *backend;
- char *setting;
- char **backends;
- int i;
- GtkSettings *settings;
- GIOExtensionPoint *ep;
-
- result = NULL;
-
- ep = g_io_extension_point_lookup (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
-
- settings = gtk_settings_get_default ();
- if (settings)
- g_object_get (settings, "gtk-print-backends", &setting, NULL);
- else
- setting = g_strdup (GTK_PRINT_BACKENDS);
-
- backends = g_strsplit (setting, ",", -1);
-
- for (i = 0; backends[i]; i++)
- {
- GIOExtension *ext;
- GType type;
-
- ext = g_io_extension_point_get_extension_by_name (ep, backends[i]);
- if (!ext)
- continue;
-
- GTK_DEBUG (PRINTING, "Found %s print backend", backends[i]);
-
- type = g_io_extension_get_type (ext);
- backend = g_object_new (type, NULL);
- result = g_list_append (result, backend);
- }
-
- g_strfreev (backends);
- g_free (setting);
-
- return result;
-}
-
-/*****************************************
- * GtkPrintBackend *
- *****************************************/
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
-
-static void fallback_printer_request_details (GtkPrinter *printer);
-static gboolean fallback_printer_mark_conflicts (GtkPrinter *printer,
- GtkPrinterOptionSet *options);
-static gboolean fallback_printer_get_hard_margins (GtkPrinter *printer,
- double *top,
- double *bottom,
- double *left,
- double *right);
-static gboolean fallback_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
- GtkPaperSize *paper_size,
- double *top,
- double *bottom,
- double *left,
- double *right);
-static GList * fallback_printer_list_papers (GtkPrinter *printer);
-static GtkPageSetup * fallback_printer_get_default_page_size (GtkPrinter *printer);
-static GtkPrintCapabilities fallback_printer_get_capabilities (GtkPrinter *printer);
-static void request_password (GtkPrintBackend *backend,
- gpointer auth_info_required,
- gpointer auth_info_default,
- gpointer auth_info_display,
- gpointer auth_info_visible,
- const char *prompt,
- gboolean can_store_auth_info);
-
-static void
-gtk_print_backend_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
- GtkPrintBackendPrivate *priv = backend->priv;
-
- switch (prop_id)
- {
- case PROP_STATUS:
- priv->status = g_value_get_int (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_print_backend_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
- GtkPrintBackendPrivate *priv = backend->priv;
-
- switch (prop_id)
- {
- case PROP_STATUS:
- g_value_set_int (value, priv->status);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_print_backend_class_init (GtkPrintBackendClass *class)
-{
- GObjectClass *object_class;
- object_class = (GObjectClass *) class;
-
- backend_parent_class = g_type_class_peek_parent (class);
-
- object_class->finalize = gtk_print_backend_finalize;
- object_class->dispose = gtk_print_backend_dispose;
- object_class->set_property = gtk_print_backend_set_property;
- object_class->get_property = gtk_print_backend_get_property;
-
- class->printer_request_details = fallback_printer_request_details;
- class->printer_mark_conflicts = fallback_printer_mark_conflicts;
- class->printer_get_hard_margins = fallback_printer_get_hard_margins;
- class->printer_get_hard_margins_for_paper_size = fallback_printer_get_hard_margins_for_paper_size;
- class->printer_list_papers = fallback_printer_list_papers;
- class->printer_get_default_page_size = fallback_printer_get_default_page_size;
- class->printer_get_capabilities = fallback_printer_get_capabilities;
- class->request_password = request_password;
-
- g_object_class_install_property (object_class,
- PROP_STATUS,
- g_param_spec_int ("status", NULL, NULL,
- GTK_PRINT_BACKEND_STATUS_UNKNOWN,
- GTK_PRINT_BACKEND_STATUS_UNAVAILABLE,
- GTK_PRINT_BACKEND_STATUS_UNKNOWN,
- GTK_PARAM_READWRITE));
-
- signals[PRINTER_LIST_CHANGED] =
- g_signal_new (I_("printer-list-changed"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
- signals[PRINTER_LIST_DONE] =
- g_signal_new (I_("printer-list-done"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
- signals[PRINTER_ADDED] =
- g_signal_new (I_("printer-added"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
- signals[PRINTER_REMOVED] =
- g_signal_new (I_("printer-removed"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
- signals[PRINTER_STATUS_CHANGED] =
- g_signal_new (I_("printer-status-changed"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
- signals[REQUEST_PASSWORD] =
- g_signal_new (I_("request-password"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
- NULL, NULL, NULL,
- G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER,
- G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
-}
-
-static void
-gtk_print_backend_init (GtkPrintBackend *backend)
-{
- GtkPrintBackendPrivate *priv;
-
- priv = backend->priv = gtk_print_backend_get_instance_private (backend);
-
- priv->printers = g_list_store_new (GTK_TYPE_PRINTER);
- priv->auth_info_required = NULL;
- priv->auth_info = NULL;
-}
-
-static void
-gtk_print_backend_dispose (GObject *object)
-{
- GtkPrintBackend *backend;
- GtkPrintBackendPrivate *priv;
-
- backend = GTK_PRINT_BACKEND (object);
- priv = backend->priv;
-
- /* We unref the printers in dispose, not in finalize so that
- * we can break refcount cycles with gtk_print_backend_destroy
- */
- g_list_store_remove_all (priv->printers);
-
- backend_parent_class->dispose (object);
-}
-
-static void
-gtk_print_backend_finalize (GObject *object)
-{
- GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
- GtkPrintBackendPrivate *priv = backend->priv;
-
- g_clear_object (&priv->printers);
-
- backend_parent_class->finalize (object);
-}
-
-static void
-fallback_printer_request_details (GtkPrinter *printer)
-{
-}
-
-static gboolean
-fallback_printer_mark_conflicts (GtkPrinter *printer,
- GtkPrinterOptionSet *options)
-{
- return FALSE;
-}
-
-static gboolean
-fallback_printer_get_hard_margins (GtkPrinter *printer,
- double *top,
- double *bottom,
- double *left,
- double *right)
-{
- return FALSE;
-}
-
-static gboolean
-fallback_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
- GtkPaperSize *paper_size,
- double *top,
- double *bottom,
- double *left,
- double *right)
-{
- return FALSE;
-}
-
-static GList *
-fallback_printer_list_papers (GtkPrinter *printer)
-{
- return NULL;
-}
-
-static GtkPageSetup *
-fallback_printer_get_default_page_size (GtkPrinter *printer)
-{
- return NULL;
-}
-
-static GtkPrintCapabilities
-fallback_printer_get_capabilities (GtkPrinter *printer)
-{
- return 0;
-}
-
-void
-gtk_print_backend_add_printer (GtkPrintBackend *backend,
- GtkPrinter *printer)
-{
- g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
- g_list_store_append (backend->priv->printers, printer);
-}
-
-void
-gtk_print_backend_remove_printer (GtkPrintBackend *backend,
- GtkPrinter *printer)
-{
- guint position;
-
- g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
- if (g_list_store_find (backend->priv->printers, printer, &position))
- g_list_store_remove (backend->priv->printers, position);
-}
-
-void
-gtk_print_backend_set_list_done (GtkPrintBackend *backend)
-{
- if (!backend->priv->printer_list_done)
- {
- backend->priv->printer_list_done = TRUE;
- g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
- }
-}
-
-
-/**
- * gtk_print_backend_get_printer_list:
- *
- * Returns the current list of printers.
- *
- * Returns: (element-type GtkPrinter) (transfer container):
- * A list of `GtkPrinter` objects
- */
-GList *
-gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
-{
- GList *result = NULL;
- guint i;
-
- g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
-
- for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
- {
- GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
- result = g_list_prepend (result, printer);
- g_object_unref (printer);
- }
-
- if (!backend->priv->printer_list_requested)
- {
- if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
- GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
- backend->priv->printer_list_requested = TRUE;
- }
-
- return result;
-}
-
-GListModel *
-gtk_print_backend_get_printers (GtkPrintBackend *backend)
-{
- if (!backend->priv->printer_list_requested)
- {
- if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
- GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
- backend->priv->printer_list_requested = TRUE;
- }
-
- return G_LIST_MODEL (backend->priv->printers);
-}
-
-gboolean
-gtk_print_backend_printer_list_is_done (GtkPrintBackend *backend)
-{
- g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), TRUE);
-
- return backend->priv->printer_list_done;
-}
-
-GtkPrinter *
-gtk_print_backend_find_printer (GtkPrintBackend *backend,
- const char *printer_name)
-{
- GtkPrinter *result = NULL;
- guint i;
-
- g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
-
- for (i = 0; !result && i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
- {
- GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
- if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
- result = printer;
- g_object_unref (printer);
- }
-
- return result;
-}
-
-void
-gtk_print_backend_print_stream (GtkPrintBackend *backend,
- GtkPrintJob *job,
- GIOChannel *data_io,
- GtkPrintJobCompleteFunc callback,
- gpointer user_data,
- GDestroyNotify dnotify)
-{
- g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
- GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
- job,
- data_io,
- callback,
- user_data,
- dnotify);
-}
-
-void
-gtk_print_backend_set_password (GtkPrintBackend *backend,
- char **auth_info_required,
- char **auth_info,
- gboolean store_auth_info)
-{
- g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
- if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
- GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend,
- auth_info_required,
- auth_info,
- store_auth_info);
-}
-
-static void
-store_auth_info_toggled (GtkCheckButton *chkbtn,
- gpointer user_data)
-{
- gboolean *data = (gboolean *) user_data;
- *data = gtk_check_button_get_active (GTK_CHECK_BUTTON (chkbtn));
-}
-
-static void
-store_entry (GtkEntry *entry,
- gpointer user_data)
-{
- char **data = (char **) user_data;
-
- if (*data != NULL)
- {
- memset (*data, 0, strlen (*data));
- g_free (*data);
- }
-
- *data = g_strdup (gtk_editable_get_text (GTK_EDITABLE (entry)));
-}
-
-static void
-password_dialog_response (GtkWidget *dialog,
- int response_id,
- GtkPrintBackend *backend)
-{
- GtkPrintBackendPrivate *priv = backend->priv;
- int i, auth_info_len;
-
- if (response_id == GTK_RESPONSE_OK)
- gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info, priv->store_auth_info);
- else
- gtk_print_backend_set_password (backend, priv->auth_info_required, NULL, FALSE);
-
- /* We want to clear the data before freeing it */
- auth_info_len = g_strv_length (priv->auth_info_required);
- for (i = 0; i < auth_info_len; i++)
- {
- if (priv->auth_info[i] != NULL)
- {
- memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
- g_free (priv->auth_info[i]);
- priv->auth_info[i] = NULL;
- }
- }
-
- g_clear_pointer (&priv->auth_info, g_free);
- g_clear_pointer (&priv->auth_info_required, g_strfreev);
-
- gtk_window_destroy (GTK_WINDOW (dialog));
-
- g_object_unref (backend);
-}
-
-static void
-request_password (GtkPrintBackend *backend,
- gpointer auth_info_required,
- gpointer auth_info_default,
- gpointer auth_info_display,
- gpointer auth_info_visible,
- const char *prompt,
- gboolean can_store_auth_info)
-{
- GtkPrintBackendPrivate *priv = backend->priv;
- GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry, *chkbtn;
- GtkWidget *focus = NULL;
- GtkWidget *content_area;
- char *markup;
- int length;
- int i;
- char **ai_required = (char **) auth_info_required;
- char **ai_default = (char **) auth_info_default;
- char **ai_display = (char **) auth_info_display;
- gboolean *ai_visible = (gboolean *) auth_info_visible;
-
- priv->auth_info_required = g_strdupv (ai_required);
- length = g_strv_length (ai_required);
- priv->auth_info = g_new0 (char *, length + 1);
- priv->store_auth_info = FALSE;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL,
- _("_Cancel"), GTK_RESPONSE_CANCEL,
- _("_OK"), GTK_RESPONSE_OK,
- NULL);
-
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
- /* Left */
- icon = gtk_image_new_from_icon_name ("dialog-password-symbolic");
- gtk_image_set_icon_size (GTK_IMAGE (icon), GTK_ICON_SIZE_LARGE);
- gtk_widget_set_halign (icon, GTK_ALIGN_CENTER);
- gtk_widget_set_valign (icon, GTK_ALIGN_START);
- gtk_widget_set_margin_start (icon, 12);
- gtk_widget_set_margin_end (icon, 12);
- gtk_widget_set_margin_top (icon, 12);
- gtk_widget_set_margin_bottom (icon, 12);
-
- /* Right */
- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_set_size_request (GTK_WIDGET (vbox), 320, -1);
-
- /* Right - 1. */
- label = gtk_label_new (NULL);
- markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"large\">%s</span>", prompt);
- gtk_label_set_markup (GTK_LABEL (label), markup);
- gtk_label_set_wrap (GTK_LABEL (label), TRUE);
- gtk_widget_set_size_request (GTK_WIDGET (label), 320, -1);
- g_free (markup);
-
- /* Packing */
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-G_GNUC_END_IGNORE_DEPRECATIONS
- gtk_box_append (GTK_BOX (content_area), main_box);
-
- gtk_box_append (GTK_BOX (main_box), icon);
- gtk_box_append (GTK_BOX (main_box), vbox);
-
- gtk_box_append (GTK_BOX (vbox), label);
-
- /* Right - 2. */
- for (i = 0; i < length; i++)
- {
- priv->auth_info[i] = g_strdup (ai_default[i]);
- if (ai_display[i] != NULL)
- {
- box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
- gtk_widget_set_margin_top (box, 6);
- gtk_widget_set_margin_bottom (box, 6);
-
- label = gtk_label_new (ai_display[i]);
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
-
- entry = gtk_entry_new ();
- focus = entry;
-
- if (ai_default[i] != NULL)
- gtk_editable_set_text (GTK_EDITABLE (entry), ai_default[i]);
-
- gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
- gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
-
- gtk_box_append (GTK_BOX (vbox), box);
-
- gtk_box_append (GTK_BOX (box), label);
- gtk_box_append (GTK_BOX (box), entry);
-
- g_signal_connect (entry, "changed",
- G_CALLBACK (store_entry), &(priv->auth_info[i]));
- }
- }
-
- if (can_store_auth_info)
- {
- chkbtn = gtk_check_button_new_with_mnemonic (_("_Remember password"));
- gtk_widget_set_margin_top (chkbtn, 6);
- gtk_widget_set_margin_bottom (chkbtn, 6);
- gtk_check_button_set_active (GTK_CHECK_BUTTON (chkbtn), FALSE);
- gtk_box_append (GTK_BOX (vbox), chkbtn);
- g_signal_connect (chkbtn, "toggled",
- G_CALLBACK (store_auth_info_toggled),
- &(priv->store_auth_info));
- }
-
- if (focus != NULL)
- {
- gtk_widget_grab_focus (focus);
- focus = NULL;
- }
-
- g_object_ref (backend);
- g_signal_connect (G_OBJECT (dialog), "response",
- G_CALLBACK (password_dialog_response), backend);
-
- gtk_window_present (GTK_WINDOW (dialog));
-}
-
-void
-gtk_print_backend_destroy (GtkPrintBackend *backend)
-{
- /* The lifecycle of print backends and printers are tied, such that
- * the backend owns the printers, but the printers also ref the backend.
- * This is so that if the app has a reference to a printer its backend
- * will be around. However, this results in a cycle, which we break
- * with this call, which causes the print backend to release its printers.
- */
- g_object_run_dispose (G_OBJECT (backend));
-}
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintbackend.h: Abstract printer backend interfaces
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-/* This is a "semi-private" header; it is meant only for
- * alternate GtkPrintDialog backend modules; no stability guarantees
- * are made at this point
- */
-#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
-#error "GtkPrintBackend is not supported API for general use"
-#endif
-
-#include <gtk/gtk.h>
-#include <gtk/gtkunixprint.h>
-#include <gtk/gtkprinteroptionsetprivate.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GtkPrintBackendClass GtkPrintBackendClass;
-typedef struct _GtkPrintBackendPrivate GtkPrintBackendPrivate;
-
-#define GTK_PRINT_BACKEND_ERROR (gtk_print_backend_error_quark ())
-
-typedef enum
-{
- /* TODO: add specific errors */
- GTK_PRINT_BACKEND_ERROR_GENERIC
-} GtkPrintBackendError;
-
-GDK_AVAILABLE_IN_ALL
-GQuark gtk_print_backend_error_quark (void);
-
-#define GTK_TYPE_PRINT_BACKEND (gtk_print_backend_get_type ())
-#define GTK_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
-#define GTK_PRINT_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
-#define GTK_IS_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
-#define GTK_IS_PRINT_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND))
-#define GTK_PRINT_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
-
-typedef enum
-{
- GTK_PRINT_BACKEND_STATUS_UNKNOWN,
- GTK_PRINT_BACKEND_STATUS_OK,
- GTK_PRINT_BACKEND_STATUS_UNAVAILABLE
-} GtkPrintBackendStatus;
-
-struct _GtkPrintBackend
-{
- GObject parent_instance;
-
- GtkPrintBackendPrivate *priv;
-};
-
-struct _GtkPrintBackendClass
-{
- GObjectClass parent_class;
-
- /* Global backend methods: */
- void (*request_printer_list) (GtkPrintBackend *backend);
- void (*print_stream) (GtkPrintBackend *backend,
- GtkPrintJob *job,
- GIOChannel *data_io,
- GtkPrintJobCompleteFunc callback,
- gpointer user_data,
- GDestroyNotify dnotify);
-
- /* Printer methods: */
- void (*printer_request_details) (GtkPrinter *printer);
- cairo_surface_t * (*printer_create_cairo_surface) (GtkPrinter *printer,
- GtkPrintSettings *settings,
- double height,
- double width,
- GIOChannel *cache_io);
- GtkPrinterOptionSet * (*printer_get_options) (GtkPrinter *printer,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup,
- GtkPrintCapabilities capabilities);
- gboolean (*printer_mark_conflicts) (GtkPrinter *printer,
- GtkPrinterOptionSet *options);
- void (*printer_get_settings_from_options) (GtkPrinter *printer,
- GtkPrinterOptionSet *options,
- GtkPrintSettings *settings);
- void (*printer_prepare_for_print) (GtkPrinter *printer,
- GtkPrintJob *print_job,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup);
- GList * (*printer_list_papers) (GtkPrinter *printer);
- GtkPageSetup * (*printer_get_default_page_size) (GtkPrinter *printer);
- gboolean (*printer_get_hard_margins) (GtkPrinter *printer,
- double *top,
- double *bottom,
- double *left,
- double *right);
- GtkPrintCapabilities (*printer_get_capabilities) (GtkPrinter *printer);
-
- /* Signals */
- void (*printer_list_changed) (GtkPrintBackend *backend);
- void (*printer_list_done) (GtkPrintBackend *backend);
- void (*printer_added) (GtkPrintBackend *backend,
- GtkPrinter *printer);
- void (*printer_removed) (GtkPrintBackend *backend,
- GtkPrinter *printer);
- void (*printer_status_changed) (GtkPrintBackend *backend,
- GtkPrinter *printer);
- void (*request_password) (GtkPrintBackend *backend,
- gpointer auth_info_required,
- gpointer auth_info_default,
- gpointer auth_info_display,
- gpointer auth_info_visible,
- const char *prompt,
- gboolean can_store_auth_info);
-
- /* not a signal */
- void (*set_password) (GtkPrintBackend *backend,
- char **auth_info_required,
- char **auth_info,
- gboolean store_auth_info);
-
- gboolean (*printer_get_hard_margins_for_paper_size) (GtkPrinter *printer,
- GtkPaperSize *paper_size,
- double *top,
- double *bottom,
- double *left,
- double *right);
-};
-
-#define GTK_PRINT_BACKEND_EXTENSION_POINT_NAME "gtk-print-backend"
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_print_backend_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GList *gtk_print_backend_get_printer_list (GtkPrintBackend *print_backend);
-GDK_AVAILABLE_IN_ALL
-GListModel *gtk_print_backend_get_printers (GtkPrintBackend *print_backend);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend);
-GDK_AVAILABLE_IN_ALL
-GtkPrinter *gtk_print_backend_find_printer (GtkPrintBackend *print_backend,
- const char *printer_name);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_backend_print_stream (GtkPrintBackend *print_backend,
- GtkPrintJob *job,
- GIOChannel *data_io,
- GtkPrintJobCompleteFunc callback,
- gpointer user_data,
- GDestroyNotify dnotify);
-GDK_AVAILABLE_IN_ALL
-GList * gtk_print_backend_load_modules (void);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_backend_destroy (GtkPrintBackend *print_backend);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_backend_set_password (GtkPrintBackend *backend,
- char **auth_info_required,
- char **auth_info,
- gboolean can_store_auth_info);
-
-/* Backend-only functions for GtkPrintBackend */
-
-GDK_AVAILABLE_IN_ALL
-void gtk_print_backend_add_printer (GtkPrintBackend *print_backend,
- GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_backend_remove_printer (GtkPrintBackend *print_backend,
- GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_backend_set_list_done (GtkPrintBackend *backend);
-
-
-/* Backend-only functions for GtkPrinter */
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_is_new (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_set_accepts_pdf (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_set_accepts_ps (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_set_is_new (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_set_is_active (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_set_is_paused (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_set_is_accepting_jobs (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_set_has_details (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_set_is_default (GtkPrinter *printer,
- gboolean val);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_set_icon_name (GtkPrinter *printer,
- const char *icon);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_set_job_count (GtkPrinter *printer,
- int count);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_set_location (GtkPrinter *printer,
- const char *location);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_set_description (GtkPrinter *printer,
- const char *description);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_set_state_message (GtkPrinter *printer,
- const char *message);
-
-void gtk_print_backends_init (void);
-
-
-G_END_DECLS
-
+++ /dev/null
-/* GtkPrinter
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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 <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "gtkprivate.h"
-
-#include "gtkprinter.h"
-#include "gtkprinterprivate.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprintjob.h"
-
-/**
- * GtkPrinter:
- *
- * A `GtkPrinter` object represents a printer.
- *
- * You only need to deal directly with printers if you use the
- * non-portable [class@Gtk.PrintUnixDialog] API.
- *
- * A `GtkPrinter` allows to get status information about the printer,
- * such as its description, its location, the number of queued jobs,
- * etc. Most importantly, a `GtkPrinter` object can be used to create
- * a [class@Gtk.PrintJob] object, which lets you print to the printer.
- */
-
-
-static void gtk_printer_finalize (GObject *object);
-
-struct _GtkPrinterPrivate
-{
- char *name;
- char *location;
- char *description;
- char *icon_name;
-
- guint is_active : 1;
- guint is_paused : 1;
- guint is_accepting_jobs : 1;
- guint is_new : 1;
- guint is_virtual : 1;
- guint is_default : 1;
- guint has_details : 1;
- guint accepts_pdf : 1;
- guint accepts_ps : 1;
-
- char *state_message;
- int job_count;
-
- GtkPrintBackend *backend;
-};
-
-enum {
- DETAILS_ACQUIRED,
- LAST_SIGNAL
-};
-
-enum {
- PROP_0,
- PROP_NAME,
- PROP_BACKEND,
- PROP_IS_VIRTUAL,
- PROP_STATE_MESSAGE,
- PROP_LOCATION,
- PROP_ICON_NAME,
- PROP_JOB_COUNT,
- PROP_ACCEPTS_PDF,
- PROP_ACCEPTS_PS,
- PROP_PAUSED,
- PROP_ACCEPTING_JOBS
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void gtk_printer_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_printer_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinter, gtk_printer, G_TYPE_OBJECT)
-
-static void
-gtk_printer_class_init (GtkPrinterClass *class)
-{
- GObjectClass *object_class;
- object_class = (GObjectClass *) class;
-
- object_class->finalize = gtk_printer_finalize;
-
- object_class->set_property = gtk_printer_set_property;
- object_class->get_property = gtk_printer_get_property;
-
- /**
- * GtkPrinter:name: (attributes org.gtk.Property.get=gtk_printer_get_name)
- *
- * The name of the printer.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_NAME,
- g_param_spec_string ("name", NULL, NULL,
- "",
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrinter:backend: (attributes org.gtk.Property.get=gtk_printer_get_backend)
- *
- * The backend for the printer.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_BACKEND,
- g_param_spec_object ("backend", NULL, NULL,
- GTK_TYPE_PRINT_BACKEND,
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrinter:is-virtual: (attributes org.gtk.Property.get=gtk_printer_is_virtual)
- *
- * %FALSE if this represents a real hardware device.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_IS_VIRTUAL,
- g_param_spec_boolean ("is-virtual", NULL, NULL,
- FALSE,
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrinter:accepts-pdf: (attributes org.gtk.Property.get=gtk_printer_accepts_pdf)
- *
- * %TRUE if this printer can accept PDF.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_ACCEPTS_PDF,
- g_param_spec_boolean ("accepts-pdf", NULL, NULL,
- FALSE,
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrinter:accepts-ps: (attributes org.gtk.Property.get=gtk_printer_accepts_ps)
- *
- * %TRUE if this printer can accept PostScript.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_ACCEPTS_PS,
- g_param_spec_boolean ("accepts-ps", NULL, NULL,
- TRUE,
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrinter:state-message: (attributes org.gtk.Property.get=gtk_printer_get_state_message)
- *
- * String giving the current status of the printer.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_STATE_MESSAGE,
- g_param_spec_string ("state-message", NULL, NULL,
- "",
- GTK_PARAM_READABLE));
-
- /**
- * GtkPrinter:location: (attributes org.gtk.Property.get=gtk_printer_get_location)
- *
- * Information about the location of the printer.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_LOCATION,
- g_param_spec_string ("location", NULL, NULL,
- "",
- GTK_PARAM_READABLE));
-
- /**
- * GtkPrinter:icon-name: (attributes org.gtk.Property.get=gtk_printer_get_icon_name)
- *
- * Icon name to use for the printer.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_ICON_NAME,
- g_param_spec_string ("icon-name", NULL, NULL,
- "printer",
- GTK_PARAM_READABLE));
-
- /**
- * GtkPrinter:job-count: (attributes org.gtk.Property.get=gtk_printer_get_job_count)
- *
- * Number of jobs queued in the printer.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_JOB_COUNT,
- g_param_spec_int ("job-count", NULL, NULL,
- 0,
- G_MAXINT,
- 0,
- GTK_PARAM_READABLE));
-
- /**
- * GtkPrinter:paused: (attributes org.gtk.Property.get=gtk_printer_is_paused)
- *
- * %TRUE if this printer is paused.
- *
- * A paused printer still accepts jobs, but it does
- * not print them.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_PAUSED,
- g_param_spec_boolean ("paused", NULL, NULL,
- FALSE,
- GTK_PARAM_READABLE));
-
- /**
- * GtkPrinter:accepting-jobs: (attributes org.gtk.Property.get=gtk_printer_is_accepting_jobs)
- *
- * %TRUE if the printer is accepting jobs.
- */
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_ACCEPTING_JOBS,
- g_param_spec_boolean ("accepting-jobs", NULL, NULL,
- TRUE,
- GTK_PARAM_READABLE));
-
- /**
- * GtkPrinter::details-acquired:
- * @printer: the `GtkPrinter` on which the signal is emitted
- * @success: %TRUE if the details were successfully acquired
- *
- * Emitted in response to a request for detailed information
- * about a printer from the print backend.
- *
- * The @success parameter indicates if the information was
- * actually obtained.
- */
- signals[DETAILS_ACQUIRED] =
- g_signal_new (I_("details-acquired"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrinterClass, details_acquired),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-}
-
-static void
-gtk_printer_init (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- priv->name = NULL;
- priv->location = NULL;
- priv->description = NULL;
- priv->icon_name = g_strdup ("printer");
-
- priv->is_active = TRUE;
- priv->is_paused = FALSE;
- priv->is_accepting_jobs = TRUE;
- priv->is_new = TRUE;
- priv->has_details = FALSE;
- priv->accepts_pdf = FALSE;
- priv->accepts_ps = TRUE;
-
- priv->state_message = NULL;
- priv->job_count = 0;
-}
-
-static void
-gtk_printer_finalize (GObject *object)
-{
- GtkPrinter *printer = GTK_PRINTER (object);
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_free (priv->name);
- g_free (priv->location);
- g_free (priv->description);
- g_free (priv->state_message);
- g_free (priv->icon_name);
-
- if (priv->backend)
- g_object_unref (priv->backend);
-
- G_OBJECT_CLASS (gtk_printer_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkPrinter *printer = GTK_PRINTER (object);
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- switch (prop_id)
- {
- case PROP_NAME:
- priv->name = g_value_dup_string (value);
- break;
-
- case PROP_BACKEND:
- priv->backend = GTK_PRINT_BACKEND (g_value_dup_object (value));
- break;
-
- case PROP_IS_VIRTUAL:
- priv->is_virtual = g_value_get_boolean (value);
- break;
-
- case PROP_ACCEPTS_PDF:
- priv->accepts_pdf = g_value_get_boolean (value);
- break;
-
- case PROP_ACCEPTS_PS:
- priv->accepts_ps = g_value_get_boolean (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_printer_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkPrinter *printer = GTK_PRINTER (object);
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- switch (prop_id)
- {
- case PROP_NAME:
- if (priv->name)
- g_value_set_string (value, priv->name);
- else
- g_value_set_static_string (value, "");
- break;
- case PROP_BACKEND:
- g_value_set_object (value, priv->backend);
- break;
- case PROP_STATE_MESSAGE:
- if (priv->state_message)
- g_value_set_string (value, priv->state_message);
- else
- g_value_set_static_string (value, "");
- break;
- case PROP_LOCATION:
- if (priv->location)
- g_value_set_string (value, priv->location);
- else
- g_value_set_static_string (value, "");
- break;
- case PROP_ICON_NAME:
- if (priv->icon_name)
- g_value_set_string (value, priv->icon_name);
- else
- g_value_set_static_string (value, "printer");
- break;
- case PROP_JOB_COUNT:
- g_value_set_int (value, priv->job_count);
- break;
- case PROP_IS_VIRTUAL:
- g_value_set_boolean (value, priv->is_virtual);
- break;
- case PROP_ACCEPTS_PDF:
- g_value_set_boolean (value, priv->accepts_pdf);
- break;
- case PROP_ACCEPTS_PS:
- g_value_set_boolean (value, priv->accepts_ps);
- break;
- case PROP_PAUSED:
- g_value_set_boolean (value, priv->is_paused);
- break;
- case PROP_ACCEPTING_JOBS:
- g_value_set_boolean (value, priv->is_accepting_jobs);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/**
- * gtk_printer_new:
- * @name: the name of the printer
- * @backend: a `GtkPrintBackend`
- * @virtual_: whether the printer is virtual
- *
- * Creates a new `GtkPrinter`.
- *
- * Returns: a new `GtkPrinter`
- */
-GtkPrinter *
-gtk_printer_new (const char *name,
- GtkPrintBackend *backend,
- gboolean virtual_)
-{
- GObject *result;
-
- result = g_object_new (GTK_TYPE_PRINTER,
- "name", name,
- "backend", backend,
- "is-virtual", virtual_,
- NULL);
-
- return (GtkPrinter *) result;
-}
-
-/**
- * gtk_printer_get_backend: (attributes org.gtk.Method.get_property=backend)
- * @printer: a `GtkPrinter`
- *
- * Returns the backend of the printer.
- *
- * Returns: (transfer none): the backend of @printer
- */
-GtkPrintBackend *
-gtk_printer_get_backend (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- return priv->backend;
-}
-
-/**
- * gtk_printer_get_name: (attributes org.gtk.Method.get_property=name)
- * @printer: a `GtkPrinter`
- *
- * Returns the name of the printer.
- *
- * Returns: the name of @printer
- */
-const char *
-gtk_printer_get_name (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- return priv->name;
-}
-
-/**
- * gtk_printer_get_description:
- * @printer: a `GtkPrinter`
- *
- * Gets the description of the printer.
- *
- * Returns: the description of @printer
- */
-const char *
-gtk_printer_get_description (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- return priv->description;
-}
-
-gboolean
-gtk_printer_set_description (GtkPrinter *printer,
- const char *description)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- if (g_strcmp0 (priv->description, description) == 0)
- return FALSE;
-
- g_free (priv->description);
- priv->description = g_strdup (description);
-
- return TRUE;
-}
-
-/**
- * gtk_printer_get_state_message: (attributes org.gtk.Method.get_property=state-message)
- * @printer: a `GtkPrinter`
- *
- * Returns the state message describing the current state
- * of the printer.
- *
- * Returns: the state message of @printer
- */
-const char *
-gtk_printer_get_state_message (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- return priv->state_message;
-}
-
-gboolean
-gtk_printer_set_state_message (GtkPrinter *printer,
- const char *message)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- if (g_strcmp0 (priv->state_message, message) == 0)
- return FALSE;
-
- g_free (priv->state_message);
- priv->state_message = g_strdup (message);
- g_object_notify (G_OBJECT (printer), "state-message");
-
- return TRUE;
-}
-
-/**
- * gtk_printer_get_location: (attributes org.gtk.Method.get_property=location)
- * @printer: a `GtkPrinter`
- *
- * Returns a description of the location of the printer.
- *
- * Returns: the location of @printer
- */
-const char *
-gtk_printer_get_location (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- return priv->location;
-}
-
-gboolean
-gtk_printer_set_location (GtkPrinter *printer,
- const char *location)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- if (g_strcmp0 (priv->location, location) == 0)
- return FALSE;
-
- g_free (priv->location);
- priv->location = g_strdup (location);
- g_object_notify (G_OBJECT (printer), "location");
-
- return TRUE;
-}
-
-/**
- * gtk_printer_get_icon_name: (attributes org.gtk.Method.get_property=icon-name)
- * @printer: a `GtkPrinter`
- *
- * Gets the name of the icon to use for the printer.
- *
- * Returns: the icon name for @printer
- */
-const char *
-gtk_printer_get_icon_name (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- return priv->icon_name;
-}
-
-void
-gtk_printer_set_icon_name (GtkPrinter *printer,
- const char *icon)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_if_fail (GTK_IS_PRINTER (printer));
-
- g_free (priv->icon_name);
- priv->icon_name = g_strdup (icon);
- g_object_notify (G_OBJECT (printer), "icon-name");
-}
-
-/**
- * gtk_printer_get_job_count: (attributes org.gtk.Method.get_property=job-count)
- * @printer: a `GtkPrinter`
- *
- * Gets the number of jobs currently queued on the printer.
- *
- * Returns: the number of jobs on @printer
- */
-int
-gtk_printer_get_job_count (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
-
- return priv->job_count;
-}
-
-gboolean
-gtk_printer_set_job_count (GtkPrinter *printer,
- int count)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- if (priv->job_count == count)
- return FALSE;
-
- priv->job_count = count;
-
- g_object_notify (G_OBJECT (printer), "job-count");
-
- return TRUE;
-}
-
-/**
- * gtk_printer_has_details:
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer details are available.
- *
- * Returns: %TRUE if @printer details are available
- */
-gboolean
-gtk_printer_has_details (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- return priv->has_details;
-}
-
-void
-gtk_printer_set_has_details (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- priv->has_details = val;
-}
-
-/**
- * gtk_printer_is_active:
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is currently active (i.e.
- * accepts new jobs).
- *
- * Returns: %TRUE if @printer is active
- */
-gboolean
-gtk_printer_is_active (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-
- return priv->is_active;
-}
-
-void
-gtk_printer_set_is_active (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_if_fail (GTK_IS_PRINTER (printer));
-
- priv->is_active = val;
-}
-
-/**
- * gtk_printer_is_paused: (attributes org.gtk.Method.get_property=paused)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is currently paused.
- *
- * A paused printer still accepts jobs, but it is not
- * printing them.
- *
- * Returns: %TRUE if @printer is paused
- */
-gboolean
-gtk_printer_is_paused (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-
- return priv->is_paused;
-}
-
-gboolean
-gtk_printer_set_is_paused (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- if (val == priv->is_paused)
- return FALSE;
-
- priv->is_paused = val;
-
- return TRUE;
-}
-
-/**
- * gtk_printer_is_accepting_jobs: (attributes org.gtk.Method.get_property=accepting-jobs)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is accepting jobs
- *
- * Returns: %TRUE if @printer is accepting jobs
- */
-gboolean
-gtk_printer_is_accepting_jobs (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-
- return priv->is_accepting_jobs;
-}
-
-gboolean
-gtk_printer_set_is_accepting_jobs (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- if (val == priv->is_accepting_jobs)
- return FALSE;
-
- priv->is_accepting_jobs = val;
-
- return TRUE;
-}
-
-/**
- * gtk_printer_is_virtual: (attributes org.gtk.Method.get_property=is-virtual)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is virtual (i.e. does not
- * represent actual printer hardware, but something like
- * a CUPS class).
- *
- * Returns: %TRUE if @printer is virtual
- */
-gboolean
-gtk_printer_is_virtual (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-
- return priv->is_virtual;
-}
-
-/**
- * gtk_printer_accepts_pdf: (attributes org.gtk.Method.get_property=accepts-pdf)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer accepts input in
- * PDF format.
- *
- * Returns: %TRUE if @printer accepts PDF
- */
-gboolean
-gtk_printer_accepts_pdf (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-
- return priv->accepts_pdf;
-}
-
-void
-gtk_printer_set_accepts_pdf (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_if_fail (GTK_IS_PRINTER (printer));
-
- priv->accepts_pdf = val;
-}
-
-/**
- * gtk_printer_accepts_ps: (attributes org.gtk.Method.get_property=accepts-ps)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer accepts input in
- * PostScript format.
- *
- * Returns: %TRUE if @printer accepts PostScript
- */
-gboolean
-gtk_printer_accepts_ps (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-
- return priv->accepts_ps;
-}
-
-void
-gtk_printer_set_accepts_ps (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_if_fail (GTK_IS_PRINTER (printer));
-
- priv->accepts_ps = val;
-}
-
-gboolean
-gtk_printer_is_new (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- return priv->is_new;
-}
-
-void
-gtk_printer_set_is_new (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_if_fail (GTK_IS_PRINTER (printer));
-
- priv->is_new = val;
-}
-
-
-/**
- * gtk_printer_is_default:
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is the default printer.
- *
- * Returns: %TRUE if @printer is the default
- */
-gboolean
-gtk_printer_is_default (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
- return priv->is_default;
-}
-
-void
-gtk_printer_set_is_default (GtkPrinter *printer,
- gboolean val)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
- g_return_if_fail (GTK_IS_PRINTER (printer));
-
- priv->is_default = val;
-}
-
-/**
- * gtk_printer_request_details:
- * @printer: a `GtkPrinter`
- *
- * Requests the printer details.
- *
- * When the details are available, the
- * [signal@Gtk.Printer::details-acquired] signal
- * will be emitted on @printer.
- */
-void
-gtk_printer_request_details (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class;
-
- g_return_if_fail (GTK_IS_PRINTER (printer));
-
- backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
- backend_class->printer_request_details (printer);
-}
-
-GtkPrinterOptionSet *
-_gtk_printer_get_options (GtkPrinter *printer,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup,
- GtkPrintCapabilities capabilities)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- return backend_class->printer_get_options (printer, settings, page_setup, capabilities);
-}
-
-gboolean
-_gtk_printer_mark_conflicts (GtkPrinter *printer,
- GtkPrinterOptionSet *options)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- return backend_class->printer_mark_conflicts (printer, options);
-}
-
-void
-_gtk_printer_get_settings_from_options (GtkPrinter *printer,
- GtkPrinterOptionSet *options,
- GtkPrintSettings *settings)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- backend_class->printer_get_settings_from_options (printer, options, settings);
-}
-
-void
-_gtk_printer_prepare_for_print (GtkPrinter *printer,
- GtkPrintJob *print_job,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- backend_class->printer_prepare_for_print (printer, print_job, settings, page_setup);
-}
-
-cairo_surface_t *
-_gtk_printer_create_cairo_surface (GtkPrinter *printer,
- GtkPrintSettings *settings,
- double width,
- double height,
- GIOChannel *cache_io)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- return backend_class->printer_create_cairo_surface (printer, settings,
- width, height, cache_io);
-}
-
-/**
- * gtk_printer_list_papers:
- * @printer: a `GtkPrinter`
- *
- * Lists all the paper sizes @printer supports.
- *
- * This will return and empty list unless the printer’s details
- * are available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Returns: (element-type GtkPageSetup) (transfer full): a newly
- * allocated list of newly allocated `GtkPageSetup`s.
- */
-GList *
-gtk_printer_list_papers (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class;
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
- return backend_class->printer_list_papers (printer);
-}
-
-/**
- * gtk_printer_get_default_page_size:
- * @printer: a `GtkPrinter`
- *
- * Returns default page size of @printer.
- *
- * Returns: (transfer full): a newly allocated `GtkPageSetup` with default page size
- * of the printer.
- */
-GtkPageSetup *
-gtk_printer_get_default_page_size (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class;
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
- backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- return backend_class->printer_get_default_page_size (printer);
-}
-
-/**
- * gtk_printer_get_hard_margins:
- * @printer: a `GtkPrinter`
- * @top: (out): a location to store the top margin in
- * @bottom: (out): a location to store the bottom margin in
- * @left: (out): a location to store the left margin in
- * @right: (out): a location to store the right margin in
- *
- * Retrieve the hard margins of @printer.
- *
- * These are the margins that define the area at the borders
- * of the paper that the printer cannot print to.
- *
- * Note: This will not succeed unless the printer’s details are
- * available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Returns: %TRUE iff the hard margins were retrieved
- */
-gboolean
-gtk_printer_get_hard_margins (GtkPrinter *printer,
- double *top,
- double *bottom,
- double *left,
- double *right)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- return backend_class->printer_get_hard_margins (printer, top, bottom, left, right);
-}
-
-/**
- * gtk_printer_get_hard_margins_for_paper_size:
- * @printer: a `GtkPrinter`
- * @paper_size: a `GtkPaperSize`
- * @top: (out): a location to store the top margin in
- * @bottom: (out): a location to store the bottom margin in
- * @left: (out): a location to store the left margin in
- * @right: (out): a location to store the right margin in
- *
- * Retrieve the hard margins of @printer for @paper_size.
- *
- * These are the margins that define the area at the borders
- * of the paper that the printer cannot print to.
- *
- * Note: This will not succeed unless the printer’s details are
- * available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Return value: %TRUE iff the hard margins were retrieved
- */
-gboolean
-gtk_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
- GtkPaperSize *paper_size,
- double *top,
- double *bottom,
- double *left,
- double *right)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
- return backend_class->printer_get_hard_margins_for_paper_size (printer, paper_size, top, bottom, left, right);
-}
-
-/**
- * gtk_printer_get_capabilities:
- * @printer: a `GtkPrinter`
- *
- * Returns the printer’s capabilities.
- *
- * This is useful when you’re using `GtkPrintUnixDialog`’s
- * manual-capabilities setting and need to know which settings
- * the printer can handle and which you must handle yourself.
- *
- * This will return 0 unless the printer’s details are
- * available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Returns: the printer’s capabilities
- */
-GtkPrintCapabilities
-gtk_printer_get_capabilities (GtkPrinter *printer)
-{
- GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
- GtkPrintBackendClass *backend_class;
-
- g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
-
- backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
- return backend_class->printer_get_capabilities (printer);
-}
-
-/**
- * gtk_printer_compare:
- * @a: a `GtkPrinter`
- * @b: another `GtkPrinter`
- *
- * Compares two printers.
- *
- * Returns: 0 if the printer match, a negative value if @a < @b,
- * or a positive value if @a > @b
- */
-int
-gtk_printer_compare (GtkPrinter *a,
- GtkPrinter *b)
-{
- const char *name_a, *name_b;
-
- g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
-
- name_a = gtk_printer_get_name (a);
- name_b = gtk_printer_get_name (b);
- if (name_a == NULL && name_b == NULL)
- return 0;
- else if (name_a == NULL)
- return G_MAXINT;
- else if (name_b == NULL)
- return G_MININT;
- else
- return g_ascii_strcasecmp (name_a, name_b);
-}
-
-
-typedef struct
-{
- GList *backends;
- GtkPrinterFunc func;
- gpointer data;
- GDestroyNotify destroy;
- GMainLoop *loop;
-} PrinterList;
-
-static void list_done_cb (GtkPrintBackend *backend,
- PrinterList *printer_list);
-
-static void
-stop_enumeration (PrinterList *printer_list)
-{
- GList *list, *next;
- GtkPrintBackend *backend;
-
- for (list = printer_list->backends; list; list = next)
- {
- next = list->next;
- backend = GTK_PRINT_BACKEND (list->data);
- list_done_cb (backend, printer_list);
- }
-}
-
-static void
-free_printer_list (PrinterList *printer_list)
-{
- if (printer_list->destroy)
- printer_list->destroy (printer_list->data);
-
- if (printer_list->loop)
- {
- g_main_loop_quit (printer_list->loop);
- g_main_loop_unref (printer_list->loop);
- }
-
- g_free (printer_list);
-}
-
-static gboolean
-list_added_cb (GtkPrintBackend *backend,
- GtkPrinter *printer,
- PrinterList *printer_list)
-{
- if (printer_list->func (printer, printer_list->data))
- {
- stop_enumeration (printer_list);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-backend_status_changed (GObject *object,
- GParamSpec *pspec,
- gpointer data)
-{
- GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
- PrinterList *printer_list = data;
- GtkPrintBackendStatus status;
-
- g_object_get (backend, "status", &status, NULL);
-
- if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE)
- list_done_cb (backend, printer_list);
-}
-
-static gboolean
-list_printers_remove_backend (PrinterList *printer_list,
- GtkPrintBackend *backend)
-{
- printer_list->backends = g_list_remove (printer_list->backends, backend);
- gtk_print_backend_destroy (backend);
- g_object_unref (backend);
-
- if (printer_list->backends == NULL)
- {
- free_printer_list (printer_list);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-list_done_cb (GtkPrintBackend *backend,
- PrinterList *printer_list)
-{
- g_signal_handlers_disconnect_by_func (backend, list_added_cb, printer_list);
- g_signal_handlers_disconnect_by_func (backend, list_done_cb, printer_list);
- g_signal_handlers_disconnect_by_func (backend, backend_status_changed, printer_list);
-
- list_printers_remove_backend(printer_list, backend);
-}
-
-static gboolean
-list_printers_init (PrinterList *printer_list,
- GtkPrintBackend *backend)
-{
- GList *list, *node;
- GtkPrintBackendStatus status;
-
- list = gtk_print_backend_get_printer_list (backend);
-
- for (node = list; node != NULL; node = node->next)
- {
- if (list_added_cb (backend, node->data, printer_list))
- {
- g_list_free (list);
- return TRUE;
- }
- }
-
- g_list_free (list);
-
- g_object_get (backend, "status", &status, NULL);
-
- if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE ||
- gtk_print_backend_printer_list_is_done (backend))
- {
- if (list_printers_remove_backend (printer_list, backend))
- return TRUE;
- }
- else
- {
- g_signal_connect (backend, "printer-added",
- (GCallback) list_added_cb,
- printer_list);
- g_signal_connect (backend, "printer-list-done",
- (GCallback) list_done_cb,
- printer_list);
- g_signal_connect (backend, "notify::status",
- (GCallback) backend_status_changed,
- printer_list);
- }
-
- return FALSE;
-}
-
-/**
- * gtk_enumerate_printers:
- * @func: a function to call for each printer
- * @data: user data to pass to @func
- * @destroy: function to call if @data is no longer needed
- * @wait: if %TRUE, wait in a recursive mainloop until
- * all printers are enumerated; otherwise return early
- *
- * Calls a function for all `GtkPrinter`s.
- *
- * If @func returns %TRUE, the enumeration is stopped.
- */
-void
-gtk_enumerate_printers (GtkPrinterFunc func,
- gpointer data,
- GDestroyNotify destroy,
- gboolean wait)
-{
- PrinterList *printer_list;
- GList *node, *next;
- GtkPrintBackend *backend;
-
- printer_list = g_new0 (PrinterList, 1);
-
- printer_list->func = func;
- printer_list->data = data;
- printer_list->destroy = destroy;
-
- if (g_module_supported ())
- printer_list->backends = gtk_print_backend_load_modules ();
-
- if (printer_list->backends == NULL)
- {
- free_printer_list (printer_list);
- return;
- }
-
- for (node = printer_list->backends; node != NULL; node = next)
- {
- next = node->next;
- backend = GTK_PRINT_BACKEND (node->data);
- if (list_printers_init (printer_list, backend))
- return;
- }
-
- if (wait && printer_list->backends)
- {
- printer_list->loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (printer_list->loop);
- }
-}
-
-GType
-gtk_print_capabilities_get_type (void)
-{
- static GType etype = 0;
-
- if (G_UNLIKELY (etype == 0))
- {
- static const GFlagsValue values[] = {
- { GTK_PRINT_CAPABILITY_PAGE_SET, "GTK_PRINT_CAPABILITY_PAGE_SET", "page-set" },
- { GTK_PRINT_CAPABILITY_COPIES, "GTK_PRINT_CAPABILITY_COPIES", "copies" },
- { GTK_PRINT_CAPABILITY_COLLATE, "GTK_PRINT_CAPABILITY_COLLATE", "collate" },
- { GTK_PRINT_CAPABILITY_REVERSE, "GTK_PRINT_CAPABILITY_REVERSE", "reverse" },
- { GTK_PRINT_CAPABILITY_SCALE, "GTK_PRINT_CAPABILITY_SCALE", "scale" },
- { GTK_PRINT_CAPABILITY_GENERATE_PDF, "GTK_PRINT_CAPABILITY_GENERATE_PDF", "generate-pdf" },
- { GTK_PRINT_CAPABILITY_GENERATE_PS, "GTK_PRINT_CAPABILITY_GENERATE_PS", "generate-ps" },
- { GTK_PRINT_CAPABILITY_PREVIEW, "GTK_PRINT_CAPABILITY_PREVIEW", "preview" },
- { GTK_PRINT_CAPABILITY_NUMBER_UP, "GTK_PRINT_CAPABILITY_NUMBER_UP", "number-up"},
- { GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT, "GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT", "number-up-layout" },
- { 0, NULL, NULL }
- };
-
- etype = g_flags_register_static (I_("GtkPrintCapabilities"), values);
- }
-
- return etype;
-}
+++ /dev/null
-/* GtkPrinter
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <cairo.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINT_CAPABILITIES (gtk_print_capabilities_get_type ())
-
-/* Note, this type is manually registered with GObject in gtkprinter.c
- * If you add any flags, update the registration as well!
- */
-/**
- * GtkPrintCapabilities:
- * @GTK_PRINT_CAPABILITY_PAGE_SET: Print dialog will offer printing even/odd pages.
- * @GTK_PRINT_CAPABILITY_COPIES: Print dialog will allow to print multiple copies.
- * @GTK_PRINT_CAPABILITY_COLLATE: Print dialog will allow to collate multiple copies.
- * @GTK_PRINT_CAPABILITY_REVERSE: Print dialog will allow to print pages in reverse order.
- * @GTK_PRINT_CAPABILITY_SCALE: Print dialog will allow to scale the output.
- * @GTK_PRINT_CAPABILITY_GENERATE_PDF: The program will send the document to
- * the printer in PDF format
- * @GTK_PRINT_CAPABILITY_GENERATE_PS: The program will send the document to
- * the printer in Postscript format
- * @GTK_PRINT_CAPABILITY_PREVIEW: Print dialog will offer a preview
- * @GTK_PRINT_CAPABILITY_NUMBER_UP: Print dialog will offer printing multiple
- * pages per sheet
- * @GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT: Print dialog will allow to rearrange
- * pages when printing multiple pages per sheet
- *
- * Specifies which features the print dialog should offer.
- *
- * If neither %GTK_PRINT_CAPABILITY_GENERATE_PDF nor
- * %GTK_PRINT_CAPABILITY_GENERATE_PS is specified, GTK assumes that all
- * formats are supported.
- */
-typedef enum
-{
- GTK_PRINT_CAPABILITY_PAGE_SET = 1 << 0,
- GTK_PRINT_CAPABILITY_COPIES = 1 << 1,
- GTK_PRINT_CAPABILITY_COLLATE = 1 << 2,
- GTK_PRINT_CAPABILITY_REVERSE = 1 << 3,
- GTK_PRINT_CAPABILITY_SCALE = 1 << 4,
- GTK_PRINT_CAPABILITY_GENERATE_PDF = 1 << 5,
- GTK_PRINT_CAPABILITY_GENERATE_PS = 1 << 6,
- GTK_PRINT_CAPABILITY_PREVIEW = 1 << 7,
- GTK_PRINT_CAPABILITY_NUMBER_UP = 1 << 8,
- GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT = 1 << 9
-} GtkPrintCapabilities;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_print_capabilities_get_type (void) G_GNUC_CONST;
-
-#define GTK_TYPE_PRINTER (gtk_printer_get_type ())
-#define GTK_PRINTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER, GtkPrinter))
-#define GTK_IS_PRINTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER))
-
-typedef struct _GtkPrinter GtkPrinter;
-typedef struct _GtkPrintBackend GtkPrintBackend;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_printer_get_type (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkPrinter *gtk_printer_new (const char *name,
- GtkPrintBackend *backend,
- gboolean virtual_);
-GDK_AVAILABLE_IN_ALL
-GtkPrintBackend *gtk_printer_get_backend (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_printer_get_name (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_printer_get_state_message (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_printer_get_description (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_printer_get_location (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_printer_get_icon_name (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-int gtk_printer_get_job_count (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_is_active (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_is_paused (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_is_accepting_jobs (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_is_virtual (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_is_default (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_accepts_pdf (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_accepts_ps (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-GList *gtk_printer_list_papers (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-GtkPageSetup *gtk_printer_get_default_page_size (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-int gtk_printer_compare (GtkPrinter *a,
- GtkPrinter *b);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_has_details (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_request_details (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-GtkPrintCapabilities gtk_printer_get_capabilities (GtkPrinter *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_get_hard_margins (GtkPrinter *printer,
- double *top,
- double *bottom,
- double *left,
- double *right);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
- GtkPaperSize *paper_size,
- double *top,
- double *bottom,
- double *left,
- double *right);
-
-/**
- * GtkPrinterFunc:
- * @printer: a `GtkPrinter`
- * @data: (closure): user data passed to gtk_enumerate_printers()
- *
- * The type of function passed to gtk_enumerate_printers().
- *
- * Note that you need to ref @printer, if you want to keep
- * a reference to it after the function has returned.
- *
- * Returns: %TRUE to stop the enumeration, %FALSE to continue
- */
-typedef gboolean (*GtkPrinterFunc) (GtkPrinter *printer,
- gpointer data);
-
-GDK_AVAILABLE_IN_ALL
-void gtk_enumerate_printers (GtkPrinterFunc func,
- gpointer data,
- GDestroyNotify destroy,
- gboolean wait);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrinter, g_object_unref)
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprinteroption.c: Handling possible settings for a specific printer setting
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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 <string.h>
-#include <gmodule.h>
-
-#include "gtkprivate.h"
-#include "gtkprinteroptionprivate.h"
-
-/*****************************************
- * GtkPrinterOption *
- *****************************************/
-
-enum {
- CHANGED,
- LAST_SIGNAL
-};
-
-enum {
- PROP_0,
- PROP_VALUE
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void gtk_printer_option_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_printer_option_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
-G_DEFINE_TYPE (GtkPrinterOption, gtk_printer_option, G_TYPE_OBJECT)
-
-static void
-gtk_printer_option_finalize (GObject *object)
-{
- GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
- int i;
-
- g_free (option->name);
- g_free (option->display_text);
- g_free (option->value);
- for (i = 0; i < option->num_choices; i++)
- {
- g_free (option->choices[i]);
- g_free (option->choices_display[i]);
- }
- g_free (option->choices);
- g_free (option->choices_display);
- g_free (option->group);
-
- G_OBJECT_CLASS (gtk_printer_option_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_option_init (GtkPrinterOption *option)
-{
- option->value = g_strdup ("");
- option->activates_default = FALSE;
-}
-
-static void
-gtk_printer_option_class_init (GtkPrinterOptionClass *class)
-{
- GObjectClass *gobject_class = (GObjectClass *)class;
-
- gobject_class->finalize = gtk_printer_option_finalize;
- gobject_class->set_property = gtk_printer_option_set_property;
- gobject_class->get_property = gtk_printer_option_get_property;
-
- signals[CHANGED] =
- g_signal_new (I_("changed"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrinterOptionClass, changed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
-
- g_object_class_install_property (G_OBJECT_CLASS (class),
- PROP_VALUE,
- g_param_spec_string ("value", NULL, NULL,
- "",
- GTK_PARAM_READWRITE));
-}
-
-GtkPrinterOption *
-gtk_printer_option_new (const char *name, const char *display_text,
- GtkPrinterOptionType type)
-{
- GtkPrinterOption *option;
-
- option = g_object_new (GTK_TYPE_PRINTER_OPTION, NULL);
-
- option->name = g_strdup (name);
- option->display_text = g_strdup (display_text);
- option->type = type;
-
- return option;
-}
-
-static void
-gtk_printer_option_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
-
- switch (prop_id)
- {
- case PROP_VALUE:
- gtk_printer_option_set (option, g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_printer_option_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
-
- switch (prop_id)
- {
- case PROP_VALUE:
- g_value_set_string (value, option->value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-emit_changed (GtkPrinterOption *option)
-{
- g_signal_emit (option, signals[CHANGED], 0);
-}
-
-void
-gtk_printer_option_set (GtkPrinterOption *option,
- const char *value)
-{
- if (value == NULL)
- value = "";
-
- if (strcmp (option->value, value) == 0)
- return;
-
- if ((option->type == GTK_PRINTER_OPTION_TYPE_PICKONE ||
- option->type == GTK_PRINTER_OPTION_TYPE_ALTERNATIVE))
- {
- int i;
-
- for (i = 0; i < option->num_choices; i++)
- {
- if (g_ascii_strcasecmp (value, option->choices[i]) == 0)
- {
- value = option->choices[i];
- break;
- }
- }
-
- if (i == option->num_choices)
- return; /* Not found in available choices */
- }
-
- g_free (option->value);
- option->value = g_strdup (value);
-
- emit_changed (option);
-}
-
-void
-gtk_printer_option_set_boolean (GtkPrinterOption *option,
- gboolean value)
-{
- gtk_printer_option_set (option, value ? "True" : "False");
-}
-
-void
-gtk_printer_option_set_has_conflict (GtkPrinterOption *option,
- gboolean has_conflict)
-{
- has_conflict = has_conflict != 0;
-
- if (option->has_conflict == has_conflict)
- return;
-
- option->has_conflict = has_conflict;
- emit_changed (option);
-}
-
-void
-gtk_printer_option_clear_has_conflict (GtkPrinterOption *option)
-{
- gtk_printer_option_set_has_conflict (option, FALSE);
-}
-
-void
-gtk_printer_option_allocate_choices (GtkPrinterOption *option,
- int num)
-{
- g_free (option->choices);
- g_free (option->choices_display);
-
- option->num_choices = num;
- if (num == 0)
- {
- option->choices = NULL;
- option->choices_display = NULL;
- }
- else
- {
- option->choices = g_new0 (char *, num);
- option->choices_display = g_new0 (char *, num);
- }
-}
-
-void
-gtk_printer_option_choices_from_array (GtkPrinterOption *option,
- int num_choices,
- const char **choices,
- const char **choices_display)
-{
- int i;
-
- gtk_printer_option_allocate_choices (option, num_choices);
- for (i = 0; i < num_choices; i++)
- {
- option->choices[i] = g_strdup (choices[i]);
- option->choices_display[i] = g_strdup (choices_display[i]);
- }
-}
-
-gboolean
-gtk_printer_option_has_choice (GtkPrinterOption *option,
- const char *choice)
-{
- int i;
-
- for (i = 0; i < option->num_choices; i++)
- {
- if (strcmp (option->choices[i], choice) == 0)
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-gtk_printer_option_set_activates_default (GtkPrinterOption *option,
- gboolean activates)
-{
- g_return_if_fail (GTK_IS_PRINTER_OPTION (option));
-
- option->activates_default = activates;
-}
-
-gboolean
-gtk_printer_option_get_activates_default (GtkPrinterOption *option)
-{
- g_return_val_if_fail (GTK_IS_PRINTER_OPTION (option), FALSE);
-
- return option->activates_default;
-}
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprinteroption.h: printer option
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-/* This is a "semi-private" header; it is meant only for
- * alternate GtkPrintDialog backend modules; no stability guarantees
- * are made at this point
- */
-#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
-#error "GtkPrintBackend is not supported API for general use"
-#endif
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINTER_OPTION (gtk_printer_option_get_type ())
-#define GTK_PRINTER_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION, GtkPrinterOption))
-#define GTK_IS_PRINTER_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION))
-
-typedef struct _GtkPrinterOption GtkPrinterOption;
-typedef struct _GtkPrinterOptionClass GtkPrinterOptionClass;
-
-#define GTK_PRINTER_OPTION_GROUP_IMAGE_QUALITY "ImageQuality"
-#define GTK_PRINTER_OPTION_GROUP_FINISHING "Finishing"
-
-typedef enum {
- GTK_PRINTER_OPTION_TYPE_BOOLEAN,
- GTK_PRINTER_OPTION_TYPE_PICKONE,
- GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD,
- GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE,
- GTK_PRINTER_OPTION_TYPE_PICKONE_REAL,
- GTK_PRINTER_OPTION_TYPE_PICKONE_INT,
- GTK_PRINTER_OPTION_TYPE_PICKONE_STRING,
- GTK_PRINTER_OPTION_TYPE_ALTERNATIVE,
- GTK_PRINTER_OPTION_TYPE_STRING,
- GTK_PRINTER_OPTION_TYPE_FILESAVE,
- GTK_PRINTER_OPTION_TYPE_INFO
-} GtkPrinterOptionType;
-
-struct _GtkPrinterOption
-{
- GObject parent_instance;
-
- char *name;
- char *display_text;
- GtkPrinterOptionType type;
-
- char *value;
-
- int num_choices;
- char **choices;
- char **choices_display;
-
- gboolean activates_default;
-
- gboolean has_conflict;
- char *group;
-};
-
-struct _GtkPrinterOptionClass
-{
- GObjectClass parent_class;
-
- void (*changed) (GtkPrinterOption *option);
-
- /* Padding for future expansion */
- void (*_gtk_reserved1) (void);
- void (*_gtk_reserved2) (void);
- void (*_gtk_reserved3) (void);
- void (*_gtk_reserved4) (void);
-};
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_printer_option_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkPrinterOption *gtk_printer_option_new (const char *name,
- const char *display_text,
- GtkPrinterOptionType type);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set (GtkPrinterOption *option,
- const char *value);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_has_conflict (GtkPrinterOption *option,
- gboolean has_conflict);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_clear_has_conflict (GtkPrinterOption *option);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_boolean (GtkPrinterOption *option,
- gboolean value);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_allocate_choices (GtkPrinterOption *option,
- int num);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_choices_from_array (GtkPrinterOption *option,
- int num_choices,
- const char **choices,
- const char **choices_display);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_option_has_choice (GtkPrinterOption *option,
- const char *choice);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_activates_default (GtkPrinterOption *option,
- gboolean activates);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_option_get_activates_default (GtkPrinterOption *option);
-
-
-G_END_DECLS
-
-
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintbackendprivate.h: Abstract printer backend interfaces
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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 <string.h>
-#include <glib.h>
-#include <gmodule.h>
-
-#include "gtkprinteroptionsetprivate.h"
-#include "gtkprivate.h"
-
-/*****************************************
- * GtkPrinterOptionSet *
- *****************************************/
-
-enum {
- CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/* ugly side-effect of aliasing */
-#undef gtk_printer_option_set
-
-G_DEFINE_TYPE (GtkPrinterOptionSet, gtk_printer_option_set, G_TYPE_OBJECT)
-
-static void
-gtk_printer_option_set_finalize (GObject *object)
-{
- GtkPrinterOptionSet *set = GTK_PRINTER_OPTION_SET (object);
-
- g_hash_table_destroy (set->hash);
- g_ptr_array_foreach (set->array, (GFunc)g_object_unref, NULL);
- g_ptr_array_free (set->array, TRUE);
-
- G_OBJECT_CLASS (gtk_printer_option_set_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_option_set_init (GtkPrinterOptionSet *set)
-{
- set->array = g_ptr_array_new ();
- set->hash = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-static void
-gtk_printer_option_set_class_init (GtkPrinterOptionSetClass *class)
-{
- GObjectClass *gobject_class = (GObjectClass *)class;
-
- gobject_class->finalize = gtk_printer_option_set_finalize;
-
- signals[CHANGED] =
- g_signal_new (I_("changed"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrinterOptionSetClass, changed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
-}
-
-
-static void
-emit_changed (GtkPrinterOptionSet *set)
-{
- g_signal_emit (set, signals[CHANGED], 0);
-}
-
-GtkPrinterOptionSet *
-gtk_printer_option_set_new (void)
-{
- return g_object_new (GTK_TYPE_PRINTER_OPTION_SET, NULL);
-}
-
-void
-gtk_printer_option_set_remove (GtkPrinterOptionSet *set,
- GtkPrinterOption *option)
-{
- int i;
-
- for (i = 0; i < set->array->len; i++)
- {
- if (g_ptr_array_index (set->array, i) == option)
- {
- g_ptr_array_remove_index (set->array, i);
- g_hash_table_remove (set->hash, option->name);
- g_signal_handlers_disconnect_by_func (option, emit_changed, set);
-
- g_object_unref (option);
- break;
- }
- }
-}
-
-void
-gtk_printer_option_set_add (GtkPrinterOptionSet *set,
- GtkPrinterOption *option)
-{
- g_object_ref (option);
-
- if (gtk_printer_option_set_lookup (set, option->name))
- gtk_printer_option_set_remove (set, option);
-
- g_ptr_array_add (set->array, option);
- g_hash_table_insert (set->hash, option->name, option);
- g_signal_connect_object (option, "changed", G_CALLBACK (emit_changed), set, G_CONNECT_SWAPPED);
-}
-
-GtkPrinterOption *
-gtk_printer_option_set_lookup (GtkPrinterOptionSet *set,
- const char *name)
-{
- gpointer ptr;
-
- ptr = g_hash_table_lookup (set->hash, name);
-
- return GTK_PRINTER_OPTION (ptr);
-}
-
-void
-gtk_printer_option_set_clear_conflicts (GtkPrinterOptionSet *set)
-{
- gtk_printer_option_set_foreach (set,
- (GtkPrinterOptionSetFunc)gtk_printer_option_clear_has_conflict,
- NULL);
-}
-
-/**
- * gtk_printer_option_set_get_groups:
- * @set: a `GtkPrinterOptionSet`
- *
- * Gets the groups in this set.
- *
- * Returns: (element-type utf8) (transfer full): a list of group names.
- */
-GList *
-gtk_printer_option_set_get_groups (GtkPrinterOptionSet *set)
-{
- GtkPrinterOption *option;
- GList *list = NULL;
- int i;
-
- for (i = 0; i < set->array->len; i++)
- {
- option = g_ptr_array_index (set->array, i);
-
- if (g_list_find_custom (list, option->group, (GCompareFunc)g_strcmp0) == NULL)
- list = g_list_prepend (list, g_strdup (option->group));
- }
-
- return g_list_reverse (list);
-}
-
-void
-gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet *set,
- const char *group,
- GtkPrinterOptionSetFunc func,
- gpointer user_data)
-{
- GtkPrinterOption *option;
- int i;
-
- for (i = 0; i < set->array->len; i++)
- {
- option = g_ptr_array_index (set->array, i);
-
- if (group == NULL || g_strcmp0 (group, option->group) == 0)
- func (option, user_data);
- }
-}
-
-void
-gtk_printer_option_set_foreach (GtkPrinterOptionSet *set,
- GtkPrinterOptionSetFunc func,
- gpointer user_data)
-{
- gtk_printer_option_set_foreach_in_group (set, NULL, func, user_data);
-}
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprinteroptionset.h: printer option set
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-/* This is a "semi-private" header; it is meant only for
- * alternate GtkPrintDialog backend modules; no stability guarantees
- * are made at this point
- */
-#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
-#error "GtkPrintBackend is not supported API for general use"
-#endif
-
-#include <glib-object.h>
-#include <gdk/gdk.h>
-#include "gtkprinteroptionprivate.h"
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINTER_OPTION_SET (gtk_printer_option_set_get_type ())
-#define GTK_PRINTER_OPTION_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_SET, GtkPrinterOptionSet))
-#define GTK_IS_PRINTER_OPTION_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_SET))
-
-typedef struct _GtkPrinterOptionSet GtkPrinterOptionSet;
-typedef struct _GtkPrinterOptionSetClass GtkPrinterOptionSetClass;
-
-struct _GtkPrinterOptionSet
-{
- GObject parent_instance;
-
- /*< private >*/
- GPtrArray *array;
- GHashTable *hash;
-};
-
-struct _GtkPrinterOptionSetClass
-{
- GObjectClass parent_class;
-
- void (*changed) (GtkPrinterOptionSet *option);
-
-
- /* Padding for future expansion */
- void (*_gtk_reserved1) (void);
- void (*_gtk_reserved2) (void);
- void (*_gtk_reserved3) (void);
- void (*_gtk_reserved4) (void);
-};
-
-typedef void (*GtkPrinterOptionSetFunc) (GtkPrinterOption *option,
- gpointer user_data);
-
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_printer_option_set_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkPrinterOptionSet *gtk_printer_option_set_new (void);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_add (GtkPrinterOptionSet *set,
- GtkPrinterOption *option);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_remove (GtkPrinterOptionSet *set,
- GtkPrinterOption *option);
-GDK_AVAILABLE_IN_ALL
-GtkPrinterOption * gtk_printer_option_set_lookup (GtkPrinterOptionSet *set,
- const char *name);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_foreach (GtkPrinterOptionSet *set,
- GtkPrinterOptionSetFunc func,
- gpointer user_data);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_clear_conflicts (GtkPrinterOptionSet *set);
-GDK_AVAILABLE_IN_ALL
-GList * gtk_printer_option_set_get_groups (GtkPrinterOptionSet *set);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet *set,
- const char *group,
- GtkPrinterOptionSetFunc func,
- gpointer user_data);
-
-G_END_DECLS
-
+++ /dev/null
-/* GtkPrinterOptionWidget
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.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 <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include <glib/gi18n-lib.h>
-#include "gtkcheckbutton.h"
-#include "gtkdropdown.h"
-#include "gtklistitem.h"
-#include "gtksignallistitemfactory.h"
-#include "gtkentry.h"
-#include "gtkfiledialog.h"
-#include "gtkimage.h"
-#include "gtklabel.h"
-#include "gtkcheckbutton.h"
-#include "gtkgrid.h"
-#include "gtkorientable.h"
-#include "gtkprivate.h"
-#include "gtkstringlist.h"
-
-#include "gtkprinteroptionwidgetprivate.h"
-
-/* This defines the max file length that the file chooser
- * button should display. The total length will be
- * FILENAME_LENGTH_MAX+3 because the truncated name is prefixed
- * with “...”.
- */
-#define FILENAME_LENGTH_MAX 27
-
-static void gtk_printer_option_widget_finalize (GObject *object);
-
-static void deconstruct_widgets (GtkPrinterOptionWidget *widget);
-static void construct_widgets (GtkPrinterOptionWidget *widget);
-static void update_widgets (GtkPrinterOptionWidget *widget);
-
-static char *trim_long_filename (const char *filename);
-
-struct GtkPrinterOptionWidgetPrivate
-{
- GtkPrinterOption *source;
- gulong source_changed_handler;
-
- GtkWidget *check;
- GtkWidget *combo;
- GtkWidget *entry;
- GtkWidget *image;
- GtkWidget *label;
- GtkWidget *info_label;
- GtkWidget *box;
- GtkWidget *button;
-
- /* the last location for save to file, that the user selected */
- GFile *last_location;
-};
-
-enum {
- CHANGED,
- LAST_SIGNAL
-};
-
-enum {
- PROP_0,
- PROP_SOURCE
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinterOptionWidget, gtk_printer_option_widget, GTK_TYPE_BOX)
-
-static void gtk_printer_option_widget_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_printer_option_widget_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static gboolean gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
- gboolean group_cycling);
-
-static void
-gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class)
-{
- GObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- object_class = (GObjectClass *) class;
- widget_class = (GtkWidgetClass *) class;
-
- object_class->finalize = gtk_printer_option_widget_finalize;
- object_class->set_property = gtk_printer_option_widget_set_property;
- object_class->get_property = gtk_printer_option_widget_get_property;
-
- widget_class->mnemonic_activate = gtk_printer_option_widget_mnemonic_activate;
-
- signals[CHANGED] =
- g_signal_new (I_("changed"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrinterOptionWidgetClass, changed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
-
- g_object_class_install_property (object_class,
- PROP_SOURCE,
- g_param_spec_object ("source", NULL, NULL,
- GTK_TYPE_PRINTER_OPTION,
- GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
-}
-
-static void
-gtk_printer_option_widget_init (GtkPrinterOptionWidget *widget)
-{
- widget->priv = gtk_printer_option_widget_get_instance_private (widget);
-
- gtk_box_set_spacing (GTK_BOX (widget), 12);
-}
-
-static void
-gtk_printer_option_widget_finalize (GObject *object)
-{
- GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
- if (priv->source)
- {
- g_signal_handler_disconnect (priv->source,
- priv->source_changed_handler);
- g_object_unref (priv->source);
- priv->source = NULL;
- }
-
- G_OBJECT_CLASS (gtk_printer_option_widget_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_option_widget_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkPrinterOptionWidget *widget;
-
- widget = GTK_PRINTER_OPTION_WIDGET (object);
-
- switch (prop_id)
- {
- case PROP_SOURCE:
- gtk_printer_option_widget_set_source (widget, g_value_get_object (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_printer_option_widget_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
- switch (prop_id)
- {
- case PROP_SOURCE:
- g_value_set_object (value, priv->source);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
- gboolean group_cycling)
-{
- GtkPrinterOptionWidget *powidget = GTK_PRINTER_OPTION_WIDGET (widget);
- GtkPrinterOptionWidgetPrivate *priv = powidget->priv;
-
- if (priv->check)
- return gtk_widget_mnemonic_activate (priv->check, group_cycling);
- if (priv->combo)
- return gtk_widget_mnemonic_activate (priv->combo, group_cycling);
- if (priv->entry)
- return gtk_widget_mnemonic_activate (priv->entry, group_cycling);
- if (priv->button)
- return gtk_widget_mnemonic_activate (priv->button, group_cycling);
-
- return FALSE;
-}
-
-static void
-emit_changed (GtkPrinterOptionWidget *widget)
-{
- g_signal_emit (widget, signals[CHANGED], 0);
-}
-
-GtkWidget *
-gtk_printer_option_widget_new (GtkPrinterOption *source)
-{
- return g_object_new (GTK_TYPE_PRINTER_OPTION_WIDGET, "source", source, NULL);
-}
-
-static void
-source_changed_cb (GtkPrinterOption *source,
- GtkPrinterOptionWidget *widget)
-{
- update_widgets (widget);
- emit_changed (widget);
-}
-
-void
-gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *widget,
- GtkPrinterOption *source)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
- if (source)
- g_object_ref (source);
-
- if (priv->source)
- {
- g_signal_handler_disconnect (priv->source,
- priv->source_changed_handler);
- g_object_unref (priv->source);
- }
-
- priv->source = source;
-
- if (source)
- priv->source_changed_handler =
- g_signal_connect (source, "changed", G_CALLBACK (source_changed_cb), widget);
-
- construct_widgets (widget);
- update_widgets (widget);
-
- g_object_notify (G_OBJECT (widget), "source");
-}
-
-#define GTK_TYPE_STRING_PAIR (gtk_string_pair_get_type ())
-G_DECLARE_FINAL_TYPE (GtkStringPair, gtk_string_pair, GTK, STRING_PAIR, GObject)
-
-struct _GtkStringPair {
- GObject parent_instance;
- char *id;
- char *string;
-};
-
-enum {
- PROP_ID = 1,
- PROP_STRING,
- PROP_NUM_PROPERTIES
-};
-
-G_DEFINE_TYPE (GtkStringPair, gtk_string_pair, G_TYPE_OBJECT);
-
-static void
-gtk_string_pair_init (GtkStringPair *pair)
-{
-}
-
-static void
-gtk_string_pair_finalize (GObject *object)
-{
- GtkStringPair *pair = GTK_STRING_PAIR (object);
-
- g_free (pair->id);
- g_free (pair->string);
-
- G_OBJECT_CLASS (gtk_string_pair_parent_class)->finalize (object);
-}
-
-static void
-gtk_string_pair_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkStringPair *pair = GTK_STRING_PAIR (object);
-
- switch (property_id)
- {
- case PROP_STRING:
- g_free (pair->string);
- pair->string = g_value_dup_string (value);
- break;
-
- case PROP_ID:
- g_free (pair->id);
- pair->id = g_value_dup_string (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gtk_string_pair_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkStringPair *pair = GTK_STRING_PAIR (object);
-
- switch (property_id)
- {
- case PROP_STRING:
- g_value_set_string (value, pair->string);
- break;
-
- case PROP_ID:
- g_value_set_string (value, pair->id);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gtk_string_pair_class_init (GtkStringPairClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
- GParamSpec *pspec;
-
- object_class->finalize = gtk_string_pair_finalize;
- object_class->set_property = gtk_string_pair_set_property;
- object_class->get_property = gtk_string_pair_get_property;
-
- pspec = g_param_spec_string ("string", NULL, NULL,
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_property (object_class, PROP_STRING, pspec);
-
- pspec = g_param_spec_string ("id", NULL, NULL,
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_property (object_class, PROP_ID, pspec);
-}
-
-static GtkStringPair *
-gtk_string_pair_new (const char *id,
- const char *string)
-{
- return g_object_new (GTK_TYPE_STRING_PAIR,
- "id", id,
- "string", string,
- NULL);
-}
-
-static const char *
-gtk_string_pair_get_string (GtkStringPair *pair)
-{
- return pair->string;
-}
-
-static const char *
-gtk_string_pair_get_id (GtkStringPair *pair)
-{
- return pair->id;
-}
-
-static void
-combo_box_set_model (GtkWidget *combo_box)
-{
- GListStore *store;
-
- store = g_list_store_new (GTK_TYPE_STRING_PAIR);
- gtk_drop_down_set_model (GTK_DROP_DOWN (combo_box), G_LIST_MODEL (store));
- g_object_unref (store);
-}
-
-static void
-setup_no_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
-}
-
-static void
-setup_list_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkWidget *label;
-
- label = gtk_label_new ("");
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_list_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkStringPair *pair;
- GtkWidget *label;
-
- pair = gtk_list_item_get_item (item);
- label = gtk_list_item_get_child (item);
-
- gtk_label_set_text (GTK_LABEL (label), gtk_string_pair_get_string (pair));
-}
-
-static void
-combo_box_set_view (GtkWidget *combo_box)
-{
- GtkListItemFactory *factory;
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
- gtk_drop_down_set_factory (GTK_DROP_DOWN (combo_box), factory);
- g_object_unref (factory);
-}
-
-static void
-selected_changed (GtkDropDown *dropdown,
- GParamSpec *pspec,
- gpointer data)
-{
- GListModel *model;
- guint selected;
- GtkStringPair *pair;
- GtkWidget *entry = data;
-
- model = gtk_drop_down_get_model (dropdown);
- selected = gtk_drop_down_get_selected (dropdown);
-
- pair = g_list_model_get_item (model, selected);
- if (pair)
- {
- gtk_editable_set_text (GTK_EDITABLE (entry), gtk_string_pair_get_string (pair));
- g_object_unref (pair);
- }
- else
- gtk_editable_set_text (GTK_EDITABLE (entry), "");
-
-}
-
-static GtkWidget *
-combo_box_entry_new (void)
-{
- GtkWidget *hbox, *entry, *button;
- GtkListItemFactory *factory;
-
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_add_css_class (hbox, "linked");
-
- entry = gtk_entry_new ();
- button = gtk_drop_down_new (NULL, NULL);
- combo_box_set_model (button);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_no_item), NULL);
- gtk_drop_down_set_factory (GTK_DROP_DOWN (button), factory);
- g_object_unref (factory);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
- gtk_drop_down_set_list_factory (GTK_DROP_DOWN (button), factory);
- g_object_unref (factory);
-
- g_signal_connect (button, "notify::selected", G_CALLBACK (selected_changed), entry);
-
- gtk_box_append (GTK_BOX (hbox), entry);
- gtk_box_append (GTK_BOX (hbox), button);
-
- return hbox;
-}
-
-static GtkWidget *
-combo_box_new (void)
-{
- GtkWidget *combo_box;
-
- combo_box = gtk_drop_down_new (NULL, NULL);
-
- combo_box_set_model (combo_box);
- combo_box_set_view (combo_box);
-
- return combo_box;
-}
-
-static void
-combo_box_append (GtkWidget *combo,
- const char *display_text,
- const char *value)
-{
- GtkWidget *dropdown;
- GListModel *model;
- GtkStringPair *object;
-
- if (GTK_IS_DROP_DOWN (combo))
- dropdown = combo;
- else
- dropdown = gtk_widget_get_last_child (combo);
-
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
-
- object = gtk_string_pair_new (value, display_text);
- g_list_store_append (G_LIST_STORE (model), object);
- g_object_unref (object);
-}
-
-static void
-combo_box_set (GtkWidget *combo,
- const char *value)
-{
- GtkWidget *dropdown;
- GListModel *model;
- guint i;
-
- if (GTK_IS_DROP_DOWN (combo))
- dropdown = combo;
- else
- dropdown = gtk_widget_get_last_child (combo);
-
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
-
- for (i = 0; i < g_list_model_get_n_items (model); i++)
- {
- GtkStringPair *item = g_list_model_get_item (model, i);
- if (strcmp (value, gtk_string_pair_get_id (item)) == 0)
- {
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i);
- g_object_unref (item);
- break;
- }
- g_object_unref (item);
- }
-}
-
-static char *
-combo_box_get (GtkWidget *combo, gboolean *custom)
-{
- GtkWidget *dropdown;
- GListModel *model;
- guint selected;
- gpointer item;
- const char *id;
- const char *string;
-
- if (GTK_IS_DROP_DOWN (combo))
- dropdown = combo;
- else
- dropdown = gtk_widget_get_last_child (combo);
-
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
- selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown));
- item = g_list_model_get_item (model, selected);
- if (item)
- {
- id = gtk_string_pair_get_id (item);
- string = gtk_string_pair_get_string (item);
- g_object_unref (item);
- }
- else
- {
- id = "";
- string = NULL;
- }
-
- if (dropdown == combo) // no entry
- {
- *custom = FALSE;
- return g_strdup (id);
- }
- else
- {
- const char *text;
-
- text = gtk_editable_get_text (GTK_EDITABLE (gtk_widget_get_first_child (combo)));
- if (g_strcmp0 (text, string) == 0)
- {
- *custom = FALSE;
- return g_strdup (id);
- }
- else
- {
- *custom = TRUE;
- return g_strdup (text);
- }
- }
-}
-
-static void
-deconstruct_widgets (GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
- g_clear_pointer (&priv->check, gtk_widget_unparent);
- g_clear_pointer (&priv->combo, gtk_widget_unparent);
- g_clear_pointer (&priv->entry, gtk_widget_unparent);
- g_clear_pointer (&priv->image, gtk_widget_unparent);
- g_clear_pointer (&priv->label, gtk_widget_unparent);
- g_clear_pointer (&priv->info_label, gtk_widget_unparent);
-}
-
-static void
-check_toggled_cb (GtkCheckButton *check_button,
- GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
- g_signal_handler_block (priv->source, priv->source_changed_handler);
- gtk_printer_option_set_boolean (priv->source,
- gtk_check_button_get_active (check_button));
- g_signal_handler_unblock (priv->source, priv->source_changed_handler);
- emit_changed (widget);
-}
-
-static void
-dialog_response_callback (GObject *source,
- GAsyncResult *result,
- gpointer data)
-{
- GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
- GtkPrinterOptionWidget *widget = data;
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
- GFile *new_location = NULL;
- char *uri = NULL;
-
- new_location = gtk_file_dialog_save_finish (dialog, result, NULL);
- if (new_location)
- {
- GFileInfo *info;
-
- info = g_file_query_info (new_location,
- "standard::display-name",
- 0,
- NULL,
- NULL);
- if (info != NULL)
- {
- const char *filename_utf8 = g_file_info_get_display_name (info);
-
- char *filename_short = trim_long_filename (filename_utf8);
- gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
-
- g_free (filename_short);
- g_object_unref (info);
- }
- else
- {
- const char *path = g_file_peek_path (new_location);
- char *filename_utf8 = g_utf8_make_valid (path, -1);
-
- char *filename_short = trim_long_filename (filename_utf8);
- gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
-
- g_free (filename_short);
- g_free (filename_utf8);
- }
- }
-
- if (new_location)
- uri = g_file_get_uri (new_location);
- else
- uri = g_file_get_uri (priv->last_location);
-
- if (uri != NULL)
- {
- gtk_printer_option_set (priv->source, uri);
- emit_changed (widget);
- g_free (uri);
- }
-
- g_clear_object (&new_location);
- g_clear_object (&priv->last_location);
-
- /* unblock the handler which was blocked in the filesave_choose_cb function */
- g_signal_handler_unblock (priv->source, priv->source_changed_handler);
-}
-
-static void
-filesave_choose_cb (GtkWidget *button,
- GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
- GtkFileDialog *dialog;
-
- /* this will be unblocked in the dialog_response_callback function */
- g_signal_handler_block (priv->source, priv->source_changed_handler);
-
- dialog = gtk_file_dialog_new ();
- gtk_file_dialog_set_title (dialog, _("Select a filename"));
-
- /* select the current filename in the dialog */
- if (priv->source != NULL && priv->source->value != NULL)
- {
- priv->last_location = g_file_new_for_uri (priv->source->value);
- if (priv->last_location)
- {
- if (g_file_query_file_type (priv->last_location, 0, NULL) == G_FILE_TYPE_DIRECTORY)
- gtk_file_dialog_set_initial_folder (dialog, priv->last_location);
- else
- gtk_file_dialog_set_initial_file (dialog, priv->last_location);
- }
- }
-
- gtk_file_dialog_save (dialog,
- GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (widget))),
- NULL,
- dialog_response_callback, widget);
-}
-
-static char *
-filter_numeric (const char *val,
- gboolean allow_neg,
- gboolean allow_dec,
- gboolean *changed_out)
-{
- char *filtered_val;
- int i, j;
- int len = strlen (val);
- gboolean dec_set = FALSE;
-
- filtered_val = g_malloc (len + 1);
-
- for (i = 0, j = 0; i < len; i++)
- {
- if (isdigit (val[i]))
- {
- filtered_val[j] = val[i];
- j++;
- }
- else if (allow_dec && !dec_set &&
- (val[i] == '.' || val[i] == ','))
- {
- /* allow one period or comma
- * we should be checking locals
- * but this is good enough for now
- */
- filtered_val[j] = val[i];
- dec_set = TRUE;
- j++;
- }
- else if (allow_neg && i == 0 && val[0] == '-')
- {
- filtered_val[0] = val[0];
- j++;
- }
- }
-
- filtered_val[j] = '\0';
- *changed_out = !(i == j);
-
- return filtered_val;
-}
-
-static void
-combo_changed_cb (GtkWidget *combo,
- GParamSpec *pspec,
- GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
- char *value;
- char *filtered_val = NULL;
- gboolean changed;
- gboolean custom = TRUE;
-
- g_signal_handler_block (priv->source, priv->source_changed_handler);
-
- value = combo_box_get (priv->combo, &custom);
-
- /* Handle constraints if the user entered a custom value. */
- if (custom)
- {
- switch (priv->source->type)
- {
- case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
- filtered_val = filter_numeric (value, FALSE, FALSE, &changed);
- break;
- case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
- filtered_val = filter_numeric (value, TRUE, FALSE, &changed);
- break;
- case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
- filtered_val = filter_numeric (value, TRUE, TRUE, &changed);
- break;
- case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
- case GTK_PRINTER_OPTION_TYPE_PICKONE:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
- case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
- case GTK_PRINTER_OPTION_TYPE_STRING:
- case GTK_PRINTER_OPTION_TYPE_FILESAVE:
- case GTK_PRINTER_OPTION_TYPE_INFO:
- default:
- break;
- }
- }
-
- if (filtered_val)
- {
- g_free (value);
-
- if (changed)
- {
- GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
- gtk_editable_set_text (GTK_EDITABLE (entry), filtered_val);
- }
- value = filtered_val;
- }
-
- if (value)
- gtk_printer_option_set (priv->source, value);
- g_free (value);
- g_signal_handler_unblock (priv->source, priv->source_changed_handler);
- emit_changed (widget);
-}
-
-static void
-entry_changed_cb (GtkWidget *entry,
- GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
- const char *value;
-
- g_signal_handler_block (priv->source, priv->source_changed_handler);
- value = gtk_editable_get_text (GTK_EDITABLE (entry));
- if (value)
- gtk_printer_option_set (priv->source, value);
- g_signal_handler_unblock (priv->source, priv->source_changed_handler);
- emit_changed (widget);
-}
-
-
-static void
-radio_changed_cb (GtkWidget *button,
- GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
- char *value;
-
- g_signal_handler_block (priv->source, priv->source_changed_handler);
- value = g_object_get_data (G_OBJECT (button), "value");
- if (value)
- gtk_printer_option_set (priv->source, value);
- g_signal_handler_unblock (priv->source, priv->source_changed_handler);
- emit_changed (widget);
-}
-
-static void
-alternative_set (GtkWidget *box,
- const char *value)
-{
- GtkWidget *child;
-
- for (child = gtk_widget_get_first_child (box);
- child != NULL;
- child = gtk_widget_get_next_sibling (child))
- {
- char *v = g_object_get_data (G_OBJECT (child), "value");
-
- if (strcmp (value, v) == 0)
- {
- gtk_check_button_set_active (GTK_CHECK_BUTTON (child), TRUE);
- break;
- }
- }
-}
-
-static void
-alternative_append (GtkWidget *box,
- const char *label,
- const char *value,
- GtkPrinterOptionWidget *widget,
- GtkWidget **group)
-{
- GtkWidget *button;
-
- button = gtk_check_button_new_with_label (label);
- if (*group)
- gtk_check_button_set_group (GTK_CHECK_BUTTON (button), GTK_CHECK_BUTTON (*group));
- else
- *group = button;
-
- gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
- gtk_box_append (GTK_BOX (box), button);
-
- g_object_set_data (G_OBJECT (button), "value", (gpointer)value);
- g_signal_connect (button, "toggled", G_CALLBACK (radio_changed_cb), widget);
-}
-
-static void
-construct_widgets (GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
- GtkPrinterOption *source;
- char *text;
- int i;
- GtkWidget *group;
-
- source = priv->source;
-
- deconstruct_widgets (widget);
-
- gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE);
-
- if (source == NULL)
- {
- const char * strings[2];
- strings[0] = _("Not available");
- strings[1] = NULL;
- priv->combo = gtk_drop_down_new_from_strings (strings);
- gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->combo), 0);
- gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE);
- gtk_box_append (GTK_BOX (widget), priv->combo);
- }
- else switch (source->type)
- {
- case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
- priv->check = gtk_check_button_new_with_mnemonic (source->display_text);
- g_signal_connect (priv->check, "toggled", G_CALLBACK (check_toggled_cb), widget);
- gtk_box_append (GTK_BOX (widget), priv->check);
- break;
- case GTK_PRINTER_OPTION_TYPE_PICKONE:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
- if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE)
- {
- priv->combo = combo_box_new ();
- }
- else
- {
- priv->combo = combo_box_entry_new ();
-
- if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD ||
- source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE)
- {
- GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
- gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
- }
- }
-
- for (i = 0; i < source->num_choices; i++)
- combo_box_append (priv->combo,
- source->choices_display[i],
- source->choices[i]);
- gtk_box_append (GTK_BOX (widget), priv->combo);
- if (GTK_IS_DROP_DOWN (priv->combo))
- g_signal_connect (priv->combo, "notify::selected", G_CALLBACK (combo_changed_cb),widget);
- else
- g_signal_connect (gtk_widget_get_last_child (priv->combo), "notify::selected",G_CALLBACK (combo_changed_cb), widget);
-
- text = g_strdup_printf ("%s:", source->display_text);
- priv->label = gtk_label_new_with_mnemonic (text);
- g_free (text);
- break;
-
- case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
- group = NULL;
- priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
- gtk_widget_set_valign (priv->box, GTK_ALIGN_BASELINE_FILL);
- gtk_box_append (GTK_BOX (widget), priv->box);
- for (i = 0; i < source->num_choices; i++)
- {
- alternative_append (priv->box,
- source->choices_display[i],
- source->choices[i],
- widget,
- &group);
- /* for mnemonic activation */
- if (i == 0)
- priv->button = group;
- }
-
- if (source->display_text)
- {
- text = g_strdup_printf ("%s:", source->display_text);
- priv->label = gtk_label_new_with_mnemonic (text);
- gtk_widget_set_valign (priv->label, GTK_ALIGN_BASELINE_FILL);
- g_free (text);
- }
- break;
-
- case GTK_PRINTER_OPTION_TYPE_STRING:
- priv->entry = gtk_entry_new ();
- gtk_entry_set_activates_default (GTK_ENTRY (priv->entry),
- gtk_printer_option_get_activates_default (source));
- gtk_box_append (GTK_BOX (widget), priv->entry);
- g_signal_connect (priv->entry, "changed", G_CALLBACK (entry_changed_cb), widget);
-
- text = g_strdup_printf ("%s:", source->display_text);
- priv->label = gtk_label_new_with_mnemonic (text);
- g_free (text);
-
- break;
-
- case GTK_PRINTER_OPTION_TYPE_FILESAVE:
- priv->button = gtk_button_new ();
- gtk_box_append (GTK_BOX (widget), priv->button);
- g_signal_connect (priv->button, "clicked", G_CALLBACK (filesave_choose_cb), widget);
-
- text = g_strdup_printf ("%s:", source->display_text);
- priv->label = gtk_label_new_with_mnemonic (text);
- g_free (text);
-
- break;
-
- case GTK_PRINTER_OPTION_TYPE_INFO:
- priv->info_label = gtk_label_new (NULL);
- gtk_label_set_selectable (GTK_LABEL (priv->info_label), TRUE);
- gtk_box_append (GTK_BOX (widget), priv->info_label);
-
- text = g_strdup_printf ("%s:", source->display_text);
- priv->label = gtk_label_new_with_mnemonic (text);
- g_free (text);
-
- break;
-
- default:
- break;
- }
-
- priv->image = gtk_image_new_from_icon_name ("dialog-warning");
- gtk_box_append (GTK_BOX (widget), priv->image);
-}
-
-/*
- * If the filename exceeds FILENAME_LENGTH_MAX, then trim it and replace
- * the first three letters with three dots.
- */
-static char *
-trim_long_filename (const char *filename)
-{
- const char *home;
- int len, offset;
- char *result;
-
- home = g_get_home_dir ();
- if (g_str_has_prefix (filename, home))
- {
- char *homeless_filename;
-
- offset = g_utf8_strlen (home, -1);
- len = g_utf8_strlen (filename, -1);
- homeless_filename = g_utf8_substring (filename, offset, len);
- result = g_strconcat ("~", homeless_filename, NULL);
- g_free (homeless_filename);
- }
- else
- result = g_strdup (filename);
-
- len = g_utf8_strlen (result, -1);
- if (len > FILENAME_LENGTH_MAX)
- {
- char *suffix;
-
- suffix = g_utf8_substring (result, len - FILENAME_LENGTH_MAX, len);
- g_free (result);
- result = g_strconcat ("...", suffix, NULL);
- g_free (suffix);
- }
-
- return result;
-}
-
-static void
-update_widgets (GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
- GtkPrinterOption *source;
-
- source = priv->source;
-
- if (source == NULL)
- {
- gtk_widget_set_visible (priv->image, FALSE);
- return;
- }
-
- switch (source->type)
- {
- case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
- if (g_ascii_strcasecmp (source->value, "True") == 0)
- gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), TRUE);
- else
- gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), FALSE);
- break;
- case GTK_PRINTER_OPTION_TYPE_PICKONE:
- combo_box_set (priv->combo, source->value);
- break;
- case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
- alternative_set (priv->box, source->value);
- break;
- case GTK_PRINTER_OPTION_TYPE_STRING:
- gtk_editable_set_text (GTK_EDITABLE (priv->entry), source->value);
- break;
- case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
- case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
- {
- GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
- if (gtk_printer_option_has_choice (source, source->value))
- combo_box_set (priv->combo, source->value);
- else
- gtk_editable_set_text (GTK_EDITABLE (entry), source->value);
-
- break;
- }
- case GTK_PRINTER_OPTION_TYPE_FILESAVE:
- {
- char *text;
- char *filename;
-
- filename = g_filename_from_uri (source->value, NULL, NULL);
- if (filename != NULL)
- {
- text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
- if (text != NULL)
- {
- char *short_filename;
-
- short_filename = trim_long_filename (text);
- gtk_button_set_label (GTK_BUTTON (priv->button), short_filename);
- g_free (short_filename);
- }
-
- g_free (text);
- g_free (filename);
- }
- else
- gtk_button_set_label (GTK_BUTTON (priv->button), source->value);
- break;
- }
- case GTK_PRINTER_OPTION_TYPE_INFO:
- gtk_label_set_text (GTK_LABEL (priv->info_label), source->value);
- break;
- default:
- break;
- }
-
- gtk_widget_set_visible (priv->image, source->has_conflict);
-}
-
-gboolean
-gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *widget)
-{
- return widget->priv->label != NULL;
-}
-
-GtkWidget *
-gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget *widget)
-{
- return widget->priv->label;
-}
-
-const char *
-gtk_printer_option_widget_get_value (GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
- if (priv->source)
- return priv->source->value;
-
- return "";
-}
+++ /dev/null
-/* GtkPrinterOptionWidget
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
- */
-#pragma once
-
-#include "gtkprinteroptionprivate.h"
-#include "gtkbox.h"
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINTER_OPTION_WIDGET (gtk_printer_option_widget_get_type ())
-#define GTK_PRINTER_OPTION_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidget))
-#define GTK_PRINTER_OPTION_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
-#define GTK_IS_PRINTER_OPTION_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET))
-#define GTK_IS_PRINTER_OPTION_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET))
-#define GTK_PRINTER_OPTION_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
-
-
-typedef struct _GtkPrinterOptionWidget GtkPrinterOptionWidget;
-typedef struct _GtkPrinterOptionWidgetClass GtkPrinterOptionWidgetClass;
-typedef struct GtkPrinterOptionWidgetPrivate GtkPrinterOptionWidgetPrivate;
-
-struct _GtkPrinterOptionWidget
-{
- GtkBox parent_instance;
-
- GtkPrinterOptionWidgetPrivate *priv;
-};
-
-struct _GtkPrinterOptionWidgetClass
-{
- GtkBoxClass parent_class;
-
- void (*changed) (GtkPrinterOptionWidget *widget);
-
- /* Padding for future expansion */
- void (*_gtk_reserved1) (void);
- void (*_gtk_reserved2) (void);
- void (*_gtk_reserved3) (void);
- void (*_gtk_reserved4) (void);
-};
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_printer_option_widget_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkWidget *gtk_printer_option_widget_new (GtkPrinterOption *source);
-GDK_AVAILABLE_IN_ALL
-void gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *setting,
- GtkPrinterOption *source);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *setting);
-GDK_AVAILABLE_IN_ALL
-GtkWidget *gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget *setting);
-GDK_AVAILABLE_IN_ALL
-const char *gtk_printer_option_widget_get_value (GtkPrinterOptionWidget *setting);
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintoperation.h: Print Operation
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-#include <gtk/gtk.h>
-#include <gtk/gtkunixprint.h>
-#include "gtkprinteroptionsetprivate.h"
-
-G_BEGIN_DECLS
-
-#define GTK_PRINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER, GtkPrinterClass))
-#define GTK_IS_PRINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER))
-#define GTK_PRINTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER, GtkPrinterClass))
-
-typedef struct _GtkPrinterClass GtkPrinterClass;
-typedef struct _GtkPrinterPrivate GtkPrinterPrivate;
-
-struct _GtkPrinter
-{
- GObject parent_instance;
-};
-
-struct _GtkPrinterClass
-{
- GObjectClass parent_class;
-
- void (*details_acquired) (GtkPrinter *printer,
- gboolean success);
-};
-
-GtkPrinterOptionSet *_gtk_printer_get_options (GtkPrinter *printer,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup,
- GtkPrintCapabilities capabilities);
-gboolean _gtk_printer_mark_conflicts (GtkPrinter *printer,
- GtkPrinterOptionSet *options);
-void _gtk_printer_get_settings_from_options (GtkPrinter *printer,
- GtkPrinterOptionSet *options,
- GtkPrintSettings *settings);
-void _gtk_printer_prepare_for_print (GtkPrinter *printer,
- GtkPrintJob *print_job,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup);
-cairo_surface_t * _gtk_printer_create_cairo_surface (GtkPrinter *printer,
- GtkPrintSettings *settings,
- double width,
- double height,
- GIOChannel *cache_io);
-GHashTable * _gtk_printer_get_custom_widgets (GtkPrinter *printer);
-
-/* GtkPrintJob private methods: */
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_status (GtkPrintJob *job,
- GtkPrintStatus status);
-
-G_END_DECLS
+++ /dev/null
-/* GtkPrintJob
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
- */
-
-/**
- * GtkPrintJob:
- *
- * A `GtkPrintJob` object represents a job that is sent to a printer.
- *
- * You only need to deal directly with print jobs if you use the
- * non-portable [class@Gtk.PrintUnixDialog] API.
- *
- * Use [method@Gtk.PrintJob.get_surface] to obtain the cairo surface
- * onto which the pages must be drawn. Use [method@Gtk.PrintJob.send]
- * to send the finished job to the printer. If you don’t use cairo
- * `GtkPrintJob` also supports printing of manually generated PostScript,
- * via [method@Gtk.PrintJob.set_source_file].
- */
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <glib/gstdio.h>
-#include "gtkprivate.h"
-
-#include "gtkprintjob.h"
-#include "gtkprinter.h"
-#include "gtkprinterprivate.h"
-#include "gtkprintbackendprivate.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-typedef struct _GtkPrintJobClass GtkPrintJobClass;
-
-struct _GtkPrintJob
-{
- GObject parent_instance;
-
- char *title;
-
- GIOChannel *spool_io;
- cairo_surface_t *surface;
-
- GtkPrintStatus status;
- GtkPrintBackend *backend;
- GtkPrinter *printer;
- GtkPrintSettings *settings;
- GtkPageSetup *page_setup;
-
- GtkPrintPages print_pages;
- GtkPageRange *page_ranges;
- int num_page_ranges;
- GtkPageSet page_set;
- int num_copies;
- double scale;
- guint number_up;
- GtkNumberUpLayout number_up_layout;
-
- guint printer_set : 1;
- guint page_setup_set : 1;
- guint settings_set : 1;
- guint track_print_status : 1;
- guint rotate_to_orientation : 1;
- guint collate : 1;
- guint reverse : 1;
-};
-
-struct _GtkPrintJobClass
-{
- GObjectClass parent_class;
-
- void (*status_changed) (GtkPrintJob *job);
-};
-
-static void gtk_print_job_finalize (GObject *object);
-static void gtk_print_job_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_print_job_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void gtk_print_job_constructed (GObject *object);
-
-enum {
- STATUS_CHANGED,
- LAST_SIGNAL
-};
-
-enum {
- PROP_0,
- PROP_TITLE,
- PROP_PRINTER,
- PROP_PAGE_SETUP,
- PROP_SETTINGS,
- PROP_TRACK_PRINT_STATUS
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (GtkPrintJob, gtk_print_job, G_TYPE_OBJECT)
-
-static void
-gtk_print_job_class_init (GtkPrintJobClass *class)
-{
- GObjectClass *object_class;
- object_class = (GObjectClass *) class;
-
- object_class->finalize = gtk_print_job_finalize;
- object_class->constructed = gtk_print_job_constructed;
- object_class->set_property = gtk_print_job_set_property;
- object_class->get_property = gtk_print_job_get_property;
-
- /**
- * GtkPrintJob:title: (attributes org.gtk.Property.get=gtk_print_job_get_title)
- *
- * The title of the print job.
- */
- g_object_class_install_property (object_class,
- PROP_TITLE,
- g_param_spec_string ("title", NULL, NULL,
- NULL,
- GTK_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrintJob:printer: (attributes org.gtk.Property.get=gtk_print_job_get_printer)
- *
- * The printer to send the job to.
- */
- g_object_class_install_property (object_class,
- PROP_PRINTER,
- g_param_spec_object ("printer", NULL, NULL,
- GTK_TYPE_PRINTER,
- GTK_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrintJob:settings: (attributes org.gtk.Property.get=gtk_print_job_get_settings)
- *
- * Printer settings.
- */
- g_object_class_install_property (object_class,
- PROP_SETTINGS,
- g_param_spec_object ("settings", NULL, NULL,
- GTK_TYPE_PRINT_SETTINGS,
- GTK_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrintJob:page-setup:
- *
- * Page setup.
- */
- g_object_class_install_property (object_class,
- PROP_PAGE_SETUP,
- g_param_spec_object ("page-setup", NULL, NULL,
- GTK_TYPE_PAGE_SETUP,
- GTK_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * GtkPrintJob:track-print-status: (attributes org.gtk.Property.get=gtk_print_job_get_track_print_status org.gtk.Property.set=gtk_print_job_set_track_print_status)
- *
- * %TRUE if the print job will continue to emit status-changed
- * signals after the print data has been setn to the printer.
- */
- g_object_class_install_property (object_class,
- PROP_TRACK_PRINT_STATUS,
- g_param_spec_boolean ("track-print-status", NULL, NULL,
- FALSE,
- GTK_PARAM_READWRITE));
-
- /**
- * GtkPrintJob::status-changed:
- * @job: the `GtkPrintJob` object on which the signal was emitted
- *
- * Emitted when the status of a job changes.
- *
- * The signal handler can use [method@Gtk.PrintJob.get_status]
- * to obtain the new status.
- */
- signals[STATUS_CHANGED] =
- g_signal_new (I_("status-changed"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkPrintJobClass, status_changed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
-}
-
-static void
-gtk_print_job_init (GtkPrintJob *job)
-{
- job->spool_io = NULL;
-
- job->title = g_strdup ("");
- job->surface = NULL;
- job->backend = NULL;
- job->printer = NULL;
-
- job->printer_set = FALSE;
- job->settings_set = FALSE;
- job->page_setup_set = FALSE;
- job->status = GTK_PRINT_STATUS_INITIAL;
- job->track_print_status = FALSE;
-
- job->print_pages = GTK_PRINT_PAGES_ALL;
- job->page_ranges = NULL;
- job->num_page_ranges = 0;
- job->collate = FALSE;
- job->reverse = FALSE;
- job->num_copies = 1;
- job->scale = 1.0;
- job->page_set = GTK_PAGE_SET_ALL;
- job->rotate_to_orientation = FALSE;
- job->number_up = 1;
- job->number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-}
-
-
-static void
-gtk_print_job_constructed (GObject *object)
-{
- GtkPrintJob *job = GTK_PRINT_JOB (object);
-
- G_OBJECT_CLASS (gtk_print_job_parent_class)->constructed (object);
-
- g_assert (job->printer_set &&
- job->settings_set &&
- job->page_setup_set);
-
- _gtk_printer_prepare_for_print (job->printer,
- job,
- job->settings,
- job->page_setup);
-}
-
-
-static void
-gtk_print_job_finalize (GObject *object)
-{
- GtkPrintJob *job = GTK_PRINT_JOB (object);
-
- if (job->surface)
- cairo_surface_destroy (job->surface);
-
- if (job->backend)
- g_object_unref (job->backend);
-
- if (job->spool_io != NULL)
- {
- g_io_channel_unref (job->spool_io);
- job->spool_io = NULL;
- }
-
- if (job->printer)
- g_object_unref (job->printer);
-
- if (job->settings)
- g_object_unref (job->settings);
-
- if (job->page_setup)
- g_object_unref (job->page_setup);
-
- g_free (job->page_ranges);
- job->page_ranges = NULL;
-
- g_free (job->title);
- job->title = NULL;
-
- G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize (object);
-}
-
-/**
- * gtk_print_job_new:
- * @title: the job title
- * @printer: a `GtkPrinter`
- * @settings: a `GtkPrintSettings`
- * @page_setup: a `GtkPageSetup`
- *
- * Creates a new `GtkPrintJob`.
- *
- * Returns: a new `GtkPrintJob`
- */
-GtkPrintJob *
-gtk_print_job_new (const char *title,
- GtkPrinter *printer,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup)
-{
- GObject *result;
- result = g_object_new (GTK_TYPE_PRINT_JOB,
- "title", title,
- "printer", printer,
- "settings", settings,
- "page-setup", page_setup,
- NULL);
- return (GtkPrintJob *) result;
-}
-
-/**
- * gtk_print_job_get_settings: (attributes org.gtk.Method.get_property=settings)
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPrintSettings` of the print job.
- *
- * Returns: (transfer none): the settings of @job
- */
-GtkPrintSettings *
-gtk_print_job_get_settings (GtkPrintJob *job)
-{
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-
- return job->settings;
-}
-
-/**
- * gtk_print_job_get_printer: (attributes org.gtk.Method.get_property=printer)
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPrinter` of the print job.
- *
- * Returns: (transfer none): the printer of @job
- */
-GtkPrinter *
-gtk_print_job_get_printer (GtkPrintJob *job)
-{
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-
- return job->printer;
-}
-
-/**
- * gtk_print_job_get_title: (attributes org.gtk.Method.get_property=title)
- * @job: a `GtkPrintJob`
- *
- * Gets the job title.
- *
- * Returns: the title of @job
- */
-const char *
-gtk_print_job_get_title (GtkPrintJob *job)
-{
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-
- return job->title;
-}
-
-/**
- * gtk_print_job_get_status:
- * @job: a `GtkPrintJob`
- *
- * Gets the status of the print job.
- *
- * Returns: the status of @job
- */
-GtkPrintStatus
-gtk_print_job_get_status (GtkPrintJob *job)
-{
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), GTK_PRINT_STATUS_FINISHED);
-
- return job->status;
-}
-
-void
-gtk_print_job_set_status (GtkPrintJob *job,
- GtkPrintStatus status)
-{
- g_return_if_fail (GTK_IS_PRINT_JOB (job));
-
- if (job->status == status)
- return;
-
- job->status = status;
- g_signal_emit (job, signals[STATUS_CHANGED], 0);
-}
-
-/**
- * gtk_print_job_set_source_file:
- * @job: a `GtkPrintJob`
- * @filename: (type filename): the file to be printed
- * @error: return location for errors
- *
- * Make the `GtkPrintJob` send an existing document to the
- * printing system.
- *
- * The file can be in any format understood by the platforms
- * printing system (typically PostScript, but on many platforms
- * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
- * [method@Gtk.Printer.accepts_ps].
- *
- * Returns: %FALSE if an error occurred
- */
-gboolean
-gtk_print_job_set_source_file (GtkPrintJob *job,
- const char *filename,
- GError **error)
-{
- GError *tmp_error;
-
- tmp_error = NULL;
-
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
-
- if (job->spool_io != NULL)
- g_io_channel_unref (job->spool_io);
-
- job->spool_io = g_io_channel_new_file (filename, "r", &tmp_error);
-
- if (tmp_error == NULL)
- g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
-
- if (tmp_error != NULL)
- {
- g_propagate_error (error, tmp_error);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * gtk_print_job_set_source_fd:
- * @job: a `GtkPrintJob`
- * @fd: a file descriptor
- * @error: return location for errors
- *
- * Make the `GtkPrintJob` send an existing document to the
- * printing system.
- *
- * The file can be in any format understood by the platforms
- * printing system (typically PostScript, but on many platforms
- * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
- * [method@Gtk.Printer.accepts_ps].
- *
- * This is similar to [method@Gtk.PrintJob.set_source_file],
- * but takes expects an open file descriptor for the file,
- * instead of a filename.
- *
- * Returns: %FALSE if an error occurred
- */
-gboolean
-gtk_print_job_set_source_fd (GtkPrintJob *job,
- int fd,
- GError **error)
-{
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
- g_return_val_if_fail (fd >= 0, FALSE);
-
- if (job->spool_io != NULL)
- g_io_channel_unref (job->spool_io);
-
- job->spool_io = g_io_channel_unix_new (fd);
- if (g_io_channel_set_encoding (job->spool_io, NULL, error) != G_IO_STATUS_NORMAL)
- return FALSE;
-
- return TRUE;
-}
-
-/**
- * gtk_print_job_get_surface:
- * @job: a `GtkPrintJob`
- * @error: (nullable): return location for errors
- *
- * Gets a cairo surface onto which the pages of
- * the print job should be rendered.
- *
- * Returns: (transfer none): the cairo surface of @job
- */
-cairo_surface_t *
-gtk_print_job_get_surface (GtkPrintJob *job,
- GError **error)
-{
- char *filename = NULL;
- double width, height;
- GtkPaperSize *paper_size;
- int fd;
- GError *tmp_error;
-
- tmp_error = NULL;
-
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-
- if (job->surface)
- return job->surface;
-
- g_return_val_if_fail (job->spool_io == NULL, NULL);
-
- fd = g_file_open_tmp ("gtkprint_XXXXXX",
- &filename,
- &tmp_error);
- if (fd == -1)
- {
- g_free (filename);
- g_propagate_error (error, tmp_error);
- return NULL;
- }
-
- fchmod (fd, S_IRUSR | S_IWUSR);
-
-#ifdef G_ENABLE_DEBUG
- /* If we are debugging printing don't delete the tmp files */
- if (GTK_DEBUG_CHECK (PRINTING)) ;
- else
-#endif /* G_ENABLE_DEBUG */
- g_unlink (filename);
- g_free (filename);
-
- paper_size = gtk_page_setup_get_paper_size (job->page_setup);
- width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
- height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-
- job->spool_io = g_io_channel_unix_new (fd);
- g_io_channel_set_close_on_unref (job->spool_io, TRUE);
- g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
-
- if (tmp_error != NULL)
- {
- g_io_channel_unref (job->spool_io);
- job->spool_io = NULL;
- g_propagate_error (error, tmp_error);
- return NULL;
- }
-
- job->surface = _gtk_printer_create_cairo_surface (job->printer,
- job->settings,
- width, height,
- job->spool_io);
-
- return job->surface;
-}
-
-/**
- * gtk_print_job_set_track_print_status: (attributes org.gtk.Method.set_property=track-print-status)
- * @job: a `GtkPrintJob`
- * @track_status: %TRUE to track status after printing
- *
- * If track_status is %TRUE, the print job will try to continue report
- * on the status of the print job in the printer queues and printer.
- *
- * This can allow your application to show things like “out of paper”
- * issues, and when the print job actually reaches the printer.
- *
- * This function is often implemented using some form of polling,
- * so it should not be enabled unless needed.
- */
-void
-gtk_print_job_set_track_print_status (GtkPrintJob *job,
- gboolean track_status)
-{
- g_return_if_fail (GTK_IS_PRINT_JOB (job));
-
- track_status = track_status != FALSE;
-
- if (job->track_print_status != track_status)
- {
- job->track_print_status = track_status;
-
- g_object_notify (G_OBJECT (job), "track-print-status");
- }
-}
-
-/**
- * gtk_print_job_get_track_print_status: (attributes org.gtk.Method.get_property=track-print-status)
- * @job: a `GtkPrintJob`
- *
- * Returns whether jobs will be tracked after printing.
- *
- * For details, see [method@Gtk.PrintJob.set_track_print_status].
- *
- * Returns: %TRUE if print job status will be reported after printing
- */
-gboolean
-gtk_print_job_get_track_print_status (GtkPrintJob *job)
-{
- g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
-
- return job->track_print_status;
-}
-
-static void
-gtk_print_job_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-
-{
- GtkPrintJob *job = GTK_PRINT_JOB (object);
- GtkPrintSettings *settings;
-
- switch (prop_id)
- {
- case PROP_TITLE:
- g_free (job->title);
- job->title = g_value_dup_string (value);
- break;
-
- case PROP_PRINTER:
- job->printer = GTK_PRINTER (g_value_dup_object (value));
- job->printer_set = TRUE;
- job->backend = g_object_ref (gtk_printer_get_backend (job->printer));
- break;
-
- case PROP_PAGE_SETUP:
- job->page_setup = GTK_PAGE_SETUP (g_value_dup_object (value));
- job->page_setup_set = TRUE;
- break;
-
- case PROP_SETTINGS:
- /* We save a copy of the settings since we modify
- * if when preparing the printer job. */
- settings = GTK_PRINT_SETTINGS (g_value_get_object (value));
- job->settings = gtk_print_settings_copy (settings);
- job->settings_set = TRUE;
- break;
-
- case PROP_TRACK_PRINT_STATUS:
- gtk_print_job_set_track_print_status (job, g_value_get_boolean (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_print_job_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkPrintJob *job = GTK_PRINT_JOB (object);
-
- switch (prop_id)
- {
- case PROP_TITLE:
- g_value_set_string (value, job->title);
- break;
- case PROP_PRINTER:
- g_value_set_object (value, job->printer);
- break;
- case PROP_SETTINGS:
- g_value_set_object (value, job->settings);
- break;
- case PROP_PAGE_SETUP:
- g_value_set_object (value, job->page_setup);
- break;
- case PROP_TRACK_PRINT_STATUS:
- g_value_set_boolean (value, job->track_print_status);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/**
- * gtk_print_job_send:
- * @job: a `GtkPrintJob`
- * @callback: function to call when the job completes or an error occurs
- * @user_data: (closure): user data that gets passed to @callback
- * @dnotify: destroy notify for @user_data
- *
- * Sends the print job off to the printer.
- */
-void
-gtk_print_job_send (GtkPrintJob *job,
- GtkPrintJobCompleteFunc callback,
- gpointer user_data,
- GDestroyNotify dnotify)
-{
- g_return_if_fail (GTK_IS_PRINT_JOB (job));
- g_return_if_fail (job->spool_io != NULL);
-
- gtk_print_job_set_status (job, GTK_PRINT_STATUS_SENDING_DATA);
-
- g_io_channel_seek_position (job->spool_io, 0, G_SEEK_SET, NULL);
-
- gtk_print_backend_print_stream (job->backend, job,
- job->spool_io,
- callback, user_data, dnotify);
-}
-
-/**
- * gtk_print_job_get_pages:
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPrintPages` setting for this job.
- *
- * Returns: the `GtkPrintPages` setting
- */
-GtkPrintPages
-gtk_print_job_get_pages (GtkPrintJob *job)
-{
- return job->print_pages;
-}
-
-/**
- * gtk_print_job_set_pages:
- * @job: a `GtkPrintJob`
- * @pages: the `GtkPrintPages` setting
- *
- * Sets the `GtkPrintPages` setting for this job.
- */
-void
-gtk_print_job_set_pages (GtkPrintJob *job,
- GtkPrintPages pages)
-{
- job->print_pages = pages;
-}
-
-/**
- * gtk_print_job_get_page_ranges:
- * @job: a `GtkPrintJob`
- * @n_ranges: (out): return location for the number of ranges
- *
- * Gets the page ranges for this job.
- *
- * Returns: (array length=n_ranges) (transfer none): a pointer to an
- * array of `GtkPageRange` structs
- */
-GtkPageRange *
-gtk_print_job_get_page_ranges (GtkPrintJob *job,
- int *n_ranges)
-{
- *n_ranges = job->num_page_ranges;
- return job->page_ranges;
-}
-
-/**
- * gtk_print_job_set_page_ranges:
- * @job: a `GtkPrintJob`
- * @ranges: (array length=n_ranges) (transfer full): pointer to an array of
- * `GtkPageRange` structs
- * @n_ranges: the length of the @ranges array
- *
- * Sets the page ranges for this job.
- */
-void
-gtk_print_job_set_page_ranges (GtkPrintJob *job,
- GtkPageRange *ranges,
- int n_ranges)
-{
- g_free (job->page_ranges);
- job->page_ranges = ranges;
- job->num_page_ranges = n_ranges;
-}
-
-/**
- * gtk_print_job_get_page_set:
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPageSet` setting for this job.
- *
- * Returns: the `GtkPageSet` setting
- */
-GtkPageSet
-gtk_print_job_get_page_set (GtkPrintJob *job)
-{
- return job->page_set;
-}
-
-/**
- * gtk_print_job_set_page_set:
- * @job: a `GtkPrintJob`
- * @page_set: a `GtkPageSet` setting
- *
- * Sets the `GtkPageSet` setting for this job.
- */
-void
-gtk_print_job_set_page_set (GtkPrintJob *job,
- GtkPageSet page_set)
-{
- job->page_set = page_set;
-}
-
-/**
- * gtk_print_job_get_num_copies:
- * @job: a `GtkPrintJob`
- *
- * Gets the number of copies of this job.
- *
- * Returns: the number of copies
- */
-int
-gtk_print_job_get_num_copies (GtkPrintJob *job)
-{
- return job->num_copies;
-}
-
-/**
- * gtk_print_job_set_num_copies:
- * @job: a `GtkPrintJob`
- * @num_copies: the number of copies
- *
- * Sets the number of copies for this job.
- */
-void
-gtk_print_job_set_num_copies (GtkPrintJob *job,
- int num_copies)
-{
- job->num_copies = num_copies;
-}
-
-/**
- * gtk_print_job_get_scale:
- * @job: a `GtkPrintJob`
- *
- * Gets the scale for this job.
- *
- * Returns: the scale
- */
-double
-gtk_print_job_get_scale (GtkPrintJob *job)
-
-{
- return job->scale;
-}
-
-/**
- * gtk_print_job_set_scale:
- * @job: a `GtkPrintJob`
- * @scale: the scale
- *
- * Sets the scale for this job.
- *
- * 1.0 means unscaled.
- */
-void
-gtk_print_job_set_scale (GtkPrintJob *job,
- double scale)
-{
- job->scale = scale;
-}
-
-/**
- * gtk_print_job_get_n_up:
- * @job: a `GtkPrintJob`
- *
- * Gets the n-up setting for this job.
- *
- * Returns: the n-up setting
- */
-guint
-gtk_print_job_get_n_up (GtkPrintJob *job)
-{
- return job->number_up;
-}
-
-/**
- * gtk_print_job_set_n_up:
- * @job: a `GtkPrintJob`
- * @n_up: the n-up value
- *
- * Sets the n-up setting for this job.
- */
-void
-gtk_print_job_set_n_up (GtkPrintJob *job,
- guint n_up)
-{
- job->number_up = n_up;
-}
-
-/**
- * gtk_print_job_get_n_up_layout:
- * @job: a `GtkPrintJob`
- *
- * Gets the n-up layout setting for this job.
- *
- * Returns: the n-up layout
- */
-GtkNumberUpLayout
-gtk_print_job_get_n_up_layout (GtkPrintJob *job)
-{
- return job->number_up_layout;
-}
-
-/**
- * gtk_print_job_set_n_up_layout:
- * @job: a `GtkPrintJob`
- * @layout: the n-up layout setting
- *
- * Sets the n-up layout setting for this job.
- */
-void
-gtk_print_job_set_n_up_layout (GtkPrintJob *job,
- GtkNumberUpLayout layout)
-{
- job->number_up_layout = layout;
-}
-
-/**
- * gtk_print_job_get_rotate:
- * @job: a `GtkPrintJob`
- *
- * Gets whether the job is printed rotated.
- *
- * Returns: whether the job is printed rotated
- */
-gboolean
-gtk_print_job_get_rotate (GtkPrintJob *job)
-{
- return job->rotate_to_orientation;
-}
-
-/**
- * gtk_print_job_set_rotate:
- * @job: a `GtkPrintJob`
- * @rotate: whether to print rotated
- *
- * Sets whether this job is printed rotated.
- */
-void
-gtk_print_job_set_rotate (GtkPrintJob *job,
- gboolean rotate)
-{
- job->rotate_to_orientation = rotate;
-}
-
-/**
- * gtk_print_job_get_collate:
- * @job: a `GtkPrintJob`
- *
- * Gets whether this job is printed collated.
- *
- * Returns: whether the job is printed collated
- */
-gboolean
-gtk_print_job_get_collate (GtkPrintJob *job)
-{
- return job->collate;
-}
-
-/**
- * gtk_print_job_set_collate:
- * @job: a `GtkPrintJob`
- * @collate: whether the job is printed collated
- *
- * Sets whether this job is printed collated.
- */
-void
-gtk_print_job_set_collate (GtkPrintJob *job,
- gboolean collate)
-{
- job->collate = collate;
-}
-
-/**
- * gtk_print_job_get_reverse:
- * @job: a `GtkPrintJob`
- *
- * Gets whether this job is printed reversed.
- *
- * Returns: whether the job is printed reversed.
- */
-gboolean
-gtk_print_job_get_reverse (GtkPrintJob *job)
-{
- return job->reverse;
-}
-
-/**
- * gtk_print_job_set_reverse:
- * @job: a `GtkPrintJob`
- * @reverse: whether the job is printed reversed
- *
- * Sets whether this job is printed reversed.
- */
-void
-gtk_print_job_set_reverse (GtkPrintJob *job,
- gboolean reverse)
-{
- job->reverse = reverse;
-}
+++ /dev/null
-/* GtkPrintJob
- * Copyright (C) 2006 Red Hat,Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <cairo.h>
-
-#include <gtk/gtk.h>
-#include <gtk/gtkprinter.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINT_JOB (gtk_print_job_get_type ())
-#define GTK_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_JOB, GtkPrintJob))
-#define GTK_IS_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_JOB))
-
-typedef struct _GtkPrintJob GtkPrintJob;
-
-/**
- * GtkPrintJobCompleteFunc:
- * @print_job: the `GtkPrintJob`
- * @user_data: user data that has been passed to gtk_print_job_send()
- * @error: a `GError` that contains error information if the sending
- * of the print job failed, otherwise %NULL
- *
- * The type of callback that is passed to gtk_print_job_send().
- *
- * It is called when the print job has been completely sent.
- */
-typedef void (*GtkPrintJobCompleteFunc) (GtkPrintJob *print_job,
- gpointer user_data,
- const GError *error);
-
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_print_job_get_type (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkPrintJob *gtk_print_job_new (const char *title,
- GtkPrinter *printer,
- GtkPrintSettings *settings,
- GtkPageSetup *page_setup);
-GDK_AVAILABLE_IN_ALL
-GtkPrintSettings *gtk_print_job_get_settings (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-GtkPrinter *gtk_print_job_get_printer (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_print_job_get_title (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-GtkPrintStatus gtk_print_job_get_status (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_job_set_source_file (GtkPrintJob *job,
- const char *filename,
- GError **error);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_job_set_source_fd (GtkPrintJob *job,
- int fd,
- GError **error);
-GDK_AVAILABLE_IN_ALL
-cairo_surface_t *gtk_print_job_get_surface (GtkPrintJob *job,
- GError **error);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_track_print_status (GtkPrintJob *job,
- gboolean track_status);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_job_get_track_print_status (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_send (GtkPrintJob *job,
- GtkPrintJobCompleteFunc callback,
- gpointer user_data,
- GDestroyNotify dnotify);
-
-GDK_AVAILABLE_IN_ALL
-GtkPrintPages gtk_print_job_get_pages (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_pages (GtkPrintJob *job,
- GtkPrintPages pages);
-GDK_AVAILABLE_IN_ALL
-GtkPageRange * gtk_print_job_get_page_ranges (GtkPrintJob *job,
- int *n_ranges);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_page_ranges (GtkPrintJob *job,
- GtkPageRange *ranges,
- int n_ranges);
-GDK_AVAILABLE_IN_ALL
-GtkPageSet gtk_print_job_get_page_set (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_page_set (GtkPrintJob *job,
- GtkPageSet page_set);
-GDK_AVAILABLE_IN_ALL
-int gtk_print_job_get_num_copies (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_num_copies (GtkPrintJob *job,
- int num_copies);
-GDK_AVAILABLE_IN_ALL
-double gtk_print_job_get_scale (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_scale (GtkPrintJob *job,
- double scale);
-GDK_AVAILABLE_IN_ALL
-guint gtk_print_job_get_n_up (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_n_up (GtkPrintJob *job,
- guint n_up);
-GDK_AVAILABLE_IN_ALL
-GtkNumberUpLayout gtk_print_job_get_n_up_layout (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_n_up_layout (GtkPrintJob *job,
- GtkNumberUpLayout layout);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_job_get_rotate (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_rotate (GtkPrintJob *job,
- gboolean rotate);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_job_get_collate (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_collate (GtkPrintJob *job,
- gboolean collate);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_job_get_reverse (GtkPrintJob *job);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_reverse (GtkPrintJob *job,
- gboolean reverse);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintJob, g_object_unref)
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintoperation-portal.c: Print Operation Details for sandboxed apps
- * Copyright (C) 2016, Red Hat, Inc.
- *
- * 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 <string.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <cairo-pdf.h>
-#include <cairo-ps.h>
-
-#include <gio/gunixfdlist.h>
-
-#include "gtkprintoperation-private.h"
-#include "gtkprintoperation-portal.h"
-#include "print/gtkprintsettings.h"
-#include "print/gtkpagesetup.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkfilelauncher.h"
-#include <glib/gi18n-lib.h>
-#include "gtkwindowprivate.h"
-#include "gtkprivate.h"
-
-
-typedef struct {
- GtkPrintOperation *op;
- GDBusProxy *proxy;
- guint response_signal_id;
- gboolean do_print;
- GtkPrintOperationResult result;
- GtkPrintOperationPrintFunc print_cb;
- GtkWindow *parent;
- char *handle;
- GMainLoop *loop;
- guint32 token;
- GDestroyNotify destroy;
- GVariant *settings;
- GVariant *setup;
- GVariant *options;
- char *prepare_print_handle;
-} PortalData;
-
-static void
-portal_data_free (gpointer data)
-{
- PortalData *portal = data;
-
- if (portal->parent && portal->handle)
- gtk_window_unexport_handle (portal->parent, portal->handle);
- g_free (portal->handle);
- g_object_unref (portal->op);
- g_object_unref (portal->proxy);
- if (portal->loop)
- g_main_loop_unref (portal->loop);
- if (portal->settings)
- g_variant_unref (portal->settings);
- if (portal->setup)
- g_variant_unref (portal->setup);
- if (portal->options)
- g_variant_unref (portal->options);
- g_free (portal->prepare_print_handle);
- g_free (portal);
-}
-
-typedef struct {
- GDBusProxy *proxy;
- GtkPrintJob *job;
- guint32 token;
- cairo_surface_t *surface;
- GMainLoop *loop;
- gboolean file_written;
-} GtkPrintOperationPortal;
-
-static void
-op_portal_free (GtkPrintOperationPortal *op_portal)
-{
- g_clear_object (&op_portal->proxy);
- g_clear_object (&op_portal->job);
- if (op_portal->loop)
- g_main_loop_unref (op_portal->loop);
- g_free (op_portal);
-}
-
-static void
-portal_start_page (GtkPrintOperation *op,
- GtkPrintContext *print_context,
- GtkPageSetup *page_setup)
-{
- GtkPrintOperationPortal *op_portal = op->priv->platform_data;
- GtkPaperSize *paper_size;
- cairo_surface_type_t type;
- double w, h;
-
- paper_size = gtk_page_setup_get_paper_size (page_setup);
-
- w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
- h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-
- type = cairo_surface_get_type (op_portal->surface);
-
- if ((op->priv->manual_number_up < 2) ||
- (op->priv->page_position % op->priv->manual_number_up == 0))
- {
- if (type == CAIRO_SURFACE_TYPE_PS)
- {
- cairo_ps_surface_set_size (op_portal->surface, w, h);
- cairo_ps_surface_dsc_begin_page_setup (op_portal->surface);
- switch (gtk_page_setup_get_orientation (page_setup))
- {
- case GTK_PAGE_ORIENTATION_PORTRAIT:
- case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
- cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Portrait");
- break;
-
- case GTK_PAGE_ORIENTATION_LANDSCAPE:
- case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
- cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Landscape");
- break;
-
- default:
- break;
- }
- }
- else if (type == CAIRO_SURFACE_TYPE_PDF)
- {
- if (!op->priv->manual_orientation)
- {
- w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
- h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
- }
- cairo_pdf_surface_set_size (op_portal->surface, w, h);
- }
- }
-}
-
-static void
-portal_end_page (GtkPrintOperation *op,
- GtkPrintContext *print_context)
-{
- cairo_t *cr;
-
- cr = gtk_print_context_get_cairo_context (print_context);
-
- if ((op->priv->manual_number_up < 2) ||
- ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
- (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
- cairo_show_page (cr);
-}
-
-static void
-print_file_done (GObject *source,
- GAsyncResult *result,
- gpointer data)
-{
- GtkPrintOperation *op = data;
- GtkPrintOperationPortal *op_portal = op->priv->platform_data;
- GError *error = NULL;
- GVariant *ret;
-
- ret = g_dbus_proxy_call_finish (op_portal->proxy,
- result,
- &error);
- if (ret == NULL)
- {
- if (op->priv->error == NULL)
- op->priv->error = g_error_copy (error);
- g_warning ("Print file failed: %s", error->message);
- g_error_free (error);
- }
- else
- g_variant_unref (ret);
-
- if (op_portal->loop)
- g_main_loop_quit (op_portal->loop);
-
- g_object_unref (op);
-}
-
-static void
-portal_job_complete (GtkPrintJob *job,
- gpointer data,
- const GError *error)
-{
- GtkPrintOperation *op = data;
- GtkPrintOperationPortal *op_portal = op->priv->platform_data;
- GtkPrintSettings *settings;
- const char *uri;
- char *filename;
- int fd, idx;
- GVariantBuilder opt_builder;
- GUnixFDList *fd_list;
-
- if (error != NULL && op->priv->error == NULL)
- {
- g_warning ("Print job failed: %s", error->message);
- op->priv->error = g_error_copy (error);
- return;
- }
-
- op_portal->file_written = TRUE;
-
- settings = gtk_print_job_get_settings (job);
- uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
- filename = g_filename_from_uri (uri, NULL, NULL);
-
- fd = open (filename, O_RDONLY|O_CLOEXEC);
- fd_list = g_unix_fd_list_new ();
- idx = g_unix_fd_list_append (fd_list, fd, NULL);
- close (fd);
-
- g_free (filename);
-
- g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add (&opt_builder, "{sv}", "token", g_variant_new_uint32 (op_portal->token));
-
- g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy,
- "Print",
- g_variant_new ("(ssh@a{sv})",
- "", /* window */
- _("Print"), /* title */
- idx,
- g_variant_builder_end (&opt_builder)),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- fd_list,
- NULL,
- print_file_done,
- op);
- g_object_unref (fd_list);
-}
-
-static void
-portal_end_run (GtkPrintOperation *op,
- gboolean wait,
- gboolean cancelled)
-{
- GtkPrintOperationPortal *op_portal = op->priv->platform_data;
-
- cairo_surface_finish (op_portal->surface);
-
- if (cancelled)
- return;
-
- if (wait)
- op_portal->loop = g_main_loop_new (NULL, FALSE);
-
- /* TODO: Check for error */
- if (op_portal->job != NULL)
- {
- g_object_ref (op);
- gtk_print_job_send (op_portal->job, portal_job_complete, op, NULL);
- }
-
- if (wait)
- {
- g_object_ref (op);
- if (!op_portal->file_written)
- g_main_loop_run (op_portal->loop);
- g_object_unref (op);
- }
-}
-
-static void
-finish_print (PortalData *portal,
- GtkPrinter *printer,
- GtkPageSetup *page_setup,
- GtkPrintSettings *settings)
-{
- GtkPrintOperation *op = portal->op;
- GtkPrintOperationPrivate *priv = op->priv;
- GtkPrintJob *job;
- GtkPrintOperationPortal *op_portal;
- cairo_t *cr;
-
- if (portal->do_print)
- {
- gtk_print_operation_set_print_settings (op, settings);
- priv->print_context = _gtk_print_context_new (op);
-
- _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
-
- gtk_print_operation_set_default_page_setup (op, page_setup);
- _gtk_print_context_set_page_setup (priv->print_context, page_setup);
-
- op_portal = g_new0 (GtkPrintOperationPortal, 1);
- priv->platform_data = op_portal;
- priv->free_platform_data = (GDestroyNotify) op_portal_free;
-
- priv->start_page = portal_start_page;
- priv->end_page = portal_end_page;
- priv->end_run = portal_end_run;
-
- job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
- op_portal->job = job;
-
- op_portal->proxy = g_object_ref (portal->proxy);
- op_portal->token = portal->token;
-
- op_portal->surface = gtk_print_job_get_surface (job, &priv->error);
- if (op_portal->surface == NULL)
- {
- portal->result = GTK_PRINT_OPERATION_RESULT_ERROR;
- portal->do_print = FALSE;
- goto out;
- }
-
- cr = cairo_create (op_portal->surface);
- gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
- cairo_destroy (cr);
-
- priv->print_pages = gtk_print_job_get_pages (job);
- priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
- priv->manual_num_copies = gtk_print_job_get_num_copies (job);
- priv->manual_collation = gtk_print_job_get_collate (job);
- priv->manual_reverse = gtk_print_job_get_reverse (job);
- priv->manual_page_set = gtk_print_job_get_page_set (job);
- priv->manual_scale = gtk_print_job_get_scale (job);
- priv->manual_orientation = gtk_print_job_get_rotate (job);
- priv->manual_number_up = gtk_print_job_get_n_up (job);
- priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
- }
-
-out:
- if (portal->print_cb)
- portal->print_cb (op, portal->parent, portal->do_print, portal->result);
-
- if (portal->destroy)
- portal->destroy (portal);
-}
-
-static GtkPrinter *
-find_file_printer (void)
-{
- GList *backends, *l, *printers;
- GtkPrinter *printer;
-
- printer = NULL;
-
- backends = gtk_print_backend_load_modules ();
- for (l = backends; l; l = l->next)
- {
- GtkPrintBackend *backend = l->data;
- if (strcmp (G_OBJECT_TYPE_NAME (backend), "GtkPrintBackendFile") == 0)
- {
- printers = gtk_print_backend_get_printer_list (backend);
- printer = printers->data;
- g_list_free (printers);
- break;
- }
- }
- g_list_free (backends);
-
- return printer;
-}
-
-static void
-prepare_print_response (GDBusConnection *connection,
- const char *sender_name,
- const char *object_path,
- const char *interface_name,
- const char *signal_name,
- GVariant *parameters,
- gpointer data)
-{
- PortalData *portal = data;
- guint32 response;
- GVariant *options = NULL;
-
- if (portal->response_signal_id != 0)
- {
- g_dbus_connection_signal_unsubscribe (connection,
- portal->response_signal_id);
- portal->response_signal_id = 0;
- }
-
- g_variant_get (parameters, "(u@a{sv})", &response, &options);
-
- portal->do_print = (response == 0);
-
- if (portal->do_print)
- {
- GVariant *v;
- GtkPrintSettings *settings;
- GtkPageSetup *page_setup;
- GtkPrinter *printer;
- char *filename;
- char *uri;
- int fd;
-
- portal->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
- v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT);
- settings = gtk_print_settings_new_from_gvariant (v);
- g_variant_unref (v);
-
- v = g_variant_lookup_value (options, "page-setup", G_VARIANT_TYPE_VARDICT);
- page_setup = gtk_page_setup_new_from_gvariant (v);
- g_variant_unref (v);
-
- g_variant_lookup (options, "token", "u", &portal->token);
-
- printer = find_file_printer ();
-
- fd = g_file_open_tmp ("gtkprintXXXXXX", &filename, NULL);
- uri = g_filename_to_uri (filename, NULL, NULL);
- gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
- g_free (uri);
- close (fd);
-
- finish_print (portal, printer, page_setup, settings);
- g_free (filename);
- }
- else
- {
- portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-
- if (portal->print_cb)
- portal->print_cb (portal->op, portal->parent, portal->do_print, portal->result);
-
- if (portal->destroy)
- portal->destroy (portal);
- }
-
- if (options)
- g_variant_unref (options);
-
- if (portal->loop)
- g_main_loop_quit (portal->loop);
-}
-
-static void
-prepare_print_called (GObject *source,
- GAsyncResult *result,
- gpointer data)
-{
- PortalData *portal = data;
- GError *error = NULL;
- const char *handle = NULL;
- GVariant *ret;
-
- ret = g_dbus_proxy_call_finish (portal->proxy, result, &error);
- if (ret == NULL)
- {
- if (portal->op->priv->error == NULL)
- portal->op->priv->error = g_error_copy (error);
- g_error_free (error);
- if (portal->loop)
- g_main_loop_quit (portal->loop);
- return;
- }
- else
- g_variant_get (ret, "(&o)", &handle);
-
- if (strcmp (portal->prepare_print_handle, handle) != 0)
- {
- g_free (portal->prepare_print_handle);
- portal->prepare_print_handle = g_strdup (handle);
- g_dbus_connection_signal_unsubscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
- portal->response_signal_id);
- portal->response_signal_id =
- g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
- PORTAL_BUS_NAME,
- PORTAL_REQUEST_INTERFACE,
- "Response",
- handle,
- NULL,
- G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
- prepare_print_response,
- portal, NULL);
- }
-
- g_variant_unref (ret);
-}
-
-static PortalData *
-create_portal_data (GtkPrintOperation *op,
- GtkWindow *parent,
- GtkPrintOperationPrintFunc print_cb)
-{
- GDBusProxy *proxy;
- PortalData *portal;
- guint signal_id;
- GError *error = NULL;
-
- signal_id = g_signal_lookup ("create-custom-widget", GTK_TYPE_PRINT_OPERATION);
- if (g_signal_has_handler_pending (op, signal_id, 0, TRUE))
- g_warning ("GtkPrintOperation::create-custom-widget not supported with portal");
-
- proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
- G_DBUS_PROXY_FLAGS_NONE,
- NULL,
- PORTAL_BUS_NAME,
- PORTAL_OBJECT_PATH,
- PORTAL_PRINT_INTERFACE,
- NULL,
- &error);
-
- if (proxy == NULL)
- {
- if (op->priv->error == NULL)
- op->priv->error = g_error_copy (error);
- g_error_free (error);
- return NULL;
- }
-
- portal = g_new0 (PortalData, 1);
- portal->proxy = proxy;
- portal->op = g_object_ref (op);
- portal->parent = parent;
- portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
- portal->print_cb = print_cb;
-
- if (print_cb) /* async case */
- {
- portal->loop = NULL;
- portal->destroy = portal_data_free;
- }
- else
- {
- portal->loop = g_main_loop_new (NULL, FALSE);
- portal->destroy = NULL;
- }
-
- return portal;
-}
-
-static void
-window_handle_exported (GtkWindow *window,
- const char *handle_str,
- gpointer user_data)
-{
- PortalData *portal = user_data;
-
- portal->handle = g_strdup (handle_str);
-
- g_dbus_proxy_call (portal->proxy,
- "PreparePrint",
- g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
- handle_str,
- _("Print"), /* title */
- portal->settings,
- portal->setup,
- portal->options),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- prepare_print_called,
- portal);
-}
-
-static void
-call_prepare_print (GtkPrintOperation *op,
- PortalData *portal)
-{
- GtkPrintOperationPrivate *priv = op->priv;
- GVariantBuilder opt_builder;
- char *token;
-
- portal->prepare_print_handle =
- gtk_get_portal_request_path (g_dbus_proxy_get_connection (portal->proxy), &token);
-
- portal->response_signal_id =
- g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
- PORTAL_BUS_NAME,
- PORTAL_REQUEST_INTERFACE,
- "Response",
- portal->prepare_print_handle,
- NULL,
- G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
- prepare_print_response,
- portal, NULL);
-
- g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token));
- g_free (token);
- portal->options = g_variant_builder_end (&opt_builder);
-
- if (priv->print_settings)
- portal->settings = gtk_print_settings_to_gvariant (priv->print_settings);
- else
- {
- GVariantBuilder builder;
- g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
- portal->settings = g_variant_builder_end (&builder);
- }
-
- if (priv->default_page_setup)
- portal->setup = gtk_page_setup_to_gvariant (priv->default_page_setup);
- else
- {
- GtkPageSetup *page_setup = gtk_page_setup_new ();
- portal->setup = gtk_page_setup_to_gvariant (page_setup);
- g_object_unref (page_setup);
- }
-
- g_variant_ref_sink (portal->options);
- g_variant_ref_sink (portal->settings);
- g_variant_ref_sink (portal->setup);
-
- if (portal->parent != NULL &&
- gtk_widget_is_visible (GTK_WIDGET (portal->parent)) &&
- gtk_window_export_handle (portal->parent, window_handle_exported, portal))
- return;
-
- g_dbus_proxy_call (portal->proxy,
- "PreparePrint",
- g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
- "",
- _("Print"), /* title */
- portal->settings,
- portal->setup,
- portal->options),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- prepare_print_called,
- portal);
-}
-
-GtkPrintOperationResult
-gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- gboolean *do_print)
-{
- PortalData *portal;
- GtkPrintOperationResult result;
-
- portal = create_portal_data (op, parent, NULL);
- if (portal == NULL)
- return GTK_PRINT_OPERATION_RESULT_ERROR;
-
- call_prepare_print (op, portal);
-
- g_main_loop_run (portal->loop);
-
- *do_print = portal->do_print;
- result = portal->result;
-
- portal_data_free (portal);
-
- return result;
-}
-
-void
-gtk_print_operation_portal_run_dialog_async (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- GtkPrintOperationPrintFunc print_cb)
-{
- PortalData *portal;
-
- portal = create_portal_data (op, parent, print_cb);
- if (portal == NULL)
- return;
-
- call_prepare_print (op, portal);
-}
-
-void
-gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
- cairo_surface_t *surface,
- GtkWindow *parent,
- const char *filename)
-{
- GFile *file;
- GtkFileLauncher *launcher;
-
- file = g_file_new_for_path (filename);
- launcher = gtk_file_launcher_new (file);
- gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
- g_object_unref (launcher);
- g_object_unref (file);
-}
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2016, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-#include "print/gtkprintoperation.h"
-
-G_BEGIN_DECLS
-
-GtkPrintOperationResult gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- gboolean *do_print);
-void gtk_print_operation_portal_run_dialog_async (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- GtkPrintOperationPrintFunc print_cb);
-void gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
- cairo_surface_t *surface,
- GtkWindow *parent,
- const char *filename);
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintoperation.h: Print Operation
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-#include "print/gtkprintoperation.h"
-
-G_BEGIN_DECLS
-
-/* Page drawing states */
-typedef enum
-{
- GTK_PAGE_DRAWING_STATE_READY,
- GTK_PAGE_DRAWING_STATE_DRAWING,
- GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING
-} GtkPageDrawingState;
-
-struct _GtkPrintOperationPrivate
-{
- GtkPrintOperationAction action;
- GtkPrintStatus status;
- GError *error;
- char *status_string;
- GtkPageSetup *default_page_setup;
- GtkPrintSettings *print_settings;
- char *job_name;
- int nr_of_pages;
- int nr_of_pages_to_print;
- int page_position;
- int current_page;
- GtkUnit unit;
- char *export_filename;
- guint use_full_page : 1;
- guint track_print_status : 1;
- guint show_progress : 1;
- guint cancelled : 1;
- guint allow_async : 1;
- guint is_sync : 1;
- guint support_selection : 1;
- guint has_selection : 1;
- guint embed_page_setup : 1;
-
- GtkPageDrawingState page_drawing_state;
-
- guint print_pages_idle_id;
- guint show_progress_timeout_id;
-
- GtkPrintContext *print_context;
-
- GtkPrintPages print_pages;
- GtkPageRange *page_ranges;
- int num_page_ranges;
-
- int manual_num_copies;
- guint manual_collation : 1;
- guint manual_reverse : 1;
- guint manual_orientation : 1;
- double manual_scale;
- GtkPageSet manual_page_set;
- guint manual_number_up;
- GtkNumberUpLayout manual_number_up_layout;
-
- GtkWidget *custom_widget;
- char *custom_tab_label;
-
- gpointer platform_data;
- GDestroyNotify free_platform_data;
-
- GMainLoop *rloop; /* recursive mainloop */
-
- void (*start_page) (GtkPrintOperation *operation,
- GtkPrintContext *print_context,
- GtkPageSetup *page_setup);
- void (*end_page) (GtkPrintOperation *operation,
- GtkPrintContext *print_context);
- void (*end_run) (GtkPrintOperation *operation,
- gboolean wait,
- gboolean cancelled);
-};
-
-
-typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation *op,
- GtkWindow *parent,
- gboolean do_print,
- GtkPrintOperationResult result);
-
-GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *operation,
- gboolean show_dialog,
- GtkWindow *parent,
- gboolean *do_print);
-void _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- GtkPrintOperationPrintFunc print_cb);
-void _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
- cairo_surface_t *surface,
- GtkWindow *parent,
- const char *filename);
-cairo_surface_t * _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- double *dpi_x,
- double *dpi_y,
- char **target);
-void _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- cairo_surface_t *surface);
-void _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr);
-void _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr);
-
-void _gtk_print_operation_set_status (GtkPrintOperation *op,
- GtkPrintStatus status,
- const char *string);
-
-/* GtkPrintContext private functions: */
-
-GtkPrintContext *_gtk_print_context_new (GtkPrintOperation *op);
-void _gtk_print_context_set_page_setup (GtkPrintContext *context,
- GtkPageSetup *page_setup);
-void _gtk_print_context_translate_into_margin (GtkPrintContext *context);
-void _gtk_print_context_rotate_according_to_orientation (GtkPrintContext *context);
-void _gtk_print_context_reverse_according_to_orientation (GtkPrintContext *context);
-void _gtk_print_context_set_hard_margins (GtkPrintContext *context,
- double top,
- double bottom,
- double left,
- double right);
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintoperation-unix.c: Print Operation Details for Unix
- * and Unix-like platforms
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#include <glib/gstdio.h>
-#include "gtkprintoperation-private.h"
-#include "gtkprintoperation-portal.h"
-
-#include <cairo-pdf.h>
-#include <cairo-ps.h>
-#include "gtkprivate.h"
-#include "gtkprintunixdialog.h"
-#include "gtkpagesetupunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprinter.h"
-#include "gtkprintjob.h"
-#include "gtklabel.h"
-#include "gtkfilelauncher.h"
-#include <glib/gi18n-lib.h>
-
-
-typedef struct
-{
- GtkWindow *parent; /* just in case we need to throw error dialogs */
- GMainLoop *loop;
- gboolean data_sent;
-
- /* Real printing (not preview) */
- GtkPrintJob *job; /* the job we are sending to the printer */
- cairo_surface_t *surface;
- gulong job_status_changed_tag;
-
-
-} GtkPrintOperationUnix;
-
-typedef struct _PrinterFinder PrinterFinder;
-
-static void printer_finder_free (PrinterFinder *finder);
-static void find_printer (const char *printer,
- GFunc func,
- gpointer data);
-
-static void
-unix_start_page (GtkPrintOperation *op,
- GtkPrintContext *print_context,
- GtkPageSetup *page_setup)
-{
- GtkPrintOperationUnix *op_unix;
- GtkPaperSize *paper_size;
- cairo_surface_type_t type;
- double w, h;
-
- op_unix = op->priv->platform_data;
-
- paper_size = gtk_page_setup_get_paper_size (page_setup);
-
- w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
- h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-
- type = cairo_surface_get_type (op_unix->surface);
-
- if ((op->priv->manual_number_up < 2) ||
- (op->priv->page_position % op->priv->manual_number_up == 0))
- {
- if (type == CAIRO_SURFACE_TYPE_PS)
- {
- cairo_ps_surface_set_size (op_unix->surface, w, h);
- cairo_ps_surface_dsc_begin_page_setup (op_unix->surface);
- switch (gtk_page_setup_get_orientation (page_setup))
- {
- case GTK_PAGE_ORIENTATION_PORTRAIT:
- case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
- cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Portrait");
- break;
-
- case GTK_PAGE_ORIENTATION_LANDSCAPE:
- case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
- cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Landscape");
- break;
- default:
- break;
- }
- }
- else if (type == CAIRO_SURFACE_TYPE_PDF)
- {
- if (!op->priv->manual_orientation)
- {
- w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
- h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
- }
- cairo_pdf_surface_set_size (op_unix->surface, w, h);
- }
- }
-}
-
-static void
-unix_end_page (GtkPrintOperation *op,
- GtkPrintContext *print_context)
-{
- cairo_t *cr;
-
- cr = gtk_print_context_get_cairo_context (print_context);
-
- if ((op->priv->manual_number_up < 2) ||
- ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
- (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
- cairo_show_page (cr);
-}
-
-static void
-op_unix_free (GtkPrintOperationUnix *op_unix)
-{
- if (op_unix->job)
- {
- if (op_unix->job_status_changed_tag > 0)
- g_signal_handler_disconnect (op_unix->job,
- op_unix->job_status_changed_tag);
- g_object_unref (op_unix->job);
- }
-
- g_free (op_unix);
-}
-
-static char *
-shell_command_substitute_file (const char *cmd,
- const char *pdf_filename,
- const char *settings_filename,
- gboolean *pdf_filename_replaced,
- gboolean *settings_filename_replaced)
-{
- const char *inptr, *start;
- GString *final;
-
- g_return_val_if_fail (cmd != NULL, NULL);
- g_return_val_if_fail (pdf_filename != NULL, NULL);
- g_return_val_if_fail (settings_filename != NULL, NULL);
-
- final = g_string_new (NULL);
-
- *pdf_filename_replaced = FALSE;
- *settings_filename_replaced = FALSE;
-
- start = inptr = cmd;
- while ((inptr = strchr (inptr, '%')) != NULL)
- {
- g_string_append_len (final, start, inptr - start);
- inptr++;
- switch (*inptr)
- {
- case 'f':
- g_string_append (final, pdf_filename);
- *pdf_filename_replaced = TRUE;
- break;
-
- case 's':
- g_string_append (final, settings_filename);
- *settings_filename_replaced = TRUE;
- break;
-
- case '%':
- g_string_append_c (final, '%');
- break;
-
- default:
- g_string_append_c (final, '%');
- if (*inptr)
- g_string_append_c (final, *inptr);
- break;
- }
- if (*inptr)
- inptr++;
- start = inptr;
- }
- g_string_append (final, start);
-
- return g_string_free (final, FALSE);
-}
-
-static void
-gtk_print_operation_unix_launch_preview (GtkPrintOperation *op,
- cairo_surface_t *surface,
- GtkWindow *parent,
- const char *filename)
-{
- GAppInfo *appinfo;
- GdkAppLaunchContext *context;
- char *cmd;
- char *preview_cmd;
- GtkSettings *settings;
- GtkPrintSettings *print_settings = NULL;
- GtkPageSetup *page_setup;
- GKeyFile *key_file = NULL;
- char *data = NULL;
- gsize data_len;
- char *settings_filename = NULL;
- char *quoted_filename;
- char *quoted_settings_filename;
- gboolean filename_used = FALSE;
- gboolean settings_used = FALSE;
- GdkDisplay *display;
- GError *error = NULL;
- int fd;
- gboolean retval;
-
- cairo_surface_destroy (surface);
-
- if (parent)
- display = gtk_widget_get_display (GTK_WIDGET (parent));
- else
- display = gdk_display_get_default ();
-
- fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, &error);
- if (fd < 0)
- goto out;
-
- key_file = g_key_file_new ();
-
- print_settings = gtk_print_settings_copy (gtk_print_operation_get_print_settings (op));
-
- if (print_settings != NULL)
- {
- gtk_print_settings_set_reverse (print_settings, FALSE);
- gtk_print_settings_set_page_set (print_settings, GTK_PAGE_SET_ALL);
- gtk_print_settings_set_scale (print_settings, 1.0);
- gtk_print_settings_set_number_up (print_settings, 1);
- gtk_print_settings_set_number_up_layout (print_settings, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
-
- /* These removals are necessary because cups-* settings have higher priority
- * than normal settings.
- */
- gtk_print_settings_unset (print_settings, "cups-reverse");
- gtk_print_settings_unset (print_settings, "cups-page-set");
- gtk_print_settings_unset (print_settings, "cups-scale");
- gtk_print_settings_unset (print_settings, "cups-number-up");
- gtk_print_settings_unset (print_settings, "cups-number-up-layout");
-
- gtk_print_settings_to_key_file (print_settings, key_file, NULL);
- g_object_unref (print_settings);
- }
-
- page_setup = gtk_print_context_get_page_setup (op->priv->print_context);
- gtk_page_setup_to_key_file (page_setup, key_file, NULL);
-
- g_key_file_set_string (key_file, "Print Job", "title", op->priv->job_name);
-
- data = g_key_file_to_data (key_file, &data_len, &error);
- if (!data)
- goto out;
-
- retval = g_file_set_contents (settings_filename, data, data_len, &error);
- if (!retval)
- goto out;
-
- settings = gtk_settings_get_for_display (display);
- g_object_get (settings, "gtk-print-preview-command", &preview_cmd, NULL);
-
- quoted_filename = g_shell_quote (filename);
- quoted_settings_filename = g_shell_quote (settings_filename);
- cmd = shell_command_substitute_file (preview_cmd, quoted_filename, quoted_settings_filename, &filename_used, &settings_used);
-
- appinfo = g_app_info_create_from_commandline (cmd,
- "Print Preview",
- G_APP_INFO_CREATE_NONE,
- &error);
-
- g_free (preview_cmd);
- g_free (quoted_filename);
- g_free (quoted_settings_filename);
- g_free (cmd);
-
- if (error != NULL)
- goto out;
-
- context = gdk_display_get_app_launch_context (display);
- g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), &error);
-
- g_object_unref (context);
- g_object_unref (appinfo);
-
- if (error != NULL)
- {
- GFile *file;
- GtkFileLauncher *launcher;
-
- g_warning ("Error launching preview: %s", error->message);
- g_clear_error (&error);
-
- file = g_file_new_for_path (filename);
- launcher = gtk_file_launcher_new (file);
- gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
- g_object_unref (launcher);
- g_object_unref (file);
- }
-
- out:
- if (error != NULL)
- {
- if (op->priv->error == NULL)
- op->priv->error = error;
- else
- g_error_free (error);
-
- filename_used = FALSE;
- settings_used = FALSE;
- }
-
- if (!filename_used)
- g_unlink (filename);
-
- if (!settings_used)
- g_unlink (settings_filename);
-
- if (fd > 0)
- close (fd);
-
- if (key_file)
- g_key_file_free (key_file);
- g_free (data);
- g_free (settings_filename);
-}
-
-static void
-unix_finish_send (GtkPrintJob *job,
- gpointer user_data,
- const GError *error)
-{
- GtkPrintOperation *op = (GtkPrintOperation *) user_data;
- GtkPrintOperationUnix *op_unix = op->priv->platform_data;
-
- if (error != NULL && op->priv->error == NULL)
- op->priv->error = g_error_copy (error);
-
- op_unix->data_sent = TRUE;
-
- if (op_unix->loop)
- g_main_loop_quit (op_unix->loop);
-
- g_object_unref (op);
-}
-
-static void
-unix_end_run (GtkPrintOperation *op,
- gboolean wait,
- gboolean cancelled)
-{
- GtkPrintOperationUnix *op_unix = op->priv->platform_data;
-
- cairo_surface_finish (op_unix->surface);
-
- if (cancelled)
- return;
-
- if (wait)
- op_unix->loop = g_main_loop_new (NULL, FALSE);
-
- /* TODO: Check for error */
- if (op_unix->job != NULL)
- {
- g_object_ref (op);
- gtk_print_job_send (op_unix->job,
- unix_finish_send,
- op, NULL);
- }
-
- if (wait)
- {
- g_object_ref (op);
- if (!op_unix->data_sent)
- g_main_loop_run (op_unix->loop);
- g_main_loop_unref (op_unix->loop);
- op_unix->loop = NULL;
- g_object_unref (op);
- }
-}
-
-static void
-job_status_changed_cb (GtkPrintJob *job,
- GtkPrintOperation *op)
-{
- _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
-}
-
-
-static void
-print_setup_changed_cb (GtkPrintUnixDialog *print_dialog,
- GParamSpec *pspec,
- gpointer user_data)
-{
- GtkPageSetup *page_setup;
- GtkPrintSettings *print_settings;
- GtkPrintOperation *op = user_data;
- GtkPrintOperationPrivate *priv = op->priv;
-
- page_setup = gtk_print_unix_dialog_get_page_setup (print_dialog);
- print_settings = gtk_print_unix_dialog_get_settings (print_dialog);
-
- g_signal_emit_by_name (op,
- "update-custom-widget",
- priv->custom_widget,
- page_setup,
- print_settings);
-}
-
-static GtkWidget *
-get_print_dialog (GtkPrintOperation *op,
- GtkWindow *parent)
-{
- GtkPrintOperationPrivate *priv = op->priv;
- GtkWidget *pd, *label;
- const char *custom_tab_label;
-
- pd = gtk_print_unix_dialog_new (NULL, parent);
-
- gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (pd),
- GTK_PRINT_CAPABILITY_PAGE_SET |
- GTK_PRINT_CAPABILITY_COPIES |
- GTK_PRINT_CAPABILITY_COLLATE |
- GTK_PRINT_CAPABILITY_REVERSE |
- GTK_PRINT_CAPABILITY_SCALE |
- GTK_PRINT_CAPABILITY_PREVIEW |
- GTK_PRINT_CAPABILITY_NUMBER_UP |
- GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT);
-
- if (priv->print_settings)
- gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd),
- priv->print_settings);
-
- if (priv->default_page_setup)
- gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
- priv->default_page_setup);
-
- gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
- priv->embed_page_setup);
-
- gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd),
- priv->current_page);
-
- gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd),
- priv->support_selection);
-
- gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd),
- priv->has_selection);
-
- g_signal_emit_by_name (op, "create-custom-widget",
- &priv->custom_widget);
-
- if (priv->custom_widget)
- {
- custom_tab_label = priv->custom_tab_label;
-
- if (custom_tab_label == NULL)
- {
- custom_tab_label = g_get_application_name ();
- if (custom_tab_label == NULL)
- custom_tab_label = _("Application");
- }
-
- label = gtk_label_new (custom_tab_label);
-
- gtk_print_unix_dialog_add_custom_tab (GTK_PRINT_UNIX_DIALOG (pd),
- priv->custom_widget, label);
-
- g_signal_connect (pd, "notify::selected-printer", (GCallback) print_setup_changed_cb, op);
- g_signal_connect (pd, "notify::page-setup", (GCallback) print_setup_changed_cb, op);
- }
-
- return pd;
-}
-
-typedef struct
-{
- GtkPrintOperation *op;
- gboolean do_print;
- gboolean do_preview;
- GtkPrintOperationResult result;
- GtkPrintOperationPrintFunc print_cb;
- GDestroyNotify destroy;
- GtkWindow *parent;
- GMainLoop *loop;
-} PrintResponseData;
-
-static void
-print_response_data_free (gpointer data)
-{
- PrintResponseData *rdata = data;
-
- g_object_unref (rdata->op);
- g_free (rdata);
-}
-
-static void
-finish_print (PrintResponseData *rdata,
- GtkPrinter *printer,
- GtkPageSetup *page_setup,
- GtkPrintSettings *settings,
- gboolean page_setup_set)
-{
- GtkPrintOperation *op = rdata->op;
- GtkPrintOperationPrivate *priv = op->priv;
- GtkPrintJob *job;
- double top, bottom, left, right;
-
- if (rdata->do_print)
- {
- gtk_print_operation_set_print_settings (op, settings);
- priv->print_context = _gtk_print_context_new (op);
-
- if (gtk_print_settings_get_number_up (settings) < 2)
- {
- if (printer && (gtk_printer_get_hard_margins_for_paper_size (printer, gtk_page_setup_get_paper_size (page_setup), &top, &bottom, &left, &right) ||
- gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right)))
- _gtk_print_context_set_hard_margins (priv->print_context, top, bottom, left, right);
- }
- else
- {
- /* Pages do not have any unprintable area when printing n-up as each page on the
- * sheet has been scaled down and translated to a position within the printable
- * area of the sheet.
- */
- _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
- }
-
- if (page_setup != NULL &&
- (gtk_print_operation_get_default_page_setup (op) == NULL ||
- page_setup_set))
- gtk_print_operation_set_default_page_setup (op, page_setup);
-
- _gtk_print_context_set_page_setup (priv->print_context, page_setup);
-
- if (!rdata->do_preview)
- {
- GtkPrintOperationUnix *op_unix;
- cairo_t *cr;
-
- op_unix = g_new0 (GtkPrintOperationUnix, 1);
- priv->platform_data = op_unix;
- priv->free_platform_data = (GDestroyNotify) op_unix_free;
- op_unix->parent = rdata->parent;
-
- priv->start_page = unix_start_page;
- priv->end_page = unix_end_page;
- priv->end_run = unix_end_run;
-
- job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
- op_unix->job = job;
- gtk_print_job_set_track_print_status (job, priv->track_print_status);
-
- op_unix->surface = gtk_print_job_get_surface (job, &priv->error);
- if (op_unix->surface == NULL)
- {
- rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR;
- rdata->do_print = FALSE;
- goto out;
- }
-
- cr = cairo_create (op_unix->surface);
- gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
- cairo_destroy (cr);
-
- _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
-
- op_unix->job_status_changed_tag =
- g_signal_connect (job, "status-changed",
- G_CALLBACK (job_status_changed_cb), op);
-
- priv->print_pages = gtk_print_job_get_pages (job);
- priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
- priv->manual_num_copies = gtk_print_job_get_num_copies (job);
- priv->manual_collation = gtk_print_job_get_collate (job);
- priv->manual_reverse = gtk_print_job_get_reverse (job);
- priv->manual_page_set = gtk_print_job_get_page_set (job);
- priv->manual_scale = gtk_print_job_get_scale (job);
- priv->manual_orientation = gtk_print_job_get_rotate (job);
- priv->manual_number_up = gtk_print_job_get_n_up (job);
- priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
- }
- }
- out:
- if (rdata->print_cb)
- rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result);
-
- if (rdata->destroy)
- rdata->destroy (rdata);
-}
-
-static void
-handle_print_response (GtkWidget *dialog,
- int response,
- gpointer data)
-{
- GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
- PrintResponseData *rdata = data;
- GtkPrintSettings *settings = NULL;
- GtkPageSetup *page_setup = NULL;
- GtkPrinter *printer = NULL;
- gboolean page_setup_set = FALSE;
-
- if (response == GTK_RESPONSE_OK)
- {
- printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
-
- rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
- rdata->do_preview = FALSE;
- if (printer != NULL)
- rdata->do_print = TRUE;
- }
- else if (response == GTK_RESPONSE_APPLY)
- {
- /* print preview */
- rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
- rdata->do_preview = TRUE;
- rdata->do_print = TRUE;
-
- rdata->op->priv->action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
- }
-
- if (rdata->do_print)
- {
- settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
- page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
- page_setup_set = gtk_print_unix_dialog_get_page_setup_set (GTK_PRINT_UNIX_DIALOG (pd));
-
- /* Set new print settings now so that custom-widget options
- * can be added to the settings in the callback
- */
- gtk_print_operation_set_print_settings (rdata->op, settings);
- g_signal_emit_by_name (rdata->op, "custom-widget-apply", rdata->op->priv->custom_widget);
- }
-
- if (rdata->loop)
- g_main_loop_quit (rdata->loop);
-
- finish_print (rdata, printer, page_setup, settings, page_setup_set);
-
- if (settings)
- g_object_unref (settings);
-
- gtk_window_destroy (GTK_WINDOW (pd));
-}
-
-
-static void
-found_printer (GtkPrinter *printer,
- PrintResponseData *rdata)
-{
- GtkPrintOperation *op = rdata->op;
- GtkPrintOperationPrivate *priv = op->priv;
- GtkPrintSettings *settings = NULL;
- GtkPageSetup *page_setup = NULL;
-
- if (rdata->loop)
- g_main_loop_quit (rdata->loop);
-
- if (printer != NULL)
- {
- rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
- rdata->do_print = TRUE;
-
- if (priv->print_settings)
- settings = gtk_print_settings_copy (priv->print_settings);
- else
- settings = gtk_print_settings_new ();
-
- gtk_print_settings_set_printer (settings,
- gtk_printer_get_name (printer));
-
- if (priv->default_page_setup)
- page_setup = gtk_page_setup_copy (priv->default_page_setup);
- else
- page_setup = gtk_page_setup_new ();
- }
-
- finish_print (rdata, printer, page_setup, settings, FALSE);
-
- if (settings)
- g_object_unref (settings);
-
- if (page_setup)
- g_object_unref (page_setup);
-}
-
-static void
-gtk_print_operation_unix_run_dialog_async (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- GtkPrintOperationPrintFunc print_cb)
-{
- GtkWidget *pd;
- PrintResponseData *rdata;
- const char *printer_name;
-
- rdata = g_new (PrintResponseData, 1);
- rdata->op = g_object_ref (op);
- rdata->do_print = FALSE;
- rdata->do_preview = FALSE;
- rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
- rdata->print_cb = print_cb;
- rdata->parent = parent;
- rdata->loop = NULL;
- rdata->destroy = print_response_data_free;
-
- if (show_dialog)
- {
- pd = get_print_dialog (op, parent);
- gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
-
- g_signal_connect (pd, "response",
- G_CALLBACK (handle_print_response), rdata);
-
- gtk_window_present (GTK_WINDOW (pd));
- }
- else
- {
- printer_name = NULL;
- if (op->priv->print_settings)
- printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
-
- find_printer (printer_name, (GFunc) found_printer, rdata);
- }
-}
-
-static cairo_status_t
-write_preview (void *closure,
- const unsigned char *data,
- unsigned int length)
-{
- int fd = GPOINTER_TO_INT (closure);
- gssize written;
-
- while (length > 0)
- {
- written = write (fd, data, length);
-
- if (written == -1)
- {
- if (errno == EAGAIN || errno == EINTR)
- continue;
-
- return CAIRO_STATUS_WRITE_ERROR;
- }
-
- data += written;
- length -= written;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-close_preview (void *data)
-{
- int fd = GPOINTER_TO_INT (data);
-
- close (fd);
-}
-
-static cairo_surface_t *
-gtk_print_operation_unix_create_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- double *dpi_x,
- double *dpi_y,
- char **target)
-{
- char *filename;
- int fd;
- GtkPaperSize *paper_size;
- double w, h;
- cairo_surface_t *surface;
- static cairo_user_data_key_t key;
-
- filename = g_build_filename (g_get_tmp_dir (), "previewXXXXXX.pdf", NULL);
- fd = g_mkstemp (filename);
-
- if (fd < 0)
- {
- g_free (filename);
- return NULL;
- }
-
- *target = filename;
-
- paper_size = gtk_page_setup_get_paper_size (page_setup);
- w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
- h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-
- *dpi_x = *dpi_y = 72;
- surface = cairo_pdf_surface_create_for_stream (write_preview, GINT_TO_POINTER (fd), w, h);
-
- cairo_surface_set_user_data (surface, &key, GINT_TO_POINTER (fd), close_preview);
-
- return surface;
-}
-
-static void
-gtk_print_operation_unix_preview_start_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr)
-{
-}
-
-static void
-gtk_print_operation_unix_preview_end_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr)
-{
- cairo_show_page (cr);
-}
-
-static void
-gtk_print_operation_unix_resize_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- cairo_surface_t *surface)
-{
- double w, h;
-
- w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
- h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
- cairo_pdf_surface_set_size (surface, w, h);
-}
-
-static GtkPrintOperationResult
-gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- gboolean *do_print)
- {
- GtkWidget *pd;
- PrintResponseData rdata;
- const char *printer_name;
-
- rdata.op = op;
- rdata.do_print = FALSE;
- rdata.do_preview = FALSE;
- rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL;
- rdata.print_cb = NULL;
- rdata.destroy = NULL;
- rdata.parent = parent;
- rdata.loop = NULL;
-
- if (show_dialog)
- {
- pd = get_print_dialog (op, parent);
- gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
-
- g_signal_connect (pd, "response",
- G_CALLBACK (handle_print_response), &rdata);
-
- gtk_window_present (GTK_WINDOW (pd));
-
- rdata.loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (rdata.loop);
- g_main_loop_unref (rdata.loop);
- rdata.loop = NULL;
- }
- else
- {
- printer_name = NULL;
- if (op->priv->print_settings)
- printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
-
- rdata.loop = g_main_loop_new (NULL, FALSE);
- find_printer (printer_name,
- (GFunc) found_printer, &rdata);
-
- g_main_loop_run (rdata.loop);
- g_main_loop_unref (rdata.loop);
- rdata.loop = NULL;
- }
-
- *do_print = rdata.do_print;
-
- return rdata.result;
-}
-
-
-typedef struct
-{
- GtkPageSetup *page_setup;
- GtkPageSetupDoneFunc done_cb;
- gpointer data;
- GDestroyNotify destroy;
- GMainLoop *loop;
-} PageSetupResponseData;
-
-static void
-page_setup_data_free (gpointer data)
-{
- PageSetupResponseData *rdata = data;
-
- if (rdata->page_setup)
- g_object_unref (rdata->page_setup);
-
- g_free (rdata);
-}
-
-static void
-handle_page_setup_response (GtkWidget *dialog,
- int response,
- gpointer data)
-{
- GtkPageSetupUnixDialog *psd;
- PageSetupResponseData *rdata = data;
-
- if (rdata->loop)
- g_main_loop_quit (rdata->loop);
-
- psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog);
- if (response == GTK_RESPONSE_OK)
- rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (psd);
-
- gtk_window_destroy (GTK_WINDOW (dialog));
-
- if (rdata->done_cb)
- rdata->done_cb (rdata->page_setup, rdata->data);
-
- if (rdata->destroy)
- rdata->destroy (rdata);
-}
-
-static GtkWidget *
-get_page_setup_dialog (GtkWindow *parent,
- GtkPageSetup *page_setup,
- GtkPrintSettings *settings)
-{
- GtkWidget *dialog;
-
- dialog = gtk_page_setup_unix_dialog_new (NULL, parent);
- if (page_setup)
- gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
- page_setup);
- gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
- settings);
-
- return dialog;
-}
-
-/**
- * gtk_print_run_page_setup_dialog:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- *
- * Runs a page setup dialog, letting the user modify the values from
- * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
- * is identical to the passed in @page_setup, otherwise it contains the
- * modifications done in the dialog.
- *
- * Note that this function may use a recursive mainloop to show the page
- * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
- * a problem.
- *
- * Returns: (transfer full): a new `GtkPageSetup`
- */
-GtkPageSetup *
-gtk_print_run_page_setup_dialog (GtkWindow *parent,
- GtkPageSetup *page_setup,
- GtkPrintSettings *settings)
-{
- GtkWidget *dialog;
- PageSetupResponseData rdata;
-
- rdata.page_setup = NULL;
- rdata.done_cb = NULL;
- rdata.data = NULL;
- rdata.destroy = NULL;
- rdata.loop = g_main_loop_new (NULL, FALSE);
-
- dialog = get_page_setup_dialog (parent, page_setup, settings);
-
- g_signal_connect (dialog, "response",
- G_CALLBACK (handle_page_setup_response),
- &rdata);
-
- gtk_window_present (GTK_WINDOW (dialog));
-
- g_main_loop_run (rdata.loop);
- g_main_loop_unref (rdata.loop);
- rdata.loop = NULL;
-
- if (rdata.page_setup)
- return rdata.page_setup;
- else if (page_setup)
- return gtk_page_setup_copy (page_setup);
- else
- return gtk_page_setup_new ();
-}
-
-/**
- * gtk_print_run_page_setup_dialog_async:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- * @done_cb: (scope async): a function to call when the user saves
- * the modified page setup
- * @data: user data to pass to @done_cb
- *
- * Runs a page setup dialog, letting the user modify the values from @page_setup.
- *
- * In contrast to gtk_print_run_page_setup_dialog(), this function returns after
- * showing the page setup dialog on platforms that support this, and calls @done_cb
- * from a signal handler for the ::response signal of the dialog.
- */
-void
-gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
- GtkPageSetup *page_setup,
- GtkPrintSettings *settings,
- GtkPageSetupDoneFunc done_cb,
- gpointer data)
-{
- GtkWidget *dialog;
- PageSetupResponseData *rdata;
-
- dialog = get_page_setup_dialog (parent, page_setup, settings);
- gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-
- rdata = g_new (PageSetupResponseData, 1);
- rdata->page_setup = NULL;
- rdata->done_cb = done_cb;
- rdata->data = data;
- rdata->destroy = page_setup_data_free;
- rdata->loop = NULL;
-
- g_signal_connect (dialog, "response",
- G_CALLBACK (handle_page_setup_response), rdata);
-
- gtk_window_present (GTK_WINDOW (dialog));
- }
-
-struct _PrinterFinder
-{
- gboolean found_printer;
- GFunc func;
- gpointer data;
- char *printer_name;
- GList *backends;
- guint timeout_tag;
- GtkPrinter *printer;
- GtkPrinter *default_printer;
- GtkPrinter *first_printer;
-};
-
-static gboolean
-find_printer_idle (gpointer data)
-{
- PrinterFinder *finder = data;
- GtkPrinter *printer;
-
- if (finder->printer != NULL)
- printer = finder->printer;
- else if (finder->default_printer != NULL)
- printer = finder->default_printer;
- else if (finder->first_printer != NULL)
- printer = finder->first_printer;
- else
- printer = NULL;
-
- finder->func (printer, finder->data);
-
- printer_finder_free (finder);
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-printer_added_cb (GtkPrintBackend *backend,
- GtkPrinter *printer,
- PrinterFinder *finder)
-{
- if (finder->found_printer)
- return;
-
- /* FIXME this skips "Print to PDF" - is this intentional ? */
- if (gtk_printer_is_virtual (printer))
- return;
-
- if (finder->printer_name != NULL &&
- strcmp (gtk_printer_get_name (printer), finder->printer_name) == 0)
- {
- finder->printer = g_object_ref (printer);
- finder->found_printer = TRUE;
- }
- else if (finder->default_printer == NULL &&
- gtk_printer_is_default (printer))
- {
- finder->default_printer = g_object_ref (printer);
- if (finder->printer_name == NULL)
- finder->found_printer = TRUE;
- }
- else
- {
- if (finder->first_printer == NULL)
- finder->first_printer = g_object_ref (printer);
- }
-
- if (finder->found_printer)
- g_idle_add (find_printer_idle, finder);
-}
-
-static void
-printer_list_done_cb (GtkPrintBackend *backend,
- PrinterFinder *finder)
-{
- finder->backends = g_list_remove (finder->backends, backend);
-
- g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
- g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
-
- gtk_print_backend_destroy (backend);
- g_object_unref (backend);
-
- if (finder->backends == NULL)
- g_idle_add (find_printer_idle, finder);
-}
-
-static void
-find_printer_init (PrinterFinder *finder,
- GtkPrintBackend *backend)
-{
- GList *list;
- GList *node;
-
- list = gtk_print_backend_get_printer_list (backend);
-
- node = list;
- while (node != NULL)
- {
- printer_added_cb (backend, node->data, finder);
- node = node->next;
-
- if (finder->found_printer)
- break;
- }
-
- g_list_free (list);
-
- if (gtk_print_backend_printer_list_is_done (backend))
- {
- finder->backends = g_list_remove (finder->backends, backend);
- gtk_print_backend_destroy (backend);
- g_object_unref (backend);
- }
- else
- {
- g_signal_connect (backend, "printer-added",
- (GCallback) printer_added_cb,
- finder);
- g_signal_connect (backend, "printer-list-done",
- (GCallback) printer_list_done_cb,
- finder);
- }
-
-}
-
-static void
-printer_finder_free (PrinterFinder *finder)
-{
- GList *l;
-
- g_free (finder->printer_name);
-
- if (finder->printer)
- g_object_unref (finder->printer);
-
- if (finder->default_printer)
- g_object_unref (finder->default_printer);
-
- if (finder->first_printer)
- g_object_unref (finder->first_printer);
-
- for (l = finder->backends; l != NULL; l = l->next)
- {
- GtkPrintBackend *backend = l->data;
- g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
- g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
- gtk_print_backend_destroy (backend);
- g_object_unref (backend);
- }
-
- g_list_free (finder->backends);
-
- g_free (finder);
-}
-
-static void
-find_printer (const char *printer,
- GFunc func,
- gpointer data)
-{
- GList *node, *next;
- PrinterFinder *finder;
-
- finder = g_new0 (PrinterFinder, 1);
-
- finder->printer_name = g_strdup (printer);
- finder->func = func;
- finder->data = data;
-
- finder->backends = NULL;
- if (g_module_supported ())
- finder->backends = gtk_print_backend_load_modules ();
-
- for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
- {
- next = node->next;
- find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
- }
-
- if (finder->backends == NULL)
- g_idle_add (find_printer_idle, finder);
-}
-
-
-GtkPrintOperationResult
-_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- gboolean *do_print)
-{
- if (gdk_should_use_portal ())
- return gtk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print);
- else
- return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
-}
-void
-_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- GtkPrintOperationPrintFunc print_cb)
-{
- if (gdk_should_use_portal ())
- gtk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb);
- else
- gtk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb);
-}
-
-void
-_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
- cairo_surface_t *surface,
- GtkWindow *parent,
- const char *filename)
-{
- if (gdk_should_use_portal ())
- gtk_print_operation_portal_launch_preview (op, surface, parent, filename);
- else
- gtk_print_operation_unix_launch_preview (op, surface, parent, filename);
-}
-
-cairo_surface_t *
-_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- double *dpi_x,
- double *dpi_y,
- char **target)
-{
- return gtk_print_operation_unix_create_preview_surface (op, page_setup, dpi_x, dpi_y, target);
-}
-
-void
-_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- cairo_surface_t *surface)
-{
- gtk_print_operation_unix_resize_preview_surface (op, page_setup, surface);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr)
-{
- gtk_print_operation_unix_preview_start_page (op, surface, cr);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr)
-{
- gtk_print_operation_unix_preview_end_page (op, surface, cr);
-}
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintoperation-win32.c: Print Operation Details for Win32
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#ifndef _MSC_VER
-#ifndef _WIN32_WINNT
-/* Vista or newer */
-#define _WIN32_WINNT 0x0600
-#endif
-#ifndef WINVER
-#define WINVER _WIN32_WINNT
-#endif
-#endif
-
-#define COBJMACROS
-#include "config.h"
-#include <math.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <windows.h>
-#include <cairo-win32.h>
-#include <glib.h>
-#include <glib/gi18n-lib.h>
-#include "gtkprintoperation-private.h"
-#include "gtkprint-win32.h"
-#include "gtkwindow.h"
-#include "gtkprivate.h"
-#include "gtkwidgetprivate.h"
-#include "gtknative.h"
-#include "win32/gdkprivate-win32.h"
-
-#define MAX_PAGE_RANGES 20
-#define STATUS_POLLING_TIME 2000
-
-#ifndef JOB_STATUS_RESTART
-#define JOB_STATUS_RESTART 0x800
-#endif
-
-#ifndef JOB_STATUS_COMPLETE
-#define JOB_STATUS_COMPLETE 0x1000
-#endif
-
-/* Forward declarations */
-GtkPrintOperationResult
-gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
- gboolean *do_print);
-GtkPrintOperationResult
-gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
- GtkWindow *parent,
- gboolean *do_print);
-UINT_PTR CALLBACK
-run_mainloop_hook (HWND hdlg,
- UINT uiMsg,
- WPARAM wParam,
- LPARAM lParam);
-void
-win32_start_page (GtkPrintOperation *op,
- GtkPrintContext *print_context,
- GtkPageSetup *page_setup);
-
-typedef struct {
- HDC hdc;
- HGLOBAL devmode;
- HGLOBAL devnames;
- HANDLE printerHandle;
- int job_id;
- guint timeout_id;
-
- cairo_surface_t *surface;
- GtkWidget *embed_widget;
-} GtkPrintOperationWin32;
-
-static void win32_poll_status (GtkPrintOperation *op);
-
-static const GUID myIID_IPrintDialogCallback = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
-
-#if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK)
-#undef INTERFACE
-#define INTERFACE IPrintDialogCallback
-DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
-{
- STDMETHOD (QueryInterface)(THIS_ REFIID,LPVOID*) PURE;
- STDMETHOD_ (ULONG, AddRef)(THIS) PURE;
- STDMETHOD_ (ULONG, Release)(THIS) PURE;
- STDMETHOD (InitDone)(THIS) PURE;
- STDMETHOD (SelectionChange)(THIS) PURE;
- STDMETHOD (HandleMessage)(THIS_ HWND,UINT,WPARAM,LPARAM,LRESULT*) PURE;
-};
-#endif
-
-static UINT got_gdk_events_message;
-
-UINT_PTR CALLBACK
-run_mainloop_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
-{
- if (uiMsg == WM_INITDIALOG)
- {
- gdk_win32_set_modal_dialog_libgtk_only (hdlg);
- while (g_main_context_pending (NULL))
- g_main_context_iteration (NULL, TRUE);
- }
- else if (uiMsg == got_gdk_events_message)
- {
- while (g_main_context_pending (NULL))
- g_main_context_iteration (NULL, TRUE);
- return 1;
- }
- return 0;
-}
-
-static GtkPageOrientation
-orientation_from_win32 (short orientation)
-{
- if (orientation == DMORIENT_LANDSCAPE)
- return GTK_PAGE_ORIENTATION_LANDSCAPE;
- return GTK_PAGE_ORIENTATION_PORTRAIT;
-}
-
-static short
-orientation_to_win32 (GtkPageOrientation orientation)
-{
- if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
- orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
- return DMORIENT_LANDSCAPE;
- return DMORIENT_PORTRAIT;
-}
-
-static GtkPaperSize *
-paper_size_from_win32 (short size)
-{
- const char *name;
-
- switch (size)
- {
- case DMPAPER_LETTER_TRANSVERSE:
- case DMPAPER_LETTER:
- case DMPAPER_LETTERSMALL:
- name = "na_letter";
- break;
- case DMPAPER_TABLOID:
- case DMPAPER_LEDGER:
- name = "na_ledger";
- break;
- case DMPAPER_LEGAL:
- name = "na_legal";
- break;
- case DMPAPER_STATEMENT:
- name = "na_invoice";
- break;
- case DMPAPER_EXECUTIVE:
- name = "na_executive";
- break;
- case DMPAPER_A3:
- case DMPAPER_A3_TRANSVERSE:
- name = "iso_a3";
- break;
- case DMPAPER_A4:
- case DMPAPER_A4SMALL:
- case DMPAPER_A4_TRANSVERSE:
- name = "iso_a4";
- break;
- case DMPAPER_A5:
- case DMPAPER_A5_TRANSVERSE:
- name = "iso_a5";
- break;
- case DMPAPER_B4:
- name = "jis_b4";
- break;
- case DMPAPER_B5:
- case DMPAPER_B5_TRANSVERSE:
- name = "jis_b5";
- break;
- case DMPAPER_QUARTO:
- name = "na_quarto";
- break;
- case DMPAPER_10X14:
- name = "na_10x14";
- break;
- case DMPAPER_11X17:
- name = "na_ledger";
- break;
- case DMPAPER_NOTE:
- name = "na_letter";
- break;
- case DMPAPER_ENV_9:
- name = "na_number-9";
- break;
- case DMPAPER_ENV_10:
- name = "na_number-10";
- break;
- case DMPAPER_ENV_11:
- name = "na_number-11";
- break;
- case DMPAPER_ENV_12:
- name = "na_number-12";
- break;
- case DMPAPER_ENV_14:
- name = "na_number-14";
- break;
- case DMPAPER_CSHEET:
- name = "na_c";
- break;
- case DMPAPER_DSHEET:
- name = "na_d";
- break;
- case DMPAPER_ESHEET:
- name = "na_e";
- break;
- case DMPAPER_ENV_DL:
- name = "iso_dl";
- break;
- case DMPAPER_ENV_C5:
- name = "iso_c5";
- break;
- case DMPAPER_ENV_C3:
- name = "iso_c3";
- break;
- case DMPAPER_ENV_C4:
- name = "iso_c4";
- break;
- case DMPAPER_ENV_C6:
- name = "iso_c6";
- break;
- case DMPAPER_ENV_C65:
- name = "iso_c6c5";
- break;
- case DMPAPER_ENV_B4:
- name = "iso_b4";
- break;
- case DMPAPER_ENV_B5:
- name = "iso_b5";
- break;
- case DMPAPER_ENV_B6:
- name = "iso_b6";
- break;
- case DMPAPER_ENV_ITALY:
- name = "om_italian";
- break;
- case DMPAPER_ENV_MONARCH:
- name = "na_monarch";
- break;
- case DMPAPER_ENV_PERSONAL:
- name = "na_personal";
- break;
- case DMPAPER_FANFOLD_US:
- name = "na_fanfold-us";
- break;
- case DMPAPER_FANFOLD_STD_GERMAN:
- name = "na_fanfold-eur";
- break;
- case DMPAPER_FANFOLD_LGL_GERMAN:
- name = "na_foolscap";
- break;
- case DMPAPER_ISO_B4:
- name = "iso_b4";
- break;
- case DMPAPER_JAPANESE_POSTCARD:
- name = "jpn_hagaki";
- break;
- case DMPAPER_9X11:
- name = "na_9x11";
- break;
- case DMPAPER_10X11:
- name = "na_10x11";
- break;
- case DMPAPER_ENV_INVITE:
- name = "om_invite";
- break;
- case DMPAPER_LETTER_EXTRA:
- case DMPAPER_LETTER_EXTRA_TRANSVERSE:
- name = "na_letter-extra";
- break;
- case DMPAPER_LEGAL_EXTRA:
- name = "na_legal-extra";
- break;
- case DMPAPER_TABLOID_EXTRA:
- name = "na_arch";
- break;
- case DMPAPER_A4_EXTRA:
- name = "iso_a4-extra";
- break;
- case DMPAPER_B_PLUS:
- name = "na_b-plus";
- break;
- case DMPAPER_LETTER_PLUS:
- name = "na_letter-plus";
- break;
- case DMPAPER_A3_EXTRA:
- case DMPAPER_A3_EXTRA_TRANSVERSE:
- name = "iso_a3-extra";
- break;
- case DMPAPER_A5_EXTRA:
- name = "iso_a5-extra";
- break;
- case DMPAPER_B5_EXTRA:
- name = "iso_b5-extra";
- break;
- case DMPAPER_A2:
- name = "iso_a2";
- break;
-
- default:
- name = NULL;
- break;
- }
-
- if (name)
- return gtk_paper_size_new (name);
- else
- return NULL;
-}
-
-static short
-paper_size_to_win32 (GtkPaperSize *paper_size)
-{
- const char *format;
-
- if (gtk_paper_size_is_custom (paper_size))
- return 0;
-
- format = gtk_paper_size_get_name (paper_size);
-
- if (strcmp (format, "na_letter") == 0)
- return DMPAPER_LETTER;
- if (strcmp (format, "na_ledger") == 0)
- return DMPAPER_LEDGER;
- if (strcmp (format, "na_legal") == 0)
- return DMPAPER_LEGAL;
- if (strcmp (format, "na_invoice") == 0)
- return DMPAPER_STATEMENT;
- if (strcmp (format, "na_executive") == 0)
- return DMPAPER_EXECUTIVE;
- if (strcmp (format, "iso_a2") == 0)
- return DMPAPER_A2;
- if (strcmp (format, "iso_a3") == 0)
- return DMPAPER_A3;
- if (strcmp (format, "iso_a4") == 0)
- return DMPAPER_A4;
- if (strcmp (format, "iso_a5") == 0)
- return DMPAPER_A5;
- if (strcmp (format, "iso_b4") == 0)
- return DMPAPER_B4;
- if (strcmp (format, "iso_b5") == 0)
- return DMPAPER_B5;
- if (strcmp (format, "na_quarto") == 0)
- return DMPAPER_QUARTO;
- if (strcmp (format, "na_10x14") == 0)
- return DMPAPER_10X14;
- if (strcmp (format, "na_number-9") == 0)
- return DMPAPER_ENV_9;
- if (strcmp (format, "na_number-10") == 0)
- return DMPAPER_ENV_10;
- if (strcmp (format, "na_number-11") == 0)
- return DMPAPER_ENV_11;
- if (strcmp (format, "na_number-12") == 0)
- return DMPAPER_ENV_12;
- if (strcmp (format, "na_number-14") == 0)
- return DMPAPER_ENV_14;
- if (strcmp (format, "na_c") == 0)
- return DMPAPER_CSHEET;
- if (strcmp (format, "na_d") == 0)
- return DMPAPER_DSHEET;
- if (strcmp (format, "na_e") == 0)
- return DMPAPER_ESHEET;
- if (strcmp (format, "iso_dl") == 0)
- return DMPAPER_ENV_DL;
- if (strcmp (format, "iso_c3") == 0)
- return DMPAPER_ENV_C3;
- if (strcmp (format, "iso_c4") == 0)
- return DMPAPER_ENV_C4;
- if (strcmp (format, "iso_c5") == 0)
- return DMPAPER_ENV_C5;
- if (strcmp (format, "iso_c6") == 0)
- return DMPAPER_ENV_C6;
- if (strcmp (format, "iso_c5c6") == 0)
- return DMPAPER_ENV_C65;
- if (strcmp (format, "iso_b6") == 0)
- return DMPAPER_ENV_B6;
- if (strcmp (format, "om_italian") == 0)
- return DMPAPER_ENV_ITALY;
- if (strcmp (format, "na_monarch") == 0)
- return DMPAPER_ENV_MONARCH;
- if (strcmp (format, "na_personal") == 0)
- return DMPAPER_ENV_PERSONAL;
- if (strcmp (format, "na_fanfold-us") == 0)
- return DMPAPER_FANFOLD_US;
- if (strcmp (format, "na_fanfold-eur") == 0)
- return DMPAPER_FANFOLD_STD_GERMAN;
- if (strcmp (format, "na_foolscap") == 0)
- return DMPAPER_FANFOLD_LGL_GERMAN;
- if (strcmp (format, "jpn_hagaki") == 0)
- return DMPAPER_JAPANESE_POSTCARD;
- if (strcmp (format, "na_9x11") == 0)
- return DMPAPER_9X11;
- if (strcmp (format, "na_10x11") == 0)
- return DMPAPER_10X11;
- if (strcmp (format, "om_invite") == 0)
- return DMPAPER_ENV_INVITE;
- if (strcmp (format, "na_letter-extra") == 0)
- return DMPAPER_LETTER_EXTRA;
- if (strcmp (format, "na_legal-extra") == 0)
- return DMPAPER_LEGAL_EXTRA;
- if (strcmp (format, "na_arch") == 0)
- return DMPAPER_TABLOID_EXTRA;
- if (strcmp (format, "iso_a3-extra") == 0)
- return DMPAPER_A3_EXTRA;
- if (strcmp (format, "iso_a4-extra") == 0)
- return DMPAPER_A4_EXTRA;
- if (strcmp (format, "iso_a5-extra") == 0)
- return DMPAPER_A5_EXTRA;
- if (strcmp (format, "iso_b5-extra") == 0)
- return DMPAPER_B5_EXTRA;
- if (strcmp (format, "na_b-plus") == 0)
- return DMPAPER_B_PLUS;
- if (strcmp (format, "na_letter-plus") == 0)
- return DMPAPER_LETTER_PLUS;
-
- return 0;
-}
-
-static char *
-get_default_printer (void)
-{
- wchar_t *win32_printer_name = NULL;
- char *printer_name = NULL;
- DWORD needed;
-
- GetDefaultPrinterW (NULL, &needed);
- win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
- if (!GetDefaultPrinterW (win32_printer_name, &needed))
- {
- g_free (win32_printer_name);
- return NULL;
- }
- printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
- g_free (win32_printer_name);
-
- return printer_name;
-}
-
-static void
-set_hard_margins (GtkPrintOperation *op)
-{
- double top, bottom, left, right;
- GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-
- top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
- bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT)
- - GetDeviceCaps (op_win32->hdc, VERTRES) - top;
- left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
- right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH)
- - GetDeviceCaps (op_win32->hdc, HORZRES) - left;
-
- _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right);
-}
-
-void
-win32_start_page (GtkPrintOperation *op,
- GtkPrintContext *print_context,
- GtkPageSetup *page_setup)
-{
- GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
- LPDEVMODEW devmode;
- GtkPaperSize *paper_size;
- double x_off, y_off;
-
- devmode = GlobalLock (op_win32->devmode);
-
- devmode->dmFields |= DM_ORIENTATION;
- devmode->dmOrientation =
- orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
-
- paper_size = gtk_page_setup_get_paper_size (page_setup);
- devmode->dmFields |= DM_PAPERSIZE;
- devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
- devmode->dmPaperSize = paper_size_to_win32 (paper_size);
- if (devmode->dmPaperSize == 0)
- {
- devmode->dmPaperSize = DMPAPER_USER;
- devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
-
- /* Lengths in DEVMODE are in tenths of a millimeter */
- devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
- devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
- }
-
- ResetDCW (op_win32->hdc, devmode);
-
- GlobalUnlock (op_win32->devmode);
-
- set_hard_margins (op);
- x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
- y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
- cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
-
- StartPage (op_win32->hdc);
-}
-
-static void
-win32_end_page (GtkPrintOperation *op,
- GtkPrintContext *print_context)
-{
- GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-
- cairo_surface_show_page (op_win32->surface);
-
- EndPage (op_win32->hdc);
-}
-
-static gboolean
-win32_poll_status_timeout (GtkPrintOperation *op)
-{
- GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-
- op_win32->timeout_id = 0;
- /* We need to ref this, as setting the status to finished
- might unref the object */
- g_object_ref (op);
- win32_poll_status (op);
-
- if (!gtk_print_operation_is_finished (op)) {
- op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
- (GSourceFunc)win32_poll_status_timeout,
- op);
- gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
- }
- g_object_unref (op);
- return FALSE;
-}
-
-
-static void
-win32_end_run (GtkPrintOperation *op,
- gboolean wait,
- gboolean cancelled)
-{
- GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
- LPDEVNAMES devnames;
- HANDLE printerHandle = 0;
-
- cairo_surface_finish (op_win32->surface);
-
- EndDoc (op_win32->hdc);
-
- if (op->priv->track_print_status)
- {
- devnames = GlobalLock (op_win32->devnames);
- if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
- &printerHandle, NULL))
- printerHandle = 0;
- GlobalUnlock (op_win32->devnames);
- }
-
- GlobalFree (op_win32->devmode);
- GlobalFree (op_win32->devnames);
-
- cairo_surface_destroy (op_win32->surface);
- op_win32->surface = NULL;
-
- DeleteDC (op_win32->hdc);
-
- if (printerHandle != 0)
- {
- op_win32->printerHandle = printerHandle;
- win32_poll_status (op);
- op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
- (GSourceFunc)win32_poll_status_timeout,
- op);
- gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
- }
- else
- /* Dunno what happened, pretend its finished */
- _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
-}
-
-static void
-win32_poll_status (GtkPrintOperation *op)
-{
- GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
- guchar *data;
- DWORD needed;
- JOB_INFO_1W *job_info;
- GtkPrintStatus status;
- char *status_str;
- BOOL ret;
-
- GetJobW (op_win32->printerHandle, op_win32->job_id,
- 1,(LPBYTE)NULL, 0, &needed);
- data = g_malloc (needed);
- ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
- 1, (LPBYTE)data, needed, &needed);
-
- status_str = NULL;
- if (ret)
- {
- DWORD win32_status;
- job_info = (JOB_INFO_1W *)data;
- win32_status = job_info->Status;
-
- if (job_info->pStatus)
- status_str = g_utf16_to_utf8 (job_info->pStatus,
- -1, NULL, NULL, NULL);
-
- if (win32_status &
- (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
- status = GTK_PRINT_STATUS_FINISHED;
- else if (win32_status &
- (JOB_STATUS_OFFLINE |
- JOB_STATUS_PAPEROUT |
- JOB_STATUS_PAUSED |
- JOB_STATUS_USER_INTERVENTION))
- {
- status = GTK_PRINT_STATUS_PENDING_ISSUE;
- if (status_str == NULL)
- {
- if (win32_status & JOB_STATUS_OFFLINE)
- status_str = g_strdup (_("Printer offline"));
- else if (win32_status & JOB_STATUS_PAPEROUT)
- status_str = g_strdup (_("Out of paper"));
- else if (win32_status & JOB_STATUS_PAUSED)
- status_str = g_strdup (_("Paused"));
- else if (win32_status & JOB_STATUS_USER_INTERVENTION)
- status_str = g_strdup (_("Need user intervention"));
- }
- }
- else if (win32_status &
- (JOB_STATUS_BLOCKED_DEVQ |
- JOB_STATUS_DELETED |
- JOB_STATUS_ERROR))
- status = GTK_PRINT_STATUS_FINISHED_ABORTED;
- else if (win32_status &
- (JOB_STATUS_SPOOLING |
- JOB_STATUS_DELETING))
- status = GTK_PRINT_STATUS_PENDING;
- else if (win32_status & JOB_STATUS_PRINTING)
- status = GTK_PRINT_STATUS_PRINTING;
- else
- status = GTK_PRINT_STATUS_FINISHED;
- }
- else
- status = GTK_PRINT_STATUS_FINISHED;
-
- g_free (data);
-
- _gtk_print_operation_set_status (op, status, status_str);
-
- g_free (status_str);
-}
-
-static void
-op_win32_free (GtkPrintOperationWin32 *op_win32)
-{
- if (op_win32->printerHandle)
- ClosePrinter (op_win32->printerHandle);
- if (op_win32->timeout_id != 0)
- g_source_remove (op_win32->timeout_id);
- g_free (op_win32);
-}
-
-static HWND
-get_parent_hwnd (GtkWidget *widget)
-{
- GtkNative *native;
-
- native = gtk_widget_get_native (widget);
- gtk_widget_realize (GTK_WIDGET (native));
- return gdk_win32_surface_get_handle (gtk_native_get_surface (native));
-}
-
-static void
-devnames_to_settings (GtkPrintSettings *settings,
- HANDLE hDevNames)
-{
- GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
- gtk_print_settings_set_printer (settings, devnames->device);
- gtk_print_win32_devnames_free (devnames);
-}
-
-static void
-devmode_to_settings (GtkPrintSettings *settings,
- HANDLE hDevMode)
-{
- LPDEVMODEW devmode;
-
- devmode = GlobalLock (hDevMode);
-
- gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
- devmode->dmDriverVersion);
- if (devmode->dmDriverExtra != 0)
- {
- char *extra = g_base64_encode (((const guchar *)devmode) + sizeof (DEVMODEW),
- devmode->dmDriverExtra);
- gtk_print_settings_set (settings,
- GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
- extra);
- g_free (extra);
- }
-
- char *devmode_name = g_utf16_to_utf8 (devmode->dmDeviceName, -1, NULL, NULL, NULL);
- gtk_print_settings_set (settings, "win32-devmode-name", devmode_name);
- g_free (devmode_name);
-
- if (devmode->dmFields & DM_ORIENTATION)
- gtk_print_settings_set_orientation (settings,
- orientation_from_win32 (devmode->dmOrientation));
-
-
- if (devmode->dmFields & DM_PAPERSIZE &&
- devmode->dmPaperSize != 0)
- {
- GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
- if (paper_size)
- {
- gtk_print_settings_set_paper_size (settings, paper_size);
- gtk_paper_size_free (paper_size);
- }
- gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
- }
- else if ((devmode->dmFields & DM_PAPERSIZE &&
- devmode->dmPaperSize == 0) ||
- ((devmode->dmFields & DM_PAPERWIDTH) &&
- (devmode->dmFields & DM_PAPERLENGTH)))
- {
- GtkPaperSize *paper_size;
- char *form_name = NULL;
- if (devmode->dmFields & DM_FORMNAME)
- form_name = g_utf16_to_utf8 (devmode->dmFormName,
- -1, NULL, NULL, NULL);
- if (form_name == NULL || form_name[0] == 0)
- form_name = g_strdup (_("Custom size"));
-
- /* Lengths in DEVMODE are in tenths of a millimeter */
- paper_size = gtk_paper_size_new_custom (form_name,
- form_name,
- devmode->dmPaperWidth / 10.0,
- devmode->dmPaperLength / 10.0,
- GTK_UNIT_MM);
- gtk_print_settings_set_paper_size (settings, paper_size);
- gtk_paper_size_free (paper_size);
- }
-
- if (devmode->dmFields & DM_SCALE)
- gtk_print_settings_set_scale (settings, devmode->dmScale);
-
- if (devmode->dmFields & DM_COPIES)
- gtk_print_settings_set_n_copies (settings,
- devmode->dmCopies);
-
- if (devmode->dmFields & DM_DEFAULTSOURCE)
- {
- const char *source;
- switch (devmode->dmDefaultSource)
- {
- default:
- case DMBIN_AUTO:
- source = "auto";
- break;
- case DMBIN_CASSETTE:
- source = "cassette";
- break;
- case DMBIN_ENVELOPE:
- source = "envelope";
- break;
- case DMBIN_ENVMANUAL:
- source = "envelope-manual";
- break;
- case DMBIN_LOWER:
- source = "lower";
- break;
- case DMBIN_MANUAL:
- source = "manual";
- break;
- case DMBIN_MIDDLE:
- source = "middle";
- break;
- case DMBIN_ONLYONE:
- source = "only-one";
- break;
- case DMBIN_FORMSOURCE:
- source = "form-source";
- break;
- case DMBIN_LARGECAPACITY:
- source = "large-capacity";
- break;
- case DMBIN_LARGEFMT:
- source = "large-format";
- break;
- case DMBIN_TRACTOR:
- source = "tractor";
- break;
- case DMBIN_SMALLFMT:
- source = "small-format";
- break;
- }
- gtk_print_settings_set_default_source (settings, source);
- gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
- }
-
- if (devmode->dmFields & DM_PRINTQUALITY)
- {
- GtkPrintQuality quality;
- switch (devmode->dmPrintQuality)
- {
- case DMRES_LOW:
- quality = GTK_PRINT_QUALITY_LOW;
- break;
- case DMRES_MEDIUM:
- quality = GTK_PRINT_QUALITY_NORMAL;
- break;
- default:
- case DMRES_HIGH:
- quality = GTK_PRINT_QUALITY_HIGH;
- break;
- case DMRES_DRAFT:
- quality = GTK_PRINT_QUALITY_DRAFT;
- break;
- }
- gtk_print_settings_set_quality (settings, quality);
- gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
- }
-
- if (devmode->dmFields & DM_COLOR)
- gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
-
- if (devmode->dmFields & DM_DUPLEX)
- {
- GtkPrintDuplex duplex;
- switch (devmode->dmDuplex)
- {
- default:
- case DMDUP_SIMPLEX:
- duplex = GTK_PRINT_DUPLEX_SIMPLEX;
- break;
- case DMDUP_HORIZONTAL:
- duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
- break;
- case DMDUP_VERTICAL:
- duplex = GTK_PRINT_DUPLEX_VERTICAL;
- break;
- }
-
- gtk_print_settings_set_duplex (settings, duplex);
- }
-
- if (devmode->dmFields & DM_COLLATE)
- gtk_print_settings_set_collate (settings,
- devmode->dmCollate == DMCOLLATE_TRUE);
-
- if (devmode->dmFields & DM_MEDIATYPE)
- {
- const char *media_type;
- switch (devmode->dmMediaType)
- {
- default:
- case DMMEDIA_STANDARD:
- media_type = "stationery";
- break;
- case DMMEDIA_TRANSPARENCY:
- media_type = "transparency";
- break;
- case DMMEDIA_GLOSSY:
- media_type = "photographic-glossy";
- break;
- }
- gtk_print_settings_set_media_type (settings, media_type);
- gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
- }
-
- if (devmode->dmFields & DM_DITHERTYPE)
- {
- const char *dither;
- switch (devmode->dmDitherType)
- {
- default:
- case DMDITHER_FINE:
- dither = "fine";
- break;
- case DMDITHER_NONE:
- dither = "none";
- break;
- case DMDITHER_COARSE:
- dither = "coarse";
- break;
- case DMDITHER_LINEART:
- dither = "lineart";
- break;
- case DMDITHER_GRAYSCALE:
- dither = "grayscale";
- break;
- case DMDITHER_ERRORDIFFUSION:
- dither = "error-diffusion";
- break;
- }
- gtk_print_settings_set_dither (settings, dither);
- gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
- }
-
- GlobalUnlock (hDevMode);
-}
-
-static void
-dialog_to_print_settings (GtkPrintOperation *op,
- LPPRINTDLGEXW printdlgex)
-{
- guint i;
- GtkPrintSettings *settings;
-
- settings = gtk_print_settings_new ();
-
- gtk_print_settings_set_print_pages (settings,
- GTK_PRINT_PAGES_ALL);
- if (printdlgex->Flags & PD_CURRENTPAGE)
- gtk_print_settings_set_print_pages (settings,
- GTK_PRINT_PAGES_CURRENT);
- else if (printdlgex->Flags & PD_PAGENUMS)
- gtk_print_settings_set_print_pages (settings,
- GTK_PRINT_PAGES_RANGES);
-
- if (printdlgex->nPageRanges > 0)
- {
- GtkPageRange *ranges;
- ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
-
- for (i = 0; i < printdlgex->nPageRanges; i++)
- {
- ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
- ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
- }
-
- gtk_print_settings_set_page_ranges (settings, ranges,
- printdlgex->nPageRanges);
- g_free (ranges);
- }
-
- if (printdlgex->hDevNames != NULL)
- devnames_to_settings (settings, printdlgex->hDevNames);
-
- if (printdlgex->hDevMode != NULL)
- devmode_to_settings (settings, printdlgex->hDevMode);
-
- gtk_print_operation_set_print_settings (op, settings);
-}
-
-static HANDLE
-devmode_from_settings (GtkPrintSettings *settings,
- GtkPageSetup *page_setup,
- HANDLE hDevModeParam)
-{
- HANDLE hDevMode = hDevModeParam;
- LPDEVMODEW devmode;
- guchar *extras;
- GtkPaperSize *paper_size;
- const char *extras_base64;
- gsize extras_len;
- const char *val;
-
- /* If we already provided a valid hDevMode, don't initialize a new one; just lock the one we have */
- if (hDevMode)
- {
- devmode = GlobalLock (hDevMode);
- }
- else
- {
- extras = NULL;
- extras_len = 0;
- extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
- if (extras_base64)
- extras = g_base64_decode (extras_base64, &extras_len);
-
- hDevMode = GlobalAlloc (GMEM_MOVEABLE,
- sizeof (DEVMODEW) + extras_len);
-
- devmode = GlobalLock (hDevMode);
-
- memset (devmode, 0, sizeof (DEVMODEW));
-
- devmode->dmSpecVersion = DM_SPECVERSION;
- devmode->dmSize = sizeof (DEVMODEW);
-
- gunichar2 *device_name = g_utf8_to_utf16 (gtk_print_settings_get (settings, "win32-devmode-name"), -1, NULL, NULL, NULL);
- memcpy (devmode->dmDeviceName, device_name, CCHDEVICENAME);
- g_free (device_name);
-
-
- devmode->dmDriverExtra = 0;
- if (extras && extras_len > 0)
- {
- devmode->dmDriverExtra = extras_len;
- memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
- }
- g_free (extras);
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
- {
- devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
- }
- }
-
- if (page_setup ||
- gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
- {
- GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
- if (page_setup)
- orientation = gtk_page_setup_get_orientation (page_setup);
- devmode->dmFields |= DM_ORIENTATION;
- devmode->dmOrientation = orientation_to_win32 (orientation);
- }
-
- if (page_setup)
- paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
- else
- {
- int size;
- if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
- (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
- {
- devmode->dmFields |= DM_PAPERSIZE;
- devmode->dmPaperSize = size;
- paper_size = NULL;
- }
- else
- paper_size = gtk_print_settings_get_paper_size (settings);
- }
- if (paper_size)
- {
- devmode->dmFields |= DM_PAPERSIZE;
- devmode->dmPaperSize = paper_size_to_win32 (paper_size);
- if (devmode->dmPaperSize == 0)
- {
- devmode->dmPaperSize = DMPAPER_USER;
- devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
-
- /* Lengths in DEVMODE are in tenths of a millimeter */
- devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
- devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
- }
- gtk_paper_size_free (paper_size);
- }
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
- {
- devmode->dmFields |= DM_SCALE;
- devmode->dmScale = gtk_print_settings_get_scale (settings);
- }
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
- {
- devmode->dmFields |= DM_COPIES;
- devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
- }
-
- if (gtk_print_settings_has_key (settings, "win32-default-source"))
- {
- devmode->dmFields |= DM_DEFAULTSOURCE;
- devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
- }
- else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
- {
- devmode->dmFields |= DM_DEFAULTSOURCE;
- devmode->dmDefaultSource = DMBIN_AUTO;
-
- val = gtk_print_settings_get_default_source (settings);
- if (strcmp (val, "auto") == 0)
- devmode->dmDefaultSource = DMBIN_AUTO;
- if (strcmp (val, "cassette") == 0)
- devmode->dmDefaultSource = DMBIN_CASSETTE;
- if (strcmp (val, "envelope") == 0)
- devmode->dmDefaultSource = DMBIN_ENVELOPE;
- if (strcmp (val, "envelope-manual") == 0)
- devmode->dmDefaultSource = DMBIN_ENVMANUAL;
- if (strcmp (val, "lower") == 0)
- devmode->dmDefaultSource = DMBIN_LOWER;
- if (strcmp (val, "manual") == 0)
- devmode->dmDefaultSource = DMBIN_MANUAL;
- if (strcmp (val, "middle") == 0)
- devmode->dmDefaultSource = DMBIN_MIDDLE;
- if (strcmp (val, "only-one") == 0)
- devmode->dmDefaultSource = DMBIN_ONLYONE;
- if (strcmp (val, "form-source") == 0)
- devmode->dmDefaultSource = DMBIN_FORMSOURCE;
- if (strcmp (val, "large-capacity") == 0)
- devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
- if (strcmp (val, "large-format") == 0)
- devmode->dmDefaultSource = DMBIN_LARGEFMT;
- if (strcmp (val, "tractor") == 0)
- devmode->dmDefaultSource = DMBIN_TRACTOR;
- if (strcmp (val, "small-format") == 0)
- devmode->dmDefaultSource = DMBIN_SMALLFMT;
- }
-
- if (gtk_print_settings_has_key (settings, "win32-print-quality"))
- {
- devmode->dmFields |= DM_PRINTQUALITY;
- devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
- }
- else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
- {
- devmode->dmFields |= DM_PRINTQUALITY;
- devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
- }
- else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
- {
- devmode->dmFields |= DM_PRINTQUALITY;
- switch (gtk_print_settings_get_quality (settings))
- {
- case GTK_PRINT_QUALITY_LOW:
- devmode->dmPrintQuality = DMRES_LOW;
- break;
- case GTK_PRINT_QUALITY_DRAFT:
- devmode->dmPrintQuality = DMRES_DRAFT;
- break;
- default:
- case GTK_PRINT_QUALITY_NORMAL:
- devmode->dmPrintQuality = DMRES_MEDIUM;
- break;
- case GTK_PRINT_QUALITY_HIGH:
- devmode->dmPrintQuality = DMRES_HIGH;
- break;
- }
- }
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
- {
- devmode->dmFields |= DM_COLOR;
- if (gtk_print_settings_get_use_color (settings))
- devmode->dmColor = DMCOLOR_COLOR;
- else
- devmode->dmColor = DMCOLOR_MONOCHROME;
- }
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
- {
- devmode->dmFields |= DM_DUPLEX;
- switch (gtk_print_settings_get_duplex (settings))
- {
- default:
- case GTK_PRINT_DUPLEX_SIMPLEX:
- devmode->dmDuplex = DMDUP_SIMPLEX;
- break;
- case GTK_PRINT_DUPLEX_HORIZONTAL:
- devmode->dmDuplex = DMDUP_HORIZONTAL;
- break;
- case GTK_PRINT_DUPLEX_VERTICAL:
- devmode->dmDuplex = DMDUP_VERTICAL;
- break;
- }
- }
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
- {
- devmode->dmFields |= DM_COLLATE;
- if (gtk_print_settings_get_collate (settings))
- devmode->dmCollate = DMCOLLATE_TRUE;
- else
- devmode->dmCollate = DMCOLLATE_FALSE;
- }
-
- if (gtk_print_settings_has_key (settings, "win32-media-type"))
- {
- devmode->dmFields |= DM_MEDIATYPE;
- devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
- }
- else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
- {
- devmode->dmFields |= DM_MEDIATYPE;
- devmode->dmMediaType = DMMEDIA_STANDARD;
-
- val = gtk_print_settings_get_media_type (settings);
- if (strcmp (val, "transparency") == 0)
- devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
- if (strcmp (val, "photographic-glossy") == 0)
- devmode->dmMediaType = DMMEDIA_GLOSSY;
- }
-
- if (gtk_print_settings_has_key (settings, "win32-dither-type"))
- {
- devmode->dmFields |= DM_DITHERTYPE;
- devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
- }
- else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
- {
- devmode->dmFields |= DM_DITHERTYPE;
- devmode->dmDitherType = DMDITHER_FINE;
-
- val = gtk_print_settings_get_dither (settings);
- if (strcmp (val, "none") == 0)
- devmode->dmDitherType = DMDITHER_NONE;
- if (strcmp (val, "coarse") == 0)
- devmode->dmDitherType = DMDITHER_COARSE;
- if (strcmp (val, "fine") == 0)
- devmode->dmDitherType = DMDITHER_FINE;
- if (strcmp (val, "lineart") == 0)
- devmode->dmDitherType = DMDITHER_LINEART;
- if (strcmp (val, "grayscale") == 0)
- devmode->dmDitherType = DMDITHER_GRAYSCALE;
- if (strcmp (val, "error-diffusion") == 0)
- devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
- }
-
- GlobalUnlock (hDevMode);
-
- return hDevMode;
-}
-
-static void
-dialog_from_print_settings (GtkPrintOperation *op,
- LPPRINTDLGEXW printdlgex)
-{
- GtkPrintSettings *settings = op->priv->print_settings;
- const char *printer;
-
- if (settings == NULL)
- return;
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
- {
- GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
-
- switch (print_pages)
- {
- default:
- case GTK_PRINT_PAGES_SELECTION:
- case GTK_PRINT_PAGES_ALL:
- printdlgex->Flags |= PD_ALLPAGES;
- break;
- case GTK_PRINT_PAGES_CURRENT:
- printdlgex->Flags |= PD_CURRENTPAGE;
- break;
- case GTK_PRINT_PAGES_RANGES:
- printdlgex->Flags |= PD_PAGENUMS;
- break;
- }
- }
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
- {
- GtkPageRange *ranges;
- int num_ranges, i;
-
- ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
-
- if (num_ranges > MAX_PAGE_RANGES)
- num_ranges = MAX_PAGE_RANGES;
-
- printdlgex->nPageRanges = num_ranges;
- for (i = 0; i < num_ranges; i++)
- {
- printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
- printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
- }
- }
-
- /* If we have a printer saved, restore our settings */
- printer = gtk_print_settings_get_printer (settings);
- if (printer)
- {
- printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
-
- printdlgex->hDevMode = devmode_from_settings (settings,
- op->priv->default_page_setup, NULL);
- }
- else
- {
- /* Otherwise, use the default settings */
- DWORD FlagsCopy = printdlgex->Flags;
- printdlgex->Flags |= PD_RETURNDEFAULT;
- PrintDlgExW (printdlgex);
- printdlgex->Flags = FlagsCopy;
-
- devmode_from_settings (settings, op->priv->default_page_setup, printdlgex->hDevMode);
- }
-}
-
-typedef struct {
- IPrintDialogCallback iPrintDialogCallback;
- gboolean set_hwnd;
- int ref_count;
-} PrintDialogCallback;
-
-
-static ULONG STDMETHODCALLTYPE
-iprintdialogcallback_addref (IPrintDialogCallback *This)
-{
- PrintDialogCallback *callback = (PrintDialogCallback *)This;
- return ++callback->ref_count;
-}
-
-static ULONG STDMETHODCALLTYPE
-iprintdialogcallback_release (IPrintDialogCallback *This)
-{
- PrintDialogCallback *callback = (PrintDialogCallback *)This;
- int ref_count = --callback->ref_count;
-
- if (ref_count == 0)
- g_free (This);
-
- return ref_count;
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
- REFIID riid,
- LPVOID *ppvObject)
-{
- if (IsEqualIID (riid, &IID_IUnknown) ||
- IsEqualIID (riid, &myIID_IPrintDialogCallback))
- {
- *ppvObject = This;
- IUnknown_AddRef ((IUnknown *)This);
- return NOERROR;
- }
- else
- {
- *ppvObject = NULL;
- return E_NOINTERFACE;
- }
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_initdone (IPrintDialogCallback *This)
-{
- return S_FALSE;
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
-{
- return S_FALSE;
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
- HWND hDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam,
- LRESULT *pResult)
-{
- PrintDialogCallback *callback = (PrintDialogCallback *)This;
-
- if (!callback->set_hwnd)
- {
- gdk_win32_set_modal_dialog_libgtk_only (hDlg);
- callback->set_hwnd = TRUE;
- while (g_main_context_pending (NULL))
- g_main_context_iteration (NULL, TRUE);
- }
- else if (uMsg == got_gdk_events_message)
- {
- while (g_main_context_pending (NULL))
- g_main_context_iteration (NULL, TRUE);
- *pResult = TRUE;
- return S_OK;
- }
-
- *pResult = 0;
- return S_FALSE;
-}
-
-static IPrintDialogCallbackVtbl ipdc_vtbl = {
- iprintdialogcallback_queryinterface,
- iprintdialogcallback_addref,
- iprintdialogcallback_release,
- iprintdialogcallback_initdone,
- iprintdialogcallback_selectionchange,
- iprintdialogcallback_handlemessage
-};
-
-static IPrintDialogCallback *
-print_callback_new (void)
-{
- PrintDialogCallback *callback;
-
- callback = g_new0 (PrintDialogCallback, 1);
- callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
- callback->ref_count = 1;
- callback->set_hwnd = FALSE;
-
- return &callback->iPrintDialogCallback;
-}
-
-static INT_PTR CALLBACK
-pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
- GtkPrintOperation *op;
- GtkPrintOperationWin32 *op_win32;
-
- if (message == WM_INITDIALOG)
- {
- PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
- GtkWidget *plug;
-
- op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
- op_win32 = op->priv->platform_data;
- plug = g_object_new(GTK_TYPE_WIDGET, NULL);
-
- SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
-
- gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
- op_win32->embed_widget = plug;
- gtk_box_append (GTK_BOX (plug), op->priv->custom_widget);
- gtk_widget_set_visible (op->priv->custom_widget, TRUE);
- gtk_widget_set_visible (plug, TRUE);
-
- /* This dialog is modal, so we grab the embed widget */
- gtk_grab_add (plug);
- return FALSE;
- }
- else if (message == WM_DESTROY)
- {
- op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
- op_win32 = op->priv->platform_data;
-
- g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
- g_object_unref (g_object_ref_sink (op_win32->embed_widget));
- op_win32->embed_widget = NULL;
- op->priv->custom_widget = NULL;
- }
- else
- {
- op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
- op_win32 = op->priv->platform_data;
-
- /* TODO: We don't have GtkWin32EmbedWidgets anymore, but it is not currently clear
- * at this point what will be the proper replacement for this. For now,
- * do the message handling that was in _gtk_win32_embed_widget_dialog_procedure ()
- * here and fill in the rest when things become clearer.
- */
- if (message == WM_SIZE)
- {
- gtk_widget_queue_resize (op_win32->embed_widget);
- }
-
- return FALSE;
- }
-
- return FALSE;
-}
-
-static HPROPSHEETPAGE
-create_application_page (GtkPrintOperation *op)
-{
- HPROPSHEETPAGE hpage;
- PROPSHEETPAGEW page;
- DLGTEMPLATE *template;
- HGLOBAL htemplate;
- LONG base_units;
- WORD baseunitX, baseunitY;
- WORD *array;
- GtkRequisition requisition;
- const char *tab_label;
-
- /* Make the template the size of the custom widget size request */
- gtk_widget_get_preferred_size (op->priv->custom_widget,
- &requisition, NULL);
-
- base_units = GetDialogBaseUnits ();
- baseunitX = LOWORD (base_units);
- baseunitY = HIWORD (base_units);
-
- htemplate = GlobalAlloc (GMEM_MOVEABLE,
- sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
- template = GlobalLock (htemplate);
- template->style = WS_CHILDWINDOW | DS_CONTROL;
- template->dwExtendedStyle = WS_EX_CONTROLPARENT;
- template->cdit = 0;
- template->x = MulDiv (0, 4, baseunitX);
- template->y = MulDiv (0, 8, baseunitY);
- template->cx = MulDiv (requisition.width, 4, baseunitX);
- template->cy = MulDiv (requisition.height, 8, baseunitY);
-
- array = (WORD *) (template+1);
- *array++ = 0; /* menu */
- *array++ = 0; /* class */
- *array++ = 0; /* title */
-
- memset (&page, 0, sizeof (page));
- page.dwSize = sizeof (page);
- page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
- page.hInstance = NULL;
- page.pResource = template;
-
- tab_label = op->priv->custom_tab_label;
- if (tab_label == NULL)
- tab_label = g_get_application_name ();
- if (tab_label == NULL)
- tab_label = _("Application");
- page.pszTitle = g_utf8_to_utf16 (tab_label,
- -1, NULL, NULL, NULL);
- page.pfnDlgProc = pageDlgProc;
- page.pfnCallback = NULL;
- page.lParam = (LPARAM) op;
- hpage = CreatePropertySheetPageW (&page);
-
- GlobalUnlock (htemplate);
-
- /* TODO: We're leaking htemplate here... */
-
- return hpage;
-}
-
-static GtkPageSetup *
-create_page_setup (GtkPrintOperation *op)
-{
- GtkPrintOperationPrivate *priv = op->priv;
- GtkPageSetup *page_setup;
- GtkPrintSettings *settings;
-
- if (priv->default_page_setup)
- page_setup = gtk_page_setup_copy (priv->default_page_setup);
- else
- page_setup = gtk_page_setup_new ();
-
- settings = priv->print_settings;
- if (settings)
- {
- GtkPaperSize *paper_size;
-
- if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
- gtk_page_setup_set_orientation (page_setup,
- gtk_print_settings_get_orientation (settings));
-
-
- paper_size = gtk_print_settings_get_paper_size (settings);
- if (paper_size)
- {
- gtk_page_setup_set_paper_size (page_setup, paper_size);
- gtk_paper_size_free (paper_size);
- }
-
- /* TODO: Margins? */
- }
-
- return page_setup;
-}
-
-GtkPrintOperationResult
-gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
- gboolean *do_print)
-{
- GtkPrintOperationResult result;
- GtkPrintOperationWin32 *op_win32;
- GtkPrintOperationPrivate *priv;
- GtkPrintSettings *settings;
- GtkPageSetup *page_setup;
- DOCINFOW docinfo;
- HGLOBAL hDevMode = NULL;
- HGLOBAL hDevNames = NULL;
- HDC hDC = NULL;
- const char *printer = NULL;
- double dpi_x, dpi_y;
- int job_id;
- cairo_t *cr;
- DEVNAMES *pdn;
- DEVMODEW *pdm;
-
- *do_print = FALSE;
-
- priv = op->priv;
- settings = priv->print_settings;
-
- op_win32 = g_new0 (GtkPrintOperationWin32, 1);
- priv->platform_data = op_win32;
- priv->free_platform_data = (GDestroyNotify) op_win32_free;
- printer = gtk_print_settings_get_printer (settings);
-
- if (!printer)
- {
- /* No printer selected. Get the system default printer and store
- * it in settings.
- */
- char *tmp_printer = get_default_printer ();
- if (!tmp_printer)
- {
- result = GTK_PRINT_OPERATION_RESULT_ERROR;
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_INTERNAL_ERROR,
- _("No printer found"));
- goto out;
- }
- gtk_print_settings_set_printer (settings, tmp_printer);
- printer = gtk_print_settings_get_printer (settings);
- g_free (tmp_printer);
- }
-
- hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
- hDevMode = devmode_from_settings (settings, op->priv->default_page_setup, NULL);
-
- /* Create a printer DC for the print settings and page setup provided. */
- pdn = GlobalLock (hDevNames);
- pdm = GlobalLock (hDevMode);
- hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
- (wchar_t*)pdn + pdn->wDeviceOffset,
- (wchar_t*)pdn + pdn->wOutputOffset,
- pdm );
- GlobalUnlock (hDevNames);
- GlobalUnlock (hDevMode);
-
- if (!hDC)
- {
- result = GTK_PRINT_OPERATION_RESULT_ERROR;
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_INTERNAL_ERROR,
- _("Invalid argument to CreateDC"));
- goto out;
- }
-
- priv->print_context = _gtk_print_context_new (op);
- page_setup = create_page_setup (op);
- _gtk_print_context_set_page_setup (priv->print_context, page_setup);
- g_object_unref (page_setup);
-
- *do_print = TRUE;
-
- op_win32->surface = cairo_win32_printing_surface_create (hDC);
- dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
- dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
-
- cr = cairo_create (op_win32->surface);
- gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
- cairo_destroy (cr);
-
- set_hard_margins (op);
-
- memset (&docinfo, 0, sizeof (DOCINFOW));
- docinfo.cbSize = sizeof (DOCINFOW);
- docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
- docinfo.lpszOutput = NULL;
- docinfo.lpszDatatype = NULL;
- docinfo.fwType = 0;
-
- job_id = StartDocW (hDC, &docinfo);
- g_free ((void *)docinfo.lpszDocName);
- if (job_id <= 0)
- {
- result = GTK_PRINT_OPERATION_RESULT_ERROR;
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_GENERAL,
- _("Error from StartDoc"));
- *do_print = FALSE;
- cairo_surface_destroy (op_win32->surface);
- op_win32->surface = NULL;
- goto out;
- }
-
- result = GTK_PRINT_OPERATION_RESULT_APPLY;
- op_win32->hdc = hDC;
- op_win32->devmode = hDevMode;
- op_win32->devnames = hDevNames;
- op_win32->job_id = job_id;
- op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
- op->priv->num_page_ranges = 0;
- if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
- op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
- &op->priv->num_page_ranges);
- op->priv->manual_num_copies = 1;
- op->priv->manual_collation = FALSE;
- op->priv->manual_reverse = FALSE;
- op->priv->manual_orientation = FALSE;
- op->priv->manual_scale = 1.0;
- op->priv->manual_page_set = GTK_PAGE_SET_ALL;
- op->priv->manual_number_up = 1;
- op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-
- op->priv->start_page = win32_start_page;
- op->priv->end_page = win32_end_page;
- op->priv->end_run = win32_end_run;
-
- out:
- if (!*do_print && hDC != NULL)
- DeleteDC (hDC);
-
- if (!*do_print && hDevMode != NULL)
- GlobalFree (hDevMode);
-
- if (!*do_print && hDevNames != NULL)
- GlobalFree (hDevNames);
-
- return result;
-}
-
-GtkPrintOperationResult
-gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
- GtkWindow *parent,
- gboolean *do_print)
-{
- HRESULT hResult;
- LPPRINTDLGEXW printdlgex = NULL;
- LPPRINTPAGERANGE page_ranges = NULL;
- HWND parentHWnd;
- GtkWidget *invisible = NULL;
- GtkPrintOperationResult result;
- GtkPrintOperationWin32 *op_win32;
- GtkPrintOperationPrivate *priv;
- IPrintDialogCallback *callback;
- HPROPSHEETPAGE prop_page;
- static gsize common_controls_initialized = 0;
-
- if (g_once_init_enter (&common_controls_initialized))
- {
- BOOL initialized;
- INITCOMMONCONTROLSEX icc;
-
- memset (&icc, 0, sizeof (icc));
- icc.dwSize = sizeof (icc);
- icc.dwICC = ICC_WIN95_CLASSES;
-
- initialized = InitCommonControlsEx (&icc);
- if (!initialized)
- g_warning ("Failed to InitCommonControlsEx: %lu", GetLastError ());
-
- _gtk_load_dll_with_libgtk3_manifest ("comdlg32.dll");
-
- g_once_init_leave (&common_controls_initialized, initialized ? 1 : 0);
- }
-
- *do_print = FALSE;
-
- priv = op->priv;
-
- op_win32 = g_new0 (GtkPrintOperationWin32, 1);
- priv->platform_data = op_win32;
- priv->free_platform_data = (GDestroyNotify) op_win32_free;
-
- if (parent == NULL)
- {
- invisible = gtk_window_new ();
- parentHWnd = get_parent_hwnd (invisible);
- }
- else
- parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
-
- printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
- if (!printdlgex)
- {
- result = GTK_PRINT_OPERATION_RESULT_ERROR;
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_NOMEM,
- _("Not enough free memory"));
- goto out;
- }
-
- printdlgex->lStructSize = sizeof (PRINTDLGEXW);
- printdlgex->hwndOwner = parentHWnd;
- printdlgex->hDevMode = NULL;
- printdlgex->hDevNames = NULL;
- printdlgex->hDC = NULL;
- printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
- if (op->priv->current_page == -1)
- printdlgex->Flags |= PD_NOCURRENTPAGE;
- printdlgex->Flags2 = 0;
- printdlgex->ExclusionFlags = 0;
-
- page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR,
- MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
- if (!page_ranges)
- {
- result = GTK_PRINT_OPERATION_RESULT_ERROR;
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_NOMEM,
- _("Not enough free memory"));
- goto out;
- }
-
- printdlgex->nPageRanges = 0;
- printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
- printdlgex->lpPageRanges = page_ranges;
- printdlgex->nMinPage = 1;
- if (op->priv->nr_of_pages != -1)
- printdlgex->nMaxPage = op->priv->nr_of_pages;
- else
- printdlgex->nMaxPage = 10000;
- printdlgex->nCopies = 1;
- printdlgex->hInstance = 0;
- printdlgex->lpPrintTemplateName = NULL;
- printdlgex->lpCallback = NULL;
-
- g_signal_emit_by_name (op, "create-custom-widget",
- &op->priv->custom_widget);
- if (op->priv->custom_widget) {
- prop_page = create_application_page (op);
- printdlgex->nPropertyPages = 1;
- printdlgex->lphPropertyPages = &prop_page;
- } else {
- printdlgex->nPropertyPages = 0;
- printdlgex->lphPropertyPages = NULL;
- }
-
- printdlgex->nStartPage = START_PAGE_GENERAL;
- printdlgex->dwResultAction = 0;
-
- dialog_from_print_settings (op, printdlgex);
-
- callback = print_callback_new ();
- printdlgex->lpCallback = (IUnknown *)callback;
- got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
-
- hResult = PrintDlgExW (printdlgex);
- IUnknown_Release ((IUnknown *)callback);
- gdk_win32_set_modal_dialog_libgtk_only (NULL);
-
- if (hResult != S_OK)
- {
- result = GTK_PRINT_OPERATION_RESULT_ERROR;
- if (hResult == E_OUTOFMEMORY)
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_NOMEM,
- _("Not enough free memory"));
- else if (hResult == E_INVALIDARG)
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_INTERNAL_ERROR,
- _("Invalid argument to PrintDlgEx"));
- else if (hResult == E_POINTER)
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_INTERNAL_ERROR,
- _("Invalid pointer to PrintDlgEx"));
- else if (hResult == E_HANDLE)
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_INTERNAL_ERROR,
- _("Invalid handle to PrintDlgEx"));
- else /* E_FAIL */
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_GENERAL,
- _("Unspecified error"));
- goto out;
- }
-
- if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
- printdlgex->dwResultAction == PD_RESULT_APPLY)
- {
- result = GTK_PRINT_OPERATION_RESULT_APPLY;
- dialog_to_print_settings (op, printdlgex);
- }
- else
- result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-
- if (printdlgex->dwResultAction == PD_RESULT_PRINT)
- {
- DOCINFOW docinfo;
- int job_id;
- double dpi_x, dpi_y;
- cairo_t *cr;
- GtkPageSetup *page_setup;
-
- priv->print_context = _gtk_print_context_new (op);
- page_setup = create_page_setup (op);
- _gtk_print_context_set_page_setup (priv->print_context, page_setup);
- g_object_unref (page_setup);
-
- *do_print = TRUE;
-
- op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
-
- dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
- dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
-
- cr = cairo_create (op_win32->surface);
- gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
- cairo_destroy (cr);
-
- set_hard_margins (op);
-
- memset ( &docinfo, 0, sizeof (DOCINFOW));
- docinfo.cbSize = sizeof (DOCINFOW);
- docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
- docinfo.lpszOutput = (LPCWSTR) NULL;
- docinfo.lpszDatatype = (LPCWSTR) NULL;
- docinfo.fwType = 0;
-
- job_id = StartDocW (printdlgex->hDC, &docinfo);
- g_free ((void *)docinfo.lpszDocName);
- if (job_id <= 0)
- {
- result = GTK_PRINT_OPERATION_RESULT_ERROR;
- g_set_error_literal (&priv->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_GENERAL,
- _("Error from StartDoc"));
- *do_print = FALSE;
- cairo_surface_destroy (op_win32->surface);
- op_win32->surface = NULL;
- goto out;
- }
-
- op_win32->hdc = printdlgex->hDC;
- op_win32->devmode = printdlgex->hDevMode;
- op_win32->devnames = printdlgex->hDevNames;
- op_win32->job_id = job_id;
-
- op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
- op->priv->num_page_ranges = 0;
- if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
- op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
- &op->priv->num_page_ranges);
- op->priv->manual_num_copies = printdlgex->nCopies;
- op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
- op->priv->manual_reverse = FALSE;
- op->priv->manual_orientation = FALSE;
- op->priv->manual_scale = 1.0;
- op->priv->manual_page_set = GTK_PAGE_SET_ALL;
- op->priv->manual_number_up = 1;
- op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
- }
-
- op->priv->start_page = win32_start_page;
- op->priv->end_page = win32_end_page;
- op->priv->end_run = win32_end_run;
-
- out:
- if (!*do_print && printdlgex && printdlgex->hDC != NULL)
- DeleteDC (printdlgex->hDC);
-
- if (!*do_print && printdlgex && printdlgex->hDevMode != NULL)
- GlobalFree (printdlgex->hDevMode);
-
- if (!*do_print && printdlgex && printdlgex->hDevNames != NULL)
- GlobalFree (printdlgex->hDevNames);
-
- if (page_ranges)
- GlobalFree (page_ranges);
-
- if (printdlgex)
- GlobalFree (printdlgex);
-
- if (invisible)
- gtk_window_destroy (GTK_WINDOW (invisible));
-
- return result;
-}
-
-GtkPrintOperationResult
-_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
- gboolean show_dialog,
- GtkWindow *parent,
- gboolean *do_print)
-{
- if (show_dialog)
- return gtk_print_operation_run_with_dialog (op, parent, do_print);
- else
- return gtk_print_operation_run_without_dialog (op, do_print);
-}
-
-void
-_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
- cairo_surface_t *surface,
- GtkWindow *parent,
- const char *filename)
-{
- HDC dc;
- HENHMETAFILE metafile;
-
- dc = cairo_win32_surface_get_dc (surface);
- cairo_surface_destroy (surface);
- metafile = CloseEnhMetaFile (dc);
- DeleteEnhMetaFile (metafile);
-
- ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr)
-{
- HDC dc = cairo_win32_surface_get_dc (surface);
- StartPage (dc);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
- cairo_surface_t *surface,
- cairo_t *cr)
-{
- HDC dc;
-
- cairo_surface_show_page (surface);
-
- /* TODO: Enhanced metafiles don't support multiple pages.
- */
- dc = cairo_win32_surface_get_dc (surface);
- EndPage (dc);
-}
-
-cairo_surface_t *
-_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- double *dpi_x,
- double *dpi_y,
- char **target)
-{
- GtkPaperSize *paper_size;
- HDC metafile_dc;
- RECT rect;
- char *template;
- char *filename;
- gunichar2 *filename_utf16;
- int fd;
-
- template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
- fd = g_mkstemp (template);
- close (fd);
-
- filename = g_strconcat (template, ".emf", NULL);
- g_free (template);
-
- filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
- g_free (filename);
-
- paper_size = gtk_page_setup_get_paper_size (page_setup);
-
- /* The rectangle dimensions are given in hundredths of a millimeter */
- rect.left = 0;
- rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
- rect.top = 0;
- rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
-
- metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
- &rect, L"Gtk+\0Print Preview\0\0");
- if (metafile_dc == NULL)
- {
- g_warning ("Can't create metafile");
- return NULL;
- }
-
- *target = (char *)filename_utf16;
-
- *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
- *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
-
- return cairo_win32_printing_surface_create (metafile_dc);
-}
-
-void
-_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
- GtkPageSetup *page_setup,
- cairo_surface_t *surface)
-{
- /* TODO: Implement */
-}
-
-/**
- * gtk_print_run_page_setup_dialog:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- *
- * Runs a page setup dialog, letting the user modify the values from
- * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
- * is identical to the passed in @page_setup, otherwise it contains the
- * modifications done in the dialog.
- *
- * Note that this function may use a recursive mainloop to show the page
- * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
- * a problem.
- *
- * Returns: (transfer full): a new `GtkPageSetup`
- */
-GtkPageSetup *
-gtk_print_run_page_setup_dialog (GtkWindow *parent,
- GtkPageSetup *page_setup,
- GtkPrintSettings *settings)
-{
- LPPAGESETUPDLGW pagesetupdlg = NULL;
- BOOL res;
- gboolean free_settings;
- const char *printer;
- GtkPaperSize *paper_size;
- DWORD measure_system;
- GtkUnit unit;
- double scale;
-
- pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
- if (!pagesetupdlg)
- return NULL;
-
- free_settings = FALSE;
- if (settings == NULL)
- {
- settings = gtk_print_settings_new ();
- free_settings = TRUE;
- }
-
- memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
-
- pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
-
- if (parent != NULL)
- pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
- else
- pagesetupdlg->hwndOwner = NULL;
-
- pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
- pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup, NULL);
- pagesetupdlg->hDevNames = NULL;
- printer = gtk_print_settings_get_printer (settings);
- if (printer)
- pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
-
- GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
- (LPWSTR)&measure_system, sizeof (DWORD));
-
- if (measure_system == 0)
- {
- pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
- unit = GTK_UNIT_MM;
- scale = 100;
- }
- else
- {
- pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
- unit = GTK_UNIT_INCH;
- scale = 1000;
- }
-
- /* This is the object we return, we allocate it here so that
- * we can use the default page margins */
- if (page_setup)
- page_setup = gtk_page_setup_copy (page_setup);
- else
- page_setup = gtk_page_setup_new ();
-
- pagesetupdlg->Flags |= PSD_MARGINS;
- pagesetupdlg->rtMargin.left =
- floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
- pagesetupdlg->rtMargin.right =
- floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
- pagesetupdlg->rtMargin.top =
- floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
- pagesetupdlg->rtMargin.bottom =
- floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
-
- pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
- pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
- got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
-
- res = PageSetupDlgW (pagesetupdlg);
- gdk_win32_set_modal_dialog_libgtk_only (NULL);
-
- if (res)
- {
- if (pagesetupdlg->hDevNames != NULL)
- devnames_to_settings (settings, pagesetupdlg->hDevNames);
-
- if (pagesetupdlg->hDevMode != NULL)
- devmode_to_settings (settings, pagesetupdlg->hDevMode);
- }
-
- if (res)
- {
- gtk_page_setup_set_orientation (page_setup,
- gtk_print_settings_get_orientation (settings));
- paper_size = gtk_print_settings_get_paper_size (settings);
- if (paper_size)
- {
- gtk_page_setup_set_paper_size (page_setup, paper_size);
- gtk_paper_size_free (paper_size);
- }
-
- if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
- {
- unit = GTK_UNIT_MM;
- scale = 100;
- }
- else
- {
- unit = GTK_UNIT_INCH;
- scale = 1000;
- }
-
- gtk_page_setup_set_left_margin (page_setup,
- pagesetupdlg->rtMargin.left / scale,
- unit);
- gtk_page_setup_set_right_margin (page_setup,
- pagesetupdlg->rtMargin.right / scale,
- unit);
- gtk_page_setup_set_top_margin (page_setup,
- pagesetupdlg->rtMargin.top / scale,
- unit);
- gtk_page_setup_set_bottom_margin (page_setup,
- pagesetupdlg->rtMargin.bottom / scale,
- unit);
- }
-
- if (free_settings)
- g_object_unref (settings);
-
- return page_setup;
-}
-
-/**
- * gtk_print_run_page_setup_dialog_async:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- * @done_cb: (scope async): a function to call when the user saves
- * the modified page setup
- * @data: user data to pass to @done_cb
- *
- * Runs a page setup dialog, letting the user modify the values from @page_setup.
- *
- * In contrast to gtk_print_run_page_setup_dialog(), this function returns after
- * showing the page setup dialog on platforms that support this, and calls @done_cb
- * from a signal handler for the ::response signal of the dialog.
- */
-void
-gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
- GtkPageSetup *page_setup,
- GtkPrintSettings *settings,
- GtkPageSetupDoneFunc done_cb,
- gpointer data)
-{
- GtkPageSetup *new_page_setup;
-
- new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
- done_cb (new_page_setup, data);
- g_object_unref (new_page_setup);
-}
+++ /dev/null
-/* GtkPrintUnixDialog
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- * Copyright © 2006, 2007 Christian Persch
- *
- * 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 <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <math.h>
-
-#include "gtkprintunixdialog.h"
-
-#include "gtkcustompaperunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprinterprivate.h"
-#include "gtkprinteroptionwidgetprivate.h"
-#include "gtkprintutilsprivate.h"
-
-#include "gtkspinbutton.h"
-#include "gtkimage.h"
-#include "gtknotebook.h"
-#include "gtkscrolledwindow.h"
-#include "gtktogglebutton.h"
-#include "gtkdrawingarea.h"
-#include "gtkbox.h"
-#include "gtkgrid.h"
-#include "gtkframe.h"
-#include "gtklabel.h"
-#include "gtkbuildable.h"
-#include "deprecated/gtkmessagedialog.h"
-#include "gtkbutton.h"
-#include "gtksnapshot.h"
-#include "gtkrenderbackgroundprivate.h"
-#include "gtkrenderborderprivate.h"
-#include <glib/gi18n-lib.h>
-#include "gtkprivate.h"
-#include "gtktypebuiltins.h"
-#include "deprecated/gtkdialogprivate.h"
-#include "gtkwidgetprivate.h"
-#include "gtkcsscolorvalueprivate.h"
-
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-
-/**
- * GtkPrintUnixDialog:
- *
- * `GtkPrintUnixDialog` implements a print dialog for platforms
- * which don’t provide a native print dialog, like Unix.
- *
- * 
- *
- * It can be used very much like any other GTK dialog, at the cost of
- * the portability offered by the high-level printing API with
- * [class@Gtk.PrintOperation].
- *
- * In order to print something with `GtkPrintUnixDialog`, you need to
- * use [method@Gtk.PrintUnixDialog.get_selected_printer] to obtain a
- * [class@Gtk.Printer] object and use it to construct a [class@Gtk.PrintJob]
- * using [ctor@Gtk.PrintJob.new].
- *
- * `GtkPrintUnixDialog` uses the following response values:
- *
- * - %GTK_RESPONSE_OK: for the “Print” button
- * - %GTK_RESPONSE_APPLY: for the “Preview” button
- * - %GTK_RESPONSE_CANCEL: for the “Cancel” button
- *
- * # GtkPrintUnixDialog as GtkBuildable
- *
- * The `GtkPrintUnixDialog` implementation of the `GtkBuildable` interface
- * exposes its @notebook internal children with the name “notebook”.
- *
- * An example of a `GtkPrintUnixDialog` UI definition fragment:
- *
- * ```xml
- * <object class="GtkPrintUnixDialog" id="dialog1">
- * <child internal-child="notebook">
- * <object class="GtkNotebook" id="notebook">
- * <child>
- * <object type="GtkNotebookPage">
- * <property name="tab_expand">False</property>
- * <property name="tab_fill">False</property>
- * <property name="tab">
- * <object class="GtkLabel" id="tablabel">
- * <property name="label">Tab label</property>
- * </object>
- * </property>
- * <property name="child">
- * <object class="GtkLabel" id="tabcontent">
- * <property name="label">Content on notebook tab</property>
- * </object>
- * </property>
- * </object>
- * </child>
- * </object>
- * </child>
- * </object>
- * ```
- *
- * # CSS nodes
- *
- * `GtkPrintUnixDialog` has a single CSS node with name window. The style classes
- * dialog and print are added.
- */
-
-
-#define EXAMPLE_PAGE_AREA_SIZE 110
-#define RULER_DISTANCE 7.5
-#define RULER_RADIUS 2
-
-
-static void gtk_print_unix_dialog_constructed (GObject *object);
-static void gtk_print_unix_dialog_dispose (GObject *object);
-static void gtk_print_unix_dialog_finalize (GObject *object);
-static void gtk_print_unix_dialog_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_print_unix_dialog_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog);
-static void selected_printer_changed (GtkPrintUnixDialog *dialog);
-static void clear_per_printer_ui (GtkPrintUnixDialog *dialog);
-static void printer_added_cb (GListModel *model,
- guint position,
- guint removed,
- guint added,
- GtkPrintUnixDialog *dialog);
-static void printer_status_cb (GtkPrintBackend *backend,
- GtkPrinter *printer,
- GtkPrintUnixDialog *dialog);
-static void update_collate_icon (GtkToggleButton *toggle_button,
- GtkPrintUnixDialog *dialog);
-static void error_dialogs (GtkPrintUnixDialog *print_dialog,
- int print_dialog_response_id,
- gpointer data);
-static gboolean page_range_entry_focus_changed (GtkWidget *entry,
- GParamSpec *pspec,
- GtkPrintUnixDialog *dialog);
-static void update_page_range_entry_sensitivity(GtkWidget *button,
- GtkPrintUnixDialog *dialog);
-static void update_print_at_entry_sensitivity (GtkWidget *button,
- GtkPrintUnixDialog *dialog);
-static void update_print_at_option (GtkPrintUnixDialog *dialog);
-static void update_dialog_from_capabilities (GtkPrintUnixDialog *dialog);
-static void draw_collate (GtkDrawingArea *da,
- cairo_t *cr,
- int width,
- int height,
- gpointer data);
-static gboolean is_printer_active (gpointer item,
- gpointer data);
-static int default_printer_list_sort_func (gconstpointer a,
- gconstpointer b,
- gpointer user_data);
-static void update_number_up_layout (GtkPrintUnixDialog *dialog);
-static void draw_page (GtkDrawingArea *da,
- cairo_t *cr,
- int width,
- int height,
- gpointer data);
-
-
-static gboolean dialog_get_collate (GtkPrintUnixDialog *dialog);
-static gboolean dialog_get_reverse (GtkPrintUnixDialog *dialog);
-static int dialog_get_n_copies (GtkPrintUnixDialog *dialog);
-
-static gboolean set_active_printer (GtkPrintUnixDialog *dialog,
- const char *printer_name);
-static void redraw_page_layout_preview (GtkPrintUnixDialog *dialog);
-static GListModel *load_print_backends (GtkPrintUnixDialog *dialog);
-
-/* GtkBuildable */
-static void gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface);
-static GObject *gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
- GtkBuilder *builder,
- const char *childname);
-
-static const char common_paper_sizes[][16] = {
- "na_letter",
- "na_legal",
- "iso_a4",
- "iso_a5",
- "roc_16k",
- "iso_b5",
- "jis_b5",
- "na_number-10",
- "iso_dl",
- "jpn_chou3",
- "na_ledger",
- "iso_a3",
-};
-
-/* Keep in line with liststore defined in gtkprintunixdialog.ui */
-enum {
- PAGE_SETUP_LIST_COL_PAGE_SETUP,
- PAGE_SETUP_LIST_COL_IS_SEPARATOR,
- PAGE_SETUP_LIST_N_COLS
-};
-
-/* Keep in line with liststore defined in gtkprintunixdialog.ui */
-enum {
- PRINTER_LIST_COL_ICON,
- PRINTER_LIST_COL_NAME,
- PRINTER_LIST_COL_STATE,
- PRINTER_LIST_COL_JOBS,
- PRINTER_LIST_COL_LOCATION,
- PRINTER_LIST_COL_PRINTER_OBJ,
- PRINTER_LIST_N_COLS
-};
-
-enum {
- PROP_0,
- PROP_PAGE_SETUP,
- PROP_CURRENT_PAGE,
- PROP_PRINT_SETTINGS,
- PROP_SELECTED_PRINTER,
- PROP_MANUAL_CAPABILITIES,
- PROP_SUPPORT_SELECTION,
- PROP_HAS_SELECTION,
- PROP_EMBED_PAGE_SETUP
-};
-
-typedef struct _GtkPrintUnixDialogClass GtkPrintUnixDialogClass;
-
-struct _GtkPrintUnixDialog
-{
- GtkDialog parent_instance;
-
- GtkWidget *notebook;
-
- GtkWidget *printer_list;
-
- GtkPrintCapabilities manual_capabilities;
- GtkPrintCapabilities printer_capabilities;
-
- GtkPageSetup *page_setup;
- gboolean page_setup_set;
- gboolean embed_page_setup;
- GListStore *page_setup_list;
- GListStore *custom_paper_list;
- GListStore *manage_papers_list;
-
- gboolean support_selection;
- gboolean has_selection;
-
- GtkWidget *all_pages_radio;
- GtkWidget *current_page_radio;
- GtkWidget *selection_radio;
- GtkWidget *range_table;
- GtkWidget *page_range_radio;
- GtkWidget *page_range_entry;
-
- GtkWidget *copies_spin;
- GtkWidget *collate_check;
- GtkWidget *reverse_check;
- GtkWidget *collate_image;
- GtkWidget *page_layout_preview;
- GtkWidget *scale_spin;
- GtkWidget *page_set_combo;
- GtkWidget *print_now_radio;
- GtkWidget *print_at_radio;
- GtkWidget *print_at_entry;
- GtkWidget *print_hold_radio;
- GtkWidget *paper_size_combo;
- GtkWidget *orientation_combo;
- gboolean internal_page_setup_change;
- gboolean updating_print_at;
- GtkPrinterOptionWidget *pages_per_sheet;
- GtkPrinterOptionWidget *duplex;
- GtkPrinterOptionWidget *paper_type;
- GtkPrinterOptionWidget *paper_source;
- GtkPrinterOptionWidget *output_tray;
- GtkPrinterOptionWidget *job_prio;
- GtkPrinterOptionWidget *billing_info;
- GtkPrinterOptionWidget *cover_before;
- GtkPrinterOptionWidget *cover_after;
- GtkPrinterOptionWidget *number_up_layout;
-
- GtkWidget *conflicts_widget;
-
- GtkWidget *job_page;
- GtkWidget *finishing_table;
- GtkWidget *finishing_page;
- GtkWidget *image_quality_table;
- GtkWidget *image_quality_page;
- GtkWidget *color_table;
- GtkWidget *color_page;
-
- GtkWidget *advanced_vbox;
- GtkWidget *advanced_page;
-
- GtkWidget *extension_point;
-
- /* These are set initially on selected printer (either default printer,
- * printer taken from set settings, or user-selected), but when any
- * setting is changed by the user it is cleared.
- */
- GtkPrintSettings *initial_settings;
-
- GtkPrinterOption *number_up_layout_n_option;
- GtkPrinterOption *number_up_layout_2_option;
-
- /* This is the initial printer set by set_settings. We look for it in
- * the added printers. We clear this whenever the user manually changes
- * to another printer, when the user changes a setting or when we find
- * this printer.
- */
- char *waiting_for_printer;
- gboolean internal_printer_change;
-
- GList *print_backends;
-
- GtkPrinter *current_printer;
- GtkPrinter *request_details_printer;
- gulong request_details_tag;
- GtkPrinterOptionSet *options;
- gulong options_changed_handler;
- gulong mark_conflicts_id;
-
- char *format_for_printer;
-
- int current_page;
- GtkCssNode *collate_paper_node;
- GtkCssNode *page_layout_paper_node;
-};
-
-struct _GtkPrintUnixDialogClass
-{
- GtkDialogClass parent_class;
-};
-
-G_DEFINE_TYPE_WITH_CODE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
- gtk_print_unix_dialog_buildable_init))
-
-static GtkBuildableIface *parent_buildable_iface;
-
-static gboolean
-is_default_printer (GtkPrintUnixDialog *dialog,
- GtkPrinter *printer)
-{
- if (dialog->format_for_printer)
- return strcmp (dialog->format_for_printer,
- gtk_printer_get_name (printer)) == 0;
- else
- return gtk_printer_is_default (printer);
-}
-
-static void
-gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class)
-{
- GObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- object_class = (GObjectClass *) class;
- widget_class = (GtkWidgetClass *) class;
-
- object_class->constructed = gtk_print_unix_dialog_constructed;
- object_class->finalize = gtk_print_unix_dialog_finalize;
- object_class->dispose = gtk_print_unix_dialog_dispose;
- object_class->set_property = gtk_print_unix_dialog_set_property;
- object_class->get_property = gtk_print_unix_dialog_get_property;
-
- /**
- * GtkPrintUnixDialog:page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_page_setup)
- *
- * The `GtkPageSetup` object to use.
- */
- g_object_class_install_property (object_class,
- PROP_PAGE_SETUP,
- g_param_spec_object ("page-setup", NULL, NULL,
- GTK_TYPE_PAGE_SETUP,
- GTK_PARAM_READWRITE));
-
- /**
- * GtkPrintUnixDialog:current-page: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_current_page org.gtk.Property.set=gtk_print_unix_dialog_set_current_page)
- *
- * The current page in the document.
- */
- g_object_class_install_property (object_class,
- PROP_CURRENT_PAGE,
- g_param_spec_int ("current-page", NULL, NULL,
- -1,
- G_MAXINT,
- -1,
- GTK_PARAM_READWRITE));
-
- /**
- * GtkPrintUnixDialog:print-settings: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_settings org.gtk.Property.set=gtk_print_unix_dialog_set_settings)
- *
- * The `GtkPrintSettings` object used for this dialog.
- */
- g_object_class_install_property (object_class,
- PROP_PRINT_SETTINGS,
- g_param_spec_object ("print-settings", NULL, NULL,
- GTK_TYPE_PRINT_SETTINGS,
- GTK_PARAM_READWRITE));
-
- /**
- * GtkPrintUnixDialog:selected-printer: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_selected_printer)
- *
- * The `GtkPrinter` which is selected.
- */
- g_object_class_install_property (object_class,
- PROP_SELECTED_PRINTER,
- g_param_spec_object ("selected-printer", NULL, NULL,
- GTK_TYPE_PRINTER,
- GTK_PARAM_READABLE));
-
- /**
- * GtkPrintUnixDialog:manual-capabilities: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_manual_capabilities org.gtk.Property.set=gtk_print_unix_dialog_set_manual_capabilities)
- *
- * Capabilities the application can handle.
- */
- g_object_class_install_property (object_class,
- PROP_MANUAL_CAPABILITIES,
- g_param_spec_flags ("manual-capabilities", NULL, NULL,
- GTK_TYPE_PRINT_CAPABILITIES,
- 0,
- GTK_PARAM_READWRITE));
-
- /**
- * GtkPrintUnixDialog:support-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_support_selection org.gtk.Property.set=gtk_print_unix_dialog_set_support_selection)
- *
- * Whether the dialog supports selection.
- */
- g_object_class_install_property (object_class,
- PROP_SUPPORT_SELECTION,
- g_param_spec_boolean ("support-selection", NULL, NULL,
- FALSE,
- GTK_PARAM_READWRITE));
-
- /**
- * GtkPrintUnixDialog:has-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_has_selection org.gtk.Property.set=gtk_print_unix_dialog_set_has_selection)
- *
- * Whether the application has a selection.
- */
- g_object_class_install_property (object_class,
- PROP_HAS_SELECTION,
- g_param_spec_boolean ("has-selection", NULL, NULL,
- FALSE,
- GTK_PARAM_READWRITE));
-
- /**
- * GtkPrintUnixDialog:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_embed_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_embed_page_setup)
- *
- * %TRUE if the page setup controls are embedded.
- */
- g_object_class_install_property (object_class,
- PROP_EMBED_PAGE_SETUP,
- g_param_spec_boolean ("embed-page-setup", NULL, NULL,
- FALSE,
- GTK_PARAM_READWRITE));
-
- /* Bind class to template
- */
- gtk_widget_class_set_template_from_resource (widget_class,
- "/org/gtk/libgtk/ui/gtkprintunixdialog.ui");
-
- /* GtkTreeView / GtkTreeModel */
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, printer_list);
-
- /* General Widgetry */
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, notebook);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, current_page_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, selection_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, range_table);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_entry);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, copies_spin);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_check);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, reverse_check);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_image);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_layout_preview);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, scale_spin);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_set_combo);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_now_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_entry);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_hold_radio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_size_combo);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, orientation_combo);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, conflicts_widget);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_page);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_table);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_page);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_table);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_page);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_table);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_page);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_vbox);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_page);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, extension_point);
-
- /* GtkPrinterOptionWidgets... */
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, pages_per_sheet);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, duplex);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_type);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_source);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, output_tray);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_prio);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, billing_info);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_before);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_after);
- gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, number_up_layout);
-
- /* Callbacks handled in the UI */
- gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
- gtk_widget_class_bind_template_callback (widget_class, error_dialogs);
- gtk_widget_class_bind_template_callback (widget_class, page_range_entry_focus_changed);
- gtk_widget_class_bind_template_callback (widget_class, update_page_range_entry_sensitivity);
- gtk_widget_class_bind_template_callback (widget_class, update_print_at_entry_sensitivity);
- gtk_widget_class_bind_template_callback (widget_class, update_print_at_option);
- gtk_widget_class_bind_template_callback (widget_class, update_dialog_from_capabilities);
- gtk_widget_class_bind_template_callback (widget_class, update_collate_icon);
- gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
- gtk_widget_class_bind_template_callback (widget_class, update_number_up_layout);
- gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
-}
-
-/* Returns a toplevel GtkWindow, or NULL if none */
-static GtkWindow *
-get_toplevel (GtkWidget *widget)
-{
- GtkWidget *toplevel = NULL;
-
- toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
- if (GTK_IS_WINDOW (toplevel))
- return GTK_WINDOW (toplevel);
- else
- return NULL;
-}
-
-static void
-set_busy_cursor (GtkPrintUnixDialog *dialog,
- gboolean busy)
-{
- GtkWidget *widget;
- GtkWindow *toplevel;
-
- toplevel = get_toplevel (GTK_WIDGET (dialog));
- widget = GTK_WIDGET (toplevel);
-
- if (!toplevel || !gtk_widget_get_realized (widget))
- return;
-
- if (busy)
- gtk_widget_set_cursor_from_name (widget, "progress");
- else
- gtk_widget_set_cursor (widget, NULL);
-}
-
-typedef struct {
- GMainLoop *loop;
- int response;
-} ConfirmationData;
-
-static void
-on_confirmation_dialog_response (GtkWidget *dialog,
- int response,
- gpointer user_data)
-{
- ConfirmationData *data = user_data;
-
- data->response = response;
-
- g_main_loop_quit (data->loop);
-
- gtk_window_destroy (GTK_WINDOW (dialog));
-}
-
-/* This function handles error messages before printing.
- */
-static void
-error_dialogs (GtkPrintUnixDialog *dialog,
- int dialog_response_id,
- gpointer data)
-{
- if (dialog != NULL && dialog_response_id == GTK_RESPONSE_OK)
- {
- GtkPrinter *printer = gtk_print_unix_dialog_get_selected_printer (dialog);
-
- if (printer != NULL)
- {
- if (dialog->request_details_tag || !gtk_printer_is_accepting_jobs (printer))
- {
- g_signal_stop_emission_by_name (dialog, "response");
- return;
- }
-
- /* Shows overwrite confirmation dialog in the case of printing
- * to file which already exists.
- */
- if (gtk_printer_is_virtual (printer))
- {
- GtkPrinterOption *option =
- gtk_printer_option_set_lookup (dialog->options,
- "gtk-main-page-custom-input");
-
- if (option != NULL &&
- option->type == GTK_PRINTER_OPTION_TYPE_FILESAVE)
- {
- GFile *file = g_file_new_for_uri (option->value);
-
- if (g_file_query_exists (file, NULL))
- {
- GtkWidget *message_dialog;
- GtkWindow *toplevel;
- char *basename;
- char *dirname;
- GFile *parent;
-
- toplevel = get_toplevel (GTK_WIDGET (dialog));
-
- basename = g_file_get_basename (file);
- parent = g_file_get_parent (file);
- dirname = g_file_get_parse_name (parent);
- g_object_unref (parent);
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- message_dialog = gtk_message_dialog_new (toplevel,
- GTK_DIALOG_MODAL |
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE,
- _("A file named “%s” already exists. Do you want to replace it?"),
- basename);
-
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
- _("The file already exists in “%s”. Replacing it will "
- "overwrite its contents."),
- dirname);
-
- gtk_dialog_add_button (GTK_DIALOG (message_dialog),
- _("_Cancel"),
- GTK_RESPONSE_CANCEL);
- gtk_dialog_add_button (GTK_DIALOG (message_dialog),
- _("_Replace"),
- GTK_RESPONSE_ACCEPT);
- gtk_dialog_set_default_response (GTK_DIALOG (message_dialog),
- GTK_RESPONSE_ACCEPT);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- if (gtk_window_has_group (toplevel))
- gtk_window_group_add_window (gtk_window_get_group (toplevel),
- GTK_WINDOW (message_dialog));
-
- gtk_window_present (GTK_WINDOW (message_dialog));
-
- /* Block on the confirmation dialog until we have a response,
- * so that we can stop the "response" signal emission on the
- * print dialog
- */
- ConfirmationData cdata;
-
- cdata.loop = g_main_loop_new (NULL, FALSE);
- cdata.response = 0;
-
- g_signal_connect (message_dialog, "response",
- G_CALLBACK (on_confirmation_dialog_response),
- &cdata);
-
- g_main_loop_run (cdata.loop);
- g_main_loop_unref (cdata.loop);
-
- g_free (dirname);
- g_free (basename);
-
- if (cdata.response != GTK_RESPONSE_ACCEPT)
- g_signal_stop_emission_by_name (dialog, "response");
- }
-
- g_object_unref (file);
- }
- }
- }
- }
-}
-
-static char *
-get_printer_key (GtkPrinter *printer)
-{
- return g_strconcat ("", gtk_printer_get_name (printer), " ", gtk_printer_get_location (printer), NULL);
-}
-
-static void
-setup_paper_size_item (GtkSignalListItemFactory *factory,
- GtkListItem *item)
-{
- GtkWidget *label;
-
- label = gtk_label_new ("");
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_paper_size_list_item (GtkSignalListItemFactory *factory,
- GtkListItem *item,
- GtkPrintUnixDialog *self)
-{
- GtkPageSetup *page_setup;
- GtkWidget *label;
- guint pos;
- GListModel *papers;
- GListModel *model;
- gpointer first;
-
- page_setup = gtk_list_item_get_item (item);
- label = gtk_list_item_get_child (item);
-
- pos = gtk_list_item_get_position (item);
- papers = gtk_drop_down_get_model (GTK_DROP_DOWN (self->paper_size_combo));
- model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), pos);
- if (model != G_LIST_MODEL (self->manage_papers_list))
- {
- GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
- gtk_label_set_text (GTK_LABEL (label), gtk_paper_size_get_display_name (paper_size));
- }
- else
- gtk_label_set_text (GTK_LABEL (label), _("Manage Custom Sizes…"));
-
- first = g_list_model_get_item (model, 0);
- g_object_unref (first);
- if (pos != 0 &&
- page_setup == GTK_PAGE_SETUP (first))
- gtk_widget_add_css_class (gtk_widget_get_parent (label), "separator");
- else
- gtk_widget_remove_css_class (gtk_widget_get_parent (label), "separator");
-}
-
-static void
-bind_paper_size_item (GtkSignalListItemFactory *factory,
- GtkListItem *item,
- GtkPrintUnixDialog *self)
-{
- GtkWidget *label;
-
- bind_paper_size_list_item (factory, item, self);
-
- label = gtk_list_item_get_child (item);
- gtk_widget_remove_css_class (label, "separator-before");
-}
-
-static void
-gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog)
-{
- GtkWidget *widget;
- GListModel *model;
- GListModel *sorted;
- GListModel *filtered;
- GListModel *selection;
- GtkSorter *sorter;
- GtkFilter *filter;
- GtkStringFilter *filter1;
- GtkCustomFilter *filter2;
- GtkListItemFactory *factory;
- GListStore *store;
- GListModel *paper_size_list;
- GtkPageSetup *page_setup;
-
- dialog->print_backends = NULL;
- dialog->current_page = -1;
- dialog->number_up_layout_n_option = NULL;
- dialog->number_up_layout_2_option = NULL;
-
- dialog->page_setup = gtk_page_setup_new ();
- dialog->page_setup_set = FALSE;
- dialog->embed_page_setup = FALSE;
- dialog->internal_page_setup_change = FALSE;
- dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
- dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
- dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
- page_setup = gtk_page_setup_new ();
- g_list_store_append (dialog->manage_papers_list, page_setup);
- g_object_unref (page_setup);
-
- dialog->support_selection = FALSE;
- dialog->has_selection = FALSE;
-
- g_type_ensure (GTK_TYPE_PRINTER);
- g_type_ensure (GTK_TYPE_PRINTER_OPTION);
- g_type_ensure (GTK_TYPE_PRINTER_OPTION_SET);
- g_type_ensure (GTK_TYPE_PRINTER_OPTION_WIDGET);
-
- gtk_widget_init_template (GTK_WIDGET (dialog));
- gtk_widget_add_css_class (GTK_WIDGET (dialog), "print");
-
- gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
- gtk_dialog_add_buttons (GTK_DIALOG (dialog),
- _("Pre_view"), GTK_RESPONSE_APPLY,
- _("_Cancel"), GTK_RESPONSE_CANCEL,
- _("_Print"), GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
- widget = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
- gtk_widget_set_sensitive (widget, FALSE);
-
- gtk_widget_set_visible (dialog->selection_radio, FALSE);
- gtk_widget_set_visible (dialog->conflicts_widget, FALSE);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
- gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
- g_object_unref (factory);
-
- factory = gtk_signal_list_item_factory_new ();
- g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
- g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
- gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
- g_object_unref (factory);
-
- store = g_list_store_new (G_TYPE_LIST_MODEL);
- g_list_store_append (store, dialog->page_setup_list);
- g_list_store_append (store, dialog->custom_paper_list);
- g_list_store_append (store, dialog->manage_papers_list);
- paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
- gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
- g_object_unref (paper_size_list);
-
- /* Load backends */
- model = load_print_backends (dialog);
- sorter = GTK_SORTER (gtk_custom_sorter_new (default_printer_list_sort_func, NULL, NULL));
- sorted = G_LIST_MODEL (gtk_sort_list_model_new (model, sorter));
-
- filter = GTK_FILTER (gtk_every_filter_new ());
-
- filter1 = gtk_string_filter_new (
- gtk_cclosure_expression_new (G_TYPE_STRING,
- NULL, 0, NULL,
- G_CALLBACK (get_printer_key),
- NULL, NULL));
- gtk_string_filter_set_match_mode (filter1, GTK_STRING_FILTER_MATCH_MODE_SUBSTRING);
- gtk_string_filter_set_ignore_case (filter1, TRUE);
- gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter1));
-
- filter2 = gtk_custom_filter_new (is_printer_active, dialog, NULL);
- gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter2));
-
- filtered = G_LIST_MODEL (gtk_filter_list_model_new (sorted, filter));
-
- selection = G_LIST_MODEL (gtk_single_selection_new (filtered));
- gtk_single_selection_set_autoselect (GTK_SINGLE_SELECTION (selection), FALSE);
- gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (selection), GTK_INVALID_LIST_POSITION);
- gtk_column_view_set_model (GTK_COLUMN_VIEW (dialog->printer_list), GTK_SELECTION_MODEL (selection));
- g_signal_connect (selection, "items-changed", G_CALLBACK (printer_added_cb), dialog);
- g_signal_connect_swapped (selection, "notify::selected", G_CALLBACK (selected_printer_changed), dialog);
- g_object_unref (selection);
-
- gtk_print_load_custom_papers (dialog->custom_paper_list);
-
- gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->collate_image),
- draw_collate,
- dialog, NULL);
- gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->page_layout_preview),
- draw_page,
- dialog, NULL);
-
- gtk_css_node_set_name (gtk_widget_get_css_node (dialog->collate_image), g_quark_from_static_string ("drawing"));
- gtk_css_node_set_name (gtk_widget_get_css_node (dialog->page_layout_preview), g_quark_from_static_string ("drawing"));
-
- dialog->collate_paper_node = gtk_css_node_new();
- gtk_css_node_set_name (dialog->collate_paper_node, g_quark_from_static_string ("paper"));
- gtk_css_node_set_parent (dialog->collate_paper_node,
- gtk_widget_get_css_node (dialog->collate_image));
- g_object_unref (dialog->collate_paper_node);
-
- dialog->page_layout_paper_node = gtk_css_node_new();
- gtk_css_node_set_name (dialog->page_layout_paper_node, g_quark_from_static_string ("paper"));
- gtk_css_node_set_parent (dialog->page_layout_paper_node,
- gtk_widget_get_css_node (dialog->page_layout_preview));
- g_object_unref (dialog->page_layout_paper_node);
-}
-
-static void
-gtk_print_unix_dialog_constructed (GObject *object)
-{
- gboolean use_header;
-
- G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->constructed (object);
-
- g_object_get (object, "use-header-bar", &use_header, NULL);
- if (use_header)
- {
- /* Reorder the preview button */
- GtkWidget *button, *parent;
- button = gtk_dialog_get_widget_for_response (GTK_DIALOG (object), GTK_RESPONSE_APPLY);
- g_object_ref (button);
- parent = gtk_widget_get_ancestor (button, GTK_TYPE_HEADER_BAR);
- gtk_box_remove (GTK_BOX (gtk_widget_get_parent (button)), button);
- gtk_header_bar_pack_end (GTK_HEADER_BAR (parent), button);
- g_object_unref (button);
- }
-
- update_dialog_from_capabilities (GTK_PRINT_UNIX_DIALOG (object));
-}
-
-static void
-gtk_print_unix_dialog_dispose (GObject *object)
-{
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
-
- /* Make sure we don't destroy custom widgets owned by the backends */
- clear_per_printer_ui (dialog);
-
- G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->dispose (object);
-}
-
-static void
-disconnect_printer_details_request (GtkPrintUnixDialog *dialog,
- gboolean details_failed)
-{
- if (dialog->request_details_tag)
- {
- g_signal_handler_disconnect (dialog->request_details_printer,
- dialog->request_details_tag);
- dialog->request_details_tag = 0;
- set_busy_cursor (dialog, FALSE);
- if (details_failed)
- gtk_printer_set_state_message (dialog->request_details_printer, _("Getting printer information failed"));
- g_clear_object (&dialog->request_details_printer);
- }
-}
-
-static void
-gtk_print_unix_dialog_finalize (GObject *object)
-{
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
- GList *iter;
-
- unschedule_idle_mark_conflicts (dialog);
- disconnect_printer_details_request (dialog, FALSE);
-
- g_clear_object (&dialog->current_printer);
- g_clear_object (&dialog->options);
-
- if (dialog->number_up_layout_2_option)
- {
- dialog->number_up_layout_2_option->choices[0] = NULL;
- dialog->number_up_layout_2_option->choices[1] = NULL;
- g_free (dialog->number_up_layout_2_option->choices_display[0]);
- g_free (dialog->number_up_layout_2_option->choices_display[1]);
- dialog->number_up_layout_2_option->choices_display[0] = NULL;
- dialog->number_up_layout_2_option->choices_display[1] = NULL;
- g_object_unref (dialog->number_up_layout_2_option);
- dialog->number_up_layout_2_option = NULL;
- }
-
- g_clear_object (&dialog->number_up_layout_n_option);
- g_clear_object (&dialog->page_setup);
- g_clear_object (&dialog->initial_settings);
- g_clear_pointer (&dialog->waiting_for_printer, (GDestroyNotify)g_free);
- g_clear_pointer (&dialog->format_for_printer, (GDestroyNotify)g_free);
-
- for (iter = dialog->print_backends; iter != NULL; iter = iter->next)
- gtk_print_backend_destroy (GTK_PRINT_BACKEND (iter->data));
- g_list_free_full (dialog->print_backends, g_object_unref);
- dialog->print_backends = NULL;
-
- g_clear_object (&dialog->page_setup_list);
- g_clear_object (&dialog->custom_paper_list);
- g_clear_object (&dialog->manage_papers_list);
-
- G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
-}
-
-static void
-gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface)
-{
- parent_buildable_iface = g_type_interface_peek_parent (iface);
-
- iface->get_internal_child = gtk_print_unix_dialog_buildable_get_internal_child;
-}
-
-static GObject *
-gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
- GtkBuilder *builder,
- const char *childname)
-{
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (buildable);
-
- if (strcmp (childname, "notebook") == 0)
- return G_OBJECT (dialog->notebook);
-
- return parent_buildable_iface->get_internal_child (buildable, builder, childname);
-}
-
-static void
-printer_status_cb (GtkPrintBackend *backend,
- GtkPrinter *printer,
- GtkPrintUnixDialog *dialog)
-{
- GListModel *model;
-
- /* When the pause state change then we need to update sensitive property
- * of GTK_RESPONSE_OK button inside of selected_printer_changed function.
- */
- selected_printer_changed (dialog);
-
- model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
-
- if (gtk_print_backend_printer_list_is_done (backend) &&
- gtk_printer_is_default (printer) &&
- gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
- set_active_printer (dialog, gtk_printer_get_name (printer));
-}
-
-static void
-printer_added_cb (GListModel *model,
- guint position,
- guint removed,
- guint added,
- GtkPrintUnixDialog *dialog)
-{
- guint i;
-
- for (i = position; i < position + added; i++)
- {
- GtkPrinter *printer = g_list_model_get_item (model, i);
-
- if (dialog->waiting_for_printer != NULL &&
- strcmp (gtk_printer_get_name (printer), dialog->waiting_for_printer) == 0)
- {
- gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
- g_free (dialog->waiting_for_printer);
- dialog->waiting_for_printer = NULL;
- g_object_unref (printer);
- return;
- }
- else if (is_default_printer (dialog, printer) &&
- gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
- {
- gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
- g_object_unref (printer);
- return;
- }
-
- g_object_unref (printer);
- }
-}
-
-static GListModel *
-load_print_backends (GtkPrintUnixDialog *dialog)
-{
- GList *node;
- GListStore *lists;
-
- lists = g_list_store_new (G_TYPE_LIST_MODEL);
-
- if (g_module_supported ())
- dialog->print_backends = gtk_print_backend_load_modules ();
-
- for (node = dialog->print_backends; node != NULL; node = node->next)
- {
- GtkPrintBackend *backend = node->data;
-
- g_signal_connect_object (backend, "printer-status-changed",
- G_CALLBACK (printer_status_cb), G_OBJECT (dialog), 0);
- g_list_store_append (lists, gtk_print_backend_get_printers (backend));
- }
-
- return G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (lists)));
-}
-
-static void
-gtk_print_unix_dialog_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-
-{
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
-
- switch (prop_id)
- {
- case PROP_PAGE_SETUP:
- gtk_print_unix_dialog_set_page_setup (dialog, g_value_get_object (value));
- break;
- case PROP_CURRENT_PAGE:
- gtk_print_unix_dialog_set_current_page (dialog, g_value_get_int (value));
- break;
- case PROP_PRINT_SETTINGS:
- gtk_print_unix_dialog_set_settings (dialog, g_value_get_object (value));
- break;
- case PROP_MANUAL_CAPABILITIES:
- gtk_print_unix_dialog_set_manual_capabilities (dialog, g_value_get_flags (value));
- break;
- case PROP_SUPPORT_SELECTION:
- gtk_print_unix_dialog_set_support_selection (dialog, g_value_get_boolean (value));
- break;
- case PROP_HAS_SELECTION:
- gtk_print_unix_dialog_set_has_selection (dialog, g_value_get_boolean (value));
- break;
- case PROP_EMBED_PAGE_SETUP:
- gtk_print_unix_dialog_set_embed_page_setup (dialog, g_value_get_boolean (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_print_unix_dialog_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
-
- switch (prop_id)
- {
- case PROP_PAGE_SETUP:
- g_value_set_object (value, dialog->page_setup);
- break;
- case PROP_CURRENT_PAGE:
- g_value_set_int (value, dialog->current_page);
- break;
- case PROP_PRINT_SETTINGS:
- g_value_take_object (value, gtk_print_unix_dialog_get_settings (dialog));
- break;
- case PROP_SELECTED_PRINTER:
- g_value_set_object (value, dialog->current_printer);
- break;
- case PROP_MANUAL_CAPABILITIES:
- g_value_set_flags (value, dialog->manual_capabilities);
- break;
- case PROP_SUPPORT_SELECTION:
- g_value_set_boolean (value, dialog->support_selection);
- break;
- case PROP_HAS_SELECTION:
- g_value_set_boolean (value, dialog->has_selection);
- break;
- case PROP_EMBED_PAGE_SETUP:
- g_value_set_boolean (value, dialog->embed_page_setup);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-is_printer_active (gpointer item, gpointer data)
-{
- GtkPrinter *printer = item;
- GtkPrintUnixDialog *dialog = data;
- gboolean result;
-
- result = gtk_printer_is_active (printer);
-
- if (result &&
- dialog->manual_capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF |
- GTK_PRINT_CAPABILITY_GENERATE_PS))
- {
- /* Check that the printer can handle at least one of the data
- * formats that the application supports.
- */
- result = ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF) &&
- gtk_printer_accepts_pdf (printer)) ||
- ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS) &&
- gtk_printer_accepts_ps (printer));
- }
-
- return result;
-}
-
-static int
-default_printer_list_sort_func (gconstpointer a,
- gconstpointer b,
- gpointer user_data)
-{
- GtkPrinter *a_printer = (gpointer)a;
- GtkPrinter *b_printer = (gpointer)b;
- const char *a_name;
- const char *b_name;
-
- if (a_printer == NULL && b_printer == NULL)
- return 0;
- else if (a_printer == NULL)
- return 1;
- else if (b_printer == NULL)
- return -1;
-
- if (gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
- return 0;
- else if (gtk_printer_is_virtual (a_printer) && !gtk_printer_is_virtual (b_printer))
- return -1;
- else if (!gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
- return 1;
-
- a_name = gtk_printer_get_name (a_printer);
- b_name = gtk_printer_get_name (b_printer);
-
- if (a_name == NULL && b_name == NULL)
- return 0;
- else if (a_name == NULL && b_name != NULL)
- return 1;
- else if (a_name != NULL && b_name == NULL)
- return -1;
-
- return g_ascii_strcasecmp (a_name, b_name);
-}
-
-static GtkWidget *
-wrap_in_frame (const char *label,
- GtkWidget *child)
-{
- GtkWidget *box, *label_widget;
- char *bold_text;
-
- label_widget = gtk_label_new (NULL);
- gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
- gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
-
- bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
- gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
- g_free (bold_text);
-
- box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
- gtk_box_append (GTK_BOX (box), label_widget);
-
- gtk_widget_set_margin_start (child, 12);
- gtk_widget_set_halign (child, GTK_ALIGN_FILL);
- gtk_widget_set_valign (child, GTK_ALIGN_FILL);
-
- gtk_box_append (GTK_BOX (box), child);
-
- return box;
-}
-
-static gboolean
-setup_option (GtkPrintUnixDialog *dialog,
- const char *option_name,
- GtkPrinterOptionWidget *widget)
-{
- GtkPrinterOption *option;
-
- option = gtk_printer_option_set_lookup (dialog->options, option_name);
- gtk_printer_option_widget_set_source (widget, option);
-
- return option != NULL;
-}
-
-static void
-add_option_to_extension_point (GtkPrinterOption *option,
- gpointer data)
-{
- GtkWidget *extension_point = data;
- GtkWidget *widget;
-
- widget = gtk_printer_option_widget_new (option);
-
- if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
- {
- GtkWidget *label, *hbox;
-
- gtk_widget_set_valign (widget, GTK_ALIGN_BASELINE_FILL);
-
- label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
- gtk_widget_set_visible (label, TRUE);
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
-
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
- gtk_widget_set_valign (hbox, GTK_ALIGN_BASELINE_FILL);
- gtk_box_append (GTK_BOX (hbox), label);
- gtk_box_append (GTK_BOX (hbox), widget);
-
- gtk_box_append (GTK_BOX (extension_point), hbox);
- }
- else
- gtk_box_append (GTK_BOX (extension_point), widget);
-}
-
-static int
-grid_rows (GtkGrid *table)
-{
- int t0, t1, l, t, w, h;
- GtkWidget *c;
- gboolean first;
-
- t0 = t1 = 0;
- for (c = gtk_widget_get_first_child (GTK_WIDGET (table)), first = TRUE;
- c != NULL;
- c = gtk_widget_get_next_sibling (GTK_WIDGET (c)), first = FALSE)
- {
- gtk_grid_query_child (table, c, &l, &t, &w, &h);
- if (first)
- {
- t0 = t;
- t1 = t + h;
- }
- else
- {
- if (t < t0)
- t0 = t;
- if (t + h > t1)
- t1 = t + h;
- }
- }
-
- return t1 - t0;
-}
-
-static void
-add_option_to_table (GtkPrinterOption *option,
- gpointer user_data)
-{
- GtkGrid *table;
- GtkWidget *label, *widget;
- guint row;
-
- table = GTK_GRID (user_data);
-
- if (g_str_has_prefix (option->name, "gtk-"))
- return;
-
- row = grid_rows (table);
-
- widget = gtk_printer_option_widget_new (option);
-
- if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
- {
- label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
- gtk_widget_set_visible (label, TRUE);
-
- gtk_widget_set_halign (label, GTK_ALIGN_START);
- gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
-
- gtk_grid_attach (table, label, 0, row - 1, 1, 1);
- gtk_grid_attach (table, widget, 1, row - 1, 1, 1);
- }
- else
- gtk_grid_attach (table, widget, 0, row - 1, 2, 1);
-}
-
-static void
-setup_page_table (GtkPrinterOptionSet *options,
- const char *group,
- GtkWidget *table,
- GtkWidget *page)
-{
- int nrows;
-
- gtk_printer_option_set_foreach_in_group (options, group,
- add_option_to_table,
- table);
-
- nrows = grid_rows (GTK_GRID (table));
- gtk_widget_set_visible (page, nrows > 0);
-}
-
-static void
-update_print_at_option (GtkPrintUnixDialog *dialog)
-{
- GtkPrinterOption *option;
-
- option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
-
- if (option == NULL)
- return;
-
- if (dialog->updating_print_at)
- return;
-
- if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_at_radio)))
- gtk_printer_option_set (option, "at");
- else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_hold_radio)))
- gtk_printer_option_set (option, "on-hold");
- else
- gtk_printer_option_set (option, "now");
-
- option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
- if (option != NULL)
- {
- const char *text;
-
- text = gtk_editable_get_text (GTK_EDITABLE (dialog->print_at_entry));
- gtk_printer_option_set (option, text);
- }
-}
-
-
-static gboolean
-setup_print_at (GtkPrintUnixDialog *dialog)
-{
- GtkPrinterOption *option;
-
- option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
-
- if (option == NULL)
- {
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
- gtk_widget_set_sensitive (dialog->print_at_radio, FALSE);
- gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
- gtk_widget_set_sensitive (dialog->print_hold_radio, FALSE);
- gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), "");
- return FALSE;
- }
-
- dialog->updating_print_at = TRUE;
-
- gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
- gtk_widget_set_sensitive (dialog->print_at_radio,
- gtk_printer_option_has_choice (option, "at"));
-
- gtk_widget_set_sensitive (dialog->print_hold_radio,
- gtk_printer_option_has_choice (option, "on-hold"));
-
- update_print_at_option (dialog);
-
- if (strcmp (option->value, "at") == 0)
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_at_radio), TRUE);
- else if (strcmp (option->value, "on-hold") == 0)
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_hold_radio), TRUE);
- else
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
-
- option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
- if (option != NULL)
- gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), option->value);
-
- dialog->updating_print_at = FALSE;
-
- return TRUE;
-}
-
-static void
-update_dialog_from_settings (GtkPrintUnixDialog *dialog)
-{
- GList *groups, *l;
- char *group;
- GtkWidget *table, *frame;
- gboolean has_advanced, has_job;
- guint nrows;
- GtkWidget *child;
-
- if (dialog->current_printer == NULL)
- {
- clear_per_printer_ui (dialog);
- gtk_widget_set_visible (dialog->job_page, FALSE);
- gtk_widget_set_visible (dialog->advanced_page, FALSE);
- gtk_widget_set_visible (dialog->image_quality_page, FALSE);
- gtk_widget_set_visible (dialog->finishing_page, FALSE);
- gtk_widget_set_visible (dialog->color_page, FALSE);
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
-
- return;
- }
-
- setup_option (dialog, "gtk-n-up", dialog->pages_per_sheet);
- setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
- setup_option (dialog, "gtk-duplex", dialog->duplex);
- setup_option (dialog, "gtk-paper-type", dialog->paper_type);
- setup_option (dialog, "gtk-paper-source", dialog->paper_source);
- setup_option (dialog, "gtk-output-tray", dialog->output_tray);
-
- has_job = FALSE;
- has_job |= setup_option (dialog, "gtk-job-prio", dialog->job_prio);
- has_job |= setup_option (dialog, "gtk-billing-info", dialog->billing_info);
- has_job |= setup_option (dialog, "gtk-cover-before", dialog->cover_before);
- has_job |= setup_option (dialog, "gtk-cover-after", dialog->cover_after);
- has_job |= setup_print_at (dialog);
-
- gtk_widget_set_visible (dialog->job_page, has_job);
-
- setup_page_table (dialog->options,
- "ImageQualityPage",
- dialog->image_quality_table,
- dialog->image_quality_page);
-
- setup_page_table (dialog->options,
- "FinishingPage",
- dialog->finishing_table,
- dialog->finishing_page);
-
- setup_page_table (dialog->options,
- "ColorPage",
- dialog->color_table,
- dialog->color_page);
-
- gtk_printer_option_set_foreach_in_group (dialog->options,
- "GtkPrintDialogExtension",
- add_option_to_extension_point,
- dialog->extension_point);
-
- /* A bit of a hack, keep the last option flush right.
- * This keeps the file format radios from moving as the
- * filename changes.
- */
- child = gtk_widget_get_last_child (dialog->extension_point);
- if (child && child != gtk_widget_get_first_child (dialog->extension_point))
- gtk_widget_set_halign (child, GTK_ALIGN_END);
-
- /* Put the rest of the groups in the advanced page */
- groups = gtk_printer_option_set_get_groups (dialog->options);
-
- has_advanced = FALSE;
- for (l = groups; l != NULL; l = l->next)
- {
- group = l->data;
-
- if (group == NULL)
- continue;
-
- if (strcmp (group, "ImageQualityPage") == 0 ||
- strcmp (group, "ColorPage") == 0 ||
- strcmp (group, "FinishingPage") == 0 ||
- strcmp (group, "GtkPrintDialogExtension") == 0)
- continue;
-
- table = gtk_grid_new ();
- gtk_grid_set_row_spacing (GTK_GRID (table), 6);
- gtk_grid_set_column_spacing (GTK_GRID (table), 12);
-
- gtk_printer_option_set_foreach_in_group (dialog->options,
- group,
- add_option_to_table,
- table);
-
- nrows = grid_rows (GTK_GRID (table));
- if (nrows == 0)
- {
- g_object_unref (g_object_ref_sink (table));
- }
- else
- {
- has_advanced = TRUE;
- frame = wrap_in_frame (group, table);
- gtk_box_append (GTK_BOX (dialog->advanced_vbox), frame);
- }
- }
-
- gtk_widget_set_visible (dialog->advanced_page, has_advanced);
-
- g_list_free_full (groups, g_free);
-}
-
-static void
-update_dialog_from_capabilities (GtkPrintUnixDialog *dialog)
-{
- GtkPrintCapabilities caps;
- gboolean can_collate;
- const char *copies;
- GtkWidget *button;
-
- copies = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
- can_collate = (*copies != '\0' && atoi (copies) > 1);
-
- caps = dialog->manual_capabilities | dialog->printer_capabilities;
-
- gtk_widget_set_sensitive (dialog->page_set_combo,
- caps & GTK_PRINT_CAPABILITY_PAGE_SET);
- gtk_widget_set_sensitive (dialog->copies_spin,
- caps & GTK_PRINT_CAPABILITY_COPIES);
- gtk_widget_set_sensitive (dialog->collate_check,
- can_collate &&
- (caps & GTK_PRINT_CAPABILITY_COLLATE));
- gtk_widget_set_sensitive (dialog->reverse_check,
- caps & GTK_PRINT_CAPABILITY_REVERSE);
- gtk_widget_set_sensitive (dialog->scale_spin,
- caps & GTK_PRINT_CAPABILITY_SCALE);
- gtk_widget_set_sensitive (GTK_WIDGET (dialog->pages_per_sheet),
- caps & GTK_PRINT_CAPABILITY_NUMBER_UP);
-
- button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
- gtk_widget_set_visible (button, (caps & GTK_PRINT_CAPABILITY_PREVIEW) != 0);
-
- update_collate_icon (NULL, dialog);
-}
-
-static gboolean
-page_setup_is_equal (GtkPageSetup *a,
- GtkPageSetup *b)
-{
- return
- gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
- gtk_page_setup_get_paper_size (b)) &&
- gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
- gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
- gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
- gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
-}
-
-static gboolean
-page_setup_is_same_size (GtkPageSetup *a,
- GtkPageSetup *b)
-{
- return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
- gtk_page_setup_get_paper_size (b));
-}
-
-static gboolean
-set_paper_size (GtkPrintUnixDialog *dialog,
- GtkPageSetup *page_setup,
- gboolean size_only,
- gboolean add_item)
-{
- GListModel *model;
- GtkPageSetup *list_page_setup;
- guint i;
-
- if (!dialog->internal_page_setup_change)
- return TRUE;
-
- if (page_setup == NULL)
- return FALSE;
-
- model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
- for (i = 0; i < g_list_model_get_n_items (model); i++)
- {
- list_page_setup = g_list_model_get_item (model, i);
- if (list_page_setup == NULL)
- continue;
-
- if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
- (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
- {
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
- gtk_page_setup_get_orientation (page_setup));
- g_object_unref (list_page_setup);
- return TRUE;
- }
-
- g_object_unref (list_page_setup);
- }
-
- if (add_item)
- {
- i = g_list_model_get_n_items (model);
- g_list_store_append (dialog->page_setup_list, page_setup);
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
- gtk_page_setup_get_orientation (page_setup));
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-fill_custom_paper_sizes (GtkPrintUnixDialog *dialog)
-{
- g_list_store_remove_all (dialog->custom_paper_list);
- gtk_print_load_custom_papers (dialog->custom_paper_list);
-}
-
-static void
-fill_paper_sizes (GtkPrintUnixDialog *dialog,
- GtkPrinter *printer)
-{
- GList *list, *l;
- GtkPageSetup *page_setup;
- GtkPaperSize *paper_size;
- int i;
-
- g_list_store_remove_all (dialog->page_setup_list);
-
- if (printer == NULL || (list = gtk_printer_list_papers (printer)) == NULL)
- {
- for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
- {
- page_setup = gtk_page_setup_new ();
- paper_size = gtk_paper_size_new (common_paper_sizes[i]);
- gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
- gtk_paper_size_free (paper_size);
- g_list_store_append (dialog->page_setup_list, page_setup);
- g_object_unref (page_setup);
- }
- }
- else
- {
- for (l = list; l != NULL; l = l->next)
- {
- page_setup = l->data;
- g_list_store_append (dialog->page_setup_list, page_setup);
- g_object_unref (page_setup);
- }
- g_list_free (list);
- }
-}
-
-static void
-update_paper_sizes (GtkPrintUnixDialog *dialog)
-{
- GtkPageSetup *current_page_setup = NULL;
- GtkPrinter *printer;
-
- printer = gtk_print_unix_dialog_get_selected_printer (dialog);
-
- fill_paper_sizes (dialog, printer);
- fill_custom_paper_sizes (dialog);
-
- current_page_setup = gtk_page_setup_copy (gtk_print_unix_dialog_get_page_setup (dialog));
-
- if (current_page_setup)
- {
- if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
- set_paper_size (dialog, current_page_setup, TRUE, TRUE);
-
- g_object_unref (current_page_setup);
- }
-}
-
-static void
-mark_conflicts (GtkPrintUnixDialog *dialog)
-{
- GtkPrinter *printer;
- gboolean have_conflict;
-
- have_conflict = FALSE;
-
- printer = dialog->current_printer;
-
- if (printer)
- {
- g_signal_handler_block (dialog->options, dialog->options_changed_handler);
-
- gtk_printer_option_set_clear_conflicts (dialog->options);
- have_conflict = _gtk_printer_mark_conflicts (printer, dialog->options);
-
- g_signal_handler_unblock (dialog->options, dialog->options_changed_handler);
- }
-
- gtk_widget_set_visible (dialog->conflicts_widget, have_conflict);
-}
-
-static gboolean
-mark_conflicts_callback (gpointer data)
-{
- GtkPrintUnixDialog *dialog = data;
-
- dialog->mark_conflicts_id = 0;
-
- mark_conflicts (dialog);
-
- return FALSE;
-}
-
-static void
-unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
-{
- if (dialog->mark_conflicts_id != 0)
- {
- g_source_remove (dialog->mark_conflicts_id);
- dialog->mark_conflicts_id = 0;
- }
-}
-
-static void
-schedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
-{
- if (dialog->mark_conflicts_id != 0)
- return;
-
- dialog->mark_conflicts_id = g_idle_add (mark_conflicts_callback, dialog);
- gdk_source_set_static_name_by_id (dialog->mark_conflicts_id, "[gtk] mark_conflicts_callback");
-}
-
-static void
-options_changed_cb (GtkPrintUnixDialog *dialog)
-{
- schedule_idle_mark_conflicts (dialog);
-
- g_free (dialog->waiting_for_printer);
- dialog->waiting_for_printer = NULL;
-}
-
-static void
-clear_per_printer_ui (GtkPrintUnixDialog *dialog)
-{
- GtkWidget *child;
-
- if (dialog->finishing_table == NULL)
- return;
-
- while ((child = gtk_widget_get_first_child (dialog->finishing_table)))
- gtk_grid_remove (GTK_GRID (dialog->finishing_table), child);
- while ((child = gtk_widget_get_first_child (dialog->image_quality_table)))
- gtk_grid_remove (GTK_GRID (dialog->image_quality_table), child);
- while ((child = gtk_widget_get_first_child (dialog->color_table)))
- gtk_grid_remove (GTK_GRID (dialog->color_table), child);
- while ((child = gtk_widget_get_first_child (dialog->advanced_vbox)))
- gtk_box_remove (GTK_BOX (dialog->advanced_vbox), child);
- while ((child = gtk_widget_get_first_child (dialog->extension_point)))
- gtk_box_remove (GTK_BOX (dialog->extension_point), child);
-}
-
-static void
-printer_details_acquired (GtkPrinter *printer,
- gboolean success,
- GtkPrintUnixDialog *dialog)
-{
- disconnect_printer_details_request (dialog, !success);
-
- if (success)
- selected_printer_changed (dialog);
-}
-
-static void
-selected_printer_changed (GtkPrintUnixDialog *dialog)
-{
- GListModel *model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
- GtkPrinter *printer;
-
- /* Whenever the user selects a printer we stop looking for
- * the printer specified in the initial settings
- */
- if (dialog->waiting_for_printer &&
- !dialog->internal_printer_change)
- {
- g_free (dialog->waiting_for_printer);
- dialog->waiting_for_printer = NULL;
- }
-
- disconnect_printer_details_request (dialog, FALSE);
-
- printer = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
-
- /* sets GTK_RESPONSE_OK button sensitivity depending on whether the printer
- * accepts/rejects jobs
- */
- if (printer != NULL)
- {
- if (!gtk_printer_is_accepting_jobs (printer))
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
- else if (dialog->current_printer == printer && gtk_printer_has_details (printer))
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
- }
-
- if (printer != NULL && !gtk_printer_has_details (printer))
- {
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
- dialog->request_details_tag = g_signal_connect (printer, "details-acquired",
- G_CALLBACK (printer_details_acquired), dialog);
-
- dialog->request_details_printer = g_object_ref (printer);
- set_busy_cursor (dialog, TRUE);
- gtk_printer_set_state_message (printer, _("Getting printer information…"));
- gtk_printer_request_details (printer);
- return;
- }
-
- if (printer == dialog->current_printer)
- return;
-
- if (dialog->options)
- {
- g_clear_object (&dialog->options);
- clear_per_printer_ui (dialog);
- }
-
- g_clear_object (&dialog->current_printer);
- dialog->printer_capabilities = 0;
-
- if (printer != NULL && gtk_printer_is_accepting_jobs (printer))
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
- dialog->current_printer = g_object_ref (printer);
-
- if (printer != NULL)
- {
- if (!dialog->page_setup_set)
- {
- /* if no explicit page setup has been set, use the printer default */
- GtkPageSetup *page_setup;
-
- page_setup = gtk_printer_get_default_page_size (printer);
-
- if (!page_setup)
- page_setup = gtk_page_setup_new ();
-
- if (page_setup && dialog->page_setup)
- gtk_page_setup_set_orientation (page_setup, gtk_page_setup_get_orientation (dialog->page_setup));
-
- g_clear_object (&dialog->page_setup);
- dialog->page_setup = page_setup; /* transfer ownership */
- }
-
- dialog->printer_capabilities = gtk_printer_get_capabilities (printer);
- dialog->options = _gtk_printer_get_options (printer,
- dialog->initial_settings,
- dialog->page_setup,
- dialog->manual_capabilities);
-
- dialog->options_changed_handler =
- g_signal_connect_swapped (dialog->options, "changed", G_CALLBACK (options_changed_cb), dialog);
- schedule_idle_mark_conflicts (dialog);
- }
-
- update_dialog_from_settings (dialog);
- update_dialog_from_capabilities (dialog);
-
- dialog->internal_page_setup_change = TRUE;
- update_paper_sizes (dialog);
- dialog->internal_page_setup_change = FALSE;
-
- g_object_notify (G_OBJECT (dialog), "selected-printer");
-}
-
-static void
-update_collate_icon (GtkToggleButton *toggle_button,
- GtkPrintUnixDialog *dialog)
-{
- gtk_widget_queue_draw (dialog->collate_image);
-}
-
-static void
-paint_page (GtkPrintUnixDialog *dialog,
- GtkWidget *widget,
- cairo_t *cr,
- int x,
- int y,
- const char *text,
- int text_x)
-{
- GtkCssStyle *style;
- int width, height;
- int text_y;
- GdkRGBA color;
- GtkSnapshot *snapshot;
- GskRenderNode *node;
- GtkCssBoxes boxes;
-
- width = 20;
- height = 26;
- text_y = 21;
-
- style = gtk_css_node_get_style (dialog->collate_paper_node);
-
- snapshot = gtk_snapshot_new ();
- gtk_css_boxes_init_border_box (&boxes, style, x, y, width, height);
- gtk_css_style_snapshot_background (&boxes, snapshot);
- gtk_css_style_snapshot_border (&boxes, snapshot);
-
- node = gtk_snapshot_free_to_node (snapshot);
- if (node)
- {
- gsk_render_node_draw (node, cr);
- gsk_render_node_unref (node);
- }
-
- color = *gtk_css_color_value_get_rgba (style->core->color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- cairo_select_font_face (cr, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
- cairo_set_font_size (cr, 9);
- cairo_move_to (cr, x + text_x, y + text_y);
- cairo_show_text (cr, text);
-}
-
-static void
-draw_collate (GtkDrawingArea *da,
- cairo_t *cr,
- int width,
- int height,
- gpointer data)
-{
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
- GtkWidget *widget = GTK_WIDGET (da);
- gboolean collate, reverse, rtl;
- int copies;
- int text_x;
- int x, y, x1, x2, p1, p2;
-
- collate = dialog_get_collate (dialog);
- reverse = dialog_get_reverse (dialog);
- copies = dialog_get_n_copies (dialog);
-
- rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
-
- x = (width - 30) / 2;
- y = (height - 36) / 2;
- if (rtl)
- {
- x1 = x;
- x2 = x - 36;
- p1 = 0;
- p2 = 10;
- text_x = 4;
- }
- else
- {
- x1 = x;
- x2 = x + 36;
- p1 = 10;
- p2 = 0;
- text_x = 11;
- }
-
- if (copies == 1)
- {
- paint_page (dialog, widget, cr, x1 + p1, y, reverse ? "1" : "2", text_x);
- paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
- }
- else
- {
- paint_page (dialog, widget, cr, x1 + p1, y, collate == reverse ? "1" : "2", text_x);
- paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
-
- paint_page (dialog, widget, cr, x2 + p1, y, reverse ? "1" : "2", text_x);
- paint_page (dialog, widget, cr, x2 + p2, y + 10, collate == reverse ? "2" : "1", text_x);
- }
-}
-
-static gboolean
-page_range_entry_focus_changed (GtkWidget *entry,
- GParamSpec *pspec,
- GtkPrintUnixDialog *dialog)
-{
- if (gtk_widget_has_focus (entry))
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
-
- return FALSE;
-}
-
-static void
-update_page_range_entry_sensitivity (GtkWidget *button,
- GtkPrintUnixDialog *dialog)
-{
- gboolean active;
-
- active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
-
- if (active)
- gtk_widget_grab_focus (dialog->page_range_entry);
-}
-
-static void
-update_print_at_entry_sensitivity (GtkWidget *button,
- GtkPrintUnixDialog *dialog)
-{
- gboolean active;
-
- active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
-
- gtk_widget_set_sensitive (dialog->print_at_entry, active);
-
- if (active)
- gtk_widget_grab_focus (dialog->print_at_entry);
-}
-
-static gboolean
-is_range_separator (char c)
-{
- return (c == ',' || c == ';' || c == ':');
-}
-
-static GtkPageRange *
-dialog_get_page_ranges (GtkPrintUnixDialog *dialog,
- int *n_ranges_out)
-{
- int i, n_ranges;
- const char *text, *p;
- char *next;
- GtkPageRange *ranges;
- int start, end;
-
- text = gtk_editable_get_text (GTK_EDITABLE (dialog->page_range_entry));
-
- if (*text == 0)
- {
- *n_ranges_out = 0;
- return NULL;
- }
-
- n_ranges = 1;
- p = text;
- while (*p)
- {
- if (is_range_separator (*p))
- n_ranges++;
- p++;
- }
-
- ranges = g_new0 (GtkPageRange, n_ranges);
-
- i = 0;
- p = text;
- while (*p)
- {
- while (isspace (*p)) p++;
-
- if (*p == '-')
- {
- /* a half-open range like -2 */
- start = 1;
- }
- else
- {
- start = (int)strtol (p, &next, 10);
- if (start < 1)
- start = 1;
- p = next;
- }
-
- end = start;
-
- while (isspace (*p)) p++;
-
- if (*p == '-')
- {
- p++;
- end = (int)strtol (p, &next, 10);
- if (next == p) /* a half-open range like 2- */
- end = 0;
- else if (end < start)
- end = start;
- }
-
- ranges[i].start = start - 1;
- ranges[i].end = end - 1;
- i++;
-
- /* Skip until end or separator */
- while (*p && !is_range_separator (*p))
- p++;
-
- /* if not at end, skip separator */
- if (*p)
- p++;
- }
-
- *n_ranges_out = i;
-
- return ranges;
-}
-
-static void
-dialog_set_page_ranges (GtkPrintUnixDialog *dialog,
- GtkPageRange *ranges,
- int n_ranges)
-{
- int i;
- GString *s = g_string_new (NULL);
-
- for (i = 0; i < n_ranges; i++)
- {
- g_string_append_printf (s, "%d", ranges[i].start + 1);
- if (ranges[i].end > ranges[i].start)
- g_string_append_printf (s, "-%d", ranges[i].end + 1);
- else if (ranges[i].end == -1)
- g_string_append (s, "-");
-
- if (i != n_ranges - 1)
- g_string_append (s, ",");
- }
-
- gtk_editable_set_text (GTK_EDITABLE (dialog->page_range_entry), s->str);
-
- g_string_free (s, TRUE);
-}
-
-static GtkPrintPages
-dialog_get_print_pages (GtkPrintUnixDialog *dialog)
-{
- if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->all_pages_radio)))
- return GTK_PRINT_PAGES_ALL;
- else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->current_page_radio)))
- return GTK_PRINT_PAGES_CURRENT;
- else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->selection_radio)))
- return GTK_PRINT_PAGES_SELECTION;
- else
- return GTK_PRINT_PAGES_RANGES;
-}
-
-static void
-dialog_set_print_pages (GtkPrintUnixDialog *dialog,
- GtkPrintPages pages)
-{
- if (pages == GTK_PRINT_PAGES_RANGES)
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
- else if (pages == GTK_PRINT_PAGES_CURRENT)
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->current_page_radio), TRUE);
- else if (pages == GTK_PRINT_PAGES_SELECTION)
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->selection_radio), TRUE);
- else
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->all_pages_radio), TRUE);
-}
-
-static double
-dialog_get_scale (GtkPrintUnixDialog *dialog)
-{
- if (gtk_widget_is_sensitive (dialog->scale_spin))
- return gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->scale_spin));
- else
- return 100.0;
-}
-
-static void
-dialog_set_scale (GtkPrintUnixDialog *dialog,
- double val)
-{
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->scale_spin), val);
-}
-
-static GtkPageSet
-dialog_get_page_set (GtkPrintUnixDialog *dialog)
-{
- if (gtk_widget_is_sensitive (dialog->page_set_combo))
- return (GtkPageSet)gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->page_set_combo));
- else
- return GTK_PAGE_SET_ALL;
-}
-
-static void
-dialog_set_page_set (GtkPrintUnixDialog *dialog,
- GtkPageSet val)
-{
- gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->page_set_combo), (guint)val);
-}
-
-static int
-dialog_get_n_copies (GtkPrintUnixDialog *dialog)
-{
- GtkAdjustment *adjustment;
- const char *text;
- char *endptr = NULL;
- int n_copies;
-
- adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (dialog->copies_spin));
-
- text = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
- n_copies = g_ascii_strtoull (text, &endptr, 0);
-
- if (gtk_widget_is_sensitive (dialog->copies_spin))
- {
- if (n_copies != 0 && endptr != text && (endptr != NULL && endptr[0] == '\0') &&
- n_copies >= gtk_adjustment_get_lower (adjustment) &&
- n_copies <= gtk_adjustment_get_upper (adjustment))
- {
- return n_copies;
- }
-
- return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->copies_spin));
- }
-
- return 1;
-}
-
-static void
-dialog_set_n_copies (GtkPrintUnixDialog *dialog,
- int n_copies)
-{
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->copies_spin), n_copies);
-}
-
-static gboolean
-dialog_get_collate (GtkPrintUnixDialog *dialog)
-{
- if (gtk_widget_is_sensitive (dialog->collate_check))
- return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->collate_check));
- return FALSE;
-}
-
-static void
-dialog_set_collate (GtkPrintUnixDialog *dialog,
- gboolean collate)
-{
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->collate_check), collate);
-}
-
-static gboolean
-dialog_get_reverse (GtkPrintUnixDialog *dialog)
-{
- if (gtk_widget_is_sensitive (dialog->reverse_check))
- return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_check));
- return FALSE;
-}
-
-static void
-dialog_set_reverse (GtkPrintUnixDialog *dialog,
- gboolean reverse)
-{
- gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_check), reverse);
-}
-
-static int
-dialog_get_pages_per_sheet (GtkPrintUnixDialog *dialog)
-{
- const char *val;
- int num;
-
- val = gtk_printer_option_widget_get_value (dialog->pages_per_sheet);
-
- num = 1;
-
- if (val)
- {
- num = atoi(val);
- if (num < 1)
- num = 1;
- }
-
- return num;
-}
-
-static GtkNumberUpLayout
-dialog_get_number_up_layout (GtkPrintUnixDialog *dialog)
-{
- GtkPrintCapabilities caps;
- GtkNumberUpLayout layout;
- const char *val;
- GEnumClass *enum_class;
- GEnumValue *enum_value;
-
- val = gtk_printer_option_widget_get_value (dialog->number_up_layout);
-
- caps = dialog->manual_capabilities | dialog->printer_capabilities;
-
- if ((caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) == 0)
- return GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-
- if (gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR)
- layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
- else
- layout = GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM;
-
- if (val == NULL)
- return layout;
-
- if (val[0] == '\0' && dialog->options)
- {
- GtkPrinterOption *option = gtk_printer_option_set_lookup (dialog->options, "gtk-n-up-layout");
- if (option)
- val = option->value;
- }
-
- enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
- enum_value = g_enum_get_value_by_nick (enum_class, val);
- if (enum_value)
- layout = enum_value->value;
- g_type_class_unref (enum_class);
-
- return layout;
-}
-
-static void
-draw_page (GtkDrawingArea *da,
- cairo_t *cr,
- int width,
- int height,
- gpointer data)
-{
- GtkWidget *widget = GTK_WIDGET (da);
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
- GtkCssStyle *style;
- double ratio;
- int w, h, tmp;
- int pages_x, pages_y, i, x, y, layout_w, layout_h;
- double page_width, page_height;
- GtkPageOrientation orientation;
- gboolean landscape;
- PangoLayout *layout;
- PangoFontDescription *font;
- char *text;
- GdkRGBA color;
- GtkNumberUpLayout number_up_layout;
- int start_x, end_x, start_y, end_y;
- int dx, dy;
- gboolean horizontal;
- GtkPageSetup *page_setup;
- double paper_width, paper_height;
- double pos_x, pos_y;
- int pages_per_sheet;
- gboolean ltr = TRUE;
- GtkSnapshot *snapshot;
- GtkCssBoxes boxes;
- GskRenderNode *node;
-
- orientation = gtk_page_setup_get_orientation (dialog->page_setup);
- landscape =
- (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
- (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
-
- number_up_layout = dialog_get_number_up_layout (dialog);
-
- cairo_save (cr);
-
- page_setup = gtk_print_unix_dialog_get_page_setup (dialog);
-
- if (page_setup != NULL)
- {
- if (!landscape)
- {
- paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
- paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
- }
- else
- {
- paper_width = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
- paper_height = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
- }
-
- if (paper_width < paper_height)
- {
- h = EXAMPLE_PAGE_AREA_SIZE - 3;
- w = (paper_height != 0) ? h * paper_width / paper_height : 0;
- }
- else
- {
- w = EXAMPLE_PAGE_AREA_SIZE - 3;
- h = (paper_width != 0) ? w * paper_height / paper_width : 0;
- }
-
- if (paper_width == 0)
- w = 0;
-
- if (paper_height == 0)
- h = 0;
- }
- else
- {
- ratio = G_SQRT2;
- w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
- h = EXAMPLE_PAGE_AREA_SIZE - 3;
- }
-
- pages_per_sheet = dialog_get_pages_per_sheet (dialog);
- switch (pages_per_sheet)
- {
- default:
- case 1:
- pages_x = 1; pages_y = 1;
- break;
- case 2:
- landscape = !landscape;
- pages_x = 1; pages_y = 2;
- break;
- case 4:
- pages_x = 2; pages_y = 2;
- break;
- case 6:
- landscape = !landscape;
- pages_x = 2; pages_y = 3;
- break;
- case 9:
- pages_x = 3; pages_y = 3;
- break;
- case 16:
- pages_x = 4; pages_y = 4;
- break;
- }
-
- if (landscape)
- {
- tmp = w;
- w = h;
- h = tmp;
-
- tmp = pages_x;
- pages_x = pages_y;
- pages_y = tmp;
- }
-
- style = gtk_css_node_get_style (dialog->page_layout_paper_node);
- color = *gtk_css_color_value_get_rgba (style->core->color);
-
- pos_x = (width - w) / 2;
- pos_y = (height - h) / 2 - 10;
- cairo_translate (cr, pos_x, pos_y);
-
- snapshot = gtk_snapshot_new ();
- gtk_css_boxes_init_border_box (&boxes, style, 1, 1, w, h);
- gtk_css_style_snapshot_background (&boxes, snapshot);
- gtk_css_style_snapshot_border (&boxes, snapshot);
-
- node = gtk_snapshot_free_to_node (snapshot);
- if (node)
- {
- gsk_render_node_draw (node, cr);
- gsk_render_node_unref (node);
- }
-
- cairo_set_line_width (cr, 1.0);
-
- i = 1;
-
- page_width = (double)w / pages_x;
- page_height = (double)h / pages_y;
-
- layout = pango_cairo_create_layout (cr);
-
- font = pango_font_description_new ();
- pango_font_description_set_family (font, "sans");
-
- if (page_height > 0)
- pango_font_description_set_absolute_size (font, page_height * 0.4 * PANGO_SCALE);
- else
- pango_font_description_set_absolute_size (font, 1);
-
- pango_layout_set_font_description (layout, font);
- pango_font_description_free (font);
-
- pango_layout_set_width (layout, page_width * PANGO_SCALE);
- pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
-
- switch (number_up_layout)
- {
- default:
- case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
- start_x = 0;
- end_x = pages_x - 1;
- start_y = 0;
- end_y = pages_y - 1;
- dx = 1;
- dy = 1;
- horizontal = TRUE;
- break;
- case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
- start_x = 0;
- end_x = pages_x - 1;
- start_y = pages_y - 1;
- end_y = 0;
- dx = 1;
- dy = - 1;
- horizontal = TRUE;
- break;
- case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
- start_x = pages_x - 1;
- end_x = 0;
- start_y = 0;
- end_y = pages_y - 1;
- dx = - 1;
- dy = 1;
- horizontal = TRUE;
- break;
- case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
- start_x = pages_x - 1;
- end_x = 0;
- start_y = pages_y - 1;
- end_y = 0;
- dx = - 1;
- dy = - 1;
- horizontal = TRUE;
- break;
- case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
- start_x = 0;
- end_x = pages_x - 1;
- start_y = 0;
- end_y = pages_y - 1;
- dx = 1;
- dy = 1;
- horizontal = FALSE;
- break;
- case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
- start_x = pages_x - 1;
- end_x = 0;
- start_y = 0;
- end_y = pages_y - 1;
- dx = - 1;
- dy = 1;
- horizontal = FALSE;
- break;
- case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
- start_x = 0;
- end_x = pages_x - 1;
- start_y = pages_y - 1;
- end_y = 0;
- dx = 1;
- dy = - 1;
- horizontal = FALSE;
- break;
- case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
- start_x = pages_x - 1;
- end_x = 0;
- start_y = pages_y - 1;
- end_y = 0;
- dx = - 1;
- dy = - 1;
- horizontal = FALSE;
- break;
- }
-
- gdk_cairo_set_source_rgba (cr, &color);
- if (horizontal)
- for (y = start_y; y != end_y + dy; y += dy)
- {
- for (x = start_x; x != end_x + dx; x += dx)
- {
- text = g_strdup_printf ("%d", i++);
- pango_layout_set_text (layout, text, -1);
- g_free (text);
- pango_layout_get_size (layout, &layout_w, &layout_h);
- cairo_save (cr);
- cairo_translate (cr,
- x * page_width,
- y * page_height + (page_height - layout_h / 1024.0) / 2);
-
- pango_cairo_show_layout (cr, layout);
- cairo_restore (cr);
- }
- }
- else
- for (x = start_x; x != end_x + dx; x += dx)
- {
- for (y = start_y; y != end_y + dy; y += dy)
- {
- text = g_strdup_printf ("%d", i++);
- pango_layout_set_text (layout, text, -1);
- g_free (text);
- pango_layout_get_size (layout, &layout_w, &layout_h);
- cairo_save (cr);
- cairo_translate (cr,
- x * page_width,
- y * page_height + (page_height - layout_h / 1024.0) / 2);
-
- pango_cairo_show_layout (cr, layout);
- cairo_restore (cr);
- }
- }
-
- g_object_unref (layout);
-
- style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
- color = *gtk_css_color_value_get_rgba (style->core->color);
-
- if (page_setup != NULL)
- {
- PangoContext *pango_c = NULL;
- PangoFontDescription *pango_f = NULL;
- int font_size = 12 * PANGO_SCALE;
-
- pos_x += 1;
- pos_y += 1;
-
- if (pages_per_sheet == 2 || pages_per_sheet == 6)
- {
- paper_width = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
- paper_height = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
- }
- else
- {
- paper_width = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
- paper_height = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
- }
-
- cairo_restore (cr);
- cairo_save (cr);
-
- layout = pango_cairo_create_layout (cr);
-
- font = pango_font_description_new ();
- pango_font_description_set_family (font, "sans");
-
- pango_c = gtk_widget_get_pango_context (widget);
- if (pango_c != NULL)
- {
- pango_f = pango_context_get_font_description (pango_c);
- if (pango_f != NULL)
- font_size = pango_font_description_get_size (pango_f);
- }
-
- pango_font_description_set_size (font, font_size);
- pango_layout_set_font_description (layout, font);
- pango_font_description_free (font);
-
- pango_layout_set_width (layout, -1);
- pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
-
- if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
- text = g_strdup_printf ("%.1f mm", paper_height);
- else
- text = g_strdup_printf ("%.2f inch", paper_height);
-
- pango_layout_set_text (layout, text, -1);
- g_free (text);
- pango_layout_get_size (layout, &layout_w, &layout_h);
-
- ltr = gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR;
-
- if (ltr)
- cairo_translate (cr, pos_x - layout_w / PANGO_SCALE - 2 * RULER_DISTANCE,
- (height - layout_h / PANGO_SCALE) / 2);
- else
- cairo_translate (cr, pos_x + w + 2 * RULER_DISTANCE,
- (height - layout_h / PANGO_SCALE) / 2);
-
- gdk_cairo_set_source_rgba (cr, &color);
- pango_cairo_show_layout (cr, layout);
-
- cairo_restore (cr);
- cairo_save (cr);
-
- if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
- text = g_strdup_printf ("%.1f mm", paper_width);
- else
- text = g_strdup_printf ("%.2f inch", paper_width);
-
- pango_layout_set_text (layout, text, -1);
- g_free (text);
- pango_layout_get_size (layout, &layout_w, &layout_h);
-
- cairo_translate (cr, (width - layout_w / PANGO_SCALE) / 2,
- pos_y + h + 2 * RULER_DISTANCE);
-
- gdk_cairo_set_source_rgba (cr, &color);
- pango_cairo_show_layout (cr, layout);
-
- g_object_unref (layout);
-
- cairo_restore (cr);
-
- cairo_set_line_width (cr, 1);
-
- gdk_cairo_set_source_rgba (cr, &color);
-
- if (ltr)
- {
- cairo_move_to (cr, pos_x - RULER_DISTANCE, pos_y);
- cairo_line_to (cr, pos_x - RULER_DISTANCE, pos_y + h);
- cairo_stroke (cr);
-
- cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
- cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
- cairo_stroke (cr);
-
- cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
- cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
- cairo_stroke (cr);
- }
- else
- {
- cairo_move_to (cr, pos_x + w + RULER_DISTANCE, pos_y);
- cairo_line_to (cr, pos_x + w + RULER_DISTANCE, pos_y + h);
- cairo_stroke (cr);
-
- cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
- cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
- cairo_stroke (cr);
-
- cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
- cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
- cairo_stroke (cr);
- }
-
- cairo_move_to (cr, pos_x, pos_y + h + RULER_DISTANCE);
- cairo_line_to (cr, pos_x + w, pos_y + h + RULER_DISTANCE);
- cairo_stroke (cr);
-
- cairo_move_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
- cairo_line_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
- cairo_stroke (cr);
-
- cairo_move_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
- cairo_line_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
- cairo_stroke (cr);
- }
-}
-
-static void
-redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
-{
- if (dialog->page_layout_preview)
- gtk_widget_queue_draw (dialog->page_layout_preview);
-}
-
-static void
-update_number_up_layout (GtkPrintUnixDialog *dialog)
-{
- GtkPrintCapabilities caps;
- GtkPrinterOptionSet *set;
- GtkNumberUpLayout layout;
- GtkPrinterOption *option;
- GtkPrinterOption *old_option;
- GtkPageOrientation page_orientation;
-
- set = dialog->options;
-
- caps = dialog->manual_capabilities | dialog->printer_capabilities;
-
- if (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT)
- {
- if (dialog->number_up_layout_n_option == NULL)
- {
- dialog->number_up_layout_n_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
- if (dialog->number_up_layout_n_option == NULL)
- {
- const char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" };
- /* Translators: These strings name the possible arrangements of
- * multiple pages on a sheet when printing (same as in gtkprintbackendcups.c)
- */
- const char *n_up_layout_display[] = { N_("Left to right, top to bottom"), N_("Left to right, bottom to top"),
- N_("Right to left, top to bottom"), N_("Right to left, bottom to top"),
- N_("Top to bottom, left to right"), N_("Top to bottom, right to left"),
- N_("Bottom to top, left to right"), N_("Bottom to top, right to left") };
- int i;
-
- dialog->number_up_layout_n_option = gtk_printer_option_new ("gtk-n-up-layout",
- _("Page Ordering"),
- GTK_PRINTER_OPTION_TYPE_PICKONE);
- gtk_printer_option_allocate_choices (dialog->number_up_layout_n_option, 8);
-
- for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++)
- {
- dialog->number_up_layout_n_option->choices[i] = g_strdup (n_up_layout[i]);
- dialog->number_up_layout_n_option->choices_display[i] = g_strdup (_(n_up_layout_display[i]));
- }
- }
- g_object_ref (dialog->number_up_layout_n_option);
-
- dialog->number_up_layout_2_option = gtk_printer_option_new ("gtk-n-up-layout",
- _("Page Ordering"),
- GTK_PRINTER_OPTION_TYPE_PICKONE);
- gtk_printer_option_allocate_choices (dialog->number_up_layout_2_option, 2);
- }
-
- page_orientation = gtk_page_setup_get_orientation (dialog->page_setup);
- if (page_orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
- page_orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
- {
- if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
- dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[2]))
- {
- g_free (dialog->number_up_layout_2_option->choices_display[0]);
- g_free (dialog->number_up_layout_2_option->choices_display[1]);
- dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
- dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[2];
- dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Left to right"));
- dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Right to left"));
- }
- }
- else
- {
- if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
- dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[1]))
- {
- g_free (dialog->number_up_layout_2_option->choices_display[0]);
- g_free (dialog->number_up_layout_2_option->choices_display[1]);
- dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
- dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[1];
- dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Top to bottom"));
- dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Bottom to top"));
- }
- }
-
- layout = dialog_get_number_up_layout (dialog);
-
- old_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
- if (old_option != NULL)
- gtk_printer_option_set_remove (set, old_option);
-
- if (dialog_get_pages_per_sheet (dialog) != 1)
- {
- GEnumClass *enum_class;
- GEnumValue *enum_value;
- enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
-
- if (dialog_get_pages_per_sheet (dialog) == 2)
- {
- option = dialog->number_up_layout_2_option;
-
- switch (layout)
- {
- case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
- case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
- enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
- break;
-
- case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
- case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
- enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP);
- break;
-
- case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
- case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
- enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM);
- break;
-
- case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
- case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
- enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP);
- break;
-
- default:
- g_assert_not_reached();
- enum_value = NULL;
- }
- }
- else
- {
- option = dialog->number_up_layout_n_option;
-
- enum_value = g_enum_get_value (enum_class, layout);
- }
-
- g_assert (enum_value != NULL);
- gtk_printer_option_set (option, enum_value->value_nick);
- g_type_class_unref (enum_class);
-
- gtk_printer_option_set_add (set, option);
- }
- }
-
- setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
-
- if (dialog->number_up_layout != NULL)
- gtk_widget_set_sensitive (GTK_WIDGET (dialog->number_up_layout),
- (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) &&
- (dialog_get_pages_per_sheet (dialog) > 1));
-}
-
-static void
-custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
- int response_id,
- gpointer user_data)
-{
- GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (user_data);
-
- dialog->internal_page_setup_change = TRUE;
- gtk_print_load_custom_papers (dialog->custom_paper_list);
- update_paper_sizes (dialog);
- dialog->internal_page_setup_change = FALSE;
-
- if (dialog->page_setup_set)
- {
- GListModel *model;
- guint n, i;
-
- model = G_LIST_MODEL (dialog->custom_paper_list);
- n = g_list_model_get_n_items (model);
- for (i = 0; i < n; i++)
- {
- GtkPageSetup *page_setup = g_list_model_get_item (model, i);
-
- if (g_strcmp0 (gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (page_setup)),
- gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (dialog->page_setup))) == 0)
- gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
-
- g_clear_object (&page_setup);
- }
- }
-
- gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
-}
-
-static void
-orientation_changed (GObject *object,
- GParamSpec *pspec,
- GtkPrintUnixDialog *dialog)
-{
- GtkPageOrientation orientation;
- GtkPageSetup *page_setup;
-
- if (dialog->internal_page_setup_change)
- return;
-
- orientation = (GtkPageOrientation) gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->orientation_combo));
-
- if (dialog->page_setup)
- {
- page_setup = gtk_page_setup_copy (dialog->page_setup);
- if (page_setup)
- gtk_page_setup_set_orientation (page_setup, orientation);
-
- gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
- }
-
- redraw_page_layout_preview (dialog);
-}
-
-static void
-paper_size_changed (GtkDropDown *combo_box,
- GParamSpec *pspec,
- GtkPrintUnixDialog *dialog)
-{
- GtkPageSetup *page_setup, *last_page_setup;
- GtkPageOrientation orientation;
- guint selected;
-
- if (dialog->internal_page_setup_change)
- return;
-
- selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
- if (selected != GTK_INVALID_LIST_POSITION)
- {
- GListModel *papers, *model;
-
- papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
- page_setup = g_list_model_get_item (papers, selected);
- model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
-
- if (model == G_LIST_MODEL (dialog->manage_papers_list))
- {
- GtkWidget *custom_paper_dialog;
-
- /* Change from "manage" menu item to last value */
- if (dialog->page_setup)
- last_page_setup = g_object_ref (dialog->page_setup);
- else
- last_page_setup = gtk_page_setup_new (); /* "good" default */
-
- if (!set_paper_size (dialog, last_page_setup, FALSE, FALSE))
- set_paper_size (dialog, last_page_setup, TRUE, TRUE);
- g_object_unref (last_page_setup);
-
- /* And show the custom paper dialog */
- custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), _("Manage Custom Sizes"));
- g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
- gtk_window_present (GTK_WINDOW (custom_paper_dialog));
-
- g_object_unref (page_setup);
-
- return;
- }
-
- if (dialog->page_setup)
- orientation = gtk_page_setup_get_orientation (dialog->page_setup);
- else
- orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
-
- gtk_page_setup_set_orientation (page_setup, orientation);
- gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
-
- g_object_unref (page_setup);
- }
-
- redraw_page_layout_preview (dialog);
-}
-
-/**
- * gtk_print_unix_dialog_new:
- * @title: (nullable): Title of the dialog
- * @parent: (nullable): Transient parent of the dialog
- *
- * Creates a new `GtkPrintUnixDialog`.
- *
- * Returns: a new `GtkPrintUnixDialog`
- */
-GtkWidget *
-gtk_print_unix_dialog_new (const char *title,
- GtkWindow *parent)
-{
- GtkWidget *result;
-
- result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
- "transient-for", parent,
- "title", title ? title : _("Print"),
- NULL);
-
- return result;
-}
-
-/**
- * gtk_print_unix_dialog_get_selected_printer: (attributes org.gtk.Method.get_property=selected-printer)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the currently selected printer.
- *
- * Returns: (transfer none) (nullable): the currently selected printer
- */
-GtkPrinter *
-gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
-
- return dialog->current_printer;
-}
-
-/**
- * gtk_print_unix_dialog_set_page_setup: (attributes org.gtk.Method.set_property=page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- * @page_setup: a `GtkPageSetup`
- *
- * Sets the page setup of the `GtkPrintUnixDialog`.
- */
-void
-gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
- GtkPageSetup *page_setup)
-{
- g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
- g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
-
- if (dialog->page_setup != page_setup)
- {
- g_clear_object (&dialog->page_setup);
- dialog->page_setup = g_object_ref (page_setup);
-
- dialog->page_setup_set = TRUE;
-
- g_object_notify (G_OBJECT (dialog), "page-setup");
- }
-}
-
-/**
- * gtk_print_unix_dialog_get_page_setup: (attributes org.gtk.Method.get_property=page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the page setup that is used by the `GtkPrintUnixDialog`.
- *
- * Returns: (transfer none): the page setup of @dialog.
- */
-GtkPageSetup *
-gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
-
- return dialog->page_setup;
-}
-
-/**
- * gtk_print_unix_dialog_get_page_setup_set:
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether a page setup was set by the user.
- *
- * Returns: whether a page setup was set by user.
- */
-gboolean
-gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
- return dialog->page_setup_set;
-}
-
-/**
- * gtk_print_unix_dialog_set_current_page: (attributes org.gtk.Method.set_property=current-page)
- * @dialog: a `GtkPrintUnixDialog`
- * @current_page: the current page number.
- *
- * Sets the current page number.
- *
- * If @current_page is not -1, this enables the current page choice
- * for the range of pages to print.
- */
-void
-gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
- int current_page)
-{
- g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
- if (dialog->current_page != current_page)
- {
- dialog->current_page = current_page;
-
- if (dialog->current_page_radio)
- gtk_widget_set_sensitive (dialog->current_page_radio, current_page != -1);
-
- g_object_notify (G_OBJECT (dialog), "current-page");
- }
-}
-
-/**
- * gtk_print_unix_dialog_get_current_page: (attributes org.gtk.Method.get_property=current-page)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the current page of the `GtkPrintUnixDialog`.
- *
- * Returns: the current page of @dialog
- */
-int
-gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
-
- return dialog->current_page;
-}
-
-static gboolean
-set_active_printer (GtkPrintUnixDialog *dialog,
- const char *printer_name)
-{
- GListModel *model;
- GtkPrinter *printer;
- guint i;
-
- model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
-
- for (i = 0; i < g_list_model_get_n_items (model); i++)
- {
- printer = g_list_model_get_item (model, i);
-
- if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
- {
- gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
-
- g_free (dialog->waiting_for_printer);
- dialog->waiting_for_printer = NULL;
-
- g_object_unref (printer);
- return TRUE;
- }
-
- g_object_unref (printer);
- }
-
- return FALSE;
-}
-
-/**
- * gtk_print_unix_dialog_set_settings: (attributes org.gtk.Method.set_property=print-settings)
- * @dialog: a `GtkPrintUnixDialog`
- * @settings: (nullable): a `GtkPrintSettings`
- *
- * Sets the `GtkPrintSettings` for the `GtkPrintUnixDialog`.
- *
- * Typically, this is used to restore saved print settings
- * from a previous print operation before the print dialog
- * is shown.
- */
-void
-gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
- GtkPrintSettings *settings)
-{
- const char *printer;
- GtkPageRange *ranges;
- int num_ranges;
-
- g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
- g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
-
- if (settings != NULL)
- {
- dialog_set_collate (dialog, gtk_print_settings_get_collate (settings));
- dialog_set_reverse (dialog, gtk_print_settings_get_reverse (settings));
- dialog_set_n_copies (dialog, gtk_print_settings_get_n_copies (settings));
- dialog_set_scale (dialog, gtk_print_settings_get_scale (settings));
- dialog_set_page_set (dialog, gtk_print_settings_get_page_set (settings));
- dialog_set_print_pages (dialog, gtk_print_settings_get_print_pages (settings));
- ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
- if (ranges)
- {
- dialog_set_page_ranges (dialog, ranges, num_ranges);
- g_free (ranges);
- }
-
- dialog->format_for_printer =
- g_strdup (gtk_print_settings_get (settings, "format-for-printer"));
- }
-
- if (dialog->initial_settings)
- g_object_unref (dialog->initial_settings);
-
- dialog->initial_settings = settings;
-
- g_free (dialog->waiting_for_printer);
- dialog->waiting_for_printer = NULL;
-
- if (settings)
- {
- g_object_ref (settings);
-
- printer = gtk_print_settings_get_printer (settings);
-
- if (printer && !set_active_printer (dialog, printer))
- dialog->waiting_for_printer = g_strdup (printer);
- }
-
- g_object_notify (G_OBJECT (dialog), "print-settings");
-}
-
-/**
- * gtk_print_unix_dialog_get_settings: (attributes org.gtk.Method.set_property=print-settings)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets a new `GtkPrintSettings` object that represents the
- * current values in the print dialog.
- *
- * Note that this creates a new object, and you need to unref
- * it if don’t want to keep it.
- *
- * Returns: (transfer full): a new `GtkPrintSettings` object with the values from @dialog
- */
-GtkPrintSettings *
-gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
-{
- GtkPrintSettings *settings;
- GtkPrintPages print_pages;
- GtkPageRange *ranges;
- int n_ranges;
-
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
-
- settings = gtk_print_settings_new ();
-
- if (dialog->current_printer)
- gtk_print_settings_set_printer (settings,
- gtk_printer_get_name (dialog->current_printer));
- else
- gtk_print_settings_set_printer (settings, "default");
-
- gtk_print_settings_set (settings, "format-for-printer",
- dialog->format_for_printer);
-
- gtk_print_settings_set_collate (settings,
- dialog_get_collate (dialog));
-
- gtk_print_settings_set_reverse (settings,
- dialog_get_reverse (dialog));
-
- gtk_print_settings_set_n_copies (settings,
- dialog_get_n_copies (dialog));
-
- gtk_print_settings_set_scale (settings,
- dialog_get_scale (dialog));
-
- gtk_print_settings_set_page_set (settings,
- dialog_get_page_set (dialog));
-
- print_pages = dialog_get_print_pages (dialog);
- gtk_print_settings_set_print_pages (settings, print_pages);
-
- ranges = dialog_get_page_ranges (dialog, &n_ranges);
- if (ranges)
- {
- gtk_print_settings_set_page_ranges (settings, ranges, n_ranges);
- g_free (ranges);
- }
-
- /* TODO: print when. How to handle? */
-
- if (dialog->current_printer)
- _gtk_printer_get_settings_from_options (dialog->current_printer,
- dialog->options,
- settings);
-
- return settings;
-}
-
-/**
- * gtk_print_unix_dialog_add_custom_tab:
- * @dialog: a `GtkPrintUnixDialog`
- * @child: the widget to put in the custom tab
- * @tab_label: the widget to use as tab label
- *
- * Adds a custom tab to the print dialog.
- */
-void
-gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
- GtkWidget *child,
- GtkWidget *tab_label)
-{
- gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->notebook),
- child, tab_label, 2);
- gtk_widget_set_visible (child, TRUE);
- gtk_widget_set_visible (tab_label, TRUE);
-}
-
-/**
- * gtk_print_unix_dialog_set_manual_capabilities: (attributes org.gtk.Method.set_property=manual-capabilities)
- * @dialog: a `GtkPrintUnixDialog`
- * @capabilities: the printing capabilities of your application
- *
- * This lets you specify the printing capabilities your application
- * supports.
- *
- * For instance, if you can handle scaling the output then you pass
- * %GTK_PRINT_CAPABILITY_SCALE. If you don’t pass that, then the dialog
- * will only let you select the scale if the printing system automatically
- * handles scaling.
- */
-void
-gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog,
- GtkPrintCapabilities capabilities)
-{
- if (dialog->manual_capabilities != capabilities)
- {
- dialog->manual_capabilities = capabilities;
- update_dialog_from_capabilities (dialog);
-
- if (dialog->current_printer)
- {
- g_clear_object (&dialog->current_printer);
- selected_printer_changed (dialog);
- }
-
- g_object_notify (G_OBJECT (dialog), "manual-capabilities");
- }
-}
-
-/**
- * gtk_print_unix_dialog_get_manual_capabilities: (attributes org.gtk.Method.get_property=manual-capabilities)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the capabilities that have been set on this `GtkPrintUnixDialog`.
- *
- * Returns: the printing capabilities
- */
-GtkPrintCapabilities
-gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
- return dialog->manual_capabilities;
-}
-
-/**
- * gtk_print_unix_dialog_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
- * @dialog: a `GtkPrintUnixDialog`
- * @support_selection: %TRUE to allow print selection
- *
- * Sets whether the print dialog allows user to print a selection.
- */
-void
-gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
- gboolean support_selection)
-{
- g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
- support_selection = support_selection != FALSE;
- if (dialog->support_selection != support_selection)
- {
- dialog->support_selection = support_selection;
-
- if (dialog->selection_radio)
- {
- gtk_widget_set_visible (dialog->selection_radio, support_selection);
- gtk_widget_set_sensitive (dialog->selection_radio, support_selection && dialog->has_selection);
- }
-
- g_object_notify (G_OBJECT (dialog), "support-selection");
- }
-}
-
-/**
- * gtk_print_unix_dialog_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether the print dialog allows user to print a selection.
- *
- * Returns: whether the application supports print of selection
- */
-gboolean
-gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
- return dialog->support_selection;
-}
-
-/**
- * gtk_print_unix_dialog_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
- * @dialog: a `GtkPrintUnixDialog`
- * @has_selection: %TRUE indicates that a selection exists
- *
- * Sets whether a selection exists.
- */
-void
-gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
- gboolean has_selection)
-{
- g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
- has_selection = has_selection != FALSE;
- if (dialog->has_selection != has_selection)
- {
- dialog->has_selection = has_selection;
-
- if (dialog->selection_radio)
- {
- if (dialog->support_selection)
- gtk_widget_set_sensitive (dialog->selection_radio, has_selection);
- else
- gtk_widget_set_sensitive (dialog->selection_radio, FALSE);
- }
-
- g_object_notify (G_OBJECT (dialog), "has-selection");
- }
-}
-
-/**
- * gtk_print_unix_dialog_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether there is a selection.
- *
- * Returns: whether there is a selection
- */
-gboolean
-gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
- return dialog->has_selection;
-}
-
-/**
- * gtk_print_unix_dialog_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- * @embed: embed page setup selection
- *
- * Embed page size combo box and orientation combo box into page setup page.
- */
-void
-gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
- gboolean embed)
-{
- g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
- embed = embed != FALSE;
- if (dialog->embed_page_setup != embed)
- {
- dialog->embed_page_setup = embed;
-
- gtk_widget_set_sensitive (dialog->paper_size_combo, dialog->embed_page_setup);
- gtk_widget_set_sensitive (dialog->orientation_combo, dialog->embed_page_setup);
-
- if (dialog->embed_page_setup)
- {
- if (dialog->paper_size_combo != NULL)
- g_signal_connect (dialog->paper_size_combo, "notify::selected", G_CALLBACK (paper_size_changed), dialog);
-
- if (dialog->orientation_combo)
- g_signal_connect (dialog->orientation_combo, "notify::selected", G_CALLBACK (orientation_changed), dialog);
- }
- else
- {
- if (dialog->paper_size_combo != NULL)
- g_signal_handlers_disconnect_by_func (dialog->paper_size_combo, G_CALLBACK (paper_size_changed), dialog);
-
- if (dialog->orientation_combo)
- g_signal_handlers_disconnect_by_func (dialog->orientation_combo, G_CALLBACK (orientation_changed), dialog);
- }
-
- dialog->internal_page_setup_change = TRUE;
- update_paper_sizes (dialog);
- dialog->internal_page_setup_change = FALSE;
- }
-}
-
-/**
- * gtk_print_unix_dialog_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether to embed the page setup.
- *
- * Returns: whether to embed the page setup
- */
-gboolean
-gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog)
-{
- g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
- return dialog->embed_page_setup;
-}
+++ /dev/null
-/* GtkPrintUnixDialog
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <gtk/gtk.h>
-#include <gtk/gtkprinter.h>
-#include <gtk/gtkprintjob.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINT_UNIX_DIALOG (gtk_print_unix_dialog_get_type ())
-#define GTK_PRINT_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_UNIX_DIALOG, GtkPrintUnixDialog))
-#define GTK_IS_PRINT_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_UNIX_DIALOG))
-
-
-typedef struct _GtkPrintUnixDialog GtkPrintUnixDialog;
-
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_print_unix_dialog_get_type (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkWidget * gtk_print_unix_dialog_new (const char *title,
- GtkWindow *parent);
-
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
- GtkPageSetup *page_setup);
-GDK_AVAILABLE_IN_ALL
-GtkPageSetup * gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
- int current_page);
-GDK_AVAILABLE_IN_ALL
-int gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
- GtkPrintSettings *settings);
-GDK_AVAILABLE_IN_ALL
-GtkPrintSettings * gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-GtkPrinter * gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
- GtkWidget *child,
- GtkWidget *tab_label);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog,
- GtkPrintCapabilities capabilities);
-GDK_AVAILABLE_IN_ALL
-GtkPrintCapabilities gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
- gboolean support_selection);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
- gboolean has_selection);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
- gboolean embed);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintUnixDialog, g_object_unref)
-
-G_END_DECLS
-
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * 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/>.
- */
-
-#pragma once
-
-#include <gdk/gdk.h>
-#include "gtkenums.h"
-
-
-G_BEGIN_DECLS
-
-#define MM_PER_INCH 25.4
-#define POINTS_PER_INCH 72
-
-double _gtk_print_convert_to_mm (double len, GtkUnit unit);
-double _gtk_print_convert_from_mm (double len, GtkUnit unit);
-
-G_END_DECLS
-
+++ /dev/null
-/* GtkUnixPrint
- *
- * 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/>.
- */
-
-#pragma once
-
-#define __GTK_UNIX_PRINT_H_INSIDE__
-
-#include <gtk/gtkpagesetupunixdialog.h>
-#include <gtk/gtkprinter.h>
-#include <gtk/gtkprintjob.h>
-#include <gtk/gtkprintunixdialog.h>
-
-#undef __GTK_UNIX_PRINT_H_INSIDE__
-
endif
if os_unix
- gtk_unix_print_headers = [
- 'gtkpagesetupunixdialog.h',
- 'gtkprintunixdialog.h',
- 'gtkprinter.h',
- 'gtkprintjob.h',
- 'gtkunixprint.h',
- ]
install_headers(gtk_unix_print_headers, subdir: 'gtk-4.0/unix-print/gtk')
-
- gtk_unix_print_sources = files([
- 'gtkcustompaperunixdialog.c',
- 'gtkpagesetupunixdialog.c',
- 'gtkprintbackend.c',
- 'gtkprinter.c',
- 'gtkprinteroption.c',
- 'gtkprinteroptionset.c',
- 'gtkprinteroptionwidget.c',
- 'gtkprintjob.c',
- 'gtkprintoperation-unix.c',
- 'gtkprintoperation-portal.c',
- 'gtkprintunixdialog.c',
- ])
-
gtk_sources += gtk_unix_print_sources
endif
if os_win32
- gtk_win32_print_headers = []
- gtk_win32_print_sources = files([
- 'gtkprint-win32.c',
- 'gtkprintoperation-win32.c',
- 'gtkfilechoosernativewin32.c',
- 'gtkwin32.c',
- ])
-
gtk_sources += gtk_win32_print_sources
gtk_sources += [
'gtkcolorpickerwin32.c',
- 'gtkimcontextime.c'
+ 'gtkimcontextime.c',
+ 'gtkfilechoosernativewin32.c',
+ 'gtkwin32.c',
]
-
- if cc.has_header_symbol('windows.h', 'IPrintDialogCallback')
- cdata.set('HAVE_IPRINTDIALOGCALLBACK', 1)
- endif
endif
if x11_enabled
+++ /dev/null
-#define N_(s) s
-
-/* The paper size names are from:
- * PWG 5101.1-2002 PWG: Standard for Media Standardized Names
- * PWG 5101.1-2013 PWG: PWG Media Standardized Names 2.0 (MSN2)
- *
- * The PPD names come from the PPD specification and from
- * CUPS' cups/pwg-media.c.
- */
-
-typedef struct {
- const char *name;
- const char *size;
- const char *display_name;
- const char *ppd_name;
-} PaperInfo;
-
-static const PaperInfo standard_names[] = {
- /* sorted by name, remember to sort when changing */
- {"asme_f", "28x40in", N_("asme_f")}, /* f 5 e1 */
- {"iso_2a0", "1189x1682mm", N_("A0×2")},
- {"iso_a0", "841x1189mm", N_("A0"), "A0"},
- {"iso_a0x3", "1189x2523mm", N_("A0×3")},
- {"iso_a1", "594x841mm", N_("A1"), "A1"},
- {"iso_a10", "26x37mm", N_("A10"), "A10"},
- {"iso_a1x3", "841x1783mm", N_("A1×3")},
- {"iso_a1x4", "841x2378mm", N_("A1×4")},
- {"iso_a2", "420x594mm", N_("A2"), "A2"},
- {"iso_a2x3", "594x1261mm", N_("A2×3")},
- {"iso_a2x4", "594x1682mm", N_("A2×4")},
- {"iso_a2x5", "594x2102mm", N_("A2×5")},
- {"iso_a3", "297x420mm", N_("A3"), "A3"},
- {"iso_a3-extra", "322x445mm", N_("A3 Extra"), "A3Extra"},
- {"iso_a3x3", "420x891mm", N_("A3×3")},
- {"iso_a3x4", "420x1189mm", N_("A3×4")},
- {"iso_a3x5", "420x1486mm", N_("A3×5")},
- {"iso_a3x6", "420x1783mm", N_("A3×6")},
- {"iso_a3x7", "420x2080mm", N_("A3×7")},
- {"iso_a4", "210x297mm", N_("A4"), "A4"},
- {"iso_a4-extra", "235.5x322.3mm", N_("A4 Extra"), "A4Extra"},
- {"iso_a4-tab", "225x297mm", N_("A4 Tab"), "A4Tab"},
- {"iso_a4x3", "297x630mm", N_("A4×3")},
- {"iso_a4x4", "297x841mm", N_("A4×4")},
- {"iso_a4x5", "297x1051mm", N_("A4×5")},
- {"iso_a4x6", "297x1261mm", N_("A4×6")},
- {"iso_a4x7", "297x1471mm", N_("A4×7")},
- {"iso_a4x8", "297x1682mm", N_("A4×8")},
- {"iso_a4x9", "297x1892mm", N_("A4×9")},
- {"iso_a5", "148x210mm", N_("A5"), "A5"},
- {"iso_a5-extra", "174x235mm", N_("A5 Extra"), "A5Extra"},
- {"iso_a6", "105x148mm", N_("A6"), "A6"},
- {"iso_a7", "74x105mm", N_("A7"), "A7"},
- {"iso_a8", "52x74mm", N_("A8"), "A8"},
- {"iso_a9", "37x52mm", N_("A9"), "A9"},
- {"iso_b0", "1000x1414mm", N_("B0"), "ISOB0"},
- {"iso_b1", "707x1000mm", N_("B1"), "ISOB1"},
- {"iso_b10", "31x44mm", N_("B10"), "ISOB10"},
- {"iso_b2", "500x707mm", N_("B2"), "ISOB2"},
- {"iso_b3", "353x500mm", N_("B3"), "ISOB3"},
- {"iso_b4", "250x353mm", N_("B4"), "ISOB4"},
- {"iso_b5", "176x250mm", N_("B5"), "ISOB5"},
- {"iso_b5-extra", "201x276mm", N_("B5 Extra"), "ISOB5Extra"},
- {"iso_b6", "125x176mm", N_("B6"), "ISOB6"},
- {"iso_b6c4", "125x324mm", N_("B6/C4")}, /* b6/c4 Envelope */
- {"iso_b7", "88x125mm", N_("B7"), "ISOB7"},
- {"iso_b8", "62x88mm", N_("B8"), "ISOB8"},
- {"iso_b9", "44x62mm", N_("B9"), "ISOB9"},
- {"iso_c0", "917x1297mm", N_("C0"), "EnvC0"},
- {"iso_c1", "648x917mm", N_("C1"), "EnvC1"},
- {"iso_c10", "28x40mm", N_("C10"), "EnvC10"},
- {"iso_c2", "458x648mm", N_("C2"), "EnvC2"},
- {"iso_c3", "324x458mm", N_("C3"), "EnvC3"},
- {"iso_c4", "229x324mm", N_("C4"), "EnvC4"},
- {"iso_c5", "162x229mm", N_("C5"), "EnvC5"},
- {"iso_c6", "114x162mm", N_("C6"), "EnvC6"},
- {"iso_c6c5", "114x229mm", N_("C6/C5"), "EnvC65"},
- {"iso_c7", "81x114mm", N_("C7"), "EnvC7"},
- {"iso_c7c6", "81x162mm", N_("C7/C6")}, /* c7/c6 Envelope */
- {"iso_c8", "57x81mm", N_("C8"), "EnvC8"},
- {"iso_c9", "40x57mm", N_("C9"), "EnvC9"},
- {"iso_dl", "110x220mm", N_("DL Envelope"), "EnvDL"}, /* iso-designated 1, 2 designated-long, dl Envelope */
- {"iso_ra0", "860x1220mm", N_("RA0")},
- {"iso_ra1", "610x860mm", N_("RA1")},
- {"iso_ra2", "430x610mm", N_("RA2")},
- {"iso_ra3", "305x430mm", N_("RA3")},
- {"iso_ra4", "215x305mm", N_("RA4")},
- {"iso_sra0", "900x1280mm", N_("SRA0")},
- {"iso_sra1", "640x900mm", N_("SRA1")},
- {"iso_sra2", "450x640mm", N_("SRA2")},
- {"iso_sra3", "320x450mm", N_("SRA3")},
- {"iso_sra4", "225x320mm", N_("SRA4")},
- {"jis_b0", "1030x1456mm", N_("JB0"), "B0"},
- {"jis_b1", "728x1030mm", N_("JB1"), "B1"},
- {"jis_b10", "32x45mm", N_("JB10"), "B10"},
- {"jis_b2", "515x728mm", N_("JB2"), "B2"},
- {"jis_b3", "364x515mm", N_("JB3"), "B3"},
- {"jis_b4", "257x364mm", N_("JB4"), "B4"},
- {"jis_b5", "182x257mm", N_("JB5"), "B5"},
- {"jis_b6", "128x182mm", N_("JB6"), "B6"},
- {"jis_b7", "91x128mm", N_("JB7"), "B7"},
- {"jis_b8", "64x91mm", N_("JB8"), "B8"},
- {"jis_b9", "45x64mm", N_("JB9"), "B9"},
- {"jis_exec", "216x330mm", N_("jis exec")},
- {"jpn_chou2", "111.1x146mm", N_("Choukei 2 Envelope")},
- {"jpn_chou3", "120x235mm", N_("Choukei 3 Envelope"), "EnvChou3"},
- {"jpn_chou4", "90x205mm", N_("Choukei 4 Envelope"), "EnvChou4"},
- {"jpn_chou40", "90x225mm", N_("Choukei 40 Envelope"), "EnvChou40"},
- {"jpn_hagaki", "100x148mm", N_("hagaki (postcard)"), "Postcard"},
- {"jpn_kahu", "240x322.1mm", N_("kahu Envelope")},
- {"jpn_kaku2", "240x332mm", N_("kaku2 Envelope"), "EnvKaku2"},
- {"jpn_kaku3", "216x277mm", N_("kaku3 Envelope"), "EnvKaku3"},
- {"jpn_kaku4", "197x267mm", N_("kaku4 Envelope"), "EnvKaku4"},
- {"jpn_kaku5", "190x240mm", N_("kaku5 Envelope"), "EnvKaku5"},
- {"jpn_kaku7", "142x205mm", N_("kaku7 Envelope"), "EnvKaku7"},
- {"jpn_kaku8", "119x197mm", N_("kaku8 Envelope"), "EnvKaku8"},
- {"jpn_oufuku", "148x200mm", N_("oufuku (reply postcard)"), "DoublePostcard"},
- {"jpn_you4", "105x235mm", N_("you4 Envelope"), "EnvYou4"},
- {"jpn_you6", "98x190mm", N_("you6 Envelope"), "EnvYou6"},
- {"na_10x11", "10x11in", N_("10×11"), "10x11"},
- {"na_10x13", "10x13in", N_("10×13"), "10x13"},
- {"na_10x14", "10x14in", N_("10×14"), "10x14"},
- {"na_10x15", "10x15in", N_("10×15"), "10x15"},
- {"na_11x12", "11x12in", N_("11×12"), "12x11"},
- {"na_11x15", "11x15in", N_("11×15"), "15x11"},
- {"na_12x19", "12x19in", N_("12×19"), "12x19"},
- {"na_5x7", "5x7in", N_("5×7"), "5x7"},
- {"na_6x9", "6x9in", N_("6×9 Envelope"), "6x9"},
- {"na_7x9", "7x9in", N_("7×9 Envelope"), "7x9"},
- {"na_8x10", "8x10in", N_("8×10 Envelope"), "8x10"},
- {"na_9x11", "9x11in", N_("9×11 Envelope"), "9x11"},
- {"na_9x12", "9x12in", N_("9×12 Envelope"), "9x12"},
- {"na_a2", "4.375x5.75in", N_("a2 Envelope"), "EnvA2"},
- {"na_arch-a", "9x12in", N_("Arch A"), "ARCHA"},
- {"na_arch-b", "12x18in", N_("Arch B"), "ARCHB"},
- {"na_arch-c", "18x24in", N_("Arch C"), "ARCHC"},
- {"na_arch-d", "24x36in", N_("Arch D"), "ARCHD"},
- {"na_arch-e", "36x48in", N_("Arch E"), "ARCHE"},
- {"na_b-plus", "12x19.17in", N_("b-plus"), "SuperB"},
- {"na_c", "17x22in", N_("c"), "AnsiC"},
- {"na_c5", "6.5x9.5in", N_("c5 Envelope"), "6.5x9.5"},
- {"na_d", "22x34in", N_("d"), "AnsiD"},
- {"na_e", "34x44in", N_("e"), "AnsiE"},
- {"na_edp", "11x14in", N_("edp"), "11x14"},
- {"na_eur-edp", "12x14in", N_("European edp")},
- {"na_executive", "7.25x10.5in", N_("Executive"), "Executive"},
- {"na_f", "44x68in", N_("f"), "AnsiF"},
- {"na_fanfold-eur", "8.5x12in", N_("Fan-Fold European"), "FanFoldGerman"},
- {"na_fanfold-us", "11x14.875in", N_("Fan-Fold US"), "FanFoldUS"},
- {"na_foolscap", "8.5x13in", N_("Fan-Fold German Legal"), "FanFoldGermanLegal"}, /* foolscap, german-legal-fanfold */
- {"na_govt-legal", "8x13in", N_("Government Legal"), "8x13"},
- {"na_govt-letter", "8x10in", N_("Government Letter"), "8x10"},
- {"na_index-3x5", "3x5in", N_("Index 3×5"), "3x5"},
- {"na_index-4x6", "4x6in", N_("Index 4×6 (postcard)"), "4x6"},
- {"na_index-4x6-ext", "6x8in", N_("Index 4×6 ext")},
- {"na_index-5x8", "5x8in", N_("Index 5×8"), "5x8"},
- {"na_invoice", "5.5x8.5in", N_("Invoice"), "Statement"}, /* invoice, statement, mini, half-letter */
- {"na_ledger", "11x17in", N_("Tabloid"), "Ledger"}, /* tabloid, engineering-b */
- {"na_legal", "8.5x14in", N_("US Legal"), "Legal"},
- {"na_legal-extra", "9.5x15in", N_("US Legal Extra"), "LegalExtra"},
- {"na_letter", "8.5x11in", N_("US Letter"), "Letter"},
- {"na_letter-extra", "9.5x12in", N_("US Letter Extra"), "LetterExtra"},
- {"na_letter-plus", "8.5x12.69in", N_("US Letter Plus"), "LetterPlus"},
- {"na_monarch", "3.875x7.5in", N_("Monarch Envelope"), "EnvMonarch"},
- {"na_number-10", "4.125x9.5in", N_("#10 Envelope"), "Env10"}, /* na-number-10-envelope 1, 2 comm-10 Envelope */
- {"na_number-11", "4.5x10.375in", N_("#11 Envelope"), "Env11"}, /* number-11 Envelope */
- {"na_number-12", "4.75x11in", N_("#12 Envelope"), "Env12"}, /* number-12 Envelope */
- {"na_number-14", "5x11.5in", N_("#14 Envelope"), "Env14"}, /* number-14 Envelope */
- {"na_number-9", "3.875x8.875in", N_("#9 Envelope"), "Env9"},
- {"na_oficio", "8.5x13.4in", N_("Oficio"), "Oficio"},
- {"na_personal", "3.625x6.5in", N_("Personal Envelope"), "EnvPersonal"},
- {"na_quarto", "8.5x10.83in", N_("Quarto"), "Quarto"},
- {"na_super-a", "8.94x14in", N_("Super A"), "SuperA"},
- {"na_super-b", "13x19in", N_("Super B"), "SuperB"},
- {"na_wide-format", "30x42in", N_("Wide Format")},
- {"oe_photo-l", "3.5x5in", N_("Photo L"), "3.5x5"},
- {"om_dai-pa-kai", "275x395mm", N_("Dai-pa-kai")},
- {"om_folio", "210x330mm", N_("Folio"), "Folio"},
- {"om_folio-sp", "215x315mm", N_("Folio sp"), "FolioSP"},
- {"om_invite", "220x220mm", N_("Invite Envelope"), "EnvInvite"},
- {"om_italian", "110x230mm", N_("Italian Envelope"), "EnvItalian"},
- {"om_juuro-ku-kai", "198x275mm", N_("juuro-ku-kai")},
- {"om_large-photo", "200x300mm", N_("Large Photo"), "om_large-photo"},
- {"om_medium-photo", "130x180mm", N_("Medium Photo")},
- {"om_pa-kai", "267x389mm", N_("pa-kai")},
- {"om_postfix", "114x229mm", N_("Postfix Envelope")},
- {"om_small-photo", "100x150mm", N_("Small Photo"), "om_small-photo"},
- {"om_wide-photo", "100x200mm", N_("Wide Photo"), "om_wide-photo"},
- {"prc_1", "102x165mm", N_("prc1 Envelope"), "EnvPRC1"},
- {"prc_10", "324x458mm", N_("prc10 Envelope"), "EnvPRC10"},
- {"prc_16k", "146x215mm", N_("prc 16k"), "PRC16K"},
- {"prc_2", "102x176mm", N_("prc2 Envelope"), "EnvPRC2"},
- {"prc_3", "125x176mm", N_("prc3 Envelope"), "EnvPRC3"},
- {"prc_32k", "97x151mm", N_("prc 32k"), "PRC32K"},
- {"prc_4", "110x208mm", N_("prc4 Envelope"), "EnvPRC4"},
- {"prc_5", "110x220mm", N_("prc5 Envelope"), "EnvPRC5"},
- {"prc_6", "120x230mm", N_("prc6 Envelope"), "EnvPRC6"},
- {"prc_7", "160x230mm", N_("prc7 Envelope"), "EnvPRC7"},
- {"prc_8", "120x309mm", N_("prc8 Envelope"), "EnvPRC8"},
- {"prc_9", "229x324mm", N_("prc9 Envelope"), "EnvPRC9"},
- {"roc_16k", "7.75x10.75in", N_("ROC 16k"), "roc16k"},
- {"roc_8k", "10.75x15.5in", N_("ROC 8k"), "roc8k"},
-};
-
-/* Some page sizes have multiple PPD names in use.
- * The array above only contains the preferred one,
- * and this array fills out with the duplicates.
- */
-const struct {
- const char *ppd_name;
- const char *standard_name;
-} extra_ppd_names[] = {
- /* sorted by ppd_name, remember to sort when changing */
- { "C4", "iso_c4"},
- { "C5", "iso_c5"},
- { "C6", "iso_c6"},
- { "Comm10", "na_number-10"},
- { "DL", "iso_dl"},
- { "Monarch", "na_monarch"},
-};
+++ /dev/null
-/* Generated by gen-paper-names */
-
-#if 0
-NC_("paper size", "asme_f")
-NC_("paper size", "A0×2")
-NC_("paper size", "A0")
-NC_("paper size", "A0×3")
-NC_("paper size", "A1")
-NC_("paper size", "A10")
-NC_("paper size", "A1×3")
-NC_("paper size", "A1×4")
-NC_("paper size", "A2")
-NC_("paper size", "A2×3")
-NC_("paper size", "A2×4")
-NC_("paper size", "A2×5")
-NC_("paper size", "A3")
-NC_("paper size", "A3 Extra")
-NC_("paper size", "A3×3")
-NC_("paper size", "A3×4")
-NC_("paper size", "A3×5")
-NC_("paper size", "A3×6")
-NC_("paper size", "A3×7")
-NC_("paper size", "A4")
-NC_("paper size", "A4 Extra")
-NC_("paper size", "A4 Tab")
-NC_("paper size", "A4×3")
-NC_("paper size", "A4×4")
-NC_("paper size", "A4×5")
-NC_("paper size", "A4×6")
-NC_("paper size", "A4×7")
-NC_("paper size", "A4×8")
-NC_("paper size", "A4×9")
-NC_("paper size", "A5")
-NC_("paper size", "A5 Extra")
-NC_("paper size", "A6")
-NC_("paper size", "A7")
-NC_("paper size", "A8")
-NC_("paper size", "A9")
-NC_("paper size", "B0")
-NC_("paper size", "B1")
-NC_("paper size", "B10")
-NC_("paper size", "B2")
-NC_("paper size", "B3")
-NC_("paper size", "B4")
-NC_("paper size", "B5")
-NC_("paper size", "B5 Extra")
-NC_("paper size", "B6")
-NC_("paper size", "B6/C4")
-NC_("paper size", "B7")
-NC_("paper size", "B8")
-NC_("paper size", "B9")
-NC_("paper size", "C0")
-NC_("paper size", "C1")
-NC_("paper size", "C10")
-NC_("paper size", "C2")
-NC_("paper size", "C3")
-NC_("paper size", "C4")
-NC_("paper size", "C5")
-NC_("paper size", "C6")
-NC_("paper size", "C6/C5")
-NC_("paper size", "C7")
-NC_("paper size", "C7/C6")
-NC_("paper size", "C8")
-NC_("paper size", "C9")
-NC_("paper size", "DL Envelope")
-NC_("paper size", "RA0")
-NC_("paper size", "RA1")
-NC_("paper size", "RA2")
-NC_("paper size", "RA3")
-NC_("paper size", "RA4")
-NC_("paper size", "SRA0")
-NC_("paper size", "SRA1")
-NC_("paper size", "SRA2")
-NC_("paper size", "SRA3")
-NC_("paper size", "SRA4")
-NC_("paper size", "JB0")
-NC_("paper size", "JB1")
-NC_("paper size", "JB10")
-NC_("paper size", "JB2")
-NC_("paper size", "JB3")
-NC_("paper size", "JB4")
-NC_("paper size", "JB5")
-NC_("paper size", "JB6")
-NC_("paper size", "JB7")
-NC_("paper size", "JB8")
-NC_("paper size", "JB9")
-NC_("paper size", "jis exec")
-NC_("paper size", "Choukei 2 Envelope")
-NC_("paper size", "Choukei 3 Envelope")
-NC_("paper size", "Choukei 4 Envelope")
-NC_("paper size", "Choukei 40 Envelope")
-NC_("paper size", "hagaki (postcard)")
-NC_("paper size", "kahu Envelope")
-NC_("paper size", "kaku2 Envelope")
-NC_("paper size", "kaku3 Envelope")
-NC_("paper size", "kaku4 Envelope")
-NC_("paper size", "kaku5 Envelope")
-NC_("paper size", "kaku7 Envelope")
-NC_("paper size", "kaku8 Envelope")
-NC_("paper size", "oufuku (reply postcard)")
-NC_("paper size", "you4 Envelope")
-NC_("paper size", "you6 Envelope")
-NC_("paper size", "10×11")
-NC_("paper size", "10×13")
-NC_("paper size", "10×14")
-NC_("paper size", "10×15")
-NC_("paper size", "11×12")
-NC_("paper size", "11×15")
-NC_("paper size", "12×19")
-NC_("paper size", "5×7")
-NC_("paper size", "6×9 Envelope")
-NC_("paper size", "7×9 Envelope")
-NC_("paper size", "8×10 Envelope")
-NC_("paper size", "9×11 Envelope")
-NC_("paper size", "9×12 Envelope")
-NC_("paper size", "a2 Envelope")
-NC_("paper size", "Arch A")
-NC_("paper size", "Arch B")
-NC_("paper size", "Arch C")
-NC_("paper size", "Arch D")
-NC_("paper size", "Arch E")
-NC_("paper size", "b-plus")
-NC_("paper size", "c")
-NC_("paper size", "c5 Envelope")
-NC_("paper size", "d")
-NC_("paper size", "e")
-NC_("paper size", "edp")
-NC_("paper size", "European edp")
-NC_("paper size", "Executive")
-NC_("paper size", "f")
-NC_("paper size", "Fan-Fold European")
-NC_("paper size", "Fan-Fold US")
-NC_("paper size", "Fan-Fold German Legal")
-NC_("paper size", "Government Legal")
-NC_("paper size", "Government Letter")
-NC_("paper size", "Index 3×5")
-NC_("paper size", "Index 4×6 (postcard)")
-NC_("paper size", "Index 4×6 ext")
-NC_("paper size", "Index 5×8")
-NC_("paper size", "Invoice")
-NC_("paper size", "Tabloid")
-NC_("paper size", "US Legal")
-NC_("paper size", "US Legal Extra")
-NC_("paper size", "US Letter")
-NC_("paper size", "US Letter Extra")
-NC_("paper size", "US Letter Plus")
-NC_("paper size", "Monarch Envelope")
-NC_("paper size", "#10 Envelope")
-NC_("paper size", "#11 Envelope")
-NC_("paper size", "#12 Envelope")
-NC_("paper size", "#14 Envelope")
-NC_("paper size", "#9 Envelope")
-NC_("paper size", "Oficio")
-NC_("paper size", "Personal Envelope")
-NC_("paper size", "Quarto")
-NC_("paper size", "Super A")
-NC_("paper size", "Super B")
-NC_("paper size", "Wide Format")
-NC_("paper size", "Photo L")
-NC_("paper size", "Dai-pa-kai")
-NC_("paper size", "Folio")
-NC_("paper size", "Folio sp")
-NC_("paper size", "Invite Envelope")
-NC_("paper size", "Italian Envelope")
-NC_("paper size", "juuro-ku-kai")
-NC_("paper size", "Large Photo")
-NC_("paper size", "Medium Photo")
-NC_("paper size", "pa-kai")
-NC_("paper size", "Postfix Envelope")
-NC_("paper size", "Small Photo")
-NC_("paper size", "Wide Photo")
-NC_("paper size", "prc1 Envelope")
-NC_("paper size", "prc10 Envelope")
-NC_("paper size", "prc 16k")
-NC_("paper size", "prc2 Envelope")
-NC_("paper size", "prc3 Envelope")
-NC_("paper size", "prc 32k")
-NC_("paper size", "prc4 Envelope")
-NC_("paper size", "prc5 Envelope")
-NC_("paper size", "prc6 Envelope")
-NC_("paper size", "prc7 Envelope")
-NC_("paper size", "prc8 Envelope")
-NC_("paper size", "prc9 Envelope")
-NC_("paper size", "ROC 16k")
-NC_("paper size", "ROC 8k")
-#endif
-
-static const char paper_names[] =
- "asme_f\0"
- "iso_2a0\0"
- "A0×2\0"
- "iso_a0\0"
- "iso_a0x3\0"
- "A0×3\0"
- "iso_a1\0"
- "iso_a10\0"
- "A10\0"
- "iso_a1x3\0"
- "A1×3\0"
- "iso_a1x4\0"
- "A1×4\0"
- "iso_a2\0"
- "iso_a2x3\0"
- "A2×3\0"
- "iso_a2x4\0"
- "A2×4\0"
- "iso_a2x5\0"
- "A2×5\0"
- "iso_a3\0"
- "iso_a3-extra\0"
- "A3 Extra\0"
- "A3Extra\0"
- "iso_a3x3\0"
- "A3×3\0"
- "iso_a3x4\0"
- "A3×4\0"
- "iso_a3x5\0"
- "A3×5\0"
- "iso_a3x6\0"
- "A3×6\0"
- "iso_a3x7\0"
- "A3×7\0"
- "iso_a4\0"
- "iso_a4-extra\0"
- "A4 Extra\0"
- "A4Extra\0"
- "iso_a4-tab\0"
- "A4 Tab\0"
- "A4Tab\0"
- "iso_a4x3\0"
- "A4×3\0"
- "iso_a4x4\0"
- "A4×4\0"
- "iso_a4x5\0"
- "A4×5\0"
- "iso_a4x6\0"
- "A4×6\0"
- "iso_a4x7\0"
- "A4×7\0"
- "iso_a4x8\0"
- "A4×8\0"
- "iso_a4x9\0"
- "A4×9\0"
- "iso_a5\0"
- "A5\0"
- "iso_a5-extra\0"
- "A5 Extra\0"
- "A5Extra\0"
- "iso_a6\0"
- "A6\0"
- "iso_a7\0"
- "A7\0"
- "iso_a8\0"
- "A8\0"
- "iso_a9\0"
- "A9\0"
- "iso_b0\0"
- "ISOB0\0"
- "iso_b1\0"
- "ISOB1\0"
- "iso_b10\0"
- "ISOB10\0"
- "iso_b2\0"
- "ISOB2\0"
- "iso_b3\0"
- "ISOB3\0"
- "iso_b4\0"
- "ISOB4\0"
- "iso_b5\0"
- "ISOB5\0"
- "iso_b5-extra\0"
- "B5 Extra\0"
- "ISOB5Extra\0"
- "iso_b6\0"
- "ISOB6\0"
- "iso_b6c4\0"
- "B6/C4\0"
- "iso_b7\0"
- "ISOB7\0"
- "iso_b8\0"
- "ISOB8\0"
- "iso_b9\0"
- "ISOB9\0"
- "iso_c0\0"
- "EnvC0\0"
- "iso_c1\0"
- "EnvC1\0"
- "iso_c10\0"
- "EnvC10\0"
- "iso_c2\0"
- "EnvC2\0"
- "iso_c3\0"
- "EnvC3\0"
- "iso_c4\0"
- "EnvC4\0"
- "iso_c5\0"
- "EnvC5\0"
- "iso_c6\0"
- "EnvC6\0"
- "iso_c6c5\0"
- "C6/C5\0"
- "EnvC65\0"
- "iso_c7\0"
- "EnvC7\0"
- "iso_c7c6\0"
- "C7/C6\0"
- "iso_c8\0"
- "EnvC8\0"
- "iso_c9\0"
- "EnvC9\0"
- "iso_dl\0"
- "DL Envelope\0"
- "EnvDL\0"
- "iso_ra0\0"
- "iso_ra1\0"
- "iso_ra2\0"
- "iso_ra3\0"
- "iso_ra4\0"
- "iso_sra0\0"
- "SRA0\0"
- "iso_sra1\0"
- "SRA1\0"
- "iso_sra2\0"
- "SRA2\0"
- "iso_sra3\0"
- "SRA3\0"
- "iso_sra4\0"
- "SRA4\0"
- "jis_b0\0"
- "JB0\0"
- "jis_b1\0"
- "JB1\0"
- "jis_b10\0"
- "JB10\0"
- "jis_b2\0"
- "JB2\0"
- "jis_b3\0"
- "JB3\0"
- "jis_b4\0"
- "JB4\0"
- "jis_b5\0"
- "JB5\0"
- "jis_b6\0"
- "JB6\0"
- "jis_b7\0"
- "JB7\0"
- "jis_b8\0"
- "JB8\0"
- "jis_b9\0"
- "JB9\0"
- "jis_exec\0"
- "jis exec\0"
- "jpn_chou2\0"
- "Choukei 2 Envelope\0"
- "jpn_chou3\0"
- "Choukei 3 Envelope\0"
- "EnvChou3\0"
- "jpn_chou4\0"
- "Choukei 4 Envelope\0"
- "EnvChou4\0"
- "jpn_chou40\0"
- "Choukei 40 Envelope\0"
- "EnvChou40\0"
- "jpn_hagaki\0"
- "hagaki (postcard)\0"
- "jpn_kahu\0"
- "kahu Envelope\0"
- "jpn_kaku2\0"
- "kaku2 Envelope\0"
- "EnvKaku2\0"
- "jpn_kaku3\0"
- "kaku3 Envelope\0"
- "EnvKaku3\0"
- "jpn_kaku4\0"
- "kaku4 Envelope\0"
- "EnvKaku4\0"
- "jpn_kaku5\0"
- "kaku5 Envelope\0"
- "EnvKaku5\0"
- "jpn_kaku7\0"
- "kaku7 Envelope\0"
- "EnvKaku7\0"
- "jpn_kaku8\0"
- "kaku8 Envelope\0"
- "EnvKaku8\0"
- "jpn_oufuku\0"
- "oufuku (reply postcard)\0"
- "DoublePostcard\0"
- "jpn_you4\0"
- "you4 Envelope\0"
- "EnvYou4\0"
- "jpn_you6\0"
- "you6 Envelope\0"
- "EnvYou6\0"
- "na_10x11\0"
- "10×11\0"
- "na_10x13\0"
- "10×13\0"
- "na_10x14\0"
- "10×14\0"
- "na_10x15\0"
- "10×15\0"
- "na_11x12\0"
- "11×12\0"
- "12x11\0"
- "na_11x15\0"
- "11×15\0"
- "15x11\0"
- "na_12x19\0"
- "12×19\0"
- "na_5x7\0"
- "5×7\0"
- "na_6x9\0"
- "6×9 Envelope\0"
- "na_7x9\0"
- "7×9 Envelope\0"
- "na_8x10\0"
- "8×10 Envelope\0"
- "na_9x11\0"
- "9×11 Envelope\0"
- "na_9x12\0"
- "9×12 Envelope\0"
- "na_a2\0"
- "a2 Envelope\0"
- "EnvA2\0"
- "na_arch-a\0"
- "Arch A\0"
- "ARCHA\0"
- "na_arch-b\0"
- "Arch B\0"
- "ARCHB\0"
- "na_arch-c\0"
- "Arch C\0"
- "ARCHC\0"
- "na_arch-d\0"
- "Arch D\0"
- "ARCHD\0"
- "na_arch-e\0"
- "Arch E\0"
- "ARCHE\0"
- "na_b-plus\0"
- "SuperB\0"
- "na_c\0"
- "AnsiC\0"
- "na_c5\0"
- "6.5x9.5\0"
- "na_d\0"
- "AnsiD\0"
- "na_e\0"
- "AnsiE\0"
- "na_edp\0"
- "11x14\0"
- "na_eur-edp\0"
- "European edp\0"
- "na_executive\0"
- "Executive\0"
- "na_f\0"
- "AnsiF\0"
- "na_fanfold-eur\0"
- "Fan-Fold European\0"
- "FanFoldGerman\0"
- "na_fanfold-us\0"
- "Fan-Fold US\0"
- "FanFoldUS\0"
- "na_foolscap\0"
- "Fan-Fold German Legal\0"
- "FanFoldGermanLegal\0"
- "na_govt-legal\0"
- "Government Legal\0"
- "8x13\0"
- "na_govt-letter\0"
- "Government Letter\0"
- "na_index-3x5\0"
- "Index 3×5\0"
- "na_index-4x6\0"
- "Index 4×6 (postcard)\0"
- "na_index-4x6-ext\0"
- "Index 4×6 ext\0"
- "na_index-5x8\0"
- "Index 5×8\0"
- "na_invoice\0"
- "Invoice\0"
- "Statement\0"
- "na_ledger\0"
- "Tabloid\0"
- "Ledger\0"
- "na_legal\0"
- "US Legal\0"
- "na_legal-extra\0"
- "US Legal Extra\0"
- "LegalExtra\0"
- "na_letter\0"
- "US Letter\0"
- "na_letter-extra\0"
- "US Letter Extra\0"
- "LetterExtra\0"
- "na_letter-plus\0"
- "US Letter Plus\0"
- "LetterPlus\0"
- "na_monarch\0"
- "Monarch Envelope\0"
- "EnvMonarch\0"
- "na_number-10\0"
- "#10 Envelope\0"
- "Env10\0"
- "na_number-11\0"
- "#11 Envelope\0"
- "Env11\0"
- "na_number-12\0"
- "#12 Envelope\0"
- "Env12\0"
- "na_number-14\0"
- "#14 Envelope\0"
- "Env14\0"
- "na_number-9\0"
- "#9 Envelope\0"
- "Env9\0"
- "na_oficio\0"
- "Oficio\0"
- "na_personal\0"
- "Personal Envelope\0"
- "EnvPersonal\0"
- "na_quarto\0"
- "Quarto\0"
- "na_super-a\0"
- "Super A\0"
- "SuperA\0"
- "na_super-b\0"
- "Super B\0"
- "na_wide-format\0"
- "Wide Format\0"
- "oe_photo-l\0"
- "Photo L\0"
- "3.5x5\0"
- "om_dai-pa-kai\0"
- "Dai-pa-kai\0"
- "om_folio\0"
- "Folio\0"
- "om_folio-sp\0"
- "Folio sp\0"
- "FolioSP\0"
- "om_invite\0"
- "Invite Envelope\0"
- "EnvInvite\0"
- "om_italian\0"
- "Italian Envelope\0"
- "EnvItalian\0"
- "om_juuro-ku-kai\0"
- "om_large-photo\0"
- "Large Photo\0"
- "om_medium-photo\0"
- "Medium Photo\0"
- "om_pa-kai\0"
- "om_postfix\0"
- "Postfix Envelope\0"
- "om_small-photo\0"
- "Small Photo\0"
- "om_wide-photo\0"
- "Wide Photo\0"
- "prc_1\0"
- "prc1 Envelope\0"
- "EnvPRC1\0"
- "prc_10\0"
- "prc10 Envelope\0"
- "EnvPRC10\0"
- "prc_16k\0"
- "prc 16k\0"
- "PRC16K\0"
- "prc_2\0"
- "prc2 Envelope\0"
- "EnvPRC2\0"
- "prc_3\0"
- "prc3 Envelope\0"
- "EnvPRC3\0"
- "prc_32k\0"
- "prc 32k\0"
- "PRC32K\0"
- "prc_4\0"
- "prc4 Envelope\0"
- "EnvPRC4\0"
- "prc_5\0"
- "prc5 Envelope\0"
- "EnvPRC5\0"
- "prc_6\0"
- "prc6 Envelope\0"
- "EnvPRC6\0"
- "prc_7\0"
- "prc7 Envelope\0"
- "EnvPRC7\0"
- "prc_8\0"
- "prc8 Envelope\0"
- "EnvPRC8\0"
- "prc_9\0"
- "prc9 Envelope\0"
- "EnvPRC9\0"
- "roc_16k\0"
- "ROC 16k\0"
- "roc16k\0"
- "roc_8k\0"
- "ROC 8k\0"
- "roc8k\0"
- "Comm10\0";
-
-typedef struct {
- int name;
- float width;
- float height;
- int display_name;
- int ppd_name;
-} PaperInfo;
-
-static const PaperInfo standard_names_offsets[] = {
- { 0, 711.2, 1016, 0, -1 },
- { 7, 1189, 1682, 15, -1 },
- { 21, 841, 1189, 953, 953 },
- { 28, 1189, 2523, 37, -1 },
- { 43, 594, 841, 967, 967 },
- { 50, 26, 37, 58, 58 },
- { 62, 841, 1783, 71, -1 },
- { 77, 841, 2378, 86, -1 },
- { 92, 420, 594, 981, 981 },
- { 99, 594, 1261, 108, -1 },
- { 114, 594, 1682, 123, -1 },
- { 129, 594, 2102, 138, -1 },
- { 144, 297, 420, 995, 995 },
- { 151, 322, 445, 164, 173 },
- { 181, 420, 891, 190, -1 },
- { 196, 420, 1189, 205, -1 },
- { 211, 420, 1486, 220, -1 },
- { 226, 420, 1783, 235, -1 },
- { 241, 420, 2080, 250, -1 },
- { 256, 210, 297, 1009, 1009 },
- { 263, 235.5, 322.3, 276, 285 },
- { 293, 225, 297, 304, 311 },
- { 317, 297, 630, 326, -1 },
- { 332, 297, 841, 341, -1 },
- { 347, 297, 1051, 356, -1 },
- { 362, 297, 1261, 371, -1 },
- { 377, 297, 1471, 386, -1 },
- { 392, 297, 1682, 401, -1 },
- { 407, 297, 1892, 416, -1 },
- { 422, 148, 210, 429, 429 },
- { 432, 174, 235, 445, 454 },
- { 462, 105, 148, 469, 469 },
- { 472, 74, 105, 479, 479 },
- { 482, 52, 74, 489, 489 },
- { 492, 37, 52, 499, 499 },
- { 502, 1000, 1414, 512, 509 },
- { 515, 707, 1000, 525, 522 },
- { 528, 31, 44, 539, 536 },
- { 543, 500, 707, 553, 550 },
- { 556, 353, 500, 566, 563 },
- { 569, 250, 353, 579, 576 },
- { 582, 176, 250, 592, 589 },
- { 595, 201, 276, 608, 617 },
- { 628, 125, 176, 638, 635 },
- { 641, 125, 324, 650, -1 },
- { 656, 88, 125, 666, 663 },
- { 669, 62, 88, 679, 676 },
- { 682, 44, 62, 692, 689 },
- { 695, 917, 1297, 705, 702 },
- { 708, 648, 917, 718, 715 },
- { 721, 28, 40, 732, 729 },
- { 736, 458, 648, 746, 743 },
- { 749, 324, 458, 759, 756 },
- { 762, 229, 324, 653, 769 },
- { 775, 162, 229, 785, 782 },
- { 788, 114, 162, 798, 795 },
- { 801, 114, 229, 810, 816 },
- { 823, 81, 114, 833, 830 },
- { 836, 81, 162, 845, -1 },
- { 851, 57, 81, 861, 858 },
- { 864, 40, 57, 874, 871 },
- { 877, 110, 220, 884, 896 },
- { 902, 860, 1220, 952, -1 },
- { 910, 610, 860, 966, -1 },
- { 918, 430, 610, 980, -1 },
- { 926, 305, 430, 994, -1 },
- { 934, 215, 305, 1008, -1 },
- { 942, 900, 1280, 951, -1 },
- { 956, 640, 900, 965, -1 },
- { 970, 450, 640, 979, -1 },
- { 984, 320, 450, 993, -1 },
- { 998, 225, 320, 1007, -1 },
- { 1012, 1030, 1456, 1019, 512 },
- { 1023, 728, 1030, 1030, 525 },
- { 1034, 32, 45, 1042, 539 },
- { 1047, 515, 728, 1054, 553 },
- { 1058, 364, 515, 1065, 566 },
- { 1069, 257, 364, 1076, 579 },
- { 1080, 182, 257, 1087, 592 },
- { 1091, 128, 182, 1098, 638 },
- { 1102, 91, 128, 1109, 666 },
- { 1113, 64, 91, 1120, 679 },
- { 1124, 45, 64, 1131, 692 },
- { 1135, 216, 330, 1144, -1 },
- { 1153, 111.1, 146, 1163, -1 },
- { 1182, 120, 235, 1192, 1211 },
- { 1220, 90, 205, 1230, 1249 },
- { 1258, 90, 225, 1269, 1289 },
- { 1299, 100, 148, 1310, 1596 },
- { 1328, 240, 322.1, 1337, -1 },
- { 1351, 240, 332, 1361, 1376 },
- { 1385, 216, 277, 1395, 1410 },
- { 1419, 197, 267, 1429, 1444 },
- { 1453, 190, 240, 1463, 1478 },
- { 1487, 142, 205, 1497, 1512 },
- { 1521, 119, 197, 1531, 1546 },
- { 1555, 148, 200, 1566, 1590 },
- { 1605, 105, 235, 1614, 1628 },
- { 1636, 98, 190, 1645, 1659 },
- { 1667, 254, 279.4, 1676, 1670 },
- { 1683, 254, 330.2, 1692, 1686 },
- { 1699, 254, 355.6, 1708, 1702 },
- { 1715, 254, 381, 1724, 1718 },
- { 1731, 279.4, 304.8, 1740, 1747 },
- { 1753, 279.4, 381, 1762, 1769 },
- { 1775, 304.8, 482.6, 1784, 1778 },
- { 1791, 127, 177.8, 1798, 1794 },
- { 1803, 152.4, 228.6, 1810, 1806 },
- { 1824, 177.8, 228.6, 1831, 1827 },
- { 1845, 203.2, 254, 1853, 1848 },
- { 1868, 228.6, 279.4, 1876, 1871 },
- { 1891, 228.6, 304.8, 1899, 1894 },
- { 1914, 111.125, 146.05, 1920, 1932 },
- { 1938, 228.6, 304.8, 1948, 1955 },
- { 1961, 304.8, 457.2, 1971, 1978 },
- { 1984, 457.2, 609.6, 1994, 2001 },
- { 2007, 609.6, 914.4, 2017, 2024 },
- { 2030, 914.4, 1219.2, 2040, 2047 },
- { 2053, 304.8, 486.918, 2056, 2063 },
- { 2070, 431.8, 558.8, 1142, 2075 },
- { 2081, 165.1, 241.3, 3598, 2087 },
- { 2095, 558.8, 863.6, 1603, 2100 },
- { 2106, 863.6, 1117.6, 894, 2111 },
- { 2117, 279.4, 355.6, 2120, 2124 },
- { 2130, 304.8, 355.6, 2141, -1 },
- { 2154, 184.15, 266.7, 2167, 2167 },
- { 2177, 1117.6, 1727.2, 5, 2182 },
- { 2188, 215.9, 304.8, 2203, 2221 },
- { 2235, 279.4, 377.825, 2249, 2261 },
- { 2271, 215.9, 330.2, 2283, 2305 },
- { 2324, 203.2, 330.2, 2338, 2355 },
- { 2360, 203.2, 254, 2375, 1848 },
- { 2393, 76.2, 127, 2406, 216 },
- { 2417, 101.6, 152.4, 2430, 367 },
- { 2452, 152.4, 203.2, 2469, -1 },
- { 2484, 127, 203.2, 2497, 2493 },
- { 2508, 139.7, 215.9, 2519, 2527 },
- { 2537, 279.4, 431.8, 2547, 2555 },
- { 2562, 215.9, 355.6, 2571, 2299 },
- { 2580, 241.3, 381, 2595, 2610 },
- { 2621, 215.9, 279.4, 2631, 2386 },
- { 2641, 241.3, 304.8, 2657, 2673 },
- { 2685, 215.9, 322.326, 2700, 2715 },
- { 2726, 98.425, 190.5, 2737, 2754 },
- { 2765, 104.775, 241.3, 2778, 2791 },
- { 2797, 114.3, 263.525, 2810, 2823 },
- { 2829, 120.65, 279.4, 2842, 2855 },
- { 2861, 127, 292.1, 2874, 2887 },
- { 2893, 98.425, 225.425, 2905, 2917 },
- { 2922, 215.9, 340.36, 2932, 2932 },
- { 2939, 92.075, 165.1, 2951, 2969 },
- { 2981, 215.9, 275.082, 2991, 2991 },
- { 2998, 227.076, 355.6, 3009, 3017 },
- { 3024, 330.2, 482.6, 3035, 2063 },
- { 3043, 762, 1066.8, 3058, -1 },
- { 3070, 88.9, 127, 3081, 3089 },
- { 3095, 275, 395, 3109, -1 },
- { 3120, 210, 330, 3129, 3129 },
- { 3135, 215, 315, 3147, 3156 },
- { 3164, 220, 220, 3174, 3190 },
- { 3200, 110, 230, 3211, 3228 },
- { 3239, 198, 275, 3242, -1 },
- { 3255, 200, 300, 3270, 3255 },
- { 3282, 130, 180, 3298, -1 },
- { 3311, 267, 389, 3102, -1 },
- { 3321, 114, 229, 3332, -1 },
- { 3349, 100, 150, 3364, 3349 },
- { 3376, 100, 200, 3390, 3376 },
- { 3401, 102, 165, 3407, 3421 },
- { 3429, 324, 458, 3436, 3451 },
- { 3460, 146, 215, 3468, 3476 },
- { 3483, 102, 176, 3489, 3503 },
- { 3511, 125, 176, 3517, 3531 },
- { 3539, 97, 151, 3547, 3555 },
- { 3562, 110, 208, 3568, 3582 },
- { 3590, 110, 220, 3596, 3610 },
- { 3618, 120, 230, 3624, 3638 },
- { 3646, 160, 230, 3652, 3666 },
- { 3674, 120, 309, 3680, 3694 },
- { 3702, 229, 324, 3708, 3722 },
- { 3730, 196.85, 273.05, 3738, 3746 },
- { 3753, 273.05, 393.7, 3760, 3767 },
-};
-
-static const struct {
- int ppd_name;
- int standard_name;
-} extra_ppd_names_offsets[] = {
- { 653, 762 },
- { 785, 775 },
- { 798, 788 },
- { 3773, 2765 },
- { 899, 877 },
- { 2757, 2726 },
-};
-
--- /dev/null
+/* GtkCustomPaperUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ * Copyright © 2006, 2007, 2008 Christian Persch
+ *
+ * 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 <string.h>
+#include <locale.h>
+
+#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
+#include <langinfo.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+#include "gtkprivate.h"
+
+#include "deprecated/gtkliststore.h"
+
+#include "gtksignallistitemfactory.h"
+#include "gtklabel.h"
+#include "gtkspinbutton.h"
+
+#include "gtkcustompaperunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprintutilsprivate.h"
+#include "deprecated/gtkdialogprivate.h"
+
+#define LEGACY_CUSTOM_PAPER_FILENAME ".gtk-custom-papers"
+#define CUSTOM_PAPER_FILENAME "custom-papers"
+
+
+typedef struct
+{
+ GtkUnit display_unit;
+ GtkWidget *spin_button;
+} UnitWidget;
+
+struct _GtkCustomPaperUnixDialog
+{
+ GtkDialog parent_instance;
+
+ GtkWidget *listview;
+ GtkWidget *values_box;
+ GtkWidget *printer_combo;
+ GtkWidget *width_widget;
+ GtkWidget *height_widget;
+ GtkWidget *top_widget;
+ GtkWidget *bottom_widget;
+ GtkWidget *left_widget;
+ GtkWidget *right_widget;
+
+ gulong printer_inserted_tag;
+
+ guint request_details_tag;
+ GtkPrinter *request_details_printer;
+
+ guint non_user_change : 1;
+
+ GListStore *custom_paper_list;
+ GListModel *printer_list;
+
+ GList *print_backends;
+};
+
+typedef struct _GtkCustomPaperUnixDialogClass GtkCustomPaperUnixDialogClass;
+
+struct _GtkCustomPaperUnixDialogClass
+{
+ GtkDialogClass parent_class;
+};
+
+
+enum {
+ PRINTER_LIST_COL_NAME,
+ PRINTER_LIST_COL_PRINTER,
+ PRINTER_LIST_N_COLS
+};
+
+
+G_DEFINE_TYPE (GtkCustomPaperUnixDialog, gtk_custom_paper_unix_dialog, GTK_TYPE_DIALOG)
+
+
+static void gtk_custom_paper_unix_dialog_constructed (GObject *object);
+static void gtk_custom_paper_unix_dialog_finalize (GObject *object);
+static void populate_dialog (GtkCustomPaperUnixDialog *dialog);
+
+
+
+GtkUnit
+_gtk_print_get_default_user_units (void)
+{
+ /* Translate to the default units to use for presenting
+ * lengths to the user. Translate to default:inch if you
+ * want inches, otherwise translate to default:mm.
+ * Do *not* translate it to "predefinito:mm", if it
+ * it isn't default:mm or default:inch it will not work
+ */
+ char *e = _("default:mm");
+
+#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
+ char *imperial = NULL;
+
+ imperial = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
+ if (imperial && imperial[0] == 2 )
+ return GTK_UNIT_INCH; /* imperial */
+ if (imperial && imperial[0] == 1 )
+ return GTK_UNIT_MM; /* metric */
+#endif
+
+ if (strcmp (e, "default:inch")==0)
+ return GTK_UNIT_INCH;
+ else if (strcmp (e, "default:mm"))
+ g_warning ("Whoever translated default:mm did so wrongly.");
+ return GTK_UNIT_MM;
+}
+
+static char *
+custom_paper_get_legacy_filename (void)
+{
+ char *filename;
+
+ filename = g_build_filename (g_get_home_dir (),
+ LEGACY_CUSTOM_PAPER_FILENAME, NULL);
+ g_assert (filename != NULL);
+ return filename;
+}
+
+static char *
+custom_paper_get_filename (void)
+{
+ char *filename;
+
+ filename = g_build_filename (g_get_user_config_dir (),
+ "gtk-4.0",
+ CUSTOM_PAPER_FILENAME, NULL);
+ g_assert (filename != NULL);
+ return filename;
+}
+
+GList *
+_gtk_load_custom_papers (void)
+{
+ GKeyFile *keyfile;
+ char *filename;
+ char **groups;
+ gsize n_groups, i;
+ gboolean load_ok;
+ GList *result = NULL;
+
+ filename = custom_paper_get_filename ();
+
+ keyfile = g_key_file_new ();
+ load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
+ g_free (filename);
+ if (!load_ok)
+ {
+ /* try legacy file */
+ filename = custom_paper_get_legacy_filename ();
+ load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
+ g_free (filename);
+ }
+ if (!load_ok)
+ {
+ g_key_file_free (keyfile);
+ return NULL;
+ }
+
+ groups = g_key_file_get_groups (keyfile, &n_groups);
+ for (i = 0; i < n_groups; ++i)
+ {
+ GtkPageSetup *page_setup;
+
+ page_setup = gtk_page_setup_new_from_key_file (keyfile, groups[i], NULL);
+ if (!page_setup)
+ continue;
+
+ result = g_list_prepend (result, page_setup);
+ }
+
+ g_strfreev (groups);
+ g_key_file_free (keyfile);
+
+ return g_list_reverse (result);
+}
+
+void
+gtk_print_load_custom_papers (GListStore *store)
+{
+ GList *papers, *p;
+ GtkPageSetup *page_setup;
+
+ g_list_store_remove_all (store);
+
+ papers = _gtk_load_custom_papers ();
+ for (p = papers; p; p = p->next)
+ {
+ page_setup = p->data;
+ g_list_store_append (store, page_setup);
+ g_object_unref (page_setup);
+ }
+
+ g_list_free (papers);
+}
+
+static void
+gtk_print_save_custom_papers (GListStore *store)
+{
+ GKeyFile *keyfile;
+ char *filename, *data, *parentdir;
+ gsize len;
+ int i = 0;
+
+ keyfile = g_key_file_new ();
+
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
+ {
+ GtkPageSetup *page_setup;
+ char group[32];
+
+ page_setup = g_list_model_get_item (G_LIST_MODEL (store), i);
+ g_snprintf (group, sizeof (group), "Paper%u", i);
+ gtk_page_setup_to_key_file (page_setup, keyfile, group);
+ g_object_unref (page_setup);
+ }
+
+ filename = custom_paper_get_filename ();
+ parentdir = g_build_filename (g_get_user_config_dir (),
+ "gtk-4.0",
+ NULL);
+ if (g_mkdir_with_parents (parentdir, 0700) == 0)
+ {
+ data = g_key_file_to_data (keyfile, &len, NULL);
+ g_file_set_contents (filename, data, len, NULL);
+ g_free (data);
+ }
+ g_free (parentdir);
+ g_free (filename);
+}
+
+static void
+gtk_custom_paper_unix_dialog_class_init (GtkCustomPaperUnixDialogClass *class)
+{
+ G_OBJECT_CLASS (class)->constructed = gtk_custom_paper_unix_dialog_constructed;
+ G_OBJECT_CLASS (class)->finalize = gtk_custom_paper_unix_dialog_finalize;
+}
+
+static void
+custom_paper_dialog_response_cb (GtkDialog *dialog,
+ int response,
+ gpointer user_data)
+{
+ GtkCustomPaperUnixDialog *self = GTK_CUSTOM_PAPER_UNIX_DIALOG (dialog);
+
+ gtk_print_save_custom_papers (self->custom_paper_list);
+}
+
+static gboolean
+match_func (gpointer item, gpointer user_data)
+{
+ return !gtk_printer_is_virtual (GTK_PRINTER (item));
+}
+
+static void
+gtk_custom_paper_unix_dialog_init (GtkCustomPaperUnixDialog *dialog)
+{
+ GtkPrinter *printer;
+ GListStore *printer_list;
+ GListStore *printer_list_list;
+ GListModel *full_list;
+ GtkFilter *filter;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ dialog->print_backends = NULL;
+
+ dialog->request_details_printer = NULL;
+ dialog->request_details_tag = 0;
+
+ printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
+ printer_list = g_list_store_new (GTK_TYPE_PRINTER);
+ printer = gtk_printer_new (_("Margins from Printer…"), NULL, FALSE);
+ g_list_store_append (printer_list, printer);
+ g_object_unref (printer);
+ g_list_store_append (printer_list_list, printer_list);
+ g_object_unref (printer_list);
+
+ full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
+
+ filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
+ dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
+
+ dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+ gtk_print_load_custom_papers (dialog->custom_paper_list);
+
+ populate_dialog (dialog);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), NULL);
+}
+
+static void
+gtk_custom_paper_unix_dialog_constructed (GObject *object)
+{
+ gboolean use_header;
+
+ G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->constructed (object);
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ g_object_get (object, "use-header-bar", &use_header, NULL);
+ if (!use_header)
+ {
+ gtk_dialog_add_buttons (GTK_DIALOG (object),
+ _("_Close"), GTK_RESPONSE_CLOSE,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_CLOSE);
+ }
+G_GNUC_END_IGNORE_DEPRECATIONS
+}
+
+static void
+gtk_custom_paper_unix_dialog_finalize (GObject *object)
+{
+ GtkCustomPaperUnixDialog *dialog = GTK_CUSTOM_PAPER_UNIX_DIALOG (object);
+ GList *node;
+
+ if (dialog->printer_list)
+ {
+ g_signal_handler_disconnect (dialog->printer_list, dialog->printer_inserted_tag);
+ g_object_unref (dialog->printer_list);
+ dialog->printer_list = NULL;
+ }
+
+ if (dialog->request_details_tag)
+ {
+ g_signal_handler_disconnect (dialog->request_details_printer,
+ dialog->request_details_tag);
+ g_object_unref (dialog->request_details_printer);
+ dialog->request_details_printer = NULL;
+ dialog->request_details_tag = 0;
+ }
+
+ g_clear_object (&dialog->custom_paper_list);
+
+ for (node = dialog->print_backends; node; node = node->next)
+ gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
+ g_list_free_full (dialog->print_backends, g_object_unref);
+ dialog->print_backends = NULL;
+
+ G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->finalize (object);
+}
+
+/**
+ * gtk_custom_paper_unix_dialog_new:
+ * @title: (nullable): the title of the dialog
+ * @parent: (nullable): transient parent of the dialog
+ *
+ * Creates a new custom paper dialog.
+ *
+ * Returns: the new `GtkCustomPaperUnixDialog`
+ */
+GtkWidget *
+_gtk_custom_paper_unix_dialog_new (GtkWindow *parent,
+ const char *title)
+{
+ GtkWidget *result;
+
+ if (title == NULL)
+ title = _("Manage Custom Sizes");
+
+ result = g_object_new (GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG,
+ "title", title,
+ "transient-for", parent,
+ "modal", parent != NULL,
+ "destroy-with-parent", TRUE,
+ "resizable", FALSE,
+ NULL);
+
+ return result;
+}
+
+static void
+load_print_backends (GtkCustomPaperUnixDialog *dialog)
+{
+ GListModel *full_list;
+ GListStore *printer_list_list;
+ GList *node;
+
+ full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
+ printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
+
+ if (g_module_supported ())
+ dialog->print_backends = gtk_print_backend_load_modules ();
+
+ for (node = dialog->print_backends; node != NULL; node = node->next)
+ {
+ GtkPrintBackend *backend = GTK_PRINT_BACKEND (node->data);
+ g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
+ }
+}
+
+static void unit_widget_changed (GtkCustomPaperUnixDialog *dialog);
+
+static GtkWidget *
+new_unit_widget (GtkCustomPaperUnixDialog *dialog,
+ GtkUnit unit,
+ GtkWidget *mnemonic_label)
+{
+ GtkWidget *hbox, *button, *label;
+ UnitWidget *data;
+
+ data = g_new0 (UnitWidget, 1);
+ data->display_unit = unit;
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+ button = gtk_spin_button_new_with_range (0.0, 9999.0, 1);
+ gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
+ if (unit == GTK_UNIT_INCH)
+ gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 2);
+ else
+ gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 1);
+
+ gtk_box_append (GTK_BOX (hbox), button);
+
+ data->spin_button = button;
+
+ g_signal_connect_swapped (button, "value-changed",
+ G_CALLBACK (unit_widget_changed), dialog);
+
+ if (unit == GTK_UNIT_INCH)
+ label = gtk_label_new (_("inch"));
+ else
+ label = gtk_label_new (_("mm"));
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+
+ gtk_box_append (GTK_BOX (hbox), label);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (mnemonic_label), button);
+
+ g_object_set_data_full (G_OBJECT (hbox), "unit-data", data, g_free);
+
+ return hbox;
+}
+
+static double
+unit_widget_get (GtkWidget *unit_widget)
+{
+ UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
+ return _gtk_print_convert_to_mm (gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->spin_button)),
+ data->display_unit);
+}
+
+static void
+unit_widget_set (GtkWidget *unit_widget,
+ double value)
+{
+ UnitWidget *data;
+
+ data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->spin_button),
+ _gtk_print_convert_from_mm (value, data->display_unit));
+}
+
+static void
+update_combo_sensitivity_from_printers (GtkCustomPaperUnixDialog *dialog)
+{
+ gboolean sensitive = FALSE;
+
+ if (g_list_model_get_n_items (dialog->printer_list) > 1)
+ sensitive = TRUE;
+
+ gtk_widget_set_sensitive (dialog->printer_combo, sensitive);
+}
+
+static void
+update_custom_widgets_from_list (GtkCustomPaperUnixDialog *dialog)
+{
+ GListModel *model;
+ GtkPageSetup *page_setup;
+
+ model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
+ page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
+
+ dialog->non_user_change = TRUE;
+ if (page_setup != NULL)
+ {
+ unit_widget_set (dialog->width_widget,
+ gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM));
+ unit_widget_set (dialog->height_widget,
+ gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM));
+ unit_widget_set (dialog->top_widget,
+ gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
+ unit_widget_set (dialog->bottom_widget,
+ gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
+ unit_widget_set (dialog->left_widget,
+ gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
+ unit_widget_set (dialog->right_widget,
+ gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
+
+ gtk_widget_set_sensitive (dialog->values_box, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (dialog->values_box, FALSE);
+ }
+
+ if (dialog->printer_list)
+ update_combo_sensitivity_from_printers (dialog);
+ dialog->non_user_change = FALSE;
+}
+
+static void
+selected_custom_paper_changed (GObject *list,
+ GParamSpec *pspec,
+ GtkCustomPaperUnixDialog *dialog)
+{
+ update_custom_widgets_from_list (dialog);
+}
+
+static void
+unit_widget_changed (GtkCustomPaperUnixDialog *dialog)
+{
+ double w, h, top, bottom, left, right;
+ GListModel *model;
+ GtkPageSetup *page_setup;
+ GtkPaperSize *paper_size;
+
+ if (dialog->non_user_change)
+ return;
+
+ model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
+ page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
+
+ if (page_setup != NULL)
+ {
+ w = unit_widget_get (dialog->width_widget);
+ h = unit_widget_get (dialog->height_widget);
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+ gtk_paper_size_set_size (paper_size, w, h, GTK_UNIT_MM);
+
+ top = unit_widget_get (dialog->top_widget);
+ bottom = unit_widget_get (dialog->bottom_widget);
+ left = unit_widget_get (dialog->left_widget);
+ right = unit_widget_get (dialog->right_widget);
+
+ gtk_page_setup_set_top_margin (page_setup, top, GTK_UNIT_MM);
+ gtk_page_setup_set_bottom_margin (page_setup, bottom, GTK_UNIT_MM);
+ gtk_page_setup_set_left_margin (page_setup, left, GTK_UNIT_MM);
+ gtk_page_setup_set_right_margin (page_setup, right, GTK_UNIT_MM);
+ }
+}
+
+static gboolean
+custom_paper_name_used (GtkCustomPaperUnixDialog *dialog,
+ const char *name)
+{
+ GtkPageSetup *page_setup;
+ GtkPaperSize *paper_size;
+ guint i;
+
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)); i++)
+ {
+ page_setup = g_list_model_get_item (G_LIST_MODEL (dialog->custom_paper_list), i);
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+ if (strcmp (name, gtk_paper_size_get_name (paper_size)) == 0)
+ {
+ g_object_unref (page_setup);
+ return TRUE;
+ }
+ g_object_unref (page_setup);
+ }
+
+ return FALSE;
+}
+
+static void
+add_custom_paper (GtkCustomPaperUnixDialog *dialog)
+{
+ GtkPageSetup *page_setup;
+ GtkPaperSize *paper_size;
+ char *name;
+ int i;
+
+ i = 1;
+ name = NULL;
+ do
+ {
+ g_free (name);
+ name = g_strdup_printf (_("Custom Size %d"), i);
+ i++;
+ } while (custom_paper_name_used (dialog, name));
+
+ page_setup = gtk_page_setup_new ();
+ paper_size = gtk_paper_size_new_custom (name, name,
+ gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
+ gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
+ GTK_UNIT_MM);
+ gtk_page_setup_set_paper_size (page_setup, paper_size);
+ gtk_paper_size_free (paper_size);
+
+ g_list_store_append (dialog->custom_paper_list, page_setup);
+ g_object_unref (page_setup);
+
+ /* FIXME start editing */
+
+ g_free (name);
+}
+
+static void
+remove_custom_paper (GtkCustomPaperUnixDialog *dialog)
+{
+ GListModel *model;
+ guint selected;
+
+ model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
+ selected = gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model));
+ if (selected != GTK_INVALID_LIST_POSITION)
+ g_list_store_remove (dialog->custom_paper_list, selected);
+}
+
+static void
+set_margins_from_printer (GtkCustomPaperUnixDialog *dialog,
+ GtkPrinter *printer)
+{
+ double top, bottom, left, right;
+
+ top = bottom = left = right = 0;
+ if (!gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right))
+ return;
+
+ dialog->non_user_change = TRUE;
+ unit_widget_set (dialog->top_widget, _gtk_print_convert_to_mm (top, GTK_UNIT_POINTS));
+ unit_widget_set (dialog->bottom_widget, _gtk_print_convert_to_mm (bottom, GTK_UNIT_POINTS));
+ unit_widget_set (dialog->left_widget, _gtk_print_convert_to_mm (left, GTK_UNIT_POINTS));
+ unit_widget_set (dialog->right_widget, _gtk_print_convert_to_mm (right, GTK_UNIT_POINTS));
+ dialog->non_user_change = FALSE;
+
+ /* Only send one change */
+ unit_widget_changed (dialog);
+}
+
+static void
+get_margins_finished_callback (GtkPrinter *printer,
+ gboolean success,
+ GtkCustomPaperUnixDialog *dialog)
+{
+ g_signal_handler_disconnect (dialog->request_details_printer,
+ dialog->request_details_tag);
+ g_object_unref (dialog->request_details_printer);
+ dialog->request_details_tag = 0;
+ dialog->request_details_printer = NULL;
+
+ if (success)
+ set_margins_from_printer (dialog, printer);
+
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
+}
+
+static void
+margins_from_printer_changed (GtkCustomPaperUnixDialog *dialog)
+{
+ guint selected;
+ GtkPrinter *printer;
+
+ if (dialog->request_details_tag)
+ {
+ g_signal_handler_disconnect (dialog->request_details_printer,
+ dialog->request_details_tag);
+ g_object_unref (dialog->request_details_printer);
+ dialog->request_details_printer = NULL;
+ dialog->request_details_tag = 0;
+ }
+
+ selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
+ if (selected != 0)
+ {
+ GListModel *model;
+
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
+ printer = g_list_model_get_item (model, selected);
+
+ if (printer)
+ {
+ if (gtk_printer_has_details (printer))
+ {
+ set_margins_from_printer (dialog, printer);
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
+ }
+ else
+ {
+ dialog->request_details_printer = g_object_ref (printer);
+ dialog->request_details_tag =
+ g_signal_connect (printer, "details-acquired",
+ G_CALLBACK (get_margins_finished_callback), dialog);
+ gtk_printer_request_details (printer);
+ }
+
+ g_object_unref (printer);
+ }
+ }
+}
+
+static GtkWidget *
+wrap_in_frame (const char *label,
+ GtkWidget *child)
+{
+ GtkWidget *frame, *label_widget;
+ char *bold_text;
+
+ label_widget = gtk_label_new (NULL);
+ gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
+ gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
+
+ bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
+ gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
+ g_free (bold_text);
+
+ frame = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_append (GTK_BOX (frame), label_widget);
+
+ gtk_widget_set_margin_start (child, 12);
+ gtk_widget_set_halign (child, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (child, GTK_ALIGN_FILL);
+
+ gtk_box_append (GTK_BOX (frame), child);
+
+ return frame;
+}
+
+static void
+setup_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ gtk_list_item_set_child (item, gtk_editable_label_new (""));
+}
+
+static void
+label_changed (GObject *object,
+ GParamSpec *pspec,
+ GtkListItem *item)
+{
+ GtkPageSetup *page_setup;
+ GtkPaperSize *paper_size;
+ const char *new_text;
+
+ page_setup = gtk_list_item_get_item (item);
+
+ new_text = gtk_editable_get_text (GTK_EDITABLE (object));
+
+ paper_size = gtk_paper_size_new_custom (new_text, new_text,
+ gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
+ gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM), GTK_UNIT_MM);
+ gtk_page_setup_set_paper_size (page_setup, paper_size);
+ gtk_paper_size_free (paper_size);
+}
+
+static void
+state_changed (GtkWidget *item,
+ GtkStateFlags old_state,
+ GtkWidget *label)
+{
+ gboolean selected;
+
+ selected = (gtk_widget_get_state_flags (item) & GTK_STATE_FLAG_SELECTED) != 0;
+ gtk_editable_set_editable (GTK_EDITABLE (label), selected);
+}
+
+static void
+bind_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkPageSetup *page_setup;
+ GtkPaperSize *paper_size;
+ GtkWidget *label;
+
+ page_setup = gtk_list_item_get_item (item);
+ label = gtk_list_item_get_child (item);
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+ gtk_editable_set_text (GTK_EDITABLE (label),
+ gtk_paper_size_get_display_name (paper_size));
+ g_signal_connect (label, "notify::text",
+ G_CALLBACK (label_changed), item);
+ g_signal_connect (gtk_widget_get_parent (label), "state-flags-changed",
+ G_CALLBACK (state_changed), label);
+}
+
+static void
+unbind_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkWidget *label;
+
+ label = gtk_list_item_get_child (item);
+ g_signal_handlers_disconnect_by_func (label, label_changed, item);
+ g_signal_handlers_disconnect_by_func (gtk_widget_get_parent (label), state_changed, label);
+}
+
+static void
+setup_printer_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new ("");
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_printer_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkPrinter *printer;
+ GtkWidget *label;
+
+ printer = gtk_list_item_get_item (item);
+ label = gtk_list_item_get_child (item);
+
+ gtk_label_set_label (GTK_LABEL (label), gtk_printer_get_name (printer));
+}
+
+static void
+populate_dialog (GtkCustomPaperUnixDialog *dialog)
+{
+ GtkDialog *cpu_dialog = GTK_DIALOG (dialog);
+ GtkWidget *content_area;
+ GtkWidget *grid, *label, *widget, *frame, *combo;
+ GtkWidget *hbox, *vbox, *listview, *scrolled, *toolbar, *button;
+ GtkUnit user_units;
+ GtkSelectionModel *model;
+ GtkListItemFactory *factory;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ content_area = gtk_dialog_get_content_area (cpu_dialog);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18);
+ gtk_widget_set_margin_start (hbox, 20);
+ gtk_widget_set_margin_end (hbox, 20);
+ gtk_widget_set_margin_top (hbox, 20);
+ gtk_widget_set_margin_bottom (hbox, 20);
+ gtk_box_append (GTK_BOX (content_area), hbox);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_append (GTK_BOX (hbox), vbox);
+
+ scrolled = gtk_scrolled_window_new ();
+ gtk_widget_set_vexpand (scrolled, TRUE);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled), TRUE);
+ gtk_box_append (GTK_BOX (vbox), scrolled);
+
+ model = GTK_SELECTION_MODEL (gtk_single_selection_new (g_object_ref (G_LIST_MODEL (dialog->custom_paper_list))));
+ g_signal_connect (model, "notify::selected", G_CALLBACK (selected_custom_paper_changed), dialog);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
+ g_signal_connect (factory, "unbind", G_CALLBACK (unbind_item), NULL);
+
+ listview = gtk_list_view_new (model, factory);
+ gtk_widget_set_size_request (listview, 140, -1);
+
+ dialog->listview = listview;
+
+ gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), listview);
+
+ toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ gtk_widget_add_css_class (toolbar, "linked");
+
+ gtk_box_append (GTK_BOX (vbox), toolbar);
+
+ button = gtk_button_new_from_icon_name ("list-add-symbolic");
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_custom_paper), dialog);
+
+ gtk_box_append (GTK_BOX (toolbar), button);
+
+ button = gtk_button_new_from_icon_name ("list-remove-symbolic");
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (remove_custom_paper), dialog);
+
+ gtk_box_append (GTK_BOX (toolbar), button);
+
+ user_units = _gtk_print_get_default_user_units ();
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18);
+ dialog->values_box = vbox;
+ gtk_box_append (GTK_BOX (hbox), vbox);
+
+ grid = gtk_grid_new ();
+
+ gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+ gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+
+ label = gtk_label_new_with_mnemonic (_("_Width:"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
+
+ widget = new_unit_widget (dialog, user_units, label);
+ dialog->width_widget = widget;
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
+
+ label = gtk_label_new_with_mnemonic (_("_Height:"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
+
+ widget = new_unit_widget (dialog, user_units, label);
+ dialog->height_widget = widget;
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
+
+ frame = wrap_in_frame (_("Paper Size"), grid);
+ gtk_box_append (GTK_BOX (vbox), frame);
+
+ grid = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+ gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+
+ label = gtk_label_new_with_mnemonic (_("_Top:"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
+
+ widget = new_unit_widget (dialog, user_units, label);
+ dialog->top_widget = widget;
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
+
+ label = gtk_label_new_with_mnemonic (_("_Bottom:"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
+
+ widget = new_unit_widget (dialog, user_units, label);
+ dialog->bottom_widget = widget;
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
+
+ label = gtk_label_new_with_mnemonic (_("_Left:"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
+
+ widget = new_unit_widget (dialog, user_units, label);
+ dialog->left_widget = widget;
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, 2, 1, 1);
+
+ label = gtk_label_new_with_mnemonic (_("_Right:"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
+
+ widget = new_unit_widget (dialog, user_units, label);
+ dialog->right_widget = widget;
+ gtk_grid_attach (GTK_GRID (grid), widget, 1, 3, 1, 1);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_grid_attach (GTK_GRID (grid), hbox, 0, 4, 2, 1);
+
+ combo = gtk_drop_down_new (g_object_ref (dialog->printer_list), NULL);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
+ gtk_drop_down_set_factory (GTK_DROP_DOWN (combo), factory);
+ g_object_unref (factory);
+
+ dialog->printer_combo = combo;
+
+ dialog->printer_inserted_tag =
+ g_signal_connect_swapped (dialog->printer_list, "items-changed",
+ G_CALLBACK (update_combo_sensitivity_from_printers), dialog);
+ update_combo_sensitivity_from_printers (dialog);
+
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), 0);
+ gtk_box_append (GTK_BOX (hbox), combo);
+
+ g_signal_connect_swapped (combo, "notify::selected",
+ G_CALLBACK (margins_from_printer_changed), dialog);
+
+ frame = wrap_in_frame (_("Paper Margins"), grid);
+ gtk_box_append (GTK_BOX (vbox), frame);
+
+ update_custom_widgets_from_list (dialog);
+
+ if (g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)) == 0)
+ add_custom_paper (dialog);
+
+ load_print_backends (dialog);
+}
--- /dev/null
+/* GtkCustomPaperUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG (gtk_custom_paper_unix_dialog_get_type ())
+#define GTK_CUSTOM_PAPER_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG, GtkCustomPaperUnixDialog))
+#define GTK_IS_CUSTOM_PAPER_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG))
+
+typedef struct _GtkCustomPaperUnixDialog GtkCustomPaperUnixDialog;
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_custom_paper_unix_dialog_get_type (void) G_GNUC_CONST;
+GtkWidget * _gtk_custom_paper_unix_dialog_new (GtkWindow *parent,
+ const char *title);
+GtkUnit _gtk_print_get_default_user_units (void);
+void gtk_print_load_custom_papers (GListStore *store);
+GList * _gtk_load_custom_papers (void);
+
+
+G_END_DECLS
+
--- /dev/null
+/* GtkPageSetupUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ * Copyright © 2006, 2007, 2008 Christian Persch
+ *
+ * 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 <string.h>
+#include <locale.h>
+
+#include <glib/gi18n-lib.h>
+#include "gtkprivate.h"
+
+#include "gtkbutton.h"
+#include "gtkscrolledwindow.h"
+#include "gtkcheckbutton.h"
+#include "gtklabel.h"
+#include "gtkgrid.h"
+
+#include "gtkpagesetupunixdialog.h"
+#include "gtkcustompaperunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkpapersize.h"
+#include "gtkprintutilsprivate.h"
+#include "deprecated/gtkdialogprivate.h"
+
+/**
+ * GtkPageSetupUnixDialog:
+ *
+ * `GtkPageSetupUnixDialog` implements a page setup dialog for platforms
+ * which don’t provide a native page setup dialog, like Unix.
+ *
+ * 
+ *
+ * It can be used very much like any other GTK dialog, at the
+ * cost of the portability offered by the high-level printing
+ * API in [class@Gtk.PrintOperation].
+ *
+ * ## CSS nodes
+ *
+ * `GtkPageSetupUnixDialog` has a single CSS node with the name `window` and
+ * style class `.pagesetup`.
+ */
+
+typedef struct _GtkPageSetupUnixDialogClass GtkPageSetupUnixDialogClass;
+
+struct _GtkPageSetupUnixDialog
+{
+ GtkDialog parent_instance;
+
+ GListModel *printer_list;
+ GListStore *page_setup_list;
+ GListStore *custom_paper_list;
+ GListStore *manage_papers_list;
+ GListStore *paper_size_list;
+
+ GList *print_backends;
+
+ GtkWidget *printer_combo;
+ GtkWidget *paper_size_combo;
+ GtkWidget *paper_size_label;
+
+ GtkWidget *portrait_radio;
+ GtkWidget *reverse_portrait_radio;
+ GtkWidget *landscape_radio;
+ GtkWidget *reverse_landscape_radio;
+
+ gulong request_details_tag;
+ GtkPrinter *request_details_printer;
+
+ GtkPrintSettings *print_settings;
+
+ gboolean internal_change;
+
+ /* Save last setup so we can re-set it after selecting manage custom sizes */
+ GtkPageSetup *last_setup;
+};
+
+struct _GtkPageSetupUnixDialogClass
+{
+ GtkDialogClass parent_class;
+};
+
+
+/* Keep these in line with GtkListStores defined in gtkpagesetupunixprintdialog.ui */
+enum {
+ PRINTER_LIST_COL_NAME,
+ PRINTER_LIST_COL_PRINTER,
+ PRINTER_LIST_N_COLS
+};
+
+enum {
+ PAGE_SETUP_LIST_COL_PAGE_SETUP,
+ PAGE_SETUP_LIST_COL_IS_SEPARATOR,
+ PAGE_SETUP_LIST_N_COLS
+};
+
+G_DEFINE_TYPE (GtkPageSetupUnixDialog, gtk_page_setup_unix_dialog, GTK_TYPE_DIALOG)
+
+static void gtk_page_setup_unix_dialog_finalize (GObject *object);
+static void fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
+ GtkPrinter *printer);
+static void printer_changed_callback (GtkDropDown *combo_box,
+ GParamSpec *pspec,
+ GtkPageSetupUnixDialog *dialog);
+static void paper_size_changed (GtkDropDown *combo_box,
+ GParamSpec *pspec,
+ GtkPageSetupUnixDialog *dialog);
+static void load_print_backends (GtkPageSetupUnixDialog *dialog);
+
+
+static const char common_paper_sizes[][16] = {
+ "na_letter",
+ "na_legal",
+ "iso_a4",
+ "iso_a5",
+ "roc_16k",
+ "iso_b5",
+ "jis_b5",
+ "na_number-10",
+ "iso_dl",
+ "jpn_chou3",
+ "na_ledger",
+ "iso_a3"
+};
+
+
+static void
+gtk_page_setup_unix_dialog_class_init (GtkPageSetupUnixDialogClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ widget_class = GTK_WIDGET_CLASS (class);
+
+ object_class->finalize = gtk_page_setup_unix_dialog_finalize;
+
+ /* Bind class to template
+ */
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gtk/libgtk/ui/gtkpagesetupunixdialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, printer_combo);
+ gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, paper_size_combo);
+ gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, paper_size_label);
+ gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, portrait_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, reverse_portrait_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, landscape_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPageSetupUnixDialog, reverse_landscape_radio);
+
+ gtk_widget_class_bind_template_callback (widget_class, printer_changed_callback);
+ gtk_widget_class_bind_template_callback (widget_class, paper_size_changed);
+}
+
+static void
+setup_paper_size_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new ("");
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_paper_size_list_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item,
+ GtkPageSetupUnixDialog *self)
+{
+ GtkPageSetup *page_setup;
+ GtkWidget *label;
+ guint pos;
+ GListModel *papers;
+ GListModel *model;
+ gpointer first;
+
+ page_setup = gtk_list_item_get_item (item);
+ label = gtk_list_item_get_child (item);
+
+ pos = gtk_list_item_get_position (item);
+ papers = gtk_drop_down_get_model (GTK_DROP_DOWN (self->paper_size_combo));
+ model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), pos);
+ if (model != G_LIST_MODEL (self->manage_papers_list))
+ {
+ GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
+ gtk_label_set_text (GTK_LABEL (label), gtk_paper_size_get_display_name (paper_size));
+ }
+ else
+ gtk_label_set_text (GTK_LABEL (label), _("Manage Custom Sizes…"));
+
+ first = g_list_model_get_item (model, 0);
+ g_object_unref (first);
+ if (pos != 0 &&
+ page_setup == GTK_PAGE_SETUP (first))
+ gtk_widget_add_css_class (gtk_widget_get_parent (label), "separator");
+ else
+ gtk_widget_remove_css_class (gtk_widget_get_parent (label), "separator");
+}
+
+static void
+bind_paper_size_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item,
+ GtkPageSetupUnixDialog *self)
+{
+ GtkWidget *label;
+
+ bind_paper_size_list_item (factory, item, self);
+
+ label = gtk_list_item_get_child (item);
+ gtk_widget_remove_css_class (label, "separator-before");
+}
+
+static gboolean
+match_func (gpointer item, gpointer user_data)
+{
+ return !gtk_printer_is_virtual (GTK_PRINTER (item));
+}
+
+static void
+setup_printer_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new ("");
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_printer_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item,
+ GtkPageSetupUnixDialog *self)
+{
+ GtkPrinter *printer;
+ GtkWidget *label;
+ const char *location;
+ const char *name;
+ char *str;
+
+ printer = gtk_list_item_get_item (item);
+ label = gtk_list_item_get_child (item);
+
+ name = gtk_printer_get_name (printer);
+ location = gtk_printer_get_location (printer);
+ str = g_strdup_printf ("<b>%s</b>\n%s", name, location ? location : "");
+ gtk_label_set_markup (GTK_LABEL (label), str);
+ g_free (str);
+}
+
+static void
+gtk_page_setup_unix_dialog_init (GtkPageSetupUnixDialog *dialog)
+{
+ GtkListItemFactory *factory;
+ GListStore *store;
+ GListModel *paper_size_list;
+ GtkPrinter *printer;
+ GListStore *printer_list;
+ GListStore *printer_list_list;
+ GListModel *full_list;
+ GtkFilter *filter;
+ GtkPageSetup *page_setup;
+
+ dialog->internal_change = TRUE;
+ dialog->print_backends = NULL;
+
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Apply"), GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+ dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+ dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+ page_setup = gtk_page_setup_new ();
+ g_list_store_append (dialog->manage_papers_list, page_setup);
+ g_object_unref (page_setup);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
+ gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+ g_object_unref (factory);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
+ gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+ g_object_unref (factory);
+
+ store = g_list_store_new (G_TYPE_LIST_MODEL);
+ g_list_store_append (store, dialog->page_setup_list);
+ g_list_store_append (store, dialog->custom_paper_list);
+ g_list_store_append (store, dialog->manage_papers_list);
+ paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
+ gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
+ g_object_unref (paper_size_list);
+
+ /* Do this in code, we want the translatable strings without the markup */
+ printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
+ printer_list = g_list_store_new (GTK_TYPE_PRINTER);
+ printer = gtk_printer_new (_("Any Printer"), NULL, FALSE);
+ gtk_printer_set_location (printer, _("For portable documents"));
+ g_list_store_append (printer_list, printer);
+ g_object_unref (printer);
+ g_list_store_append (printer_list_list, printer_list);
+ g_object_unref (printer_list);
+
+ full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
+
+ filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
+ dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
+ gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->printer_combo), factory);
+ g_object_unref (factory);
+
+ gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->printer_combo), dialog->printer_list);
+ printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
+
+ /* Load data */
+ gtk_print_load_custom_papers (dialog->custom_paper_list);
+ load_print_backends (dialog);
+ dialog->internal_change = FALSE;
+}
+
+static void
+gtk_page_setup_unix_dialog_finalize (GObject *object)
+{
+ GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
+ GList *node;
+
+ if (dialog->request_details_tag)
+ {
+ g_signal_handler_disconnect (dialog->request_details_printer,
+ dialog->request_details_tag);
+ g_object_unref (dialog->request_details_printer);
+ dialog->request_details_printer = NULL;
+ dialog->request_details_tag = 0;
+ }
+
+ g_clear_object (&dialog->printer_list);
+ g_clear_object (&dialog->page_setup_list);
+ g_clear_object (&dialog->custom_paper_list);
+ g_clear_object (&dialog->manage_papers_list);
+
+ if (dialog->print_settings)
+ {
+ g_object_unref (dialog->print_settings);
+ dialog->print_settings = NULL;
+ }
+
+ for (node = dialog->print_backends; node != NULL; node = node->next)
+ gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
+ g_list_free_full (dialog->print_backends, g_object_unref);
+ dialog->print_backends = NULL;
+
+ G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
+}
+
+static void
+load_print_backends (GtkPageSetupUnixDialog *dialog)
+{
+ GListModel *full_list;
+ GListStore *printer_list_list;
+ GList *node;
+
+ full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
+ printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
+
+ if (g_module_supported ())
+ dialog->print_backends = gtk_print_backend_load_modules ();
+
+ for (node = dialog->print_backends; node != NULL; node = node->next)
+ {
+ GtkPrintBackend *backend = node->data;
+ g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
+ }
+}
+
+static GtkPageSetup *
+get_current_page_setup (GtkPageSetupUnixDialog *dialog)
+{
+ guint selected;
+ GListModel *model;
+
+ selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->paper_size_combo));
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+ if (selected != GTK_INVALID_LIST_POSITION)
+ return g_list_model_get_item (model, selected);
+
+ return gtk_page_setup_new ();
+}
+
+static gboolean
+page_setup_is_equal (GtkPageSetup *a,
+ GtkPageSetup *b)
+{
+ return
+ gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+ gtk_page_setup_get_paper_size (b)) &&
+ gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
+ gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
+ gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
+ gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
+}
+
+static gboolean
+page_setup_is_same_size (GtkPageSetup *a,
+ GtkPageSetup *b)
+{
+ return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+ gtk_page_setup_get_paper_size (b));
+}
+
+static gboolean
+set_paper_size (GtkPageSetupUnixDialog *dialog,
+ GtkPageSetup *page_setup,
+ gboolean size_only,
+ gboolean add_item)
+{
+ GListModel *model;
+ GtkPageSetup *list_page_setup;
+ guint i;
+
+ if (page_setup == NULL)
+ return FALSE;
+
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+ for (i = 0; i < g_list_model_get_n_items (model); i++)
+ {
+ list_page_setup = g_list_model_get_item (model, i);
+ if (list_page_setup == NULL)
+ continue;
+
+ if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
+ (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
+ {
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+ g_object_unref (list_page_setup);
+ return TRUE;
+ }
+
+ g_object_unref (list_page_setup);
+ }
+
+ if (add_item)
+ {
+ i = g_list_model_get_n_items (model);
+ g_list_store_append (dialog->page_setup_list, page_setup);
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
+ GtkPrinter *printer)
+{
+ GList *list, *l;
+ GtkPageSetup *current_page_setup, *page_setup;
+ GtkPaperSize *paper_size;
+ int i;
+
+ g_list_store_remove_all (dialog->page_setup_list);
+
+ if (printer == NULL)
+ {
+ for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
+ {
+ page_setup = gtk_page_setup_new ();
+ paper_size = gtk_paper_size_new (common_paper_sizes[i]);
+ gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
+ gtk_paper_size_free (paper_size);
+
+ g_list_store_append (dialog->page_setup_list, page_setup);
+ g_object_unref (page_setup);
+ }
+ }
+ else
+ {
+ list = gtk_printer_list_papers (printer);
+ /* TODO: We should really sort this list so interesting size
+ are at the top */
+ for (l = list; l != NULL; l = l->next)
+ {
+ page_setup = l->data;
+ g_list_store_append (dialog->page_setup_list, page_setup);
+ g_object_unref (page_setup);
+ }
+ g_list_free (list);
+ }
+
+ current_page_setup = NULL;
+
+ /* When selecting a different printer, select its default paper size */
+ if (printer != NULL)
+ current_page_setup = gtk_printer_get_default_page_size (printer);
+
+ if (current_page_setup == NULL)
+ current_page_setup = get_current_page_setup (dialog);
+
+ if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
+ set_paper_size (dialog, current_page_setup, TRUE, TRUE);
+
+ if (current_page_setup)
+ g_object_unref (current_page_setup);
+}
+
+static void
+printer_changed_finished_callback (GtkPrinter *printer,
+ gboolean success,
+ GtkPageSetupUnixDialog *dialog)
+{
+ g_signal_handler_disconnect (dialog->request_details_printer,
+ dialog->request_details_tag);
+ g_object_unref (dialog->request_details_printer);
+ dialog->request_details_tag = 0;
+ dialog->request_details_printer = NULL;
+
+ if (success)
+ fill_paper_sizes_from_printer (dialog, printer);
+
+}
+
+static void
+printer_changed_callback (GtkDropDown *combo_box,
+ GParamSpec *pspec,
+ GtkPageSetupUnixDialog *dialog)
+{
+ GtkPrinter *printer;
+ guint selected;
+
+ if (dialog->request_details_tag)
+ {
+ g_signal_handler_disconnect (dialog->request_details_printer,
+ dialog->request_details_tag);
+ g_object_unref (dialog->request_details_printer);
+ dialog->request_details_printer = NULL;
+ dialog->request_details_tag = 0;
+ }
+
+ selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
+ if (selected != GTK_INVALID_LIST_POSITION)
+ {
+ GListModel *model;
+
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
+ printer = g_list_model_get_item (model, selected);
+ if (strcmp (gtk_printer_get_name (printer), _("Any Printer")) == 0)
+ g_clear_object (&printer);
+
+ if (printer == NULL ||
+ gtk_printer_has_details (printer))
+ fill_paper_sizes_from_printer (dialog, printer);
+ else
+ {
+ dialog->request_details_printer = g_object_ref (printer);
+ dialog->request_details_tag =
+ g_signal_connect (printer, "details-acquired",
+ G_CALLBACK (printer_changed_finished_callback), dialog);
+ gtk_printer_request_details (printer);
+ }
+
+ if (printer)
+ g_object_unref (printer);
+
+ if (dialog->print_settings)
+ {
+ const char *name = NULL;
+
+ if (printer)
+ name = gtk_printer_get_name (printer);
+
+ gtk_print_settings_set (dialog->print_settings,
+ "format-for-printer", name);
+ }
+ }
+}
+
+/* We do this munging because we don't want to show zero digits
+ after the decimal point, and not to many such digits if they
+ are nonzero. I wish printf let you specify max precision for %f... */
+static char *
+double_to_string (double d,
+ GtkUnit unit)
+{
+ char *val, *p;
+ struct lconv *locale_data;
+ const char *decimal_point;
+ int decimal_point_len;
+
+ locale_data = localeconv ();
+ decimal_point = locale_data->decimal_point;
+ decimal_point_len = strlen (decimal_point);
+
+ /* Max two decimal digits for inch, max one for mm */
+ if (unit == GTK_UNIT_INCH)
+ val = g_strdup_printf ("%.2f", d);
+ else
+ val = g_strdup_printf ("%.1f", d);
+
+ if (strstr (val, decimal_point))
+ {
+ p = val + strlen (val) - 1;
+ while (*p == '0')
+ p--;
+ if (p - val + 1 >= decimal_point_len &&
+ strncmp (p - (decimal_point_len - 1), decimal_point, decimal_point_len) == 0)
+ p -= decimal_point_len;
+ p[1] = '\0';
+ }
+
+ return val;
+}
+
+
+static void
+custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
+ int response_id,
+ gpointer user_data)
+{
+ GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (user_data);
+ GtkPageSetup *last_page_setup;
+
+ dialog->internal_change = TRUE;
+ gtk_print_load_custom_papers (dialog->custom_paper_list);
+ printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
+ dialog->internal_change = FALSE;
+
+ if (dialog->last_setup)
+ last_page_setup = g_object_ref (dialog->last_setup);
+ else
+ last_page_setup = gtk_page_setup_new (); /* "good" default */
+ set_paper_size (dialog, last_page_setup, FALSE, TRUE);
+ g_object_unref (last_page_setup);
+
+ gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
+}
+
+static void
+paper_size_changed (GtkDropDown *combo_box,
+ GParamSpec *pspec,
+ GtkPageSetupUnixDialog *dialog)
+{
+ GtkPageSetup *page_setup, *last_page_setup;
+ guint selected;
+ GtkUnit unit;
+ char *str, *w, *h;
+ char *top, *bottom, *left, *right;
+ GtkLabel *label;
+ const char *unit_str;
+
+ if (dialog->internal_change)
+ return;
+
+ label = GTK_LABEL (dialog->paper_size_label);
+
+ selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
+ if (selected != GTK_INVALID_LIST_POSITION)
+ {
+ GListModel *papers, *model;
+
+ papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+ page_setup = g_list_model_get_item (papers, selected);
+ model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
+
+ if (model == G_LIST_MODEL (dialog->manage_papers_list))
+ {
+ GtkWidget *custom_paper_dialog;
+
+ /* Change from "manage" menu item to last value */
+ if (dialog->last_setup)
+ last_page_setup = g_object_ref (dialog->last_setup);
+ else
+ last_page_setup = gtk_page_setup_new (); /* "good" default */
+ set_paper_size (dialog, last_page_setup, FALSE, TRUE);
+ g_object_unref (last_page_setup);
+
+ /* And show the custom paper dialog */
+ custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), NULL);
+ g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
+ gtk_window_present (GTK_WINDOW (custom_paper_dialog));
+
+ g_object_unref (page_setup);
+
+ return;
+ }
+
+ if (dialog->last_setup)
+ g_object_unref (dialog->last_setup);
+
+ dialog->last_setup = g_object_ref (page_setup);
+
+ unit = _gtk_print_get_default_user_units ();
+
+ if (unit == GTK_UNIT_MM)
+ unit_str = _("mm");
+ else
+ unit_str = _("inch");
+
+ w = double_to_string (gtk_page_setup_get_paper_width (page_setup, unit),
+ unit);
+ h = double_to_string (gtk_page_setup_get_paper_height (page_setup, unit),
+ unit);
+ str = g_strdup_printf ("%s × %s %s", w, h, unit_str);
+ g_free (w);
+ g_free (h);
+
+ gtk_label_set_text (label, str);
+ g_free (str);
+
+ top = double_to_string (gtk_page_setup_get_top_margin (page_setup, unit), unit);
+ bottom = double_to_string (gtk_page_setup_get_bottom_margin (page_setup, unit), unit);
+ left = double_to_string (gtk_page_setup_get_left_margin (page_setup, unit), unit);
+ right = double_to_string (gtk_page_setup_get_right_margin (page_setup, unit), unit);
+
+ str = g_strdup_printf (_("Margins:\n"
+ " Left: %s %s\n"
+ " Right: %s %s\n"
+ " Top: %s %s\n"
+ " Bottom: %s %s"
+ ),
+ left, unit_str,
+ right, unit_str,
+ top, unit_str,
+ bottom, unit_str);
+ g_free (top);
+ g_free (bottom);
+ g_free (left);
+ g_free (right);
+
+ gtk_widget_set_tooltip_text (dialog->paper_size_label, str);
+ g_free (str);
+
+ g_object_unref (page_setup);
+ }
+ else
+ {
+ gtk_label_set_text (label, "");
+ gtk_widget_set_tooltip_text (dialog->paper_size_label, NULL);
+ if (dialog->last_setup)
+ g_object_unref (dialog->last_setup);
+ dialog->last_setup = NULL;
+ }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_new:
+ * @title: (nullable): the title of the dialog
+ * @parent: (nullable): transient parent of the dialog
+ *
+ * Creates a new page setup dialog.
+ *
+ * Returns: the new `GtkPageSetupUnixDialog`
+ */
+GtkWidget *
+gtk_page_setup_unix_dialog_new (const char *title,
+ GtkWindow *parent)
+{
+ GtkWidget *result;
+
+ if (title == NULL)
+ title = _("Page Setup");
+
+ result = g_object_new (GTK_TYPE_PAGE_SETUP_UNIX_DIALOG,
+ "title", title,
+ NULL);
+
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (result), parent);
+
+ return result;
+}
+
+static GtkPageOrientation
+get_orientation (GtkPageSetupUnixDialog *dialog)
+{
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->portrait_radio)))
+ return GTK_PAGE_ORIENTATION_PORTRAIT;
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->landscape_radio)))
+ return GTK_PAGE_ORIENTATION_LANDSCAPE;
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio)))
+ return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
+ return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
+}
+
+static void
+set_orientation (GtkPageSetupUnixDialog *dialog,
+ GtkPageOrientation orientation)
+{
+ switch (orientation)
+ {
+ case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_portrait_radio), TRUE);
+ break;
+ case GTK_PAGE_ORIENTATION_PORTRAIT:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->portrait_radio), TRUE);
+ break;
+ case GTK_PAGE_ORIENTATION_LANDSCAPE:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->landscape_radio), TRUE);
+ break;
+ case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio), TRUE);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_set_page_setup:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ * @page_setup: a `GtkPageSetup`
+ *
+ * Sets the `GtkPageSetup` from which the page setup
+ * dialog takes its values.
+ */
+void
+gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
+ GtkPageSetup *page_setup)
+{
+ if (page_setup)
+ {
+ set_paper_size (dialog, page_setup, FALSE, TRUE);
+ set_orientation (dialog, gtk_page_setup_get_orientation (page_setup));
+ }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_get_page_setup:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ *
+ * Gets the currently selected page setup from the dialog.
+ *
+ * Returns: (transfer none): the current page setup
+ */
+GtkPageSetup *
+gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog)
+{
+ GtkPageSetup *page_setup;
+
+ page_setup = get_current_page_setup (dialog);
+
+ gtk_page_setup_set_orientation (page_setup, get_orientation (dialog));
+
+ return page_setup;
+}
+
+static gboolean
+set_active_printer (GtkPageSetupUnixDialog *dialog,
+ const char *printer_name)
+{
+ guint i, n;
+ GtkPrinter *printer;
+
+ if (!printer_name)
+ return FALSE;
+
+ for (i = 0, n = g_list_model_get_n_items (dialog->printer_list); i < n; i++)
+ {
+ printer = g_list_model_get_item (dialog->printer_list, i);
+
+ if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
+ {
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), i);
+ g_object_unref (printer);
+
+ return TRUE;
+ }
+
+ g_object_unref (printer);
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_page_setup_unix_dialog_set_print_settings:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ * @print_settings: (nullable): a `GtkPrintSettings`
+ *
+ * Sets the `GtkPrintSettings` from which the page setup dialog
+ * takes its values.
+ */
+void
+gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
+ GtkPrintSettings *print_settings)
+{
+ const char *format_for_printer;
+
+ if (dialog->print_settings == print_settings) return;
+
+ if (dialog->print_settings)
+ g_object_unref (dialog->print_settings);
+
+ dialog->print_settings = print_settings;
+
+ if (print_settings)
+ {
+ g_object_ref (print_settings);
+
+ format_for_printer = gtk_print_settings_get (print_settings, "format-for-printer");
+
+ /* Set printer if in list, otherwise set when
+ * that printer is added
+ */
+ set_active_printer (dialog, format_for_printer);
+ }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_get_print_settings:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ *
+ * Gets the current print settings from the dialog.
+ *
+ * Returns: (transfer none) (nullable): the current print settings
+ **/
+GtkPrintSettings *
+gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog)
+{
+ return dialog->print_settings;
+}
--- /dev/null
+/* GtkPageSetupUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.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/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PAGE_SETUP_UNIX_DIALOG (gtk_page_setup_unix_dialog_get_type ())
+#define GTK_PAGE_SETUP_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG, GtkPageSetupUnixDialog))
+#define GTK_IS_PAGE_SETUP_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG))
+
+
+typedef struct _GtkPageSetupUnixDialog GtkPageSetupUnixDialog;
+
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_page_setup_unix_dialog_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkWidget * gtk_page_setup_unix_dialog_new (const char *title,
+ GtkWindow *parent);
+GDK_AVAILABLE_IN_ALL
+void gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
+ GtkPageSetup *page_setup);
+GDK_AVAILABLE_IN_ALL
+GtkPageSetup * gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
+ GtkPrintSettings *print_settings);
+GDK_AVAILABLE_IN_ALL
+GtkPrintSettings *gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog);
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation.c: Print Operation
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#ifndef _MSC_VER
+#ifndef _WIN32_WINNT
+/* Vista or newer */
+#define _WIN32_WINNT 0x0600
+#endif
+#ifndef WINVER
+#define WINVER _WIN32_WINNT
+#endif
+#endif
+
+#include "config.h"
+#include "gtkprint-win32.h"
+
+void
+gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames)
+{
+ g_free (devnames->driver);
+ g_free (devnames->device);
+ g_free (devnames->output);
+ g_free (devnames);
+}
+
+GtkPrintWin32Devnames *
+gtk_print_win32_devnames_from_win32 (HGLOBAL global)
+{
+ LPDEVNAMES win = GlobalLock (global);
+ gunichar2 *data = (gunichar2 *)win;
+ GtkPrintWin32Devnames *devnames = g_new (GtkPrintWin32Devnames, 1);
+
+ devnames->driver = g_utf16_to_utf8 (data + win->wDriverOffset,
+ -1, NULL, NULL, NULL);
+ devnames->device = g_utf16_to_utf8 (data + win->wDeviceOffset,
+ -1, NULL, NULL, NULL);
+ devnames->output = g_utf16_to_utf8 (data + win->wOutputOffset,
+ -1, NULL, NULL, NULL);
+ devnames->flags = win->wDefault;
+
+ GlobalUnlock (global);
+
+ return devnames;
+}
+
+HGLOBAL
+gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames)
+{
+ HGLOBAL global;
+ LPDEVNAMES windevnames;
+ gunichar2 *data;
+ gunichar2 *driver, *device, *output;
+ glong driver_len, device_len, output_len;
+ int i;
+
+ driver = g_utf8_to_utf16 (devnames->driver, -1, NULL, &driver_len, NULL);
+ device = g_utf8_to_utf16 (devnames->device, -1, NULL, &device_len, NULL);
+ output = g_utf8_to_utf16 (devnames->output, -1, NULL, &output_len, NULL);
+
+ global = GlobalAlloc (GMEM_MOVEABLE,
+ sizeof (DEVNAMES) +
+ (driver_len + 1) * 2 +
+ (device_len + 1) * 2 +
+ (output_len + 1) * 2);
+
+ windevnames = GlobalLock (global);
+ data = (gunichar2 *)windevnames;
+ i = sizeof(DEVNAMES) / sizeof (gunichar2);
+
+ windevnames->wDriverOffset = i;
+ memcpy (data + i, driver, (driver_len + 1) * sizeof (gunichar2));
+ i += driver_len + 1;
+ windevnames->wDeviceOffset = i;
+ memcpy (data + i, device, (device_len + 1) * sizeof (gunichar2));
+ i += device_len + 1;
+ windevnames->wOutputOffset = i;
+ memcpy (data + i, output, (output_len + 1) * sizeof (gunichar2));
+ i += output_len + 1;
+ windevnames->wDefault = devnames->flags;
+ GlobalUnlock (global);
+
+ g_free (driver);
+ g_free (device);
+ g_free (output);
+
+ return global;
+}
+
+HGLOBAL
+gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer_name)
+{
+ HGLOBAL global;
+ GtkPrintWin32Devnames *devnames;
+
+ devnames = gtk_print_win32_devnames_from_printer_name(printer_name);
+ if (devnames)
+ {
+ global = gtk_print_win32_devnames_to_win32 (devnames);
+ gtk_print_win32_devnames_free (devnames);
+ }
+ else
+ global = NULL;
+
+ return global;
+}
+
+/*
+ * Used to get printer device information from a printer name. This
+ * can fail if the user has no right to read printer properties, so
+ * this function can return NULL.
+ */
+GtkPrintWin32Devnames *
+gtk_print_win32_devnames_from_printer_name (const char *printer_name)
+{
+ HANDLE hprinter;
+ gunichar2* win32_printer_name;
+ GtkPrintWin32Devnames *devnames;
+
+ win32_printer_name = g_utf8_to_utf16 (printer_name, -1, NULL, NULL, NULL);
+ if (OpenPrinterW (win32_printer_name, &hprinter, NULL))
+ {
+ DWORD needed;
+ PRINTER_INFO_2W* printer_info;
+
+ GetPrinterW (hprinter, 2, NULL, 0, &needed);
+ printer_info = (PRINTER_INFO_2W* )g_malloc ((gsize) needed);
+ GetPrinterW (hprinter, 2, (LPBYTE) printer_info, needed, &needed);
+ devnames = g_new (GtkPrintWin32Devnames, 1);
+ devnames->driver = g_utf16_to_utf8 (printer_info->pDriverName, -1, NULL, NULL, NULL);
+ devnames->device = g_strdup (printer_name);
+ devnames->output = g_utf16_to_utf8 (printer_info->pPortName, -1, NULL, NULL, NULL);
+ devnames->flags = 0;
+ ClosePrinter (hprinter);
+ g_free (printer_info);
+ }
+ else
+ {
+ /* Could not open printer */
+ devnames = NULL;
+ }
+ g_free (win32_printer_name);
+
+ return devnames;
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprint-win32.h: Win32 Print utils
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "win32/gdkwin32.h"
+
+G_BEGIN_DECLS
+
+#ifndef START_PAGE_GENERAL
+#define START_PAGE_GENERAL 0xffffffff
+#endif
+
+#ifndef PD_RESULT_CANCEL
+#define PD_RESULT_CANCEL 0
+#define PD_RESULT_PRINT 1
+#define PD_RESULT_APPLY 2
+#endif
+
+#ifndef PD_NOCURRENTPAGE
+#define PD_NOCURRENTPAGE 0x00800000
+#endif
+
+#ifndef PD_CURRENTPAGE
+#define PD_CURRENTPAGE 0x00400000
+#endif
+
+typedef struct {
+ char *driver;
+ char *device;
+ char *output;
+ int flags;
+} GtkPrintWin32Devnames;
+
+GDK_AVAILABLE_IN_ALL
+void gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames);
+GDK_AVAILABLE_IN_ALL
+GtkPrintWin32Devnames *gtk_print_win32_devnames_from_win32 (HGLOBAL global);
+GDK_AVAILABLE_IN_ALL
+GtkPrintWin32Devnames *gtk_print_win32_devnames_from_printer_name (const char *printer);
+GDK_AVAILABLE_IN_ALL
+HGLOBAL gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames);
+GDK_AVAILABLE_IN_ALL
+HGLOBAL gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer);
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintbackendprivate.h: Abstract printer backend interfaces
+ * Copyright (C) 2003, Red Hat, Inc.
+ *
+ * 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 <string.h>
+
+#include <gmodule.h>
+
+#include <glib/gi18n-lib.h>
+#include "gtkdebug.h"
+#include "gtkmodulesprivate.h"
+#include "gtkmarshalers.h"
+#include "gtkprivate.h"
+#include "gtkprintbackendprivate.h"
+
+
+static void gtk_print_backend_finalize (GObject *object);
+static void gtk_print_backend_dispose (GObject *object);
+static void gtk_print_backend_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_print_backend_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+struct _GtkPrintBackendPrivate
+{
+ GListStore *printers;
+ guint printer_list_requested : 1;
+ guint printer_list_done : 1;
+ GtkPrintBackendStatus status;
+ char **auth_info_required;
+ char **auth_info;
+ gboolean store_auth_info;
+};
+
+enum {
+ PRINTER_LIST_CHANGED,
+ PRINTER_LIST_DONE,
+ PRINTER_ADDED,
+ PRINTER_REMOVED,
+ PRINTER_STATUS_CHANGED,
+ REQUEST_PASSWORD,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum
+{
+ PROP_ZERO,
+ PROP_STATUS
+};
+
+static GObjectClass *backend_parent_class;
+
+GQuark
+gtk_print_backend_error_quark (void)
+{
+ static GQuark quark = 0;
+ if (quark == 0)
+ quark = g_quark_from_static_string ("gtk-print-backend-error-quark");
+ return quark;
+}
+
+void
+gtk_print_backends_init (void)
+{
+ GIOExtensionPoint *ep;
+ GIOModuleScope *scope;
+ char **paths;
+ int i;
+
+ GTK_DEBUG (MODULES, "Registering extension point %s", GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
+
+ ep = g_io_extension_point_register (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
+ g_io_extension_point_set_required_type (ep, GTK_TYPE_PRINT_BACKEND);
+
+ scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
+
+ paths = _gtk_get_module_path ("printbackends");
+ for (i = 0; paths[i]; i++)
+ {
+ GTK_DEBUG (MODULES, "Scanning io modules in %s", paths[i]);
+ g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
+ }
+ g_strfreev (paths);
+
+ g_io_module_scope_free (scope);
+
+ if (GTK_DEBUG_CHECK (MODULES))
+ {
+ GList *list, *l;
+
+ list = g_io_extension_point_get_extensions (ep);
+ for (l = list; l; l = l->next)
+ {
+ GIOExtension *ext = l->data;
+ g_print ("extension: %s: type %s\n",
+ g_io_extension_get_name (ext),
+ g_type_name (g_io_extension_get_type (ext)));
+ }
+ }
+}
+
+/**
+ * gtk_print_backend_load_modules:
+ *
+ * Returns: (element-type GtkPrintBackend) (transfer container):
+ */
+GList *
+gtk_print_backend_load_modules (void)
+{
+ GList *result;
+ GtkPrintBackend *backend;
+ char *setting;
+ char **backends;
+ int i;
+ GtkSettings *settings;
+ GIOExtensionPoint *ep;
+
+ result = NULL;
+
+ ep = g_io_extension_point_lookup (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
+
+ settings = gtk_settings_get_default ();
+ if (settings)
+ g_object_get (settings, "gtk-print-backends", &setting, NULL);
+ else
+ setting = g_strdup (GTK_PRINT_BACKENDS);
+
+ backends = g_strsplit (setting, ",", -1);
+
+ for (i = 0; backends[i]; i++)
+ {
+ GIOExtension *ext;
+ GType type;
+
+ ext = g_io_extension_point_get_extension_by_name (ep, backends[i]);
+ if (!ext)
+ continue;
+
+ GTK_DEBUG (PRINTING, "Found %s print backend", backends[i]);
+
+ type = g_io_extension_get_type (ext);
+ backend = g_object_new (type, NULL);
+ result = g_list_append (result, backend);
+ }
+
+ g_strfreev (backends);
+ g_free (setting);
+
+ return result;
+}
+
+/*****************************************
+ * GtkPrintBackend *
+ *****************************************/
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
+
+static void fallback_printer_request_details (GtkPrinter *printer);
+static gboolean fallback_printer_mark_conflicts (GtkPrinter *printer,
+ GtkPrinterOptionSet *options);
+static gboolean fallback_printer_get_hard_margins (GtkPrinter *printer,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right);
+static gboolean fallback_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
+ GtkPaperSize *paper_size,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right);
+static GList * fallback_printer_list_papers (GtkPrinter *printer);
+static GtkPageSetup * fallback_printer_get_default_page_size (GtkPrinter *printer);
+static GtkPrintCapabilities fallback_printer_get_capabilities (GtkPrinter *printer);
+static void request_password (GtkPrintBackend *backend,
+ gpointer auth_info_required,
+ gpointer auth_info_default,
+ gpointer auth_info_display,
+ gpointer auth_info_visible,
+ const char *prompt,
+ gboolean can_store_auth_info);
+
+static void
+gtk_print_backend_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+ GtkPrintBackendPrivate *priv = backend->priv;
+
+ switch (prop_id)
+ {
+ case PROP_STATUS:
+ priv->status = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_print_backend_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+ GtkPrintBackendPrivate *priv = backend->priv;
+
+ switch (prop_id)
+ {
+ case PROP_STATUS:
+ g_value_set_int (value, priv->status);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_print_backend_class_init (GtkPrintBackendClass *class)
+{
+ GObjectClass *object_class;
+ object_class = (GObjectClass *) class;
+
+ backend_parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = gtk_print_backend_finalize;
+ object_class->dispose = gtk_print_backend_dispose;
+ object_class->set_property = gtk_print_backend_set_property;
+ object_class->get_property = gtk_print_backend_get_property;
+
+ class->printer_request_details = fallback_printer_request_details;
+ class->printer_mark_conflicts = fallback_printer_mark_conflicts;
+ class->printer_get_hard_margins = fallback_printer_get_hard_margins;
+ class->printer_get_hard_margins_for_paper_size = fallback_printer_get_hard_margins_for_paper_size;
+ class->printer_list_papers = fallback_printer_list_papers;
+ class->printer_get_default_page_size = fallback_printer_get_default_page_size;
+ class->printer_get_capabilities = fallback_printer_get_capabilities;
+ class->request_password = request_password;
+
+ g_object_class_install_property (object_class,
+ PROP_STATUS,
+ g_param_spec_int ("status", NULL, NULL,
+ GTK_PRINT_BACKEND_STATUS_UNKNOWN,
+ GTK_PRINT_BACKEND_STATUS_UNAVAILABLE,
+ GTK_PRINT_BACKEND_STATUS_UNKNOWN,
+ GTK_PARAM_READWRITE));
+
+ signals[PRINTER_LIST_CHANGED] =
+ g_signal_new (I_("printer-list-changed"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+ signals[PRINTER_LIST_DONE] =
+ g_signal_new (I_("printer-list-done"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+ signals[PRINTER_ADDED] =
+ g_signal_new (I_("printer-added"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+ signals[PRINTER_REMOVED] =
+ g_signal_new (I_("printer-removed"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+ signals[PRINTER_STATUS_CHANGED] =
+ g_signal_new (I_("printer-status-changed"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+ signals[REQUEST_PASSWORD] =
+ g_signal_new (I_("request-password"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER,
+ G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
+}
+
+static void
+gtk_print_backend_init (GtkPrintBackend *backend)
+{
+ GtkPrintBackendPrivate *priv;
+
+ priv = backend->priv = gtk_print_backend_get_instance_private (backend);
+
+ priv->printers = g_list_store_new (GTK_TYPE_PRINTER);
+ priv->auth_info_required = NULL;
+ priv->auth_info = NULL;
+}
+
+static void
+gtk_print_backend_dispose (GObject *object)
+{
+ GtkPrintBackend *backend;
+ GtkPrintBackendPrivate *priv;
+
+ backend = GTK_PRINT_BACKEND (object);
+ priv = backend->priv;
+
+ /* We unref the printers in dispose, not in finalize so that
+ * we can break refcount cycles with gtk_print_backend_destroy
+ */
+ g_list_store_remove_all (priv->printers);
+
+ backend_parent_class->dispose (object);
+}
+
+static void
+gtk_print_backend_finalize (GObject *object)
+{
+ GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+ GtkPrintBackendPrivate *priv = backend->priv;
+
+ g_clear_object (&priv->printers);
+
+ backend_parent_class->finalize (object);
+}
+
+static void
+fallback_printer_request_details (GtkPrinter *printer)
+{
+}
+
+static gboolean
+fallback_printer_mark_conflicts (GtkPrinter *printer,
+ GtkPrinterOptionSet *options)
+{
+ return FALSE;
+}
+
+static gboolean
+fallback_printer_get_hard_margins (GtkPrinter *printer,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right)
+{
+ return FALSE;
+}
+
+static gboolean
+fallback_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
+ GtkPaperSize *paper_size,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right)
+{
+ return FALSE;
+}
+
+static GList *
+fallback_printer_list_papers (GtkPrinter *printer)
+{
+ return NULL;
+}
+
+static GtkPageSetup *
+fallback_printer_get_default_page_size (GtkPrinter *printer)
+{
+ return NULL;
+}
+
+static GtkPrintCapabilities
+fallback_printer_get_capabilities (GtkPrinter *printer)
+{
+ return 0;
+}
+
+void
+gtk_print_backend_add_printer (GtkPrintBackend *backend,
+ GtkPrinter *printer)
+{
+ g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+ g_list_store_append (backend->priv->printers, printer);
+}
+
+void
+gtk_print_backend_remove_printer (GtkPrintBackend *backend,
+ GtkPrinter *printer)
+{
+ guint position;
+
+ g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+ if (g_list_store_find (backend->priv->printers, printer, &position))
+ g_list_store_remove (backend->priv->printers, position);
+}
+
+void
+gtk_print_backend_set_list_done (GtkPrintBackend *backend)
+{
+ if (!backend->priv->printer_list_done)
+ {
+ backend->priv->printer_list_done = TRUE;
+ g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
+ }
+}
+
+
+/**
+ * gtk_print_backend_get_printer_list:
+ *
+ * Returns the current list of printers.
+ *
+ * Returns: (element-type GtkPrinter) (transfer container):
+ * A list of `GtkPrinter` objects
+ */
+GList *
+gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
+{
+ GList *result = NULL;
+ guint i;
+
+ g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
+ {
+ GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
+ result = g_list_prepend (result, printer);
+ g_object_unref (printer);
+ }
+
+ if (!backend->priv->printer_list_requested)
+ {
+ if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
+ GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
+ backend->priv->printer_list_requested = TRUE;
+ }
+
+ return result;
+}
+
+GListModel *
+gtk_print_backend_get_printers (GtkPrintBackend *backend)
+{
+ if (!backend->priv->printer_list_requested)
+ {
+ if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
+ GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
+ backend->priv->printer_list_requested = TRUE;
+ }
+
+ return G_LIST_MODEL (backend->priv->printers);
+}
+
+gboolean
+gtk_print_backend_printer_list_is_done (GtkPrintBackend *backend)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), TRUE);
+
+ return backend->priv->printer_list_done;
+}
+
+GtkPrinter *
+gtk_print_backend_find_printer (GtkPrintBackend *backend,
+ const char *printer_name)
+{
+ GtkPrinter *result = NULL;
+ guint i;
+
+ g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+ for (i = 0; !result && i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
+ {
+ GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
+ if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
+ result = printer;
+ g_object_unref (printer);
+ }
+
+ return result;
+}
+
+void
+gtk_print_backend_print_stream (GtkPrintBackend *backend,
+ GtkPrintJob *job,
+ GIOChannel *data_io,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify)
+{
+ g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+ GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
+ job,
+ data_io,
+ callback,
+ user_data,
+ dnotify);
+}
+
+void
+gtk_print_backend_set_password (GtkPrintBackend *backend,
+ char **auth_info_required,
+ char **auth_info,
+ gboolean store_auth_info)
+{
+ g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+ if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
+ GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend,
+ auth_info_required,
+ auth_info,
+ store_auth_info);
+}
+
+static void
+store_auth_info_toggled (GtkCheckButton *chkbtn,
+ gpointer user_data)
+{
+ gboolean *data = (gboolean *) user_data;
+ *data = gtk_check_button_get_active (GTK_CHECK_BUTTON (chkbtn));
+}
+
+static void
+store_entry (GtkEntry *entry,
+ gpointer user_data)
+{
+ char **data = (char **) user_data;
+
+ if (*data != NULL)
+ {
+ memset (*data, 0, strlen (*data));
+ g_free (*data);
+ }
+
+ *data = g_strdup (gtk_editable_get_text (GTK_EDITABLE (entry)));
+}
+
+static void
+password_dialog_response (GtkWidget *dialog,
+ int response_id,
+ GtkPrintBackend *backend)
+{
+ GtkPrintBackendPrivate *priv = backend->priv;
+ int i, auth_info_len;
+
+ if (response_id == GTK_RESPONSE_OK)
+ gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info, priv->store_auth_info);
+ else
+ gtk_print_backend_set_password (backend, priv->auth_info_required, NULL, FALSE);
+
+ /* We want to clear the data before freeing it */
+ auth_info_len = g_strv_length (priv->auth_info_required);
+ for (i = 0; i < auth_info_len; i++)
+ {
+ if (priv->auth_info[i] != NULL)
+ {
+ memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
+ g_free (priv->auth_info[i]);
+ priv->auth_info[i] = NULL;
+ }
+ }
+
+ g_clear_pointer (&priv->auth_info, g_free);
+ g_clear_pointer (&priv->auth_info_required, g_strfreev);
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ g_object_unref (backend);
+}
+
+static void
+request_password (GtkPrintBackend *backend,
+ gpointer auth_info_required,
+ gpointer auth_info_default,
+ gpointer auth_info_display,
+ gpointer auth_info_visible,
+ const char *prompt,
+ gboolean can_store_auth_info)
+{
+ GtkPrintBackendPrivate *priv = backend->priv;
+ GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry, *chkbtn;
+ GtkWidget *focus = NULL;
+ GtkWidget *content_area;
+ char *markup;
+ int length;
+ int i;
+ char **ai_required = (char **) auth_info_required;
+ char **ai_default = (char **) auth_info_default;
+ char **ai_display = (char **) auth_info_display;
+ gboolean *ai_visible = (gboolean *) auth_info_visible;
+
+ priv->auth_info_required = g_strdupv (ai_required);
+ length = g_strv_length (ai_required);
+ priv->auth_info = g_new0 (char *, length + 1);
+ priv->store_auth_info = FALSE;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_OK"), GTK_RESPONSE_OK,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ /* Left */
+ icon = gtk_image_new_from_icon_name ("dialog-password-symbolic");
+ gtk_image_set_icon_size (GTK_IMAGE (icon), GTK_ICON_SIZE_LARGE);
+ gtk_widget_set_halign (icon, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (icon, GTK_ALIGN_START);
+ gtk_widget_set_margin_start (icon, 12);
+ gtk_widget_set_margin_end (icon, 12);
+ gtk_widget_set_margin_top (icon, 12);
+ gtk_widget_set_margin_bottom (icon, 12);
+
+ /* Right */
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_size_request (GTK_WIDGET (vbox), 320, -1);
+
+ /* Right - 1. */
+ label = gtk_label_new (NULL);
+ markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"large\">%s</span>", prompt);
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ gtk_label_set_wrap (GTK_LABEL (label), TRUE);
+ gtk_widget_set_size_request (GTK_WIDGET (label), 320, -1);
+ g_free (markup);
+
+ /* Packing */
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+G_GNUC_END_IGNORE_DEPRECATIONS
+ gtk_box_append (GTK_BOX (content_area), main_box);
+
+ gtk_box_append (GTK_BOX (main_box), icon);
+ gtk_box_append (GTK_BOX (main_box), vbox);
+
+ gtk_box_append (GTK_BOX (vbox), label);
+
+ /* Right - 2. */
+ for (i = 0; i < length; i++)
+ {
+ priv->auth_info[i] = g_strdup (ai_default[i]);
+ if (ai_display[i] != NULL)
+ {
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
+ gtk_widget_set_margin_top (box, 6);
+ gtk_widget_set_margin_bottom (box, 6);
+
+ label = gtk_label_new (ai_display[i]);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+
+ entry = gtk_entry_new ();
+ focus = entry;
+
+ if (ai_default[i] != NULL)
+ gtk_editable_set_text (GTK_EDITABLE (entry), ai_default[i]);
+
+ gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
+ gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+
+ gtk_box_append (GTK_BOX (vbox), box);
+
+ gtk_box_append (GTK_BOX (box), label);
+ gtk_box_append (GTK_BOX (box), entry);
+
+ g_signal_connect (entry, "changed",
+ G_CALLBACK (store_entry), &(priv->auth_info[i]));
+ }
+ }
+
+ if (can_store_auth_info)
+ {
+ chkbtn = gtk_check_button_new_with_mnemonic (_("_Remember password"));
+ gtk_widget_set_margin_top (chkbtn, 6);
+ gtk_widget_set_margin_bottom (chkbtn, 6);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (chkbtn), FALSE);
+ gtk_box_append (GTK_BOX (vbox), chkbtn);
+ g_signal_connect (chkbtn, "toggled",
+ G_CALLBACK (store_auth_info_toggled),
+ &(priv->store_auth_info));
+ }
+
+ if (focus != NULL)
+ {
+ gtk_widget_grab_focus (focus);
+ focus = NULL;
+ }
+
+ g_object_ref (backend);
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (password_dialog_response), backend);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+gtk_print_backend_destroy (GtkPrintBackend *backend)
+{
+ /* The lifecycle of print backends and printers are tied, such that
+ * the backend owns the printers, but the printers also ref the backend.
+ * This is so that if the app has a reference to a printer its backend
+ * will be around. However, this results in a cycle, which we break
+ * with this call, which causes the print backend to release its printers.
+ */
+ g_object_run_dispose (G_OBJECT (backend));
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintbackend.h: Abstract printer backend interfaces
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+/* This is a "semi-private" header; it is meant only for
+ * alternate GtkPrintDialog backend modules; no stability guarantees
+ * are made at this point
+ */
+#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
+#error "GtkPrintBackend is not supported API for general use"
+#endif
+
+#include <gtk/gtk.h>
+#include "gtkunixprint.h"
+#include "gtkprinteroptionsetprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GtkPrintBackendClass GtkPrintBackendClass;
+typedef struct _GtkPrintBackendPrivate GtkPrintBackendPrivate;
+
+#define GTK_PRINT_BACKEND_ERROR (gtk_print_backend_error_quark ())
+
+typedef enum
+{
+ /* TODO: add specific errors */
+ GTK_PRINT_BACKEND_ERROR_GENERIC
+} GtkPrintBackendError;
+
+GDK_AVAILABLE_IN_ALL
+GQuark gtk_print_backend_error_quark (void);
+
+#define GTK_TYPE_PRINT_BACKEND (gtk_print_backend_get_type ())
+#define GTK_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
+#define GTK_PRINT_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
+#define GTK_IS_PRINT_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
+#define GTK_IS_PRINT_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND))
+#define GTK_PRINT_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
+
+typedef enum
+{
+ GTK_PRINT_BACKEND_STATUS_UNKNOWN,
+ GTK_PRINT_BACKEND_STATUS_OK,
+ GTK_PRINT_BACKEND_STATUS_UNAVAILABLE
+} GtkPrintBackendStatus;
+
+struct _GtkPrintBackend
+{
+ GObject parent_instance;
+
+ GtkPrintBackendPrivate *priv;
+};
+
+struct _GtkPrintBackendClass
+{
+ GObjectClass parent_class;
+
+ /* Global backend methods: */
+ void (*request_printer_list) (GtkPrintBackend *backend);
+ void (*print_stream) (GtkPrintBackend *backend,
+ GtkPrintJob *job,
+ GIOChannel *data_io,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify);
+
+ /* Printer methods: */
+ void (*printer_request_details) (GtkPrinter *printer);
+ cairo_surface_t * (*printer_create_cairo_surface) (GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ double height,
+ double width,
+ GIOChannel *cache_io);
+ GtkPrinterOptionSet * (*printer_get_options) (GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup,
+ GtkPrintCapabilities capabilities);
+ gboolean (*printer_mark_conflicts) (GtkPrinter *printer,
+ GtkPrinterOptionSet *options);
+ void (*printer_get_settings_from_options) (GtkPrinter *printer,
+ GtkPrinterOptionSet *options,
+ GtkPrintSettings *settings);
+ void (*printer_prepare_for_print) (GtkPrinter *printer,
+ GtkPrintJob *print_job,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup);
+ GList * (*printer_list_papers) (GtkPrinter *printer);
+ GtkPageSetup * (*printer_get_default_page_size) (GtkPrinter *printer);
+ gboolean (*printer_get_hard_margins) (GtkPrinter *printer,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right);
+ GtkPrintCapabilities (*printer_get_capabilities) (GtkPrinter *printer);
+
+ /* Signals */
+ void (*printer_list_changed) (GtkPrintBackend *backend);
+ void (*printer_list_done) (GtkPrintBackend *backend);
+ void (*printer_added) (GtkPrintBackend *backend,
+ GtkPrinter *printer);
+ void (*printer_removed) (GtkPrintBackend *backend,
+ GtkPrinter *printer);
+ void (*printer_status_changed) (GtkPrintBackend *backend,
+ GtkPrinter *printer);
+ void (*request_password) (GtkPrintBackend *backend,
+ gpointer auth_info_required,
+ gpointer auth_info_default,
+ gpointer auth_info_display,
+ gpointer auth_info_visible,
+ const char *prompt,
+ gboolean can_store_auth_info);
+
+ /* not a signal */
+ void (*set_password) (GtkPrintBackend *backend,
+ char **auth_info_required,
+ char **auth_info,
+ gboolean store_auth_info);
+
+ gboolean (*printer_get_hard_margins_for_paper_size) (GtkPrinter *printer,
+ GtkPaperSize *paper_size,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right);
+};
+
+#define GTK_PRINT_BACKEND_EXTENSION_POINT_NAME "gtk-print-backend"
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_print_backend_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GList *gtk_print_backend_get_printer_list (GtkPrintBackend *print_backend);
+GDK_AVAILABLE_IN_ALL
+GListModel *gtk_print_backend_get_printers (GtkPrintBackend *print_backend);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend);
+GDK_AVAILABLE_IN_ALL
+GtkPrinter *gtk_print_backend_find_printer (GtkPrintBackend *print_backend,
+ const char *printer_name);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_backend_print_stream (GtkPrintBackend *print_backend,
+ GtkPrintJob *job,
+ GIOChannel *data_io,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify);
+GDK_AVAILABLE_IN_ALL
+GList * gtk_print_backend_load_modules (void);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_backend_destroy (GtkPrintBackend *print_backend);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_backend_set_password (GtkPrintBackend *backend,
+ char **auth_info_required,
+ char **auth_info,
+ gboolean can_store_auth_info);
+
+/* Backend-only functions for GtkPrintBackend */
+
+GDK_AVAILABLE_IN_ALL
+void gtk_print_backend_add_printer (GtkPrintBackend *print_backend,
+ GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_backend_remove_printer (GtkPrintBackend *print_backend,
+ GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_backend_set_list_done (GtkPrintBackend *backend);
+
+
+/* Backend-only functions for GtkPrinter */
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_is_new (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_set_accepts_pdf (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_set_accepts_ps (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_set_is_new (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_set_is_active (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_set_is_paused (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_set_is_accepting_jobs (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_set_has_details (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_set_is_default (GtkPrinter *printer,
+ gboolean val);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_set_icon_name (GtkPrinter *printer,
+ const char *icon);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_set_job_count (GtkPrinter *printer,
+ int count);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_set_location (GtkPrinter *printer,
+ const char *location);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_set_description (GtkPrinter *printer,
+ const char *description);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_set_state_message (GtkPrinter *printer,
+ const char *message);
+
+void gtk_print_backends_init (void);
+
+
+G_END_DECLS
+
--- /dev/null
+/* GtkPrinter
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "gtkprivate.h"
+
+#include "gtkprinter.h"
+#include "gtkprinterprivate.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprintjob.h"
+
+/**
+ * GtkPrinter:
+ *
+ * A `GtkPrinter` object represents a printer.
+ *
+ * You only need to deal directly with printers if you use the
+ * non-portable [class@Gtk.PrintUnixDialog] API.
+ *
+ * A `GtkPrinter` allows to get status information about the printer,
+ * such as its description, its location, the number of queued jobs,
+ * etc. Most importantly, a `GtkPrinter` object can be used to create
+ * a [class@Gtk.PrintJob] object, which lets you print to the printer.
+ */
+
+
+static void gtk_printer_finalize (GObject *object);
+
+struct _GtkPrinterPrivate
+{
+ char *name;
+ char *location;
+ char *description;
+ char *icon_name;
+
+ guint is_active : 1;
+ guint is_paused : 1;
+ guint is_accepting_jobs : 1;
+ guint is_new : 1;
+ guint is_virtual : 1;
+ guint is_default : 1;
+ guint has_details : 1;
+ guint accepts_pdf : 1;
+ guint accepts_ps : 1;
+
+ char *state_message;
+ int job_count;
+
+ GtkPrintBackend *backend;
+};
+
+enum {
+ DETAILS_ACQUIRED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_BACKEND,
+ PROP_IS_VIRTUAL,
+ PROP_STATE_MESSAGE,
+ PROP_LOCATION,
+ PROP_ICON_NAME,
+ PROP_JOB_COUNT,
+ PROP_ACCEPTS_PDF,
+ PROP_ACCEPTS_PS,
+ PROP_PAUSED,
+ PROP_ACCEPTING_JOBS
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gtk_printer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_printer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinter, gtk_printer, G_TYPE_OBJECT)
+
+static void
+gtk_printer_class_init (GtkPrinterClass *class)
+{
+ GObjectClass *object_class;
+ object_class = (GObjectClass *) class;
+
+ object_class->finalize = gtk_printer_finalize;
+
+ object_class->set_property = gtk_printer_set_property;
+ object_class->get_property = gtk_printer_get_property;
+
+ /**
+ * GtkPrinter:name: (attributes org.gtk.Property.get=gtk_printer_get_name)
+ *
+ * The name of the printer.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_NAME,
+ g_param_spec_string ("name", NULL, NULL,
+ "",
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrinter:backend: (attributes org.gtk.Property.get=gtk_printer_get_backend)
+ *
+ * The backend for the printer.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_BACKEND,
+ g_param_spec_object ("backend", NULL, NULL,
+ GTK_TYPE_PRINT_BACKEND,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrinter:is-virtual: (attributes org.gtk.Property.get=gtk_printer_is_virtual)
+ *
+ * %FALSE if this represents a real hardware device.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_IS_VIRTUAL,
+ g_param_spec_boolean ("is-virtual", NULL, NULL,
+ FALSE,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrinter:accepts-pdf: (attributes org.gtk.Property.get=gtk_printer_accepts_pdf)
+ *
+ * %TRUE if this printer can accept PDF.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_ACCEPTS_PDF,
+ g_param_spec_boolean ("accepts-pdf", NULL, NULL,
+ FALSE,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrinter:accepts-ps: (attributes org.gtk.Property.get=gtk_printer_accepts_ps)
+ *
+ * %TRUE if this printer can accept PostScript.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_ACCEPTS_PS,
+ g_param_spec_boolean ("accepts-ps", NULL, NULL,
+ TRUE,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrinter:state-message: (attributes org.gtk.Property.get=gtk_printer_get_state_message)
+ *
+ * String giving the current status of the printer.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_STATE_MESSAGE,
+ g_param_spec_string ("state-message", NULL, NULL,
+ "",
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkPrinter:location: (attributes org.gtk.Property.get=gtk_printer_get_location)
+ *
+ * Information about the location of the printer.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_LOCATION,
+ g_param_spec_string ("location", NULL, NULL,
+ "",
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkPrinter:icon-name: (attributes org.gtk.Property.get=gtk_printer_get_icon_name)
+ *
+ * Icon name to use for the printer.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_ICON_NAME,
+ g_param_spec_string ("icon-name", NULL, NULL,
+ "printer",
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkPrinter:job-count: (attributes org.gtk.Property.get=gtk_printer_get_job_count)
+ *
+ * Number of jobs queued in the printer.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_JOB_COUNT,
+ g_param_spec_int ("job-count", NULL, NULL,
+ 0,
+ G_MAXINT,
+ 0,
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkPrinter:paused: (attributes org.gtk.Property.get=gtk_printer_is_paused)
+ *
+ * %TRUE if this printer is paused.
+ *
+ * A paused printer still accepts jobs, but it does
+ * not print them.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_PAUSED,
+ g_param_spec_boolean ("paused", NULL, NULL,
+ FALSE,
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkPrinter:accepting-jobs: (attributes org.gtk.Property.get=gtk_printer_is_accepting_jobs)
+ *
+ * %TRUE if the printer is accepting jobs.
+ */
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_ACCEPTING_JOBS,
+ g_param_spec_boolean ("accepting-jobs", NULL, NULL,
+ TRUE,
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkPrinter::details-acquired:
+ * @printer: the `GtkPrinter` on which the signal is emitted
+ * @success: %TRUE if the details were successfully acquired
+ *
+ * Emitted in response to a request for detailed information
+ * about a printer from the print backend.
+ *
+ * The @success parameter indicates if the information was
+ * actually obtained.
+ */
+ signals[DETAILS_ACQUIRED] =
+ g_signal_new (I_("details-acquired"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrinterClass, details_acquired),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+gtk_printer_init (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ priv->name = NULL;
+ priv->location = NULL;
+ priv->description = NULL;
+ priv->icon_name = g_strdup ("printer");
+
+ priv->is_active = TRUE;
+ priv->is_paused = FALSE;
+ priv->is_accepting_jobs = TRUE;
+ priv->is_new = TRUE;
+ priv->has_details = FALSE;
+ priv->accepts_pdf = FALSE;
+ priv->accepts_ps = TRUE;
+
+ priv->state_message = NULL;
+ priv->job_count = 0;
+}
+
+static void
+gtk_printer_finalize (GObject *object)
+{
+ GtkPrinter *printer = GTK_PRINTER (object);
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_free (priv->name);
+ g_free (priv->location);
+ g_free (priv->description);
+ g_free (priv->state_message);
+ g_free (priv->icon_name);
+
+ if (priv->backend)
+ g_object_unref (priv->backend);
+
+ G_OBJECT_CLASS (gtk_printer_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrinter *printer = GTK_PRINTER (object);
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ priv->name = g_value_dup_string (value);
+ break;
+
+ case PROP_BACKEND:
+ priv->backend = GTK_PRINT_BACKEND (g_value_dup_object (value));
+ break;
+
+ case PROP_IS_VIRTUAL:
+ priv->is_virtual = g_value_get_boolean (value);
+ break;
+
+ case PROP_ACCEPTS_PDF:
+ priv->accepts_pdf = g_value_get_boolean (value);
+ break;
+
+ case PROP_ACCEPTS_PS:
+ priv->accepts_ps = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_printer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrinter *printer = GTK_PRINTER (object);
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ if (priv->name)
+ g_value_set_string (value, priv->name);
+ else
+ g_value_set_static_string (value, "");
+ break;
+ case PROP_BACKEND:
+ g_value_set_object (value, priv->backend);
+ break;
+ case PROP_STATE_MESSAGE:
+ if (priv->state_message)
+ g_value_set_string (value, priv->state_message);
+ else
+ g_value_set_static_string (value, "");
+ break;
+ case PROP_LOCATION:
+ if (priv->location)
+ g_value_set_string (value, priv->location);
+ else
+ g_value_set_static_string (value, "");
+ break;
+ case PROP_ICON_NAME:
+ if (priv->icon_name)
+ g_value_set_string (value, priv->icon_name);
+ else
+ g_value_set_static_string (value, "printer");
+ break;
+ case PROP_JOB_COUNT:
+ g_value_set_int (value, priv->job_count);
+ break;
+ case PROP_IS_VIRTUAL:
+ g_value_set_boolean (value, priv->is_virtual);
+ break;
+ case PROP_ACCEPTS_PDF:
+ g_value_set_boolean (value, priv->accepts_pdf);
+ break;
+ case PROP_ACCEPTS_PS:
+ g_value_set_boolean (value, priv->accepts_ps);
+ break;
+ case PROP_PAUSED:
+ g_value_set_boolean (value, priv->is_paused);
+ break;
+ case PROP_ACCEPTING_JOBS:
+ g_value_set_boolean (value, priv->is_accepting_jobs);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * gtk_printer_new:
+ * @name: the name of the printer
+ * @backend: a `GtkPrintBackend`
+ * @virtual_: whether the printer is virtual
+ *
+ * Creates a new `GtkPrinter`.
+ *
+ * Returns: a new `GtkPrinter`
+ */
+GtkPrinter *
+gtk_printer_new (const char *name,
+ GtkPrintBackend *backend,
+ gboolean virtual_)
+{
+ GObject *result;
+
+ result = g_object_new (GTK_TYPE_PRINTER,
+ "name", name,
+ "backend", backend,
+ "is-virtual", virtual_,
+ NULL);
+
+ return (GtkPrinter *) result;
+}
+
+/**
+ * gtk_printer_get_backend: (attributes org.gtk.Method.get_property=backend)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns the backend of the printer.
+ *
+ * Returns: (transfer none): the backend of @printer
+ */
+GtkPrintBackend *
+gtk_printer_get_backend (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ return priv->backend;
+}
+
+/**
+ * gtk_printer_get_name: (attributes org.gtk.Method.get_property=name)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns the name of the printer.
+ *
+ * Returns: the name of @printer
+ */
+const char *
+gtk_printer_get_name (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ return priv->name;
+}
+
+/**
+ * gtk_printer_get_description:
+ * @printer: a `GtkPrinter`
+ *
+ * Gets the description of the printer.
+ *
+ * Returns: the description of @printer
+ */
+const char *
+gtk_printer_get_description (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ return priv->description;
+}
+
+gboolean
+gtk_printer_set_description (GtkPrinter *printer,
+ const char *description)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ if (g_strcmp0 (priv->description, description) == 0)
+ return FALSE;
+
+ g_free (priv->description);
+ priv->description = g_strdup (description);
+
+ return TRUE;
+}
+
+/**
+ * gtk_printer_get_state_message: (attributes org.gtk.Method.get_property=state-message)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns the state message describing the current state
+ * of the printer.
+ *
+ * Returns: the state message of @printer
+ */
+const char *
+gtk_printer_get_state_message (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ return priv->state_message;
+}
+
+gboolean
+gtk_printer_set_state_message (GtkPrinter *printer,
+ const char *message)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ if (g_strcmp0 (priv->state_message, message) == 0)
+ return FALSE;
+
+ g_free (priv->state_message);
+ priv->state_message = g_strdup (message);
+ g_object_notify (G_OBJECT (printer), "state-message");
+
+ return TRUE;
+}
+
+/**
+ * gtk_printer_get_location: (attributes org.gtk.Method.get_property=location)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns a description of the location of the printer.
+ *
+ * Returns: the location of @printer
+ */
+const char *
+gtk_printer_get_location (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ return priv->location;
+}
+
+gboolean
+gtk_printer_set_location (GtkPrinter *printer,
+ const char *location)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ if (g_strcmp0 (priv->location, location) == 0)
+ return FALSE;
+
+ g_free (priv->location);
+ priv->location = g_strdup (location);
+ g_object_notify (G_OBJECT (printer), "location");
+
+ return TRUE;
+}
+
+/**
+ * gtk_printer_get_icon_name: (attributes org.gtk.Method.get_property=icon-name)
+ * @printer: a `GtkPrinter`
+ *
+ * Gets the name of the icon to use for the printer.
+ *
+ * Returns: the icon name for @printer
+ */
+const char *
+gtk_printer_get_icon_name (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ return priv->icon_name;
+}
+
+void
+gtk_printer_set_icon_name (GtkPrinter *printer,
+ const char *icon)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_if_fail (GTK_IS_PRINTER (printer));
+
+ g_free (priv->icon_name);
+ priv->icon_name = g_strdup (icon);
+ g_object_notify (G_OBJECT (printer), "icon-name");
+}
+
+/**
+ * gtk_printer_get_job_count: (attributes org.gtk.Method.get_property=job-count)
+ * @printer: a `GtkPrinter`
+ *
+ * Gets the number of jobs currently queued on the printer.
+ *
+ * Returns: the number of jobs on @printer
+ */
+int
+gtk_printer_get_job_count (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
+
+ return priv->job_count;
+}
+
+gboolean
+gtk_printer_set_job_count (GtkPrinter *printer,
+ int count)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ if (priv->job_count == count)
+ return FALSE;
+
+ priv->job_count = count;
+
+ g_object_notify (G_OBJECT (printer), "job-count");
+
+ return TRUE;
+}
+
+/**
+ * gtk_printer_has_details:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer details are available.
+ *
+ * Returns: %TRUE if @printer details are available
+ */
+gboolean
+gtk_printer_has_details (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ return priv->has_details;
+}
+
+void
+gtk_printer_set_has_details (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ priv->has_details = val;
+}
+
+/**
+ * gtk_printer_is_active:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is currently active (i.e.
+ * accepts new jobs).
+ *
+ * Returns: %TRUE if @printer is active
+ */
+gboolean
+gtk_printer_is_active (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+
+ return priv->is_active;
+}
+
+void
+gtk_printer_set_is_active (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_if_fail (GTK_IS_PRINTER (printer));
+
+ priv->is_active = val;
+}
+
+/**
+ * gtk_printer_is_paused: (attributes org.gtk.Method.get_property=paused)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is currently paused.
+ *
+ * A paused printer still accepts jobs, but it is not
+ * printing them.
+ *
+ * Returns: %TRUE if @printer is paused
+ */
+gboolean
+gtk_printer_is_paused (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+
+ return priv->is_paused;
+}
+
+gboolean
+gtk_printer_set_is_paused (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ if (val == priv->is_paused)
+ return FALSE;
+
+ priv->is_paused = val;
+
+ return TRUE;
+}
+
+/**
+ * gtk_printer_is_accepting_jobs: (attributes org.gtk.Method.get_property=accepting-jobs)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is accepting jobs
+ *
+ * Returns: %TRUE if @printer is accepting jobs
+ */
+gboolean
+gtk_printer_is_accepting_jobs (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+
+ return priv->is_accepting_jobs;
+}
+
+gboolean
+gtk_printer_set_is_accepting_jobs (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ if (val == priv->is_accepting_jobs)
+ return FALSE;
+
+ priv->is_accepting_jobs = val;
+
+ return TRUE;
+}
+
+/**
+ * gtk_printer_is_virtual: (attributes org.gtk.Method.get_property=is-virtual)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is virtual (i.e. does not
+ * represent actual printer hardware, but something like
+ * a CUPS class).
+ *
+ * Returns: %TRUE if @printer is virtual
+ */
+gboolean
+gtk_printer_is_virtual (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+
+ return priv->is_virtual;
+}
+
+/**
+ * gtk_printer_accepts_pdf: (attributes org.gtk.Method.get_property=accepts-pdf)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer accepts input in
+ * PDF format.
+ *
+ * Returns: %TRUE if @printer accepts PDF
+ */
+gboolean
+gtk_printer_accepts_pdf (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+
+ return priv->accepts_pdf;
+}
+
+void
+gtk_printer_set_accepts_pdf (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_if_fail (GTK_IS_PRINTER (printer));
+
+ priv->accepts_pdf = val;
+}
+
+/**
+ * gtk_printer_accepts_ps: (attributes org.gtk.Method.get_property=accepts-ps)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer accepts input in
+ * PostScript format.
+ *
+ * Returns: %TRUE if @printer accepts PostScript
+ */
+gboolean
+gtk_printer_accepts_ps (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+
+ return priv->accepts_ps;
+}
+
+void
+gtk_printer_set_accepts_ps (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_if_fail (GTK_IS_PRINTER (printer));
+
+ priv->accepts_ps = val;
+}
+
+gboolean
+gtk_printer_is_new (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ return priv->is_new;
+}
+
+void
+gtk_printer_set_is_new (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_if_fail (GTK_IS_PRINTER (printer));
+
+ priv->is_new = val;
+}
+
+
+/**
+ * gtk_printer_is_default:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is the default printer.
+ *
+ * Returns: %TRUE if @printer is the default
+ */
+gboolean
+gtk_printer_is_default (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+ return priv->is_default;
+}
+
+void
+gtk_printer_set_is_default (GtkPrinter *printer,
+ gboolean val)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+ g_return_if_fail (GTK_IS_PRINTER (printer));
+
+ priv->is_default = val;
+}
+
+/**
+ * gtk_printer_request_details:
+ * @printer: a `GtkPrinter`
+ *
+ * Requests the printer details.
+ *
+ * When the details are available, the
+ * [signal@Gtk.Printer::details-acquired] signal
+ * will be emitted on @printer.
+ */
+void
+gtk_printer_request_details (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class;
+
+ g_return_if_fail (GTK_IS_PRINTER (printer));
+
+ backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+ backend_class->printer_request_details (printer);
+}
+
+GtkPrinterOptionSet *
+_gtk_printer_get_options (GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup,
+ GtkPrintCapabilities capabilities)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ return backend_class->printer_get_options (printer, settings, page_setup, capabilities);
+}
+
+gboolean
+_gtk_printer_mark_conflicts (GtkPrinter *printer,
+ GtkPrinterOptionSet *options)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ return backend_class->printer_mark_conflicts (printer, options);
+}
+
+void
+_gtk_printer_get_settings_from_options (GtkPrinter *printer,
+ GtkPrinterOptionSet *options,
+ GtkPrintSettings *settings)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ backend_class->printer_get_settings_from_options (printer, options, settings);
+}
+
+void
+_gtk_printer_prepare_for_print (GtkPrinter *printer,
+ GtkPrintJob *print_job,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ backend_class->printer_prepare_for_print (printer, print_job, settings, page_setup);
+}
+
+cairo_surface_t *
+_gtk_printer_create_cairo_surface (GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ double width,
+ double height,
+ GIOChannel *cache_io)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ return backend_class->printer_create_cairo_surface (printer, settings,
+ width, height, cache_io);
+}
+
+/**
+ * gtk_printer_list_papers:
+ * @printer: a `GtkPrinter`
+ *
+ * Lists all the paper sizes @printer supports.
+ *
+ * This will return and empty list unless the printer’s details
+ * are available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Returns: (element-type GtkPageSetup) (transfer full): a newly
+ * allocated list of newly allocated `GtkPageSetup`s.
+ */
+GList *
+gtk_printer_list_papers (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class;
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+ return backend_class->printer_list_papers (printer);
+}
+
+/**
+ * gtk_printer_get_default_page_size:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns default page size of @printer.
+ *
+ * Returns: (transfer full): a newly allocated `GtkPageSetup` with default page size
+ * of the printer.
+ */
+GtkPageSetup *
+gtk_printer_get_default_page_size (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class;
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+ backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ return backend_class->printer_get_default_page_size (printer);
+}
+
+/**
+ * gtk_printer_get_hard_margins:
+ * @printer: a `GtkPrinter`
+ * @top: (out): a location to store the top margin in
+ * @bottom: (out): a location to store the bottom margin in
+ * @left: (out): a location to store the left margin in
+ * @right: (out): a location to store the right margin in
+ *
+ * Retrieve the hard margins of @printer.
+ *
+ * These are the margins that define the area at the borders
+ * of the paper that the printer cannot print to.
+ *
+ * Note: This will not succeed unless the printer’s details are
+ * available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Returns: %TRUE iff the hard margins were retrieved
+ */
+gboolean
+gtk_printer_get_hard_margins (GtkPrinter *printer,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ return backend_class->printer_get_hard_margins (printer, top, bottom, left, right);
+}
+
+/**
+ * gtk_printer_get_hard_margins_for_paper_size:
+ * @printer: a `GtkPrinter`
+ * @paper_size: a `GtkPaperSize`
+ * @top: (out): a location to store the top margin in
+ * @bottom: (out): a location to store the bottom margin in
+ * @left: (out): a location to store the left margin in
+ * @right: (out): a location to store the right margin in
+ *
+ * Retrieve the hard margins of @printer for @paper_size.
+ *
+ * These are the margins that define the area at the borders
+ * of the paper that the printer cannot print to.
+ *
+ * Note: This will not succeed unless the printer’s details are
+ * available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Return value: %TRUE iff the hard margins were retrieved
+ */
+gboolean
+gtk_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
+ GtkPaperSize *paper_size,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+ return backend_class->printer_get_hard_margins_for_paper_size (printer, paper_size, top, bottom, left, right);
+}
+
+/**
+ * gtk_printer_get_capabilities:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns the printer’s capabilities.
+ *
+ * This is useful when you’re using `GtkPrintUnixDialog`’s
+ * manual-capabilities setting and need to know which settings
+ * the printer can handle and which you must handle yourself.
+ *
+ * This will return 0 unless the printer’s details are
+ * available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Returns: the printer’s capabilities
+ */
+GtkPrintCapabilities
+gtk_printer_get_capabilities (GtkPrinter *printer)
+{
+ GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+ GtkPrintBackendClass *backend_class;
+
+ g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
+
+ backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+ return backend_class->printer_get_capabilities (printer);
+}
+
+/**
+ * gtk_printer_compare:
+ * @a: a `GtkPrinter`
+ * @b: another `GtkPrinter`
+ *
+ * Compares two printers.
+ *
+ * Returns: 0 if the printer match, a negative value if @a < @b,
+ * or a positive value if @a > @b
+ */
+int
+gtk_printer_compare (GtkPrinter *a,
+ GtkPrinter *b)
+{
+ const char *name_a, *name_b;
+
+ g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
+
+ name_a = gtk_printer_get_name (a);
+ name_b = gtk_printer_get_name (b);
+ if (name_a == NULL && name_b == NULL)
+ return 0;
+ else if (name_a == NULL)
+ return G_MAXINT;
+ else if (name_b == NULL)
+ return G_MININT;
+ else
+ return g_ascii_strcasecmp (name_a, name_b);
+}
+
+
+typedef struct
+{
+ GList *backends;
+ GtkPrinterFunc func;
+ gpointer data;
+ GDestroyNotify destroy;
+ GMainLoop *loop;
+} PrinterList;
+
+static void list_done_cb (GtkPrintBackend *backend,
+ PrinterList *printer_list);
+
+static void
+stop_enumeration (PrinterList *printer_list)
+{
+ GList *list, *next;
+ GtkPrintBackend *backend;
+
+ for (list = printer_list->backends; list; list = next)
+ {
+ next = list->next;
+ backend = GTK_PRINT_BACKEND (list->data);
+ list_done_cb (backend, printer_list);
+ }
+}
+
+static void
+free_printer_list (PrinterList *printer_list)
+{
+ if (printer_list->destroy)
+ printer_list->destroy (printer_list->data);
+
+ if (printer_list->loop)
+ {
+ g_main_loop_quit (printer_list->loop);
+ g_main_loop_unref (printer_list->loop);
+ }
+
+ g_free (printer_list);
+}
+
+static gboolean
+list_added_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ PrinterList *printer_list)
+{
+ if (printer_list->func (printer, printer_list->data))
+ {
+ stop_enumeration (printer_list);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+backend_status_changed (GObject *object,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+ PrinterList *printer_list = data;
+ GtkPrintBackendStatus status;
+
+ g_object_get (backend, "status", &status, NULL);
+
+ if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE)
+ list_done_cb (backend, printer_list);
+}
+
+static gboolean
+list_printers_remove_backend (PrinterList *printer_list,
+ GtkPrintBackend *backend)
+{
+ printer_list->backends = g_list_remove (printer_list->backends, backend);
+ gtk_print_backend_destroy (backend);
+ g_object_unref (backend);
+
+ if (printer_list->backends == NULL)
+ {
+ free_printer_list (printer_list);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+list_done_cb (GtkPrintBackend *backend,
+ PrinterList *printer_list)
+{
+ g_signal_handlers_disconnect_by_func (backend, list_added_cb, printer_list);
+ g_signal_handlers_disconnect_by_func (backend, list_done_cb, printer_list);
+ g_signal_handlers_disconnect_by_func (backend, backend_status_changed, printer_list);
+
+ list_printers_remove_backend(printer_list, backend);
+}
+
+static gboolean
+list_printers_init (PrinterList *printer_list,
+ GtkPrintBackend *backend)
+{
+ GList *list, *node;
+ GtkPrintBackendStatus status;
+
+ list = gtk_print_backend_get_printer_list (backend);
+
+ for (node = list; node != NULL; node = node->next)
+ {
+ if (list_added_cb (backend, node->data, printer_list))
+ {
+ g_list_free (list);
+ return TRUE;
+ }
+ }
+
+ g_list_free (list);
+
+ g_object_get (backend, "status", &status, NULL);
+
+ if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE ||
+ gtk_print_backend_printer_list_is_done (backend))
+ {
+ if (list_printers_remove_backend (printer_list, backend))
+ return TRUE;
+ }
+ else
+ {
+ g_signal_connect (backend, "printer-added",
+ (GCallback) list_added_cb,
+ printer_list);
+ g_signal_connect (backend, "printer-list-done",
+ (GCallback) list_done_cb,
+ printer_list);
+ g_signal_connect (backend, "notify::status",
+ (GCallback) backend_status_changed,
+ printer_list);
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_enumerate_printers:
+ * @func: a function to call for each printer
+ * @data: user data to pass to @func
+ * @destroy: function to call if @data is no longer needed
+ * @wait: if %TRUE, wait in a recursive mainloop until
+ * all printers are enumerated; otherwise return early
+ *
+ * Calls a function for all `GtkPrinter`s.
+ *
+ * If @func returns %TRUE, the enumeration is stopped.
+ */
+void
+gtk_enumerate_printers (GtkPrinterFunc func,
+ gpointer data,
+ GDestroyNotify destroy,
+ gboolean wait)
+{
+ PrinterList *printer_list;
+ GList *node, *next;
+ GtkPrintBackend *backend;
+
+ printer_list = g_new0 (PrinterList, 1);
+
+ printer_list->func = func;
+ printer_list->data = data;
+ printer_list->destroy = destroy;
+
+ if (g_module_supported ())
+ printer_list->backends = gtk_print_backend_load_modules ();
+
+ if (printer_list->backends == NULL)
+ {
+ free_printer_list (printer_list);
+ return;
+ }
+
+ for (node = printer_list->backends; node != NULL; node = next)
+ {
+ next = node->next;
+ backend = GTK_PRINT_BACKEND (node->data);
+ if (list_printers_init (printer_list, backend))
+ return;
+ }
+
+ if (wait && printer_list->backends)
+ {
+ printer_list->loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (printer_list->loop);
+ }
+}
+
+GType
+gtk_print_capabilities_get_type (void)
+{
+ static GType etype = 0;
+
+ if (G_UNLIKELY (etype == 0))
+ {
+ static const GFlagsValue values[] = {
+ { GTK_PRINT_CAPABILITY_PAGE_SET, "GTK_PRINT_CAPABILITY_PAGE_SET", "page-set" },
+ { GTK_PRINT_CAPABILITY_COPIES, "GTK_PRINT_CAPABILITY_COPIES", "copies" },
+ { GTK_PRINT_CAPABILITY_COLLATE, "GTK_PRINT_CAPABILITY_COLLATE", "collate" },
+ { GTK_PRINT_CAPABILITY_REVERSE, "GTK_PRINT_CAPABILITY_REVERSE", "reverse" },
+ { GTK_PRINT_CAPABILITY_SCALE, "GTK_PRINT_CAPABILITY_SCALE", "scale" },
+ { GTK_PRINT_CAPABILITY_GENERATE_PDF, "GTK_PRINT_CAPABILITY_GENERATE_PDF", "generate-pdf" },
+ { GTK_PRINT_CAPABILITY_GENERATE_PS, "GTK_PRINT_CAPABILITY_GENERATE_PS", "generate-ps" },
+ { GTK_PRINT_CAPABILITY_PREVIEW, "GTK_PRINT_CAPABILITY_PREVIEW", "preview" },
+ { GTK_PRINT_CAPABILITY_NUMBER_UP, "GTK_PRINT_CAPABILITY_NUMBER_UP", "number-up"},
+ { GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT, "GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT", "number-up-layout" },
+ { 0, NULL, NULL }
+ };
+
+ etype = g_flags_register_static (I_("GtkPrintCapabilities"), values);
+ }
+
+ return etype;
+}
--- /dev/null
+/* GtkPrinter
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <cairo.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINT_CAPABILITIES (gtk_print_capabilities_get_type ())
+
+/* Note, this type is manually registered with GObject in gtkprinter.c
+ * If you add any flags, update the registration as well!
+ */
+/**
+ * GtkPrintCapabilities:
+ * @GTK_PRINT_CAPABILITY_PAGE_SET: Print dialog will offer printing even/odd pages.
+ * @GTK_PRINT_CAPABILITY_COPIES: Print dialog will allow to print multiple copies.
+ * @GTK_PRINT_CAPABILITY_COLLATE: Print dialog will allow to collate multiple copies.
+ * @GTK_PRINT_CAPABILITY_REVERSE: Print dialog will allow to print pages in reverse order.
+ * @GTK_PRINT_CAPABILITY_SCALE: Print dialog will allow to scale the output.
+ * @GTK_PRINT_CAPABILITY_GENERATE_PDF: The program will send the document to
+ * the printer in PDF format
+ * @GTK_PRINT_CAPABILITY_GENERATE_PS: The program will send the document to
+ * the printer in Postscript format
+ * @GTK_PRINT_CAPABILITY_PREVIEW: Print dialog will offer a preview
+ * @GTK_PRINT_CAPABILITY_NUMBER_UP: Print dialog will offer printing multiple
+ * pages per sheet
+ * @GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT: Print dialog will allow to rearrange
+ * pages when printing multiple pages per sheet
+ *
+ * Specifies which features the print dialog should offer.
+ *
+ * If neither %GTK_PRINT_CAPABILITY_GENERATE_PDF nor
+ * %GTK_PRINT_CAPABILITY_GENERATE_PS is specified, GTK assumes that all
+ * formats are supported.
+ */
+typedef enum
+{
+ GTK_PRINT_CAPABILITY_PAGE_SET = 1 << 0,
+ GTK_PRINT_CAPABILITY_COPIES = 1 << 1,
+ GTK_PRINT_CAPABILITY_COLLATE = 1 << 2,
+ GTK_PRINT_CAPABILITY_REVERSE = 1 << 3,
+ GTK_PRINT_CAPABILITY_SCALE = 1 << 4,
+ GTK_PRINT_CAPABILITY_GENERATE_PDF = 1 << 5,
+ GTK_PRINT_CAPABILITY_GENERATE_PS = 1 << 6,
+ GTK_PRINT_CAPABILITY_PREVIEW = 1 << 7,
+ GTK_PRINT_CAPABILITY_NUMBER_UP = 1 << 8,
+ GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT = 1 << 9
+} GtkPrintCapabilities;
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_print_capabilities_get_type (void) G_GNUC_CONST;
+
+#define GTK_TYPE_PRINTER (gtk_printer_get_type ())
+#define GTK_PRINTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER, GtkPrinter))
+#define GTK_IS_PRINTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER))
+
+typedef struct _GtkPrinter GtkPrinter;
+typedef struct _GtkPrintBackend GtkPrintBackend;
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_printer_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkPrinter *gtk_printer_new (const char *name,
+ GtkPrintBackend *backend,
+ gboolean virtual_);
+GDK_AVAILABLE_IN_ALL
+GtkPrintBackend *gtk_printer_get_backend (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+const char * gtk_printer_get_name (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+const char * gtk_printer_get_state_message (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+const char * gtk_printer_get_description (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+const char * gtk_printer_get_location (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+const char * gtk_printer_get_icon_name (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+int gtk_printer_get_job_count (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_is_active (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_is_paused (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_is_accepting_jobs (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_is_virtual (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_is_default (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_accepts_pdf (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_accepts_ps (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+GList *gtk_printer_list_papers (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+GtkPageSetup *gtk_printer_get_default_page_size (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+int gtk_printer_compare (GtkPrinter *a,
+ GtkPrinter *b);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_has_details (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_request_details (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+GtkPrintCapabilities gtk_printer_get_capabilities (GtkPrinter *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_get_hard_margins (GtkPrinter *printer,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
+ GtkPaperSize *paper_size,
+ double *top,
+ double *bottom,
+ double *left,
+ double *right);
+
+/**
+ * GtkPrinterFunc:
+ * @printer: a `GtkPrinter`
+ * @data: (closure): user data passed to gtk_enumerate_printers()
+ *
+ * The type of function passed to gtk_enumerate_printers().
+ *
+ * Note that you need to ref @printer, if you want to keep
+ * a reference to it after the function has returned.
+ *
+ * Returns: %TRUE to stop the enumeration, %FALSE to continue
+ */
+typedef gboolean (*GtkPrinterFunc) (GtkPrinter *printer,
+ gpointer data);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_enumerate_printers (GtkPrinterFunc func,
+ gpointer data,
+ GDestroyNotify destroy,
+ gboolean wait);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrinter, g_object_unref)
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprinteroption.c: Handling possible settings for a specific printer setting
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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 <string.h>
+#include <gmodule.h>
+
+#include "gtkprivate.h"
+#include "gtkprinteroptionprivate.h"
+
+/*****************************************
+ * GtkPrinterOption *
+ *****************************************/
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_VALUE
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gtk_printer_option_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_printer_option_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+G_DEFINE_TYPE (GtkPrinterOption, gtk_printer_option, G_TYPE_OBJECT)
+
+static void
+gtk_printer_option_finalize (GObject *object)
+{
+ GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
+ int i;
+
+ g_free (option->name);
+ g_free (option->display_text);
+ g_free (option->value);
+ for (i = 0; i < option->num_choices; i++)
+ {
+ g_free (option->choices[i]);
+ g_free (option->choices_display[i]);
+ }
+ g_free (option->choices);
+ g_free (option->choices_display);
+ g_free (option->group);
+
+ G_OBJECT_CLASS (gtk_printer_option_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_option_init (GtkPrinterOption *option)
+{
+ option->value = g_strdup ("");
+ option->activates_default = FALSE;
+}
+
+static void
+gtk_printer_option_class_init (GtkPrinterOptionClass *class)
+{
+ GObjectClass *gobject_class = (GObjectClass *)class;
+
+ gobject_class->finalize = gtk_printer_option_finalize;
+ gobject_class->set_property = gtk_printer_option_set_property;
+ gobject_class->get_property = gtk_printer_option_get_property;
+
+ signals[CHANGED] =
+ g_signal_new (I_("changed"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrinterOptionClass, changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_VALUE,
+ g_param_spec_string ("value", NULL, NULL,
+ "",
+ GTK_PARAM_READWRITE));
+}
+
+GtkPrinterOption *
+gtk_printer_option_new (const char *name, const char *display_text,
+ GtkPrinterOptionType type)
+{
+ GtkPrinterOption *option;
+
+ option = g_object_new (GTK_TYPE_PRINTER_OPTION, NULL);
+
+ option->name = g_strdup (name);
+ option->display_text = g_strdup (display_text);
+ option->type = type;
+
+ return option;
+}
+
+static void
+gtk_printer_option_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_VALUE:
+ gtk_printer_option_set (option, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_printer_option_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_VALUE:
+ g_value_set_string (value, option->value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+emit_changed (GtkPrinterOption *option)
+{
+ g_signal_emit (option, signals[CHANGED], 0);
+}
+
+void
+gtk_printer_option_set (GtkPrinterOption *option,
+ const char *value)
+{
+ if (value == NULL)
+ value = "";
+
+ if (strcmp (option->value, value) == 0)
+ return;
+
+ if ((option->type == GTK_PRINTER_OPTION_TYPE_PICKONE ||
+ option->type == GTK_PRINTER_OPTION_TYPE_ALTERNATIVE))
+ {
+ int i;
+
+ for (i = 0; i < option->num_choices; i++)
+ {
+ if (g_ascii_strcasecmp (value, option->choices[i]) == 0)
+ {
+ value = option->choices[i];
+ break;
+ }
+ }
+
+ if (i == option->num_choices)
+ return; /* Not found in available choices */
+ }
+
+ g_free (option->value);
+ option->value = g_strdup (value);
+
+ emit_changed (option);
+}
+
+void
+gtk_printer_option_set_boolean (GtkPrinterOption *option,
+ gboolean value)
+{
+ gtk_printer_option_set (option, value ? "True" : "False");
+}
+
+void
+gtk_printer_option_set_has_conflict (GtkPrinterOption *option,
+ gboolean has_conflict)
+{
+ has_conflict = has_conflict != 0;
+
+ if (option->has_conflict == has_conflict)
+ return;
+
+ option->has_conflict = has_conflict;
+ emit_changed (option);
+}
+
+void
+gtk_printer_option_clear_has_conflict (GtkPrinterOption *option)
+{
+ gtk_printer_option_set_has_conflict (option, FALSE);
+}
+
+void
+gtk_printer_option_allocate_choices (GtkPrinterOption *option,
+ int num)
+{
+ g_free (option->choices);
+ g_free (option->choices_display);
+
+ option->num_choices = num;
+ if (num == 0)
+ {
+ option->choices = NULL;
+ option->choices_display = NULL;
+ }
+ else
+ {
+ option->choices = g_new0 (char *, num);
+ option->choices_display = g_new0 (char *, num);
+ }
+}
+
+void
+gtk_printer_option_choices_from_array (GtkPrinterOption *option,
+ int num_choices,
+ const char **choices,
+ const char **choices_display)
+{
+ int i;
+
+ gtk_printer_option_allocate_choices (option, num_choices);
+ for (i = 0; i < num_choices; i++)
+ {
+ option->choices[i] = g_strdup (choices[i]);
+ option->choices_display[i] = g_strdup (choices_display[i]);
+ }
+}
+
+gboolean
+gtk_printer_option_has_choice (GtkPrinterOption *option,
+ const char *choice)
+{
+ int i;
+
+ for (i = 0; i < option->num_choices; i++)
+ {
+ if (strcmp (option->choices[i], choice) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+gtk_printer_option_set_activates_default (GtkPrinterOption *option,
+ gboolean activates)
+{
+ g_return_if_fail (GTK_IS_PRINTER_OPTION (option));
+
+ option->activates_default = activates;
+}
+
+gboolean
+gtk_printer_option_get_activates_default (GtkPrinterOption *option)
+{
+ g_return_val_if_fail (GTK_IS_PRINTER_OPTION (option), FALSE);
+
+ return option->activates_default;
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprinteroption.h: printer option
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+/* This is a "semi-private" header; it is meant only for
+ * alternate GtkPrintDialog backend modules; no stability guarantees
+ * are made at this point
+ */
+#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
+#error "GtkPrintBackend is not supported API for general use"
+#endif
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINTER_OPTION (gtk_printer_option_get_type ())
+#define GTK_PRINTER_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION, GtkPrinterOption))
+#define GTK_IS_PRINTER_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION))
+
+typedef struct _GtkPrinterOption GtkPrinterOption;
+typedef struct _GtkPrinterOptionClass GtkPrinterOptionClass;
+
+#define GTK_PRINTER_OPTION_GROUP_IMAGE_QUALITY "ImageQuality"
+#define GTK_PRINTER_OPTION_GROUP_FINISHING "Finishing"
+
+typedef enum {
+ GTK_PRINTER_OPTION_TYPE_BOOLEAN,
+ GTK_PRINTER_OPTION_TYPE_PICKONE,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_REAL,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_INT,
+ GTK_PRINTER_OPTION_TYPE_PICKONE_STRING,
+ GTK_PRINTER_OPTION_TYPE_ALTERNATIVE,
+ GTK_PRINTER_OPTION_TYPE_STRING,
+ GTK_PRINTER_OPTION_TYPE_FILESAVE,
+ GTK_PRINTER_OPTION_TYPE_INFO
+} GtkPrinterOptionType;
+
+struct _GtkPrinterOption
+{
+ GObject parent_instance;
+
+ char *name;
+ char *display_text;
+ GtkPrinterOptionType type;
+
+ char *value;
+
+ int num_choices;
+ char **choices;
+ char **choices_display;
+
+ gboolean activates_default;
+
+ gboolean has_conflict;
+ char *group;
+};
+
+struct _GtkPrinterOptionClass
+{
+ GObjectClass parent_class;
+
+ void (*changed) (GtkPrinterOption *option);
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_printer_option_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkPrinterOption *gtk_printer_option_new (const char *name,
+ const char *display_text,
+ GtkPrinterOptionType type);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set (GtkPrinterOption *option,
+ const char *value);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_has_conflict (GtkPrinterOption *option,
+ gboolean has_conflict);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_clear_has_conflict (GtkPrinterOption *option);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_boolean (GtkPrinterOption *option,
+ gboolean value);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_allocate_choices (GtkPrinterOption *option,
+ int num);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_choices_from_array (GtkPrinterOption *option,
+ int num_choices,
+ const char **choices,
+ const char **choices_display);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_option_has_choice (GtkPrinterOption *option,
+ const char *choice);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_activates_default (GtkPrinterOption *option,
+ gboolean activates);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_option_get_activates_default (GtkPrinterOption *option);
+
+
+G_END_DECLS
+
+
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintbackendprivate.h: Abstract printer backend interfaces
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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 <string.h>
+#include <glib.h>
+#include <gmodule.h>
+
+#include "gtkprinteroptionsetprivate.h"
+#include "gtkprivate.h"
+
+/*****************************************
+ * GtkPrinterOptionSet *
+ *****************************************/
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* ugly side-effect of aliasing */
+#undef gtk_printer_option_set
+
+G_DEFINE_TYPE (GtkPrinterOptionSet, gtk_printer_option_set, G_TYPE_OBJECT)
+
+static void
+gtk_printer_option_set_finalize (GObject *object)
+{
+ GtkPrinterOptionSet *set = GTK_PRINTER_OPTION_SET (object);
+
+ g_hash_table_destroy (set->hash);
+ g_ptr_array_foreach (set->array, (GFunc)g_object_unref, NULL);
+ g_ptr_array_free (set->array, TRUE);
+
+ G_OBJECT_CLASS (gtk_printer_option_set_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_option_set_init (GtkPrinterOptionSet *set)
+{
+ set->array = g_ptr_array_new ();
+ set->hash = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+static void
+gtk_printer_option_set_class_init (GtkPrinterOptionSetClass *class)
+{
+ GObjectClass *gobject_class = (GObjectClass *)class;
+
+ gobject_class->finalize = gtk_printer_option_set_finalize;
+
+ signals[CHANGED] =
+ g_signal_new (I_("changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrinterOptionSetClass, changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+}
+
+
+static void
+emit_changed (GtkPrinterOptionSet *set)
+{
+ g_signal_emit (set, signals[CHANGED], 0);
+}
+
+GtkPrinterOptionSet *
+gtk_printer_option_set_new (void)
+{
+ return g_object_new (GTK_TYPE_PRINTER_OPTION_SET, NULL);
+}
+
+void
+gtk_printer_option_set_remove (GtkPrinterOptionSet *set,
+ GtkPrinterOption *option)
+{
+ int i;
+
+ for (i = 0; i < set->array->len; i++)
+ {
+ if (g_ptr_array_index (set->array, i) == option)
+ {
+ g_ptr_array_remove_index (set->array, i);
+ g_hash_table_remove (set->hash, option->name);
+ g_signal_handlers_disconnect_by_func (option, emit_changed, set);
+
+ g_object_unref (option);
+ break;
+ }
+ }
+}
+
+void
+gtk_printer_option_set_add (GtkPrinterOptionSet *set,
+ GtkPrinterOption *option)
+{
+ g_object_ref (option);
+
+ if (gtk_printer_option_set_lookup (set, option->name))
+ gtk_printer_option_set_remove (set, option);
+
+ g_ptr_array_add (set->array, option);
+ g_hash_table_insert (set->hash, option->name, option);
+ g_signal_connect_object (option, "changed", G_CALLBACK (emit_changed), set, G_CONNECT_SWAPPED);
+}
+
+GtkPrinterOption *
+gtk_printer_option_set_lookup (GtkPrinterOptionSet *set,
+ const char *name)
+{
+ gpointer ptr;
+
+ ptr = g_hash_table_lookup (set->hash, name);
+
+ return GTK_PRINTER_OPTION (ptr);
+}
+
+void
+gtk_printer_option_set_clear_conflicts (GtkPrinterOptionSet *set)
+{
+ gtk_printer_option_set_foreach (set,
+ (GtkPrinterOptionSetFunc)gtk_printer_option_clear_has_conflict,
+ NULL);
+}
+
+/**
+ * gtk_printer_option_set_get_groups:
+ * @set: a `GtkPrinterOptionSet`
+ *
+ * Gets the groups in this set.
+ *
+ * Returns: (element-type utf8) (transfer full): a list of group names.
+ */
+GList *
+gtk_printer_option_set_get_groups (GtkPrinterOptionSet *set)
+{
+ GtkPrinterOption *option;
+ GList *list = NULL;
+ int i;
+
+ for (i = 0; i < set->array->len; i++)
+ {
+ option = g_ptr_array_index (set->array, i);
+
+ if (g_list_find_custom (list, option->group, (GCompareFunc)g_strcmp0) == NULL)
+ list = g_list_prepend (list, g_strdup (option->group));
+ }
+
+ return g_list_reverse (list);
+}
+
+void
+gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet *set,
+ const char *group,
+ GtkPrinterOptionSetFunc func,
+ gpointer user_data)
+{
+ GtkPrinterOption *option;
+ int i;
+
+ for (i = 0; i < set->array->len; i++)
+ {
+ option = g_ptr_array_index (set->array, i);
+
+ if (group == NULL || g_strcmp0 (group, option->group) == 0)
+ func (option, user_data);
+ }
+}
+
+void
+gtk_printer_option_set_foreach (GtkPrinterOptionSet *set,
+ GtkPrinterOptionSetFunc func,
+ gpointer user_data)
+{
+ gtk_printer_option_set_foreach_in_group (set, NULL, func, user_data);
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprinteroptionset.h: printer option set
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+/* This is a "semi-private" header; it is meant only for
+ * alternate GtkPrintDialog backend modules; no stability guarantees
+ * are made at this point
+ */
+#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
+#error "GtkPrintBackend is not supported API for general use"
+#endif
+
+#include <glib-object.h>
+#include <gdk/gdk.h>
+#include "gtkprinteroptionprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINTER_OPTION_SET (gtk_printer_option_set_get_type ())
+#define GTK_PRINTER_OPTION_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_SET, GtkPrinterOptionSet))
+#define GTK_IS_PRINTER_OPTION_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_SET))
+
+typedef struct _GtkPrinterOptionSet GtkPrinterOptionSet;
+typedef struct _GtkPrinterOptionSetClass GtkPrinterOptionSetClass;
+
+struct _GtkPrinterOptionSet
+{
+ GObject parent_instance;
+
+ /*< private >*/
+ GPtrArray *array;
+ GHashTable *hash;
+};
+
+struct _GtkPrinterOptionSetClass
+{
+ GObjectClass parent_class;
+
+ void (*changed) (GtkPrinterOptionSet *option);
+
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+typedef void (*GtkPrinterOptionSetFunc) (GtkPrinterOption *option,
+ gpointer user_data);
+
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_printer_option_set_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkPrinterOptionSet *gtk_printer_option_set_new (void);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_add (GtkPrinterOptionSet *set,
+ GtkPrinterOption *option);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_remove (GtkPrinterOptionSet *set,
+ GtkPrinterOption *option);
+GDK_AVAILABLE_IN_ALL
+GtkPrinterOption * gtk_printer_option_set_lookup (GtkPrinterOptionSet *set,
+ const char *name);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_foreach (GtkPrinterOptionSet *set,
+ GtkPrinterOptionSetFunc func,
+ gpointer user_data);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_clear_conflicts (GtkPrinterOptionSet *set);
+GDK_AVAILABLE_IN_ALL
+GList * gtk_printer_option_set_get_groups (GtkPrinterOptionSet *set);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet *set,
+ const char *group,
+ GtkPrinterOptionSetFunc func,
+ gpointer user_data);
+
+G_END_DECLS
+
--- /dev/null
+/* GtkPrinterOptionWidget
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <glib/gi18n-lib.h>
+#include "gtkcheckbutton.h"
+#include "gtkdropdown.h"
+#include "gtklistitem.h"
+#include "gtksignallistitemfactory.h"
+#include "gtkentry.h"
+#include "gtkfiledialog.h"
+#include "gtkimage.h"
+#include "gtklabel.h"
+#include "gtkcheckbutton.h"
+#include "gtkgrid.h"
+#include "gtkorientable.h"
+#include "gtkprivate.h"
+#include "gtkstringlist.h"
+
+#include "gtkprinteroptionwidgetprivate.h"
+
+/* This defines the max file length that the file chooser
+ * button should display. The total length will be
+ * FILENAME_LENGTH_MAX+3 because the truncated name is prefixed
+ * with “...”.
+ */
+#define FILENAME_LENGTH_MAX 27
+
+static void gtk_printer_option_widget_finalize (GObject *object);
+
+static void deconstruct_widgets (GtkPrinterOptionWidget *widget);
+static void construct_widgets (GtkPrinterOptionWidget *widget);
+static void update_widgets (GtkPrinterOptionWidget *widget);
+
+static char *trim_long_filename (const char *filename);
+
+struct GtkPrinterOptionWidgetPrivate
+{
+ GtkPrinterOption *source;
+ gulong source_changed_handler;
+
+ GtkWidget *check;
+ GtkWidget *combo;
+ GtkWidget *entry;
+ GtkWidget *image;
+ GtkWidget *label;
+ GtkWidget *info_label;
+ GtkWidget *box;
+ GtkWidget *button;
+
+ /* the last location for save to file, that the user selected */
+ GFile *last_location;
+};
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_SOURCE
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinterOptionWidget, gtk_printer_option_widget, GTK_TYPE_BOX)
+
+static void gtk_printer_option_widget_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_printer_option_widget_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static gboolean gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
+ gboolean group_cycling);
+
+static void
+gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+
+ object_class->finalize = gtk_printer_option_widget_finalize;
+ object_class->set_property = gtk_printer_option_widget_set_property;
+ object_class->get_property = gtk_printer_option_widget_get_property;
+
+ widget_class->mnemonic_activate = gtk_printer_option_widget_mnemonic_activate;
+
+ signals[CHANGED] =
+ g_signal_new (I_("changed"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrinterOptionWidgetClass, changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
+ g_object_class_install_property (object_class,
+ PROP_SOURCE,
+ g_param_spec_object ("source", NULL, NULL,
+ GTK_TYPE_PRINTER_OPTION,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+}
+
+static void
+gtk_printer_option_widget_init (GtkPrinterOptionWidget *widget)
+{
+ widget->priv = gtk_printer_option_widget_get_instance_private (widget);
+
+ gtk_box_set_spacing (GTK_BOX (widget), 12);
+}
+
+static void
+gtk_printer_option_widget_finalize (GObject *object)
+{
+ GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+ if (priv->source)
+ {
+ g_signal_handler_disconnect (priv->source,
+ priv->source_changed_handler);
+ g_object_unref (priv->source);
+ priv->source = NULL;
+ }
+
+ G_OBJECT_CLASS (gtk_printer_option_widget_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_option_widget_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrinterOptionWidget *widget;
+
+ widget = GTK_PRINTER_OPTION_WIDGET (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ gtk_printer_option_widget_set_source (widget, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_printer_option_widget_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ g_value_set_object (value, priv->source);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ GtkPrinterOptionWidget *powidget = GTK_PRINTER_OPTION_WIDGET (widget);
+ GtkPrinterOptionWidgetPrivate *priv = powidget->priv;
+
+ if (priv->check)
+ return gtk_widget_mnemonic_activate (priv->check, group_cycling);
+ if (priv->combo)
+ return gtk_widget_mnemonic_activate (priv->combo, group_cycling);
+ if (priv->entry)
+ return gtk_widget_mnemonic_activate (priv->entry, group_cycling);
+ if (priv->button)
+ return gtk_widget_mnemonic_activate (priv->button, group_cycling);
+
+ return FALSE;
+}
+
+static void
+emit_changed (GtkPrinterOptionWidget *widget)
+{
+ g_signal_emit (widget, signals[CHANGED], 0);
+}
+
+GtkWidget *
+gtk_printer_option_widget_new (GtkPrinterOption *source)
+{
+ return g_object_new (GTK_TYPE_PRINTER_OPTION_WIDGET, "source", source, NULL);
+}
+
+static void
+source_changed_cb (GtkPrinterOption *source,
+ GtkPrinterOptionWidget *widget)
+{
+ update_widgets (widget);
+ emit_changed (widget);
+}
+
+void
+gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *widget,
+ GtkPrinterOption *source)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+ if (source)
+ g_object_ref (source);
+
+ if (priv->source)
+ {
+ g_signal_handler_disconnect (priv->source,
+ priv->source_changed_handler);
+ g_object_unref (priv->source);
+ }
+
+ priv->source = source;
+
+ if (source)
+ priv->source_changed_handler =
+ g_signal_connect (source, "changed", G_CALLBACK (source_changed_cb), widget);
+
+ construct_widgets (widget);
+ update_widgets (widget);
+
+ g_object_notify (G_OBJECT (widget), "source");
+}
+
+#define GTK_TYPE_STRING_PAIR (gtk_string_pair_get_type ())
+G_DECLARE_FINAL_TYPE (GtkStringPair, gtk_string_pair, GTK, STRING_PAIR, GObject)
+
+struct _GtkStringPair {
+ GObject parent_instance;
+ char *id;
+ char *string;
+};
+
+enum {
+ PROP_ID = 1,
+ PROP_STRING,
+ PROP_NUM_PROPERTIES
+};
+
+G_DEFINE_TYPE (GtkStringPair, gtk_string_pair, G_TYPE_OBJECT);
+
+static void
+gtk_string_pair_init (GtkStringPair *pair)
+{
+}
+
+static void
+gtk_string_pair_finalize (GObject *object)
+{
+ GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+ g_free (pair->id);
+ g_free (pair->string);
+
+ G_OBJECT_CLASS (gtk_string_pair_parent_class)->finalize (object);
+}
+
+static void
+gtk_string_pair_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+ switch (property_id)
+ {
+ case PROP_STRING:
+ g_free (pair->string);
+ pair->string = g_value_dup_string (value);
+ break;
+
+ case PROP_ID:
+ g_free (pair->id);
+ pair->id = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_string_pair_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+ switch (property_id)
+ {
+ case PROP_STRING:
+ g_value_set_string (value, pair->string);
+ break;
+
+ case PROP_ID:
+ g_value_set_string (value, pair->id);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_string_pair_class_init (GtkStringPairClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GParamSpec *pspec;
+
+ object_class->finalize = gtk_string_pair_finalize;
+ object_class->set_property = gtk_string_pair_set_property;
+ object_class->get_property = gtk_string_pair_get_property;
+
+ pspec = g_param_spec_string ("string", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_property (object_class, PROP_STRING, pspec);
+
+ pspec = g_param_spec_string ("id", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_property (object_class, PROP_ID, pspec);
+}
+
+static GtkStringPair *
+gtk_string_pair_new (const char *id,
+ const char *string)
+{
+ return g_object_new (GTK_TYPE_STRING_PAIR,
+ "id", id,
+ "string", string,
+ NULL);
+}
+
+static const char *
+gtk_string_pair_get_string (GtkStringPair *pair)
+{
+ return pair->string;
+}
+
+static const char *
+gtk_string_pair_get_id (GtkStringPair *pair)
+{
+ return pair->id;
+}
+
+static void
+combo_box_set_model (GtkWidget *combo_box)
+{
+ GListStore *store;
+
+ store = g_list_store_new (GTK_TYPE_STRING_PAIR);
+ gtk_drop_down_set_model (GTK_DROP_DOWN (combo_box), G_LIST_MODEL (store));
+ g_object_unref (store);
+}
+
+static void
+setup_no_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+}
+
+static void
+setup_list_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new ("");
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_list_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkStringPair *pair;
+ GtkWidget *label;
+
+ pair = gtk_list_item_get_item (item);
+ label = gtk_list_item_get_child (item);
+
+ gtk_label_set_text (GTK_LABEL (label), gtk_string_pair_get_string (pair));
+}
+
+static void
+combo_box_set_view (GtkWidget *combo_box)
+{
+ GtkListItemFactory *factory;
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
+ gtk_drop_down_set_factory (GTK_DROP_DOWN (combo_box), factory);
+ g_object_unref (factory);
+}
+
+static void
+selected_changed (GtkDropDown *dropdown,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ GListModel *model;
+ guint selected;
+ GtkStringPair *pair;
+ GtkWidget *entry = data;
+
+ model = gtk_drop_down_get_model (dropdown);
+ selected = gtk_drop_down_get_selected (dropdown);
+
+ pair = g_list_model_get_item (model, selected);
+ if (pair)
+ {
+ gtk_editable_set_text (GTK_EDITABLE (entry), gtk_string_pair_get_string (pair));
+ g_object_unref (pair);
+ }
+ else
+ gtk_editable_set_text (GTK_EDITABLE (entry), "");
+
+}
+
+static GtkWidget *
+combo_box_entry_new (void)
+{
+ GtkWidget *hbox, *entry, *button;
+ GtkListItemFactory *factory;
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_add_css_class (hbox, "linked");
+
+ entry = gtk_entry_new ();
+ button = gtk_drop_down_new (NULL, NULL);
+ combo_box_set_model (button);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_no_item), NULL);
+ gtk_drop_down_set_factory (GTK_DROP_DOWN (button), factory);
+ g_object_unref (factory);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
+ gtk_drop_down_set_list_factory (GTK_DROP_DOWN (button), factory);
+ g_object_unref (factory);
+
+ g_signal_connect (button, "notify::selected", G_CALLBACK (selected_changed), entry);
+
+ gtk_box_append (GTK_BOX (hbox), entry);
+ gtk_box_append (GTK_BOX (hbox), button);
+
+ return hbox;
+}
+
+static GtkWidget *
+combo_box_new (void)
+{
+ GtkWidget *combo_box;
+
+ combo_box = gtk_drop_down_new (NULL, NULL);
+
+ combo_box_set_model (combo_box);
+ combo_box_set_view (combo_box);
+
+ return combo_box;
+}
+
+static void
+combo_box_append (GtkWidget *combo,
+ const char *display_text,
+ const char *value)
+{
+ GtkWidget *dropdown;
+ GListModel *model;
+ GtkStringPair *object;
+
+ if (GTK_IS_DROP_DOWN (combo))
+ dropdown = combo;
+ else
+ dropdown = gtk_widget_get_last_child (combo);
+
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+
+ object = gtk_string_pair_new (value, display_text);
+ g_list_store_append (G_LIST_STORE (model), object);
+ g_object_unref (object);
+}
+
+static void
+combo_box_set (GtkWidget *combo,
+ const char *value)
+{
+ GtkWidget *dropdown;
+ GListModel *model;
+ guint i;
+
+ if (GTK_IS_DROP_DOWN (combo))
+ dropdown = combo;
+ else
+ dropdown = gtk_widget_get_last_child (combo);
+
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+
+ for (i = 0; i < g_list_model_get_n_items (model); i++)
+ {
+ GtkStringPair *item = g_list_model_get_item (model, i);
+ if (strcmp (value, gtk_string_pair_get_id (item)) == 0)
+ {
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i);
+ g_object_unref (item);
+ break;
+ }
+ g_object_unref (item);
+ }
+}
+
+static char *
+combo_box_get (GtkWidget *combo, gboolean *custom)
+{
+ GtkWidget *dropdown;
+ GListModel *model;
+ guint selected;
+ gpointer item;
+ const char *id;
+ const char *string;
+
+ if (GTK_IS_DROP_DOWN (combo))
+ dropdown = combo;
+ else
+ dropdown = gtk_widget_get_last_child (combo);
+
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+ selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown));
+ item = g_list_model_get_item (model, selected);
+ if (item)
+ {
+ id = gtk_string_pair_get_id (item);
+ string = gtk_string_pair_get_string (item);
+ g_object_unref (item);
+ }
+ else
+ {
+ id = "";
+ string = NULL;
+ }
+
+ if (dropdown == combo) // no entry
+ {
+ *custom = FALSE;
+ return g_strdup (id);
+ }
+ else
+ {
+ const char *text;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (gtk_widget_get_first_child (combo)));
+ if (g_strcmp0 (text, string) == 0)
+ {
+ *custom = FALSE;
+ return g_strdup (id);
+ }
+ else
+ {
+ *custom = TRUE;
+ return g_strdup (text);
+ }
+ }
+}
+
+static void
+deconstruct_widgets (GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+ g_clear_pointer (&priv->check, gtk_widget_unparent);
+ g_clear_pointer (&priv->combo, gtk_widget_unparent);
+ g_clear_pointer (&priv->entry, gtk_widget_unparent);
+ g_clear_pointer (&priv->image, gtk_widget_unparent);
+ g_clear_pointer (&priv->label, gtk_widget_unparent);
+ g_clear_pointer (&priv->info_label, gtk_widget_unparent);
+}
+
+static void
+check_toggled_cb (GtkCheckButton *check_button,
+ GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+ g_signal_handler_block (priv->source, priv->source_changed_handler);
+ gtk_printer_option_set_boolean (priv->source,
+ gtk_check_button_get_active (check_button));
+ g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+ emit_changed (widget);
+}
+
+static void
+dialog_response_callback (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
+ GtkPrinterOptionWidget *widget = data;
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+ GFile *new_location = NULL;
+ char *uri = NULL;
+
+ new_location = gtk_file_dialog_save_finish (dialog, result, NULL);
+ if (new_location)
+ {
+ GFileInfo *info;
+
+ info = g_file_query_info (new_location,
+ "standard::display-name",
+ 0,
+ NULL,
+ NULL);
+ if (info != NULL)
+ {
+ const char *filename_utf8 = g_file_info_get_display_name (info);
+
+ char *filename_short = trim_long_filename (filename_utf8);
+ gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
+
+ g_free (filename_short);
+ g_object_unref (info);
+ }
+ else
+ {
+ const char *path = g_file_peek_path (new_location);
+ char *filename_utf8 = g_utf8_make_valid (path, -1);
+
+ char *filename_short = trim_long_filename (filename_utf8);
+ gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
+
+ g_free (filename_short);
+ g_free (filename_utf8);
+ }
+ }
+
+ if (new_location)
+ uri = g_file_get_uri (new_location);
+ else
+ uri = g_file_get_uri (priv->last_location);
+
+ if (uri != NULL)
+ {
+ gtk_printer_option_set (priv->source, uri);
+ emit_changed (widget);
+ g_free (uri);
+ }
+
+ g_clear_object (&new_location);
+ g_clear_object (&priv->last_location);
+
+ /* unblock the handler which was blocked in the filesave_choose_cb function */
+ g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+}
+
+static void
+filesave_choose_cb (GtkWidget *button,
+ GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+ GtkFileDialog *dialog;
+
+ /* this will be unblocked in the dialog_response_callback function */
+ g_signal_handler_block (priv->source, priv->source_changed_handler);
+
+ dialog = gtk_file_dialog_new ();
+ gtk_file_dialog_set_title (dialog, _("Select a filename"));
+
+ /* select the current filename in the dialog */
+ if (priv->source != NULL && priv->source->value != NULL)
+ {
+ priv->last_location = g_file_new_for_uri (priv->source->value);
+ if (priv->last_location)
+ {
+ if (g_file_query_file_type (priv->last_location, 0, NULL) == G_FILE_TYPE_DIRECTORY)
+ gtk_file_dialog_set_initial_folder (dialog, priv->last_location);
+ else
+ gtk_file_dialog_set_initial_file (dialog, priv->last_location);
+ }
+ }
+
+ gtk_file_dialog_save (dialog,
+ GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (widget))),
+ NULL,
+ dialog_response_callback, widget);
+}
+
+static char *
+filter_numeric (const char *val,
+ gboolean allow_neg,
+ gboolean allow_dec,
+ gboolean *changed_out)
+{
+ char *filtered_val;
+ int i, j;
+ int len = strlen (val);
+ gboolean dec_set = FALSE;
+
+ filtered_val = g_malloc (len + 1);
+
+ for (i = 0, j = 0; i < len; i++)
+ {
+ if (isdigit (val[i]))
+ {
+ filtered_val[j] = val[i];
+ j++;
+ }
+ else if (allow_dec && !dec_set &&
+ (val[i] == '.' || val[i] == ','))
+ {
+ /* allow one period or comma
+ * we should be checking locals
+ * but this is good enough for now
+ */
+ filtered_val[j] = val[i];
+ dec_set = TRUE;
+ j++;
+ }
+ else if (allow_neg && i == 0 && val[0] == '-')
+ {
+ filtered_val[0] = val[0];
+ j++;
+ }
+ }
+
+ filtered_val[j] = '\0';
+ *changed_out = !(i == j);
+
+ return filtered_val;
+}
+
+static void
+combo_changed_cb (GtkWidget *combo,
+ GParamSpec *pspec,
+ GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+ char *value;
+ char *filtered_val = NULL;
+ gboolean changed;
+ gboolean custom = TRUE;
+
+ g_signal_handler_block (priv->source, priv->source_changed_handler);
+
+ value = combo_box_get (priv->combo, &custom);
+
+ /* Handle constraints if the user entered a custom value. */
+ if (custom)
+ {
+ switch (priv->source->type)
+ {
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
+ filtered_val = filter_numeric (value, FALSE, FALSE, &changed);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
+ filtered_val = filter_numeric (value, TRUE, FALSE, &changed);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
+ filtered_val = filter_numeric (value, TRUE, TRUE, &changed);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
+ case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
+ case GTK_PRINTER_OPTION_TYPE_STRING:
+ case GTK_PRINTER_OPTION_TYPE_FILESAVE:
+ case GTK_PRINTER_OPTION_TYPE_INFO:
+ default:
+ break;
+ }
+ }
+
+ if (filtered_val)
+ {
+ g_free (value);
+
+ if (changed)
+ {
+ GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
+ gtk_editable_set_text (GTK_EDITABLE (entry), filtered_val);
+ }
+ value = filtered_val;
+ }
+
+ if (value)
+ gtk_printer_option_set (priv->source, value);
+ g_free (value);
+ g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+ emit_changed (widget);
+}
+
+static void
+entry_changed_cb (GtkWidget *entry,
+ GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+ const char *value;
+
+ g_signal_handler_block (priv->source, priv->source_changed_handler);
+ value = gtk_editable_get_text (GTK_EDITABLE (entry));
+ if (value)
+ gtk_printer_option_set (priv->source, value);
+ g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+ emit_changed (widget);
+}
+
+
+static void
+radio_changed_cb (GtkWidget *button,
+ GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+ char *value;
+
+ g_signal_handler_block (priv->source, priv->source_changed_handler);
+ value = g_object_get_data (G_OBJECT (button), "value");
+ if (value)
+ gtk_printer_option_set (priv->source, value);
+ g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+ emit_changed (widget);
+}
+
+static void
+alternative_set (GtkWidget *box,
+ const char *value)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (box);
+ child != NULL;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ char *v = g_object_get_data (G_OBJECT (child), "value");
+
+ if (strcmp (value, v) == 0)
+ {
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (child), TRUE);
+ break;
+ }
+ }
+}
+
+static void
+alternative_append (GtkWidget *box,
+ const char *label,
+ const char *value,
+ GtkPrinterOptionWidget *widget,
+ GtkWidget **group)
+{
+ GtkWidget *button;
+
+ button = gtk_check_button_new_with_label (label);
+ if (*group)
+ gtk_check_button_set_group (GTK_CHECK_BUTTON (button), GTK_CHECK_BUTTON (*group));
+ else
+ *group = button;
+
+ gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
+ gtk_box_append (GTK_BOX (box), button);
+
+ g_object_set_data (G_OBJECT (button), "value", (gpointer)value);
+ g_signal_connect (button, "toggled", G_CALLBACK (radio_changed_cb), widget);
+}
+
+static void
+construct_widgets (GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+ GtkPrinterOption *source;
+ char *text;
+ int i;
+ GtkWidget *group;
+
+ source = priv->source;
+
+ deconstruct_widgets (widget);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE);
+
+ if (source == NULL)
+ {
+ const char * strings[2];
+ strings[0] = _("Not available");
+ strings[1] = NULL;
+ priv->combo = gtk_drop_down_new_from_strings (strings);
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->combo), 0);
+ gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE);
+ gtk_box_append (GTK_BOX (widget), priv->combo);
+ }
+ else switch (source->type)
+ {
+ case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
+ priv->check = gtk_check_button_new_with_mnemonic (source->display_text);
+ g_signal_connect (priv->check, "toggled", G_CALLBACK (check_toggled_cb), widget);
+ gtk_box_append (GTK_BOX (widget), priv->check);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_PICKONE:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
+ if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE)
+ {
+ priv->combo = combo_box_new ();
+ }
+ else
+ {
+ priv->combo = combo_box_entry_new ();
+
+ if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD ||
+ source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE)
+ {
+ GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
+ gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
+ }
+ }
+
+ for (i = 0; i < source->num_choices; i++)
+ combo_box_append (priv->combo,
+ source->choices_display[i],
+ source->choices[i]);
+ gtk_box_append (GTK_BOX (widget), priv->combo);
+ if (GTK_IS_DROP_DOWN (priv->combo))
+ g_signal_connect (priv->combo, "notify::selected", G_CALLBACK (combo_changed_cb),widget);
+ else
+ g_signal_connect (gtk_widget_get_last_child (priv->combo), "notify::selected",G_CALLBACK (combo_changed_cb), widget);
+
+ text = g_strdup_printf ("%s:", source->display_text);
+ priv->label = gtk_label_new_with_mnemonic (text);
+ g_free (text);
+ break;
+
+ case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
+ group = NULL;
+ priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_widget_set_valign (priv->box, GTK_ALIGN_BASELINE_FILL);
+ gtk_box_append (GTK_BOX (widget), priv->box);
+ for (i = 0; i < source->num_choices; i++)
+ {
+ alternative_append (priv->box,
+ source->choices_display[i],
+ source->choices[i],
+ widget,
+ &group);
+ /* for mnemonic activation */
+ if (i == 0)
+ priv->button = group;
+ }
+
+ if (source->display_text)
+ {
+ text = g_strdup_printf ("%s:", source->display_text);
+ priv->label = gtk_label_new_with_mnemonic (text);
+ gtk_widget_set_valign (priv->label, GTK_ALIGN_BASELINE_FILL);
+ g_free (text);
+ }
+ break;
+
+ case GTK_PRINTER_OPTION_TYPE_STRING:
+ priv->entry = gtk_entry_new ();
+ gtk_entry_set_activates_default (GTK_ENTRY (priv->entry),
+ gtk_printer_option_get_activates_default (source));
+ gtk_box_append (GTK_BOX (widget), priv->entry);
+ g_signal_connect (priv->entry, "changed", G_CALLBACK (entry_changed_cb), widget);
+
+ text = g_strdup_printf ("%s:", source->display_text);
+ priv->label = gtk_label_new_with_mnemonic (text);
+ g_free (text);
+
+ break;
+
+ case GTK_PRINTER_OPTION_TYPE_FILESAVE:
+ priv->button = gtk_button_new ();
+ gtk_box_append (GTK_BOX (widget), priv->button);
+ g_signal_connect (priv->button, "clicked", G_CALLBACK (filesave_choose_cb), widget);
+
+ text = g_strdup_printf ("%s:", source->display_text);
+ priv->label = gtk_label_new_with_mnemonic (text);
+ g_free (text);
+
+ break;
+
+ case GTK_PRINTER_OPTION_TYPE_INFO:
+ priv->info_label = gtk_label_new (NULL);
+ gtk_label_set_selectable (GTK_LABEL (priv->info_label), TRUE);
+ gtk_box_append (GTK_BOX (widget), priv->info_label);
+
+ text = g_strdup_printf ("%s:", source->display_text);
+ priv->label = gtk_label_new_with_mnemonic (text);
+ g_free (text);
+
+ break;
+
+ default:
+ break;
+ }
+
+ priv->image = gtk_image_new_from_icon_name ("dialog-warning");
+ gtk_box_append (GTK_BOX (widget), priv->image);
+}
+
+/*
+ * If the filename exceeds FILENAME_LENGTH_MAX, then trim it and replace
+ * the first three letters with three dots.
+ */
+static char *
+trim_long_filename (const char *filename)
+{
+ const char *home;
+ int len, offset;
+ char *result;
+
+ home = g_get_home_dir ();
+ if (g_str_has_prefix (filename, home))
+ {
+ char *homeless_filename;
+
+ offset = g_utf8_strlen (home, -1);
+ len = g_utf8_strlen (filename, -1);
+ homeless_filename = g_utf8_substring (filename, offset, len);
+ result = g_strconcat ("~", homeless_filename, NULL);
+ g_free (homeless_filename);
+ }
+ else
+ result = g_strdup (filename);
+
+ len = g_utf8_strlen (result, -1);
+ if (len > FILENAME_LENGTH_MAX)
+ {
+ char *suffix;
+
+ suffix = g_utf8_substring (result, len - FILENAME_LENGTH_MAX, len);
+ g_free (result);
+ result = g_strconcat ("...", suffix, NULL);
+ g_free (suffix);
+ }
+
+ return result;
+}
+
+static void
+update_widgets (GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+ GtkPrinterOption *source;
+
+ source = priv->source;
+
+ if (source == NULL)
+ {
+ gtk_widget_set_visible (priv->image, FALSE);
+ return;
+ }
+
+ switch (source->type)
+ {
+ case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
+ if (g_ascii_strcasecmp (source->value, "True") == 0)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), TRUE);
+ else
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), FALSE);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_PICKONE:
+ combo_box_set (priv->combo, source->value);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
+ alternative_set (priv->box, source->value);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_STRING:
+ gtk_editable_set_text (GTK_EDITABLE (priv->entry), source->value);
+ break;
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
+ case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
+ {
+ GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
+ if (gtk_printer_option_has_choice (source, source->value))
+ combo_box_set (priv->combo, source->value);
+ else
+ gtk_editable_set_text (GTK_EDITABLE (entry), source->value);
+
+ break;
+ }
+ case GTK_PRINTER_OPTION_TYPE_FILESAVE:
+ {
+ char *text;
+ char *filename;
+
+ filename = g_filename_from_uri (source->value, NULL, NULL);
+ if (filename != NULL)
+ {
+ text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+ if (text != NULL)
+ {
+ char *short_filename;
+
+ short_filename = trim_long_filename (text);
+ gtk_button_set_label (GTK_BUTTON (priv->button), short_filename);
+ g_free (short_filename);
+ }
+
+ g_free (text);
+ g_free (filename);
+ }
+ else
+ gtk_button_set_label (GTK_BUTTON (priv->button), source->value);
+ break;
+ }
+ case GTK_PRINTER_OPTION_TYPE_INFO:
+ gtk_label_set_text (GTK_LABEL (priv->info_label), source->value);
+ break;
+ default:
+ break;
+ }
+
+ gtk_widget_set_visible (priv->image, source->has_conflict);
+}
+
+gboolean
+gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *widget)
+{
+ return widget->priv->label != NULL;
+}
+
+GtkWidget *
+gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget *widget)
+{
+ return widget->priv->label;
+}
+
+const char *
+gtk_printer_option_widget_get_value (GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+ if (priv->source)
+ return priv->source->value;
+
+ return "";
+}
--- /dev/null
+/* GtkPrinterOptionWidget
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
+ */
+#pragma once
+
+#include <gtk/gtk.h>
+#include "gtkprinteroptionprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINTER_OPTION_WIDGET (gtk_printer_option_widget_get_type ())
+#define GTK_PRINTER_OPTION_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidget))
+#define GTK_PRINTER_OPTION_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
+#define GTK_IS_PRINTER_OPTION_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET))
+#define GTK_IS_PRINTER_OPTION_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET))
+#define GTK_PRINTER_OPTION_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
+
+
+typedef struct _GtkPrinterOptionWidget GtkPrinterOptionWidget;
+typedef struct _GtkPrinterOptionWidgetClass GtkPrinterOptionWidgetClass;
+typedef struct GtkPrinterOptionWidgetPrivate GtkPrinterOptionWidgetPrivate;
+
+struct _GtkPrinterOptionWidget
+{
+ GtkBox parent_instance;
+
+ GtkPrinterOptionWidgetPrivate *priv;
+};
+
+struct _GtkPrinterOptionWidgetClass
+{
+ GtkBoxClass parent_class;
+
+ void (*changed) (GtkPrinterOptionWidget *widget);
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_printer_option_widget_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkWidget *gtk_printer_option_widget_new (GtkPrinterOption *source);
+GDK_AVAILABLE_IN_ALL
+void gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *setting,
+ GtkPrinterOption *source);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *setting);
+GDK_AVAILABLE_IN_ALL
+GtkWidget *gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget *setting);
+GDK_AVAILABLE_IN_ALL
+const char *gtk_printer_option_widget_get_value (GtkPrinterOptionWidget *setting);
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation.h: Print Operation
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "gtkunixprint.h"
+#include "gtkprinteroptionsetprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_PRINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER, GtkPrinterClass))
+#define GTK_IS_PRINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER))
+#define GTK_PRINTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER, GtkPrinterClass))
+
+typedef struct _GtkPrinterClass GtkPrinterClass;
+typedef struct _GtkPrinterPrivate GtkPrinterPrivate;
+
+struct _GtkPrinter
+{
+ GObject parent_instance;
+};
+
+struct _GtkPrinterClass
+{
+ GObjectClass parent_class;
+
+ void (*details_acquired) (GtkPrinter *printer,
+ gboolean success);
+};
+
+GtkPrinterOptionSet *_gtk_printer_get_options (GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup,
+ GtkPrintCapabilities capabilities);
+gboolean _gtk_printer_mark_conflicts (GtkPrinter *printer,
+ GtkPrinterOptionSet *options);
+void _gtk_printer_get_settings_from_options (GtkPrinter *printer,
+ GtkPrinterOptionSet *options,
+ GtkPrintSettings *settings);
+void _gtk_printer_prepare_for_print (GtkPrinter *printer,
+ GtkPrintJob *print_job,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup);
+cairo_surface_t * _gtk_printer_create_cairo_surface (GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ double width,
+ double height,
+ GIOChannel *cache_io);
+GHashTable * _gtk_printer_get_custom_widgets (GtkPrinter *printer);
+
+/* GtkPrintJob private methods: */
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_status (GtkPrintJob *job,
+ GtkPrintStatus status);
+
+G_END_DECLS
--- /dev/null
+/* GtkPrintJob
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
+ */
+
+/**
+ * GtkPrintJob:
+ *
+ * A `GtkPrintJob` object represents a job that is sent to a printer.
+ *
+ * You only need to deal directly with print jobs if you use the
+ * non-portable [class@Gtk.PrintUnixDialog] API.
+ *
+ * Use [method@Gtk.PrintJob.get_surface] to obtain the cairo surface
+ * onto which the pages must be drawn. Use [method@Gtk.PrintJob.send]
+ * to send the finished job to the printer. If you don’t use cairo
+ * `GtkPrintJob` also supports printing of manually generated PostScript,
+ * via [method@Gtk.PrintJob.set_source_file].
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <glib/gstdio.h>
+#include "gtkprivate.h"
+
+#include "gtkprintjob.h"
+#include "gtkprinter.h"
+#include "gtkprinterprivate.h"
+#include "gtkprintbackendprivate.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+typedef struct _GtkPrintJobClass GtkPrintJobClass;
+
+struct _GtkPrintJob
+{
+ GObject parent_instance;
+
+ char *title;
+
+ GIOChannel *spool_io;
+ cairo_surface_t *surface;
+
+ GtkPrintStatus status;
+ GtkPrintBackend *backend;
+ GtkPrinter *printer;
+ GtkPrintSettings *settings;
+ GtkPageSetup *page_setup;
+
+ GtkPrintPages print_pages;
+ GtkPageRange *page_ranges;
+ int num_page_ranges;
+ GtkPageSet page_set;
+ int num_copies;
+ double scale;
+ guint number_up;
+ GtkNumberUpLayout number_up_layout;
+
+ guint printer_set : 1;
+ guint page_setup_set : 1;
+ guint settings_set : 1;
+ guint track_print_status : 1;
+ guint rotate_to_orientation : 1;
+ guint collate : 1;
+ guint reverse : 1;
+};
+
+struct _GtkPrintJobClass
+{
+ GObjectClass parent_class;
+
+ void (*status_changed) (GtkPrintJob *job);
+};
+
+static void gtk_print_job_finalize (GObject *object);
+static void gtk_print_job_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_print_job_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gtk_print_job_constructed (GObject *object);
+
+enum {
+ STATUS_CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_TITLE,
+ PROP_PRINTER,
+ PROP_PAGE_SETUP,
+ PROP_SETTINGS,
+ PROP_TRACK_PRINT_STATUS
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GtkPrintJob, gtk_print_job, G_TYPE_OBJECT)
+
+static void
+gtk_print_job_class_init (GtkPrintJobClass *class)
+{
+ GObjectClass *object_class;
+ object_class = (GObjectClass *) class;
+
+ object_class->finalize = gtk_print_job_finalize;
+ object_class->constructed = gtk_print_job_constructed;
+ object_class->set_property = gtk_print_job_set_property;
+ object_class->get_property = gtk_print_job_get_property;
+
+ /**
+ * GtkPrintJob:title: (attributes org.gtk.Property.get=gtk_print_job_get_title)
+ *
+ * The title of the print job.
+ */
+ g_object_class_install_property (object_class,
+ PROP_TITLE,
+ g_param_spec_string ("title", NULL, NULL,
+ NULL,
+ GTK_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrintJob:printer: (attributes org.gtk.Property.get=gtk_print_job_get_printer)
+ *
+ * The printer to send the job to.
+ */
+ g_object_class_install_property (object_class,
+ PROP_PRINTER,
+ g_param_spec_object ("printer", NULL, NULL,
+ GTK_TYPE_PRINTER,
+ GTK_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrintJob:settings: (attributes org.gtk.Property.get=gtk_print_job_get_settings)
+ *
+ * Printer settings.
+ */
+ g_object_class_install_property (object_class,
+ PROP_SETTINGS,
+ g_param_spec_object ("settings", NULL, NULL,
+ GTK_TYPE_PRINT_SETTINGS,
+ GTK_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrintJob:page-setup:
+ *
+ * Page setup.
+ */
+ g_object_class_install_property (object_class,
+ PROP_PAGE_SETUP,
+ g_param_spec_object ("page-setup", NULL, NULL,
+ GTK_TYPE_PAGE_SETUP,
+ GTK_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkPrintJob:track-print-status: (attributes org.gtk.Property.get=gtk_print_job_get_track_print_status org.gtk.Property.set=gtk_print_job_set_track_print_status)
+ *
+ * %TRUE if the print job will continue to emit status-changed
+ * signals after the print data has been setn to the printer.
+ */
+ g_object_class_install_property (object_class,
+ PROP_TRACK_PRINT_STATUS,
+ g_param_spec_boolean ("track-print-status", NULL, NULL,
+ FALSE,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkPrintJob::status-changed:
+ * @job: the `GtkPrintJob` object on which the signal was emitted
+ *
+ * Emitted when the status of a job changes.
+ *
+ * The signal handler can use [method@Gtk.PrintJob.get_status]
+ * to obtain the new status.
+ */
+ signals[STATUS_CHANGED] =
+ g_signal_new (I_("status-changed"),
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPrintJobClass, status_changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gtk_print_job_init (GtkPrintJob *job)
+{
+ job->spool_io = NULL;
+
+ job->title = g_strdup ("");
+ job->surface = NULL;
+ job->backend = NULL;
+ job->printer = NULL;
+
+ job->printer_set = FALSE;
+ job->settings_set = FALSE;
+ job->page_setup_set = FALSE;
+ job->status = GTK_PRINT_STATUS_INITIAL;
+ job->track_print_status = FALSE;
+
+ job->print_pages = GTK_PRINT_PAGES_ALL;
+ job->page_ranges = NULL;
+ job->num_page_ranges = 0;
+ job->collate = FALSE;
+ job->reverse = FALSE;
+ job->num_copies = 1;
+ job->scale = 1.0;
+ job->page_set = GTK_PAGE_SET_ALL;
+ job->rotate_to_orientation = FALSE;
+ job->number_up = 1;
+ job->number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+}
+
+
+static void
+gtk_print_job_constructed (GObject *object)
+{
+ GtkPrintJob *job = GTK_PRINT_JOB (object);
+
+ G_OBJECT_CLASS (gtk_print_job_parent_class)->constructed (object);
+
+ g_assert (job->printer_set &&
+ job->settings_set &&
+ job->page_setup_set);
+
+ _gtk_printer_prepare_for_print (job->printer,
+ job,
+ job->settings,
+ job->page_setup);
+}
+
+
+static void
+gtk_print_job_finalize (GObject *object)
+{
+ GtkPrintJob *job = GTK_PRINT_JOB (object);
+
+ if (job->surface)
+ cairo_surface_destroy (job->surface);
+
+ if (job->backend)
+ g_object_unref (job->backend);
+
+ if (job->spool_io != NULL)
+ {
+ g_io_channel_unref (job->spool_io);
+ job->spool_io = NULL;
+ }
+
+ if (job->printer)
+ g_object_unref (job->printer);
+
+ if (job->settings)
+ g_object_unref (job->settings);
+
+ if (job->page_setup)
+ g_object_unref (job->page_setup);
+
+ g_free (job->page_ranges);
+ job->page_ranges = NULL;
+
+ g_free (job->title);
+ job->title = NULL;
+
+ G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize (object);
+}
+
+/**
+ * gtk_print_job_new:
+ * @title: the job title
+ * @printer: a `GtkPrinter`
+ * @settings: a `GtkPrintSettings`
+ * @page_setup: a `GtkPageSetup`
+ *
+ * Creates a new `GtkPrintJob`.
+ *
+ * Returns: a new `GtkPrintJob`
+ */
+GtkPrintJob *
+gtk_print_job_new (const char *title,
+ GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup)
+{
+ GObject *result;
+ result = g_object_new (GTK_TYPE_PRINT_JOB,
+ "title", title,
+ "printer", printer,
+ "settings", settings,
+ "page-setup", page_setup,
+ NULL);
+ return (GtkPrintJob *) result;
+}
+
+/**
+ * gtk_print_job_get_settings: (attributes org.gtk.Method.get_property=settings)
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPrintSettings` of the print job.
+ *
+ * Returns: (transfer none): the settings of @job
+ */
+GtkPrintSettings *
+gtk_print_job_get_settings (GtkPrintJob *job)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+
+ return job->settings;
+}
+
+/**
+ * gtk_print_job_get_printer: (attributes org.gtk.Method.get_property=printer)
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPrinter` of the print job.
+ *
+ * Returns: (transfer none): the printer of @job
+ */
+GtkPrinter *
+gtk_print_job_get_printer (GtkPrintJob *job)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+
+ return job->printer;
+}
+
+/**
+ * gtk_print_job_get_title: (attributes org.gtk.Method.get_property=title)
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the job title.
+ *
+ * Returns: the title of @job
+ */
+const char *
+gtk_print_job_get_title (GtkPrintJob *job)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+
+ return job->title;
+}
+
+/**
+ * gtk_print_job_get_status:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the status of the print job.
+ *
+ * Returns: the status of @job
+ */
+GtkPrintStatus
+gtk_print_job_get_status (GtkPrintJob *job)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), GTK_PRINT_STATUS_FINISHED);
+
+ return job->status;
+}
+
+void
+gtk_print_job_set_status (GtkPrintJob *job,
+ GtkPrintStatus status)
+{
+ g_return_if_fail (GTK_IS_PRINT_JOB (job));
+
+ if (job->status == status)
+ return;
+
+ job->status = status;
+ g_signal_emit (job, signals[STATUS_CHANGED], 0);
+}
+
+/**
+ * gtk_print_job_set_source_file:
+ * @job: a `GtkPrintJob`
+ * @filename: (type filename): the file to be printed
+ * @error: return location for errors
+ *
+ * Make the `GtkPrintJob` send an existing document to the
+ * printing system.
+ *
+ * The file can be in any format understood by the platforms
+ * printing system (typically PostScript, but on many platforms
+ * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
+ * [method@Gtk.Printer.accepts_ps].
+ *
+ * Returns: %FALSE if an error occurred
+ */
+gboolean
+gtk_print_job_set_source_file (GtkPrintJob *job,
+ const char *filename,
+ GError **error)
+{
+ GError *tmp_error;
+
+ tmp_error = NULL;
+
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
+
+ if (job->spool_io != NULL)
+ g_io_channel_unref (job->spool_io);
+
+ job->spool_io = g_io_channel_new_file (filename, "r", &tmp_error);
+
+ if (tmp_error == NULL)
+ g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
+
+ if (tmp_error != NULL)
+ {
+ g_propagate_error (error, tmp_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * gtk_print_job_set_source_fd:
+ * @job: a `GtkPrintJob`
+ * @fd: a file descriptor
+ * @error: return location for errors
+ *
+ * Make the `GtkPrintJob` send an existing document to the
+ * printing system.
+ *
+ * The file can be in any format understood by the platforms
+ * printing system (typically PostScript, but on many platforms
+ * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
+ * [method@Gtk.Printer.accepts_ps].
+ *
+ * This is similar to [method@Gtk.PrintJob.set_source_file],
+ * but takes expects an open file descriptor for the file,
+ * instead of a filename.
+ *
+ * Returns: %FALSE if an error occurred
+ */
+gboolean
+gtk_print_job_set_source_fd (GtkPrintJob *job,
+ int fd,
+ GError **error)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
+ g_return_val_if_fail (fd >= 0, FALSE);
+
+ if (job->spool_io != NULL)
+ g_io_channel_unref (job->spool_io);
+
+ job->spool_io = g_io_channel_unix_new (fd);
+ if (g_io_channel_set_encoding (job->spool_io, NULL, error) != G_IO_STATUS_NORMAL)
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * gtk_print_job_get_surface:
+ * @job: a `GtkPrintJob`
+ * @error: (nullable): return location for errors
+ *
+ * Gets a cairo surface onto which the pages of
+ * the print job should be rendered.
+ *
+ * Returns: (transfer none): the cairo surface of @job
+ */
+cairo_surface_t *
+gtk_print_job_get_surface (GtkPrintJob *job,
+ GError **error)
+{
+ char *filename = NULL;
+ double width, height;
+ GtkPaperSize *paper_size;
+ int fd;
+ GError *tmp_error;
+
+ tmp_error = NULL;
+
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+
+ if (job->surface)
+ return job->surface;
+
+ g_return_val_if_fail (job->spool_io == NULL, NULL);
+
+ fd = g_file_open_tmp ("gtkprint_XXXXXX",
+ &filename,
+ &tmp_error);
+ if (fd == -1)
+ {
+ g_free (filename);
+ g_propagate_error (error, tmp_error);
+ return NULL;
+ }
+
+ fchmod (fd, S_IRUSR | S_IWUSR);
+
+#ifdef G_ENABLE_DEBUG
+ /* If we are debugging printing don't delete the tmp files */
+ if (GTK_DEBUG_CHECK (PRINTING)) ;
+ else
+#endif /* G_ENABLE_DEBUG */
+ g_unlink (filename);
+ g_free (filename);
+
+ paper_size = gtk_page_setup_get_paper_size (job->page_setup);
+ width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+ height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+
+ job->spool_io = g_io_channel_unix_new (fd);
+ g_io_channel_set_close_on_unref (job->spool_io, TRUE);
+ g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
+
+ if (tmp_error != NULL)
+ {
+ g_io_channel_unref (job->spool_io);
+ job->spool_io = NULL;
+ g_propagate_error (error, tmp_error);
+ return NULL;
+ }
+
+ job->surface = _gtk_printer_create_cairo_surface (job->printer,
+ job->settings,
+ width, height,
+ job->spool_io);
+
+ return job->surface;
+}
+
+/**
+ * gtk_print_job_set_track_print_status: (attributes org.gtk.Method.set_property=track-print-status)
+ * @job: a `GtkPrintJob`
+ * @track_status: %TRUE to track status after printing
+ *
+ * If track_status is %TRUE, the print job will try to continue report
+ * on the status of the print job in the printer queues and printer.
+ *
+ * This can allow your application to show things like “out of paper”
+ * issues, and when the print job actually reaches the printer.
+ *
+ * This function is often implemented using some form of polling,
+ * so it should not be enabled unless needed.
+ */
+void
+gtk_print_job_set_track_print_status (GtkPrintJob *job,
+ gboolean track_status)
+{
+ g_return_if_fail (GTK_IS_PRINT_JOB (job));
+
+ track_status = track_status != FALSE;
+
+ if (job->track_print_status != track_status)
+ {
+ job->track_print_status = track_status;
+
+ g_object_notify (G_OBJECT (job), "track-print-status");
+ }
+}
+
+/**
+ * gtk_print_job_get_track_print_status: (attributes org.gtk.Method.get_property=track-print-status)
+ * @job: a `GtkPrintJob`
+ *
+ * Returns whether jobs will be tracked after printing.
+ *
+ * For details, see [method@Gtk.PrintJob.set_track_print_status].
+ *
+ * Returns: %TRUE if print job status will be reported after printing
+ */
+gboolean
+gtk_print_job_get_track_print_status (GtkPrintJob *job)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
+
+ return job->track_print_status;
+}
+
+static void
+gtk_print_job_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GtkPrintJob *job = GTK_PRINT_JOB (object);
+ GtkPrintSettings *settings;
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_free (job->title);
+ job->title = g_value_dup_string (value);
+ break;
+
+ case PROP_PRINTER:
+ job->printer = GTK_PRINTER (g_value_dup_object (value));
+ job->printer_set = TRUE;
+ job->backend = g_object_ref (gtk_printer_get_backend (job->printer));
+ break;
+
+ case PROP_PAGE_SETUP:
+ job->page_setup = GTK_PAGE_SETUP (g_value_dup_object (value));
+ job->page_setup_set = TRUE;
+ break;
+
+ case PROP_SETTINGS:
+ /* We save a copy of the settings since we modify
+ * if when preparing the printer job. */
+ settings = GTK_PRINT_SETTINGS (g_value_get_object (value));
+ job->settings = gtk_print_settings_copy (settings);
+ job->settings_set = TRUE;
+ break;
+
+ case PROP_TRACK_PRINT_STATUS:
+ gtk_print_job_set_track_print_status (job, g_value_get_boolean (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_print_job_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrintJob *job = GTK_PRINT_JOB (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_value_set_string (value, job->title);
+ break;
+ case PROP_PRINTER:
+ g_value_set_object (value, job->printer);
+ break;
+ case PROP_SETTINGS:
+ g_value_set_object (value, job->settings);
+ break;
+ case PROP_PAGE_SETUP:
+ g_value_set_object (value, job->page_setup);
+ break;
+ case PROP_TRACK_PRINT_STATUS:
+ g_value_set_boolean (value, job->track_print_status);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * gtk_print_job_send:
+ * @job: a `GtkPrintJob`
+ * @callback: function to call when the job completes or an error occurs
+ * @user_data: (closure): user data that gets passed to @callback
+ * @dnotify: destroy notify for @user_data
+ *
+ * Sends the print job off to the printer.
+ */
+void
+gtk_print_job_send (GtkPrintJob *job,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify)
+{
+ g_return_if_fail (GTK_IS_PRINT_JOB (job));
+ g_return_if_fail (job->spool_io != NULL);
+
+ gtk_print_job_set_status (job, GTK_PRINT_STATUS_SENDING_DATA);
+
+ g_io_channel_seek_position (job->spool_io, 0, G_SEEK_SET, NULL);
+
+ gtk_print_backend_print_stream (job->backend, job,
+ job->spool_io,
+ callback, user_data, dnotify);
+}
+
+/**
+ * gtk_print_job_get_pages:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPrintPages` setting for this job.
+ *
+ * Returns: the `GtkPrintPages` setting
+ */
+GtkPrintPages
+gtk_print_job_get_pages (GtkPrintJob *job)
+{
+ return job->print_pages;
+}
+
+/**
+ * gtk_print_job_set_pages:
+ * @job: a `GtkPrintJob`
+ * @pages: the `GtkPrintPages` setting
+ *
+ * Sets the `GtkPrintPages` setting for this job.
+ */
+void
+gtk_print_job_set_pages (GtkPrintJob *job,
+ GtkPrintPages pages)
+{
+ job->print_pages = pages;
+}
+
+/**
+ * gtk_print_job_get_page_ranges:
+ * @job: a `GtkPrintJob`
+ * @n_ranges: (out): return location for the number of ranges
+ *
+ * Gets the page ranges for this job.
+ *
+ * Returns: (array length=n_ranges) (transfer none): a pointer to an
+ * array of `GtkPageRange` structs
+ */
+GtkPageRange *
+gtk_print_job_get_page_ranges (GtkPrintJob *job,
+ int *n_ranges)
+{
+ *n_ranges = job->num_page_ranges;
+ return job->page_ranges;
+}
+
+/**
+ * gtk_print_job_set_page_ranges:
+ * @job: a `GtkPrintJob`
+ * @ranges: (array length=n_ranges) (transfer full): pointer to an array of
+ * `GtkPageRange` structs
+ * @n_ranges: the length of the @ranges array
+ *
+ * Sets the page ranges for this job.
+ */
+void
+gtk_print_job_set_page_ranges (GtkPrintJob *job,
+ GtkPageRange *ranges,
+ int n_ranges)
+{
+ g_free (job->page_ranges);
+ job->page_ranges = ranges;
+ job->num_page_ranges = n_ranges;
+}
+
+/**
+ * gtk_print_job_get_page_set:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPageSet` setting for this job.
+ *
+ * Returns: the `GtkPageSet` setting
+ */
+GtkPageSet
+gtk_print_job_get_page_set (GtkPrintJob *job)
+{
+ return job->page_set;
+}
+
+/**
+ * gtk_print_job_set_page_set:
+ * @job: a `GtkPrintJob`
+ * @page_set: a `GtkPageSet` setting
+ *
+ * Sets the `GtkPageSet` setting for this job.
+ */
+void
+gtk_print_job_set_page_set (GtkPrintJob *job,
+ GtkPageSet page_set)
+{
+ job->page_set = page_set;
+}
+
+/**
+ * gtk_print_job_get_num_copies:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the number of copies of this job.
+ *
+ * Returns: the number of copies
+ */
+int
+gtk_print_job_get_num_copies (GtkPrintJob *job)
+{
+ return job->num_copies;
+}
+
+/**
+ * gtk_print_job_set_num_copies:
+ * @job: a `GtkPrintJob`
+ * @num_copies: the number of copies
+ *
+ * Sets the number of copies for this job.
+ */
+void
+gtk_print_job_set_num_copies (GtkPrintJob *job,
+ int num_copies)
+{
+ job->num_copies = num_copies;
+}
+
+/**
+ * gtk_print_job_get_scale:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the scale for this job.
+ *
+ * Returns: the scale
+ */
+double
+gtk_print_job_get_scale (GtkPrintJob *job)
+
+{
+ return job->scale;
+}
+
+/**
+ * gtk_print_job_set_scale:
+ * @job: a `GtkPrintJob`
+ * @scale: the scale
+ *
+ * Sets the scale for this job.
+ *
+ * 1.0 means unscaled.
+ */
+void
+gtk_print_job_set_scale (GtkPrintJob *job,
+ double scale)
+{
+ job->scale = scale;
+}
+
+/**
+ * gtk_print_job_get_n_up:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the n-up setting for this job.
+ *
+ * Returns: the n-up setting
+ */
+guint
+gtk_print_job_get_n_up (GtkPrintJob *job)
+{
+ return job->number_up;
+}
+
+/**
+ * gtk_print_job_set_n_up:
+ * @job: a `GtkPrintJob`
+ * @n_up: the n-up value
+ *
+ * Sets the n-up setting for this job.
+ */
+void
+gtk_print_job_set_n_up (GtkPrintJob *job,
+ guint n_up)
+{
+ job->number_up = n_up;
+}
+
+/**
+ * gtk_print_job_get_n_up_layout:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the n-up layout setting for this job.
+ *
+ * Returns: the n-up layout
+ */
+GtkNumberUpLayout
+gtk_print_job_get_n_up_layout (GtkPrintJob *job)
+{
+ return job->number_up_layout;
+}
+
+/**
+ * gtk_print_job_set_n_up_layout:
+ * @job: a `GtkPrintJob`
+ * @layout: the n-up layout setting
+ *
+ * Sets the n-up layout setting for this job.
+ */
+void
+gtk_print_job_set_n_up_layout (GtkPrintJob *job,
+ GtkNumberUpLayout layout)
+{
+ job->number_up_layout = layout;
+}
+
+/**
+ * gtk_print_job_get_rotate:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets whether the job is printed rotated.
+ *
+ * Returns: whether the job is printed rotated
+ */
+gboolean
+gtk_print_job_get_rotate (GtkPrintJob *job)
+{
+ return job->rotate_to_orientation;
+}
+
+/**
+ * gtk_print_job_set_rotate:
+ * @job: a `GtkPrintJob`
+ * @rotate: whether to print rotated
+ *
+ * Sets whether this job is printed rotated.
+ */
+void
+gtk_print_job_set_rotate (GtkPrintJob *job,
+ gboolean rotate)
+{
+ job->rotate_to_orientation = rotate;
+}
+
+/**
+ * gtk_print_job_get_collate:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets whether this job is printed collated.
+ *
+ * Returns: whether the job is printed collated
+ */
+gboolean
+gtk_print_job_get_collate (GtkPrintJob *job)
+{
+ return job->collate;
+}
+
+/**
+ * gtk_print_job_set_collate:
+ * @job: a `GtkPrintJob`
+ * @collate: whether the job is printed collated
+ *
+ * Sets whether this job is printed collated.
+ */
+void
+gtk_print_job_set_collate (GtkPrintJob *job,
+ gboolean collate)
+{
+ job->collate = collate;
+}
+
+/**
+ * gtk_print_job_get_reverse:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets whether this job is printed reversed.
+ *
+ * Returns: whether the job is printed reversed.
+ */
+gboolean
+gtk_print_job_get_reverse (GtkPrintJob *job)
+{
+ return job->reverse;
+}
+
+/**
+ * gtk_print_job_set_reverse:
+ * @job: a `GtkPrintJob`
+ * @reverse: whether the job is printed reversed
+ *
+ * Sets whether this job is printed reversed.
+ */
+void
+gtk_print_job_set_reverse (GtkPrintJob *job,
+ gboolean reverse)
+{
+ job->reverse = reverse;
+}
--- /dev/null
+/* GtkPrintJob
+ * Copyright (C) 2006 Red Hat,Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <cairo.h>
+
+#include <gtk/gtk.h>
+#include <gtk/print/gtkprinter.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINT_JOB (gtk_print_job_get_type ())
+#define GTK_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_JOB, GtkPrintJob))
+#define GTK_IS_PRINT_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_JOB))
+
+typedef struct _GtkPrintJob GtkPrintJob;
+
+/**
+ * GtkPrintJobCompleteFunc:
+ * @print_job: the `GtkPrintJob`
+ * @user_data: user data that has been passed to gtk_print_job_send()
+ * @error: a `GError` that contains error information if the sending
+ * of the print job failed, otherwise %NULL
+ *
+ * The type of callback that is passed to gtk_print_job_send().
+ *
+ * It is called when the print job has been completely sent.
+ */
+typedef void (*GtkPrintJobCompleteFunc) (GtkPrintJob *print_job,
+ gpointer user_data,
+ const GError *error);
+
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_print_job_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkPrintJob *gtk_print_job_new (const char *title,
+ GtkPrinter *printer,
+ GtkPrintSettings *settings,
+ GtkPageSetup *page_setup);
+GDK_AVAILABLE_IN_ALL
+GtkPrintSettings *gtk_print_job_get_settings (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+GtkPrinter *gtk_print_job_get_printer (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+const char * gtk_print_job_get_title (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+GtkPrintStatus gtk_print_job_get_status (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_job_set_source_file (GtkPrintJob *job,
+ const char *filename,
+ GError **error);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_job_set_source_fd (GtkPrintJob *job,
+ int fd,
+ GError **error);
+GDK_AVAILABLE_IN_ALL
+cairo_surface_t *gtk_print_job_get_surface (GtkPrintJob *job,
+ GError **error);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_track_print_status (GtkPrintJob *job,
+ gboolean track_status);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_job_get_track_print_status (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_send (GtkPrintJob *job,
+ GtkPrintJobCompleteFunc callback,
+ gpointer user_data,
+ GDestroyNotify dnotify);
+
+GDK_AVAILABLE_IN_ALL
+GtkPrintPages gtk_print_job_get_pages (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_pages (GtkPrintJob *job,
+ GtkPrintPages pages);
+GDK_AVAILABLE_IN_ALL
+GtkPageRange * gtk_print_job_get_page_ranges (GtkPrintJob *job,
+ int *n_ranges);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_page_ranges (GtkPrintJob *job,
+ GtkPageRange *ranges,
+ int n_ranges);
+GDK_AVAILABLE_IN_ALL
+GtkPageSet gtk_print_job_get_page_set (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_page_set (GtkPrintJob *job,
+ GtkPageSet page_set);
+GDK_AVAILABLE_IN_ALL
+int gtk_print_job_get_num_copies (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_num_copies (GtkPrintJob *job,
+ int num_copies);
+GDK_AVAILABLE_IN_ALL
+double gtk_print_job_get_scale (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_scale (GtkPrintJob *job,
+ double scale);
+GDK_AVAILABLE_IN_ALL
+guint gtk_print_job_get_n_up (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_n_up (GtkPrintJob *job,
+ guint n_up);
+GDK_AVAILABLE_IN_ALL
+GtkNumberUpLayout gtk_print_job_get_n_up_layout (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_n_up_layout (GtkPrintJob *job,
+ GtkNumberUpLayout layout);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_job_get_rotate (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_rotate (GtkPrintJob *job,
+ gboolean rotate);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_job_get_collate (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_collate (GtkPrintJob *job,
+ gboolean collate);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_job_get_reverse (GtkPrintJob *job);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_reverse (GtkPrintJob *job,
+ gboolean reverse);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintJob, g_object_unref)
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation-portal.c: Print Operation Details for sandboxed apps
+ * Copyright (C) 2016, Red Hat, Inc.
+ *
+ * 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 <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <cairo-pdf.h>
+#include <cairo-ps.h>
+
+#include <gio/gunixfdlist.h>
+
+#include "gtkprintoperation-private.h"
+#include "gtkprintoperation-portal.h"
+#include "gtkprintsettings.h"
+#include "gtkpagesetup.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkfilelauncher.h"
+#include <glib/gi18n-lib.h>
+#include "gtkwindowprivate.h"
+#include "gtkprivate.h"
+
+
+typedef struct {
+ GtkPrintOperation *op;
+ GDBusProxy *proxy;
+ guint response_signal_id;
+ gboolean do_print;
+ GtkPrintOperationResult result;
+ GtkPrintOperationPrintFunc print_cb;
+ GtkWindow *parent;
+ char *handle;
+ GMainLoop *loop;
+ guint32 token;
+ GDestroyNotify destroy;
+ GVariant *settings;
+ GVariant *setup;
+ GVariant *options;
+ char *prepare_print_handle;
+} PortalData;
+
+static void
+portal_data_free (gpointer data)
+{
+ PortalData *portal = data;
+
+ if (portal->parent && portal->handle)
+ gtk_window_unexport_handle (portal->parent, portal->handle);
+ g_free (portal->handle);
+ g_object_unref (portal->op);
+ g_object_unref (portal->proxy);
+ if (portal->loop)
+ g_main_loop_unref (portal->loop);
+ if (portal->settings)
+ g_variant_unref (portal->settings);
+ if (portal->setup)
+ g_variant_unref (portal->setup);
+ if (portal->options)
+ g_variant_unref (portal->options);
+ g_free (portal->prepare_print_handle);
+ g_free (portal);
+}
+
+typedef struct {
+ GDBusProxy *proxy;
+ GtkPrintJob *job;
+ guint32 token;
+ cairo_surface_t *surface;
+ GMainLoop *loop;
+ gboolean file_written;
+} GtkPrintOperationPortal;
+
+static void
+op_portal_free (GtkPrintOperationPortal *op_portal)
+{
+ g_clear_object (&op_portal->proxy);
+ g_clear_object (&op_portal->job);
+ if (op_portal->loop)
+ g_main_loop_unref (op_portal->loop);
+ g_free (op_portal);
+}
+
+static void
+portal_start_page (GtkPrintOperation *op,
+ GtkPrintContext *print_context,
+ GtkPageSetup *page_setup)
+{
+ GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+ GtkPaperSize *paper_size;
+ cairo_surface_type_t type;
+ double w, h;
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+
+ w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+ h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+
+ type = cairo_surface_get_type (op_portal->surface);
+
+ if ((op->priv->manual_number_up < 2) ||
+ (op->priv->page_position % op->priv->manual_number_up == 0))
+ {
+ if (type == CAIRO_SURFACE_TYPE_PS)
+ {
+ cairo_ps_surface_set_size (op_portal->surface, w, h);
+ cairo_ps_surface_dsc_begin_page_setup (op_portal->surface);
+ switch (gtk_page_setup_get_orientation (page_setup))
+ {
+ case GTK_PAGE_ORIENTATION_PORTRAIT:
+ case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+ cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Portrait");
+ break;
+
+ case GTK_PAGE_ORIENTATION_LANDSCAPE:
+ case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+ cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Landscape");
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (type == CAIRO_SURFACE_TYPE_PDF)
+ {
+ if (!op->priv->manual_orientation)
+ {
+ w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+ h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+ }
+ cairo_pdf_surface_set_size (op_portal->surface, w, h);
+ }
+ }
+}
+
+static void
+portal_end_page (GtkPrintOperation *op,
+ GtkPrintContext *print_context)
+{
+ cairo_t *cr;
+
+ cr = gtk_print_context_get_cairo_context (print_context);
+
+ if ((op->priv->manual_number_up < 2) ||
+ ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
+ (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
+ cairo_show_page (cr);
+}
+
+static void
+print_file_done (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GtkPrintOperation *op = data;
+ GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+ GError *error = NULL;
+ GVariant *ret;
+
+ ret = g_dbus_proxy_call_finish (op_portal->proxy,
+ result,
+ &error);
+ if (ret == NULL)
+ {
+ if (op->priv->error == NULL)
+ op->priv->error = g_error_copy (error);
+ g_warning ("Print file failed: %s", error->message);
+ g_error_free (error);
+ }
+ else
+ g_variant_unref (ret);
+
+ if (op_portal->loop)
+ g_main_loop_quit (op_portal->loop);
+
+ g_object_unref (op);
+}
+
+static void
+portal_job_complete (GtkPrintJob *job,
+ gpointer data,
+ const GError *error)
+{
+ GtkPrintOperation *op = data;
+ GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+ GtkPrintSettings *settings;
+ const char *uri;
+ char *filename;
+ int fd, idx;
+ GVariantBuilder opt_builder;
+ GUnixFDList *fd_list;
+
+ if (error != NULL && op->priv->error == NULL)
+ {
+ g_warning ("Print job failed: %s", error->message);
+ op->priv->error = g_error_copy (error);
+ return;
+ }
+
+ op_portal->file_written = TRUE;
+
+ settings = gtk_print_job_get_settings (job);
+ uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
+ filename = g_filename_from_uri (uri, NULL, NULL);
+
+ fd = open (filename, O_RDONLY|O_CLOEXEC);
+ fd_list = g_unix_fd_list_new ();
+ idx = g_unix_fd_list_append (fd_list, fd, NULL);
+ close (fd);
+
+ g_free (filename);
+
+ g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&opt_builder, "{sv}", "token", g_variant_new_uint32 (op_portal->token));
+
+ g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy,
+ "Print",
+ g_variant_new ("(ssh@a{sv})",
+ "", /* window */
+ _("Print"), /* title */
+ idx,
+ g_variant_builder_end (&opt_builder)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ fd_list,
+ NULL,
+ print_file_done,
+ op);
+ g_object_unref (fd_list);
+}
+
+static void
+portal_end_run (GtkPrintOperation *op,
+ gboolean wait,
+ gboolean cancelled)
+{
+ GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+
+ cairo_surface_finish (op_portal->surface);
+
+ if (cancelled)
+ return;
+
+ if (wait)
+ op_portal->loop = g_main_loop_new (NULL, FALSE);
+
+ /* TODO: Check for error */
+ if (op_portal->job != NULL)
+ {
+ g_object_ref (op);
+ gtk_print_job_send (op_portal->job, portal_job_complete, op, NULL);
+ }
+
+ if (wait)
+ {
+ g_object_ref (op);
+ if (!op_portal->file_written)
+ g_main_loop_run (op_portal->loop);
+ g_object_unref (op);
+ }
+}
+
+static void
+finish_print (PortalData *portal,
+ GtkPrinter *printer,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings)
+{
+ GtkPrintOperation *op = portal->op;
+ GtkPrintOperationPrivate *priv = op->priv;
+ GtkPrintJob *job;
+ GtkPrintOperationPortal *op_portal;
+ cairo_t *cr;
+
+ if (portal->do_print)
+ {
+ gtk_print_operation_set_print_settings (op, settings);
+ priv->print_context = _gtk_print_context_new (op);
+
+ _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
+
+ gtk_print_operation_set_default_page_setup (op, page_setup);
+ _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+
+ op_portal = g_new0 (GtkPrintOperationPortal, 1);
+ priv->platform_data = op_portal;
+ priv->free_platform_data = (GDestroyNotify) op_portal_free;
+
+ priv->start_page = portal_start_page;
+ priv->end_page = portal_end_page;
+ priv->end_run = portal_end_run;
+
+ job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
+ op_portal->job = job;
+
+ op_portal->proxy = g_object_ref (portal->proxy);
+ op_portal->token = portal->token;
+
+ op_portal->surface = gtk_print_job_get_surface (job, &priv->error);
+ if (op_portal->surface == NULL)
+ {
+ portal->result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ portal->do_print = FALSE;
+ goto out;
+ }
+
+ cr = cairo_create (op_portal->surface);
+ gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
+ cairo_destroy (cr);
+
+ priv->print_pages = gtk_print_job_get_pages (job);
+ priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
+ priv->manual_num_copies = gtk_print_job_get_num_copies (job);
+ priv->manual_collation = gtk_print_job_get_collate (job);
+ priv->manual_reverse = gtk_print_job_get_reverse (job);
+ priv->manual_page_set = gtk_print_job_get_page_set (job);
+ priv->manual_scale = gtk_print_job_get_scale (job);
+ priv->manual_orientation = gtk_print_job_get_rotate (job);
+ priv->manual_number_up = gtk_print_job_get_n_up (job);
+ priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
+ }
+
+out:
+ if (portal->print_cb)
+ portal->print_cb (op, portal->parent, portal->do_print, portal->result);
+
+ if (portal->destroy)
+ portal->destroy (portal);
+}
+
+static GtkPrinter *
+find_file_printer (void)
+{
+ GList *backends, *l, *printers;
+ GtkPrinter *printer;
+
+ printer = NULL;
+
+ backends = gtk_print_backend_load_modules ();
+ for (l = backends; l; l = l->next)
+ {
+ GtkPrintBackend *backend = l->data;
+ if (strcmp (G_OBJECT_TYPE_NAME (backend), "GtkPrintBackendFile") == 0)
+ {
+ printers = gtk_print_backend_get_printer_list (backend);
+ printer = printers->data;
+ g_list_free (printers);
+ break;
+ }
+ }
+ g_list_free (backends);
+
+ return printer;
+}
+
+static void
+prepare_print_response (GDBusConnection *connection,
+ const char *sender_name,
+ const char *object_path,
+ const char *interface_name,
+ const char *signal_name,
+ GVariant *parameters,
+ gpointer data)
+{
+ PortalData *portal = data;
+ guint32 response;
+ GVariant *options = NULL;
+
+ if (portal->response_signal_id != 0)
+ {
+ g_dbus_connection_signal_unsubscribe (connection,
+ portal->response_signal_id);
+ portal->response_signal_id = 0;
+ }
+
+ g_variant_get (parameters, "(u@a{sv})", &response, &options);
+
+ portal->do_print = (response == 0);
+
+ if (portal->do_print)
+ {
+ GVariant *v;
+ GtkPrintSettings *settings;
+ GtkPageSetup *page_setup;
+ GtkPrinter *printer;
+ char *filename;
+ char *uri;
+ int fd;
+
+ portal->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+ v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT);
+ settings = gtk_print_settings_new_from_gvariant (v);
+ g_variant_unref (v);
+
+ v = g_variant_lookup_value (options, "page-setup", G_VARIANT_TYPE_VARDICT);
+ page_setup = gtk_page_setup_new_from_gvariant (v);
+ g_variant_unref (v);
+
+ g_variant_lookup (options, "token", "u", &portal->token);
+
+ printer = find_file_printer ();
+
+ fd = g_file_open_tmp ("gtkprintXXXXXX", &filename, NULL);
+ uri = g_filename_to_uri (filename, NULL, NULL);
+ gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
+ g_free (uri);
+ close (fd);
+
+ finish_print (portal, printer, page_setup, settings);
+ g_free (filename);
+ }
+ else
+ {
+ portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+
+ if (portal->print_cb)
+ portal->print_cb (portal->op, portal->parent, portal->do_print, portal->result);
+
+ if (portal->destroy)
+ portal->destroy (portal);
+ }
+
+ if (options)
+ g_variant_unref (options);
+
+ if (portal->loop)
+ g_main_loop_quit (portal->loop);
+}
+
+static void
+prepare_print_called (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ PortalData *portal = data;
+ GError *error = NULL;
+ const char *handle = NULL;
+ GVariant *ret;
+
+ ret = g_dbus_proxy_call_finish (portal->proxy, result, &error);
+ if (ret == NULL)
+ {
+ if (portal->op->priv->error == NULL)
+ portal->op->priv->error = g_error_copy (error);
+ g_error_free (error);
+ if (portal->loop)
+ g_main_loop_quit (portal->loop);
+ return;
+ }
+ else
+ g_variant_get (ret, "(&o)", &handle);
+
+ if (strcmp (portal->prepare_print_handle, handle) != 0)
+ {
+ g_free (portal->prepare_print_handle);
+ portal->prepare_print_handle = g_strdup (handle);
+ g_dbus_connection_signal_unsubscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+ portal->response_signal_id);
+ portal->response_signal_id =
+ g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+ PORTAL_BUS_NAME,
+ PORTAL_REQUEST_INTERFACE,
+ "Response",
+ handle,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+ prepare_print_response,
+ portal, NULL);
+ }
+
+ g_variant_unref (ret);
+}
+
+static PortalData *
+create_portal_data (GtkPrintOperation *op,
+ GtkWindow *parent,
+ GtkPrintOperationPrintFunc print_cb)
+{
+ GDBusProxy *proxy;
+ PortalData *portal;
+ guint signal_id;
+ GError *error = NULL;
+
+ signal_id = g_signal_lookup ("create-custom-widget", GTK_TYPE_PRINT_OPERATION);
+ if (g_signal_has_handler_pending (op, signal_id, 0, TRUE))
+ g_warning ("GtkPrintOperation::create-custom-widget not supported with portal");
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ PORTAL_BUS_NAME,
+ PORTAL_OBJECT_PATH,
+ PORTAL_PRINT_INTERFACE,
+ NULL,
+ &error);
+
+ if (proxy == NULL)
+ {
+ if (op->priv->error == NULL)
+ op->priv->error = g_error_copy (error);
+ g_error_free (error);
+ return NULL;
+ }
+
+ portal = g_new0 (PortalData, 1);
+ portal->proxy = proxy;
+ portal->op = g_object_ref (op);
+ portal->parent = parent;
+ portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+ portal->print_cb = print_cb;
+
+ if (print_cb) /* async case */
+ {
+ portal->loop = NULL;
+ portal->destroy = portal_data_free;
+ }
+ else
+ {
+ portal->loop = g_main_loop_new (NULL, FALSE);
+ portal->destroy = NULL;
+ }
+
+ return portal;
+}
+
+static void
+window_handle_exported (GtkWindow *window,
+ const char *handle_str,
+ gpointer user_data)
+{
+ PortalData *portal = user_data;
+
+ portal->handle = g_strdup (handle_str);
+
+ g_dbus_proxy_call (portal->proxy,
+ "PreparePrint",
+ g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
+ handle_str,
+ _("Print"), /* title */
+ portal->settings,
+ portal->setup,
+ portal->options),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ prepare_print_called,
+ portal);
+}
+
+static void
+call_prepare_print (GtkPrintOperation *op,
+ PortalData *portal)
+{
+ GtkPrintOperationPrivate *priv = op->priv;
+ GVariantBuilder opt_builder;
+ char *token;
+
+ portal->prepare_print_handle =
+ gtk_get_portal_request_path (g_dbus_proxy_get_connection (portal->proxy), &token);
+
+ portal->response_signal_id =
+ g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+ PORTAL_BUS_NAME,
+ PORTAL_REQUEST_INTERFACE,
+ "Response",
+ portal->prepare_print_handle,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+ prepare_print_response,
+ portal, NULL);
+
+ g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token));
+ g_free (token);
+ portal->options = g_variant_builder_end (&opt_builder);
+
+ if (priv->print_settings)
+ portal->settings = gtk_print_settings_to_gvariant (priv->print_settings);
+ else
+ {
+ GVariantBuilder builder;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+ portal->settings = g_variant_builder_end (&builder);
+ }
+
+ if (priv->default_page_setup)
+ portal->setup = gtk_page_setup_to_gvariant (priv->default_page_setup);
+ else
+ {
+ GtkPageSetup *page_setup = gtk_page_setup_new ();
+ portal->setup = gtk_page_setup_to_gvariant (page_setup);
+ g_object_unref (page_setup);
+ }
+
+ g_variant_ref_sink (portal->options);
+ g_variant_ref_sink (portal->settings);
+ g_variant_ref_sink (portal->setup);
+
+ if (portal->parent != NULL &&
+ gtk_widget_is_visible (GTK_WIDGET (portal->parent)) &&
+ gtk_window_export_handle (portal->parent, window_handle_exported, portal))
+ return;
+
+ g_dbus_proxy_call (portal->proxy,
+ "PreparePrint",
+ g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
+ "",
+ _("Print"), /* title */
+ portal->settings,
+ portal->setup,
+ portal->options),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ prepare_print_called,
+ portal);
+}
+
+GtkPrintOperationResult
+gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ gboolean *do_print)
+{
+ PortalData *portal;
+ GtkPrintOperationResult result;
+
+ portal = create_portal_data (op, parent, NULL);
+ if (portal == NULL)
+ return GTK_PRINT_OPERATION_RESULT_ERROR;
+
+ call_prepare_print (op, portal);
+
+ g_main_loop_run (portal->loop);
+
+ *do_print = portal->do_print;
+ result = portal->result;
+
+ portal_data_free (portal);
+
+ return result;
+}
+
+void
+gtk_print_operation_portal_run_dialog_async (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ GtkPrintOperationPrintFunc print_cb)
+{
+ PortalData *portal;
+
+ portal = create_portal_data (op, parent, print_cb);
+ if (portal == NULL)
+ return;
+
+ call_prepare_print (op, portal);
+}
+
+void
+gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ GtkWindow *parent,
+ const char *filename)
+{
+ GFile *file;
+ GtkFileLauncher *launcher;
+
+ file = g_file_new_for_path (filename);
+ launcher = gtk_file_launcher_new (file);
+ gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
+ g_object_unref (launcher);
+ g_object_unref (file);
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2016, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "gtkprintoperation.h"
+
+G_BEGIN_DECLS
+
+GtkPrintOperationResult gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ gboolean *do_print);
+void gtk_print_operation_portal_run_dialog_async (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ GtkPrintOperationPrintFunc print_cb);
+void gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ GtkWindow *parent,
+ const char *filename);
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation.h: Print Operation
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "gtkprintoperation.h"
+
+G_BEGIN_DECLS
+
+/* Page drawing states */
+typedef enum
+{
+ GTK_PAGE_DRAWING_STATE_READY,
+ GTK_PAGE_DRAWING_STATE_DRAWING,
+ GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING
+} GtkPageDrawingState;
+
+struct _GtkPrintOperationPrivate
+{
+ GtkPrintOperationAction action;
+ GtkPrintStatus status;
+ GError *error;
+ char *status_string;
+ GtkPageSetup *default_page_setup;
+ GtkPrintSettings *print_settings;
+ char *job_name;
+ int nr_of_pages;
+ int nr_of_pages_to_print;
+ int page_position;
+ int current_page;
+ GtkUnit unit;
+ char *export_filename;
+ guint use_full_page : 1;
+ guint track_print_status : 1;
+ guint show_progress : 1;
+ guint cancelled : 1;
+ guint allow_async : 1;
+ guint is_sync : 1;
+ guint support_selection : 1;
+ guint has_selection : 1;
+ guint embed_page_setup : 1;
+
+ GtkPageDrawingState page_drawing_state;
+
+ guint print_pages_idle_id;
+ guint show_progress_timeout_id;
+
+ GtkPrintContext *print_context;
+
+ GtkPrintPages print_pages;
+ GtkPageRange *page_ranges;
+ int num_page_ranges;
+
+ int manual_num_copies;
+ guint manual_collation : 1;
+ guint manual_reverse : 1;
+ guint manual_orientation : 1;
+ double manual_scale;
+ GtkPageSet manual_page_set;
+ guint manual_number_up;
+ GtkNumberUpLayout manual_number_up_layout;
+
+ GtkWidget *custom_widget;
+ char *custom_tab_label;
+
+ gpointer platform_data;
+ GDestroyNotify free_platform_data;
+
+ GMainLoop *rloop; /* recursive mainloop */
+
+ void (*start_page) (GtkPrintOperation *operation,
+ GtkPrintContext *print_context,
+ GtkPageSetup *page_setup);
+ void (*end_page) (GtkPrintOperation *operation,
+ GtkPrintContext *print_context);
+ void (*end_run) (GtkPrintOperation *operation,
+ gboolean wait,
+ gboolean cancelled);
+};
+
+
+typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation *op,
+ GtkWindow *parent,
+ gboolean do_print,
+ GtkPrintOperationResult result);
+
+GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *operation,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ gboolean *do_print);
+void _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ GtkPrintOperationPrintFunc print_cb);
+void _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ GtkWindow *parent,
+ const char *filename);
+cairo_surface_t * _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ double *dpi_x,
+ double *dpi_y,
+ char **target);
+void _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ cairo_surface_t *surface);
+void _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr);
+void _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr);
+
+void _gtk_print_operation_set_status (GtkPrintOperation *op,
+ GtkPrintStatus status,
+ const char *string);
+
+/* GtkPrintContext private functions: */
+
+GtkPrintContext *_gtk_print_context_new (GtkPrintOperation *op);
+void _gtk_print_context_set_page_setup (GtkPrintContext *context,
+ GtkPageSetup *page_setup);
+void _gtk_print_context_translate_into_margin (GtkPrintContext *context);
+void _gtk_print_context_rotate_according_to_orientation (GtkPrintContext *context);
+void _gtk_print_context_reverse_according_to_orientation (GtkPrintContext *context);
+void _gtk_print_context_set_hard_margins (GtkPrintContext *context,
+ double top,
+ double bottom,
+ double left,
+ double right);
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation-unix.c: Print Operation Details for Unix
+ * and Unix-like platforms
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <glib/gstdio.h>
+#include "gtkprintoperation-private.h"
+#include "gtkprintoperation-portal.h"
+
+#include <cairo-pdf.h>
+#include <cairo-ps.h>
+#include "gtkprivate.h"
+#include "gtkprintunixdialog.h"
+#include "gtkpagesetupunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprinter.h"
+#include "gtkprintjob.h"
+#include "gtklabel.h"
+#include "gtkfilelauncher.h"
+#include <glib/gi18n-lib.h>
+
+
+typedef struct
+{
+ GtkWindow *parent; /* just in case we need to throw error dialogs */
+ GMainLoop *loop;
+ gboolean data_sent;
+
+ /* Real printing (not preview) */
+ GtkPrintJob *job; /* the job we are sending to the printer */
+ cairo_surface_t *surface;
+ gulong job_status_changed_tag;
+
+
+} GtkPrintOperationUnix;
+
+typedef struct _PrinterFinder PrinterFinder;
+
+static void printer_finder_free (PrinterFinder *finder);
+static void find_printer (const char *printer,
+ GFunc func,
+ gpointer data);
+
+static void
+unix_start_page (GtkPrintOperation *op,
+ GtkPrintContext *print_context,
+ GtkPageSetup *page_setup)
+{
+ GtkPrintOperationUnix *op_unix;
+ GtkPaperSize *paper_size;
+ cairo_surface_type_t type;
+ double w, h;
+
+ op_unix = op->priv->platform_data;
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+
+ w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+ h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+
+ type = cairo_surface_get_type (op_unix->surface);
+
+ if ((op->priv->manual_number_up < 2) ||
+ (op->priv->page_position % op->priv->manual_number_up == 0))
+ {
+ if (type == CAIRO_SURFACE_TYPE_PS)
+ {
+ cairo_ps_surface_set_size (op_unix->surface, w, h);
+ cairo_ps_surface_dsc_begin_page_setup (op_unix->surface);
+ switch (gtk_page_setup_get_orientation (page_setup))
+ {
+ case GTK_PAGE_ORIENTATION_PORTRAIT:
+ case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+ cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Portrait");
+ break;
+
+ case GTK_PAGE_ORIENTATION_LANDSCAPE:
+ case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+ cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Landscape");
+ break;
+ default:
+ break;
+ }
+ }
+ else if (type == CAIRO_SURFACE_TYPE_PDF)
+ {
+ if (!op->priv->manual_orientation)
+ {
+ w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+ h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+ }
+ cairo_pdf_surface_set_size (op_unix->surface, w, h);
+ }
+ }
+}
+
+static void
+unix_end_page (GtkPrintOperation *op,
+ GtkPrintContext *print_context)
+{
+ cairo_t *cr;
+
+ cr = gtk_print_context_get_cairo_context (print_context);
+
+ if ((op->priv->manual_number_up < 2) ||
+ ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
+ (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
+ cairo_show_page (cr);
+}
+
+static void
+op_unix_free (GtkPrintOperationUnix *op_unix)
+{
+ if (op_unix->job)
+ {
+ if (op_unix->job_status_changed_tag > 0)
+ g_signal_handler_disconnect (op_unix->job,
+ op_unix->job_status_changed_tag);
+ g_object_unref (op_unix->job);
+ }
+
+ g_free (op_unix);
+}
+
+static char *
+shell_command_substitute_file (const char *cmd,
+ const char *pdf_filename,
+ const char *settings_filename,
+ gboolean *pdf_filename_replaced,
+ gboolean *settings_filename_replaced)
+{
+ const char *inptr, *start;
+ GString *final;
+
+ g_return_val_if_fail (cmd != NULL, NULL);
+ g_return_val_if_fail (pdf_filename != NULL, NULL);
+ g_return_val_if_fail (settings_filename != NULL, NULL);
+
+ final = g_string_new (NULL);
+
+ *pdf_filename_replaced = FALSE;
+ *settings_filename_replaced = FALSE;
+
+ start = inptr = cmd;
+ while ((inptr = strchr (inptr, '%')) != NULL)
+ {
+ g_string_append_len (final, start, inptr - start);
+ inptr++;
+ switch (*inptr)
+ {
+ case 'f':
+ g_string_append (final, pdf_filename);
+ *pdf_filename_replaced = TRUE;
+ break;
+
+ case 's':
+ g_string_append (final, settings_filename);
+ *settings_filename_replaced = TRUE;
+ break;
+
+ case '%':
+ g_string_append_c (final, '%');
+ break;
+
+ default:
+ g_string_append_c (final, '%');
+ if (*inptr)
+ g_string_append_c (final, *inptr);
+ break;
+ }
+ if (*inptr)
+ inptr++;
+ start = inptr;
+ }
+ g_string_append (final, start);
+
+ return g_string_free (final, FALSE);
+}
+
+static void
+gtk_print_operation_unix_launch_preview (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ GtkWindow *parent,
+ const char *filename)
+{
+ GAppInfo *appinfo;
+ GdkAppLaunchContext *context;
+ char *cmd;
+ char *preview_cmd;
+ GtkSettings *settings;
+ GtkPrintSettings *print_settings = NULL;
+ GtkPageSetup *page_setup;
+ GKeyFile *key_file = NULL;
+ char *data = NULL;
+ gsize data_len;
+ char *settings_filename = NULL;
+ char *quoted_filename;
+ char *quoted_settings_filename;
+ gboolean filename_used = FALSE;
+ gboolean settings_used = FALSE;
+ GdkDisplay *display;
+ GError *error = NULL;
+ int fd;
+ gboolean retval;
+
+ cairo_surface_destroy (surface);
+
+ if (parent)
+ display = gtk_widget_get_display (GTK_WIDGET (parent));
+ else
+ display = gdk_display_get_default ();
+
+ fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, &error);
+ if (fd < 0)
+ goto out;
+
+ key_file = g_key_file_new ();
+
+ print_settings = gtk_print_settings_copy (gtk_print_operation_get_print_settings (op));
+
+ if (print_settings != NULL)
+ {
+ gtk_print_settings_set_reverse (print_settings, FALSE);
+ gtk_print_settings_set_page_set (print_settings, GTK_PAGE_SET_ALL);
+ gtk_print_settings_set_scale (print_settings, 1.0);
+ gtk_print_settings_set_number_up (print_settings, 1);
+ gtk_print_settings_set_number_up_layout (print_settings, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
+
+ /* These removals are necessary because cups-* settings have higher priority
+ * than normal settings.
+ */
+ gtk_print_settings_unset (print_settings, "cups-reverse");
+ gtk_print_settings_unset (print_settings, "cups-page-set");
+ gtk_print_settings_unset (print_settings, "cups-scale");
+ gtk_print_settings_unset (print_settings, "cups-number-up");
+ gtk_print_settings_unset (print_settings, "cups-number-up-layout");
+
+ gtk_print_settings_to_key_file (print_settings, key_file, NULL);
+ g_object_unref (print_settings);
+ }
+
+ page_setup = gtk_print_context_get_page_setup (op->priv->print_context);
+ gtk_page_setup_to_key_file (page_setup, key_file, NULL);
+
+ g_key_file_set_string (key_file, "Print Job", "title", op->priv->job_name);
+
+ data = g_key_file_to_data (key_file, &data_len, &error);
+ if (!data)
+ goto out;
+
+ retval = g_file_set_contents (settings_filename, data, data_len, &error);
+ if (!retval)
+ goto out;
+
+ settings = gtk_settings_get_for_display (display);
+ g_object_get (settings, "gtk-print-preview-command", &preview_cmd, NULL);
+
+ quoted_filename = g_shell_quote (filename);
+ quoted_settings_filename = g_shell_quote (settings_filename);
+ cmd = shell_command_substitute_file (preview_cmd, quoted_filename, quoted_settings_filename, &filename_used, &settings_used);
+
+ appinfo = g_app_info_create_from_commandline (cmd,
+ "Print Preview",
+ G_APP_INFO_CREATE_NONE,
+ &error);
+
+ g_free (preview_cmd);
+ g_free (quoted_filename);
+ g_free (quoted_settings_filename);
+ g_free (cmd);
+
+ if (error != NULL)
+ goto out;
+
+ context = gdk_display_get_app_launch_context (display);
+ g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), &error);
+
+ g_object_unref (context);
+ g_object_unref (appinfo);
+
+ if (error != NULL)
+ {
+ GFile *file;
+ GtkFileLauncher *launcher;
+
+ g_warning ("Error launching preview: %s", error->message);
+ g_clear_error (&error);
+
+ file = g_file_new_for_path (filename);
+ launcher = gtk_file_launcher_new (file);
+ gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
+ g_object_unref (launcher);
+ g_object_unref (file);
+ }
+
+ out:
+ if (error != NULL)
+ {
+ if (op->priv->error == NULL)
+ op->priv->error = error;
+ else
+ g_error_free (error);
+
+ filename_used = FALSE;
+ settings_used = FALSE;
+ }
+
+ if (!filename_used)
+ g_unlink (filename);
+
+ if (!settings_used)
+ g_unlink (settings_filename);
+
+ if (fd > 0)
+ close (fd);
+
+ if (key_file)
+ g_key_file_free (key_file);
+ g_free (data);
+ g_free (settings_filename);
+}
+
+static void
+unix_finish_send (GtkPrintJob *job,
+ gpointer user_data,
+ const GError *error)
+{
+ GtkPrintOperation *op = (GtkPrintOperation *) user_data;
+ GtkPrintOperationUnix *op_unix = op->priv->platform_data;
+
+ if (error != NULL && op->priv->error == NULL)
+ op->priv->error = g_error_copy (error);
+
+ op_unix->data_sent = TRUE;
+
+ if (op_unix->loop)
+ g_main_loop_quit (op_unix->loop);
+
+ g_object_unref (op);
+}
+
+static void
+unix_end_run (GtkPrintOperation *op,
+ gboolean wait,
+ gboolean cancelled)
+{
+ GtkPrintOperationUnix *op_unix = op->priv->platform_data;
+
+ cairo_surface_finish (op_unix->surface);
+
+ if (cancelled)
+ return;
+
+ if (wait)
+ op_unix->loop = g_main_loop_new (NULL, FALSE);
+
+ /* TODO: Check for error */
+ if (op_unix->job != NULL)
+ {
+ g_object_ref (op);
+ gtk_print_job_send (op_unix->job,
+ unix_finish_send,
+ op, NULL);
+ }
+
+ if (wait)
+ {
+ g_object_ref (op);
+ if (!op_unix->data_sent)
+ g_main_loop_run (op_unix->loop);
+ g_main_loop_unref (op_unix->loop);
+ op_unix->loop = NULL;
+ g_object_unref (op);
+ }
+}
+
+static void
+job_status_changed_cb (GtkPrintJob *job,
+ GtkPrintOperation *op)
+{
+ _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
+}
+
+
+static void
+print_setup_changed_cb (GtkPrintUnixDialog *print_dialog,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GtkPageSetup *page_setup;
+ GtkPrintSettings *print_settings;
+ GtkPrintOperation *op = user_data;
+ GtkPrintOperationPrivate *priv = op->priv;
+
+ page_setup = gtk_print_unix_dialog_get_page_setup (print_dialog);
+ print_settings = gtk_print_unix_dialog_get_settings (print_dialog);
+
+ g_signal_emit_by_name (op,
+ "update-custom-widget",
+ priv->custom_widget,
+ page_setup,
+ print_settings);
+}
+
+static GtkWidget *
+get_print_dialog (GtkPrintOperation *op,
+ GtkWindow *parent)
+{
+ GtkPrintOperationPrivate *priv = op->priv;
+ GtkWidget *pd, *label;
+ const char *custom_tab_label;
+
+ pd = gtk_print_unix_dialog_new (NULL, parent);
+
+ gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (pd),
+ GTK_PRINT_CAPABILITY_PAGE_SET |
+ GTK_PRINT_CAPABILITY_COPIES |
+ GTK_PRINT_CAPABILITY_COLLATE |
+ GTK_PRINT_CAPABILITY_REVERSE |
+ GTK_PRINT_CAPABILITY_SCALE |
+ GTK_PRINT_CAPABILITY_PREVIEW |
+ GTK_PRINT_CAPABILITY_NUMBER_UP |
+ GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT);
+
+ if (priv->print_settings)
+ gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd),
+ priv->print_settings);
+
+ if (priv->default_page_setup)
+ gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
+ priv->default_page_setup);
+
+ gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
+ priv->embed_page_setup);
+
+ gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd),
+ priv->current_page);
+
+ gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd),
+ priv->support_selection);
+
+ gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd),
+ priv->has_selection);
+
+ g_signal_emit_by_name (op, "create-custom-widget",
+ &priv->custom_widget);
+
+ if (priv->custom_widget)
+ {
+ custom_tab_label = priv->custom_tab_label;
+
+ if (custom_tab_label == NULL)
+ {
+ custom_tab_label = g_get_application_name ();
+ if (custom_tab_label == NULL)
+ custom_tab_label = _("Application");
+ }
+
+ label = gtk_label_new (custom_tab_label);
+
+ gtk_print_unix_dialog_add_custom_tab (GTK_PRINT_UNIX_DIALOG (pd),
+ priv->custom_widget, label);
+
+ g_signal_connect (pd, "notify::selected-printer", (GCallback) print_setup_changed_cb, op);
+ g_signal_connect (pd, "notify::page-setup", (GCallback) print_setup_changed_cb, op);
+ }
+
+ return pd;
+}
+
+typedef struct
+{
+ GtkPrintOperation *op;
+ gboolean do_print;
+ gboolean do_preview;
+ GtkPrintOperationResult result;
+ GtkPrintOperationPrintFunc print_cb;
+ GDestroyNotify destroy;
+ GtkWindow *parent;
+ GMainLoop *loop;
+} PrintResponseData;
+
+static void
+print_response_data_free (gpointer data)
+{
+ PrintResponseData *rdata = data;
+
+ g_object_unref (rdata->op);
+ g_free (rdata);
+}
+
+static void
+finish_print (PrintResponseData *rdata,
+ GtkPrinter *printer,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings,
+ gboolean page_setup_set)
+{
+ GtkPrintOperation *op = rdata->op;
+ GtkPrintOperationPrivate *priv = op->priv;
+ GtkPrintJob *job;
+ double top, bottom, left, right;
+
+ if (rdata->do_print)
+ {
+ gtk_print_operation_set_print_settings (op, settings);
+ priv->print_context = _gtk_print_context_new (op);
+
+ if (gtk_print_settings_get_number_up (settings) < 2)
+ {
+ if (printer && (gtk_printer_get_hard_margins_for_paper_size (printer, gtk_page_setup_get_paper_size (page_setup), &top, &bottom, &left, &right) ||
+ gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right)))
+ _gtk_print_context_set_hard_margins (priv->print_context, top, bottom, left, right);
+ }
+ else
+ {
+ /* Pages do not have any unprintable area when printing n-up as each page on the
+ * sheet has been scaled down and translated to a position within the printable
+ * area of the sheet.
+ */
+ _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
+ }
+
+ if (page_setup != NULL &&
+ (gtk_print_operation_get_default_page_setup (op) == NULL ||
+ page_setup_set))
+ gtk_print_operation_set_default_page_setup (op, page_setup);
+
+ _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+
+ if (!rdata->do_preview)
+ {
+ GtkPrintOperationUnix *op_unix;
+ cairo_t *cr;
+
+ op_unix = g_new0 (GtkPrintOperationUnix, 1);
+ priv->platform_data = op_unix;
+ priv->free_platform_data = (GDestroyNotify) op_unix_free;
+ op_unix->parent = rdata->parent;
+
+ priv->start_page = unix_start_page;
+ priv->end_page = unix_end_page;
+ priv->end_run = unix_end_run;
+
+ job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
+ op_unix->job = job;
+ gtk_print_job_set_track_print_status (job, priv->track_print_status);
+
+ op_unix->surface = gtk_print_job_get_surface (job, &priv->error);
+ if (op_unix->surface == NULL)
+ {
+ rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ rdata->do_print = FALSE;
+ goto out;
+ }
+
+ cr = cairo_create (op_unix->surface);
+ gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
+ cairo_destroy (cr);
+
+ _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
+
+ op_unix->job_status_changed_tag =
+ g_signal_connect (job, "status-changed",
+ G_CALLBACK (job_status_changed_cb), op);
+
+ priv->print_pages = gtk_print_job_get_pages (job);
+ priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
+ priv->manual_num_copies = gtk_print_job_get_num_copies (job);
+ priv->manual_collation = gtk_print_job_get_collate (job);
+ priv->manual_reverse = gtk_print_job_get_reverse (job);
+ priv->manual_page_set = gtk_print_job_get_page_set (job);
+ priv->manual_scale = gtk_print_job_get_scale (job);
+ priv->manual_orientation = gtk_print_job_get_rotate (job);
+ priv->manual_number_up = gtk_print_job_get_n_up (job);
+ priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
+ }
+ }
+ out:
+ if (rdata->print_cb)
+ rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result);
+
+ if (rdata->destroy)
+ rdata->destroy (rdata);
+}
+
+static void
+handle_print_response (GtkWidget *dialog,
+ int response,
+ gpointer data)
+{
+ GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
+ PrintResponseData *rdata = data;
+ GtkPrintSettings *settings = NULL;
+ GtkPageSetup *page_setup = NULL;
+ GtkPrinter *printer = NULL;
+ gboolean page_setup_set = FALSE;
+
+ if (response == GTK_RESPONSE_OK)
+ {
+ printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
+
+ rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+ rdata->do_preview = FALSE;
+ if (printer != NULL)
+ rdata->do_print = TRUE;
+ }
+ else if (response == GTK_RESPONSE_APPLY)
+ {
+ /* print preview */
+ rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+ rdata->do_preview = TRUE;
+ rdata->do_print = TRUE;
+
+ rdata->op->priv->action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
+ }
+
+ if (rdata->do_print)
+ {
+ settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
+ page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
+ page_setup_set = gtk_print_unix_dialog_get_page_setup_set (GTK_PRINT_UNIX_DIALOG (pd));
+
+ /* Set new print settings now so that custom-widget options
+ * can be added to the settings in the callback
+ */
+ gtk_print_operation_set_print_settings (rdata->op, settings);
+ g_signal_emit_by_name (rdata->op, "custom-widget-apply", rdata->op->priv->custom_widget);
+ }
+
+ if (rdata->loop)
+ g_main_loop_quit (rdata->loop);
+
+ finish_print (rdata, printer, page_setup, settings, page_setup_set);
+
+ if (settings)
+ g_object_unref (settings);
+
+ gtk_window_destroy (GTK_WINDOW (pd));
+}
+
+
+static void
+found_printer (GtkPrinter *printer,
+ PrintResponseData *rdata)
+{
+ GtkPrintOperation *op = rdata->op;
+ GtkPrintOperationPrivate *priv = op->priv;
+ GtkPrintSettings *settings = NULL;
+ GtkPageSetup *page_setup = NULL;
+
+ if (rdata->loop)
+ g_main_loop_quit (rdata->loop);
+
+ if (printer != NULL)
+ {
+ rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+ rdata->do_print = TRUE;
+
+ if (priv->print_settings)
+ settings = gtk_print_settings_copy (priv->print_settings);
+ else
+ settings = gtk_print_settings_new ();
+
+ gtk_print_settings_set_printer (settings,
+ gtk_printer_get_name (printer));
+
+ if (priv->default_page_setup)
+ page_setup = gtk_page_setup_copy (priv->default_page_setup);
+ else
+ page_setup = gtk_page_setup_new ();
+ }
+
+ finish_print (rdata, printer, page_setup, settings, FALSE);
+
+ if (settings)
+ g_object_unref (settings);
+
+ if (page_setup)
+ g_object_unref (page_setup);
+}
+
+static void
+gtk_print_operation_unix_run_dialog_async (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ GtkPrintOperationPrintFunc print_cb)
+{
+ GtkWidget *pd;
+ PrintResponseData *rdata;
+ const char *printer_name;
+
+ rdata = g_new (PrintResponseData, 1);
+ rdata->op = g_object_ref (op);
+ rdata->do_print = FALSE;
+ rdata->do_preview = FALSE;
+ rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+ rdata->print_cb = print_cb;
+ rdata->parent = parent;
+ rdata->loop = NULL;
+ rdata->destroy = print_response_data_free;
+
+ if (show_dialog)
+ {
+ pd = get_print_dialog (op, parent);
+ gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
+
+ g_signal_connect (pd, "response",
+ G_CALLBACK (handle_print_response), rdata);
+
+ gtk_window_present (GTK_WINDOW (pd));
+ }
+ else
+ {
+ printer_name = NULL;
+ if (op->priv->print_settings)
+ printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
+
+ find_printer (printer_name, (GFunc) found_printer, rdata);
+ }
+}
+
+static cairo_status_t
+write_preview (void *closure,
+ const unsigned char *data,
+ unsigned int length)
+{
+ int fd = GPOINTER_TO_INT (closure);
+ gssize written;
+
+ while (length > 0)
+ {
+ written = write (fd, data, length);
+
+ if (written == -1)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+
+ return CAIRO_STATUS_WRITE_ERROR;
+ }
+
+ data += written;
+ length -= written;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+close_preview (void *data)
+{
+ int fd = GPOINTER_TO_INT (data);
+
+ close (fd);
+}
+
+static cairo_surface_t *
+gtk_print_operation_unix_create_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ double *dpi_x,
+ double *dpi_y,
+ char **target)
+{
+ char *filename;
+ int fd;
+ GtkPaperSize *paper_size;
+ double w, h;
+ cairo_surface_t *surface;
+ static cairo_user_data_key_t key;
+
+ filename = g_build_filename (g_get_tmp_dir (), "previewXXXXXX.pdf", NULL);
+ fd = g_mkstemp (filename);
+
+ if (fd < 0)
+ {
+ g_free (filename);
+ return NULL;
+ }
+
+ *target = filename;
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+ w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+ h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+
+ *dpi_x = *dpi_y = 72;
+ surface = cairo_pdf_surface_create_for_stream (write_preview, GINT_TO_POINTER (fd), w, h);
+
+ cairo_surface_set_user_data (surface, &key, GINT_TO_POINTER (fd), close_preview);
+
+ return surface;
+}
+
+static void
+gtk_print_operation_unix_preview_start_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr)
+{
+}
+
+static void
+gtk_print_operation_unix_preview_end_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr)
+{
+ cairo_show_page (cr);
+}
+
+static void
+gtk_print_operation_unix_resize_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ cairo_surface_t *surface)
+{
+ double w, h;
+
+ w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+ h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+ cairo_pdf_surface_set_size (surface, w, h);
+}
+
+static GtkPrintOperationResult
+gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ gboolean *do_print)
+ {
+ GtkWidget *pd;
+ PrintResponseData rdata;
+ const char *printer_name;
+
+ rdata.op = op;
+ rdata.do_print = FALSE;
+ rdata.do_preview = FALSE;
+ rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+ rdata.print_cb = NULL;
+ rdata.destroy = NULL;
+ rdata.parent = parent;
+ rdata.loop = NULL;
+
+ if (show_dialog)
+ {
+ pd = get_print_dialog (op, parent);
+ gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
+
+ g_signal_connect (pd, "response",
+ G_CALLBACK (handle_print_response), &rdata);
+
+ gtk_window_present (GTK_WINDOW (pd));
+
+ rdata.loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (rdata.loop);
+ g_main_loop_unref (rdata.loop);
+ rdata.loop = NULL;
+ }
+ else
+ {
+ printer_name = NULL;
+ if (op->priv->print_settings)
+ printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
+
+ rdata.loop = g_main_loop_new (NULL, FALSE);
+ find_printer (printer_name,
+ (GFunc) found_printer, &rdata);
+
+ g_main_loop_run (rdata.loop);
+ g_main_loop_unref (rdata.loop);
+ rdata.loop = NULL;
+ }
+
+ *do_print = rdata.do_print;
+
+ return rdata.result;
+}
+
+
+typedef struct
+{
+ GtkPageSetup *page_setup;
+ GtkPageSetupDoneFunc done_cb;
+ gpointer data;
+ GDestroyNotify destroy;
+ GMainLoop *loop;
+} PageSetupResponseData;
+
+static void
+page_setup_data_free (gpointer data)
+{
+ PageSetupResponseData *rdata = data;
+
+ if (rdata->page_setup)
+ g_object_unref (rdata->page_setup);
+
+ g_free (rdata);
+}
+
+static void
+handle_page_setup_response (GtkWidget *dialog,
+ int response,
+ gpointer data)
+{
+ GtkPageSetupUnixDialog *psd;
+ PageSetupResponseData *rdata = data;
+
+ if (rdata->loop)
+ g_main_loop_quit (rdata->loop);
+
+ psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog);
+ if (response == GTK_RESPONSE_OK)
+ rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (psd);
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+
+ if (rdata->done_cb)
+ rdata->done_cb (rdata->page_setup, rdata->data);
+
+ if (rdata->destroy)
+ rdata->destroy (rdata);
+}
+
+static GtkWidget *
+get_page_setup_dialog (GtkWindow *parent,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_page_setup_unix_dialog_new (NULL, parent);
+ if (page_setup)
+ gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
+ page_setup);
+ gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
+ settings);
+
+ return dialog;
+}
+
+/**
+ * gtk_print_run_page_setup_dialog:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ *
+ * Runs a page setup dialog, letting the user modify the values from
+ * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
+ * is identical to the passed in @page_setup, otherwise it contains the
+ * modifications done in the dialog.
+ *
+ * Note that this function may use a recursive mainloop to show the page
+ * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
+ * a problem.
+ *
+ * Returns: (transfer full): a new `GtkPageSetup`
+ */
+GtkPageSetup *
+gtk_print_run_page_setup_dialog (GtkWindow *parent,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings)
+{
+ GtkWidget *dialog;
+ PageSetupResponseData rdata;
+
+ rdata.page_setup = NULL;
+ rdata.done_cb = NULL;
+ rdata.data = NULL;
+ rdata.destroy = NULL;
+ rdata.loop = g_main_loop_new (NULL, FALSE);
+
+ dialog = get_page_setup_dialog (parent, page_setup, settings);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (handle_page_setup_response),
+ &rdata);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ g_main_loop_run (rdata.loop);
+ g_main_loop_unref (rdata.loop);
+ rdata.loop = NULL;
+
+ if (rdata.page_setup)
+ return rdata.page_setup;
+ else if (page_setup)
+ return gtk_page_setup_copy (page_setup);
+ else
+ return gtk_page_setup_new ();
+}
+
+/**
+ * gtk_print_run_page_setup_dialog_async:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ * @done_cb: (scope async): a function to call when the user saves
+ * the modified page setup
+ * @data: user data to pass to @done_cb
+ *
+ * Runs a page setup dialog, letting the user modify the values from @page_setup.
+ *
+ * In contrast to gtk_print_run_page_setup_dialog(), this function returns after
+ * showing the page setup dialog on platforms that support this, and calls @done_cb
+ * from a signal handler for the ::response signal of the dialog.
+ */
+void
+gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings,
+ GtkPageSetupDoneFunc done_cb,
+ gpointer data)
+{
+ GtkWidget *dialog;
+ PageSetupResponseData *rdata;
+
+ dialog = get_page_setup_dialog (parent, page_setup, settings);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ rdata = g_new (PageSetupResponseData, 1);
+ rdata->page_setup = NULL;
+ rdata->done_cb = done_cb;
+ rdata->data = data;
+ rdata->destroy = page_setup_data_free;
+ rdata->loop = NULL;
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (handle_page_setup_response), rdata);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+
+struct _PrinterFinder
+{
+ gboolean found_printer;
+ GFunc func;
+ gpointer data;
+ char *printer_name;
+ GList *backends;
+ guint timeout_tag;
+ GtkPrinter *printer;
+ GtkPrinter *default_printer;
+ GtkPrinter *first_printer;
+};
+
+static gboolean
+find_printer_idle (gpointer data)
+{
+ PrinterFinder *finder = data;
+ GtkPrinter *printer;
+
+ if (finder->printer != NULL)
+ printer = finder->printer;
+ else if (finder->default_printer != NULL)
+ printer = finder->default_printer;
+ else if (finder->first_printer != NULL)
+ printer = finder->first_printer;
+ else
+ printer = NULL;
+
+ finder->func (printer, finder->data);
+
+ printer_finder_free (finder);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+printer_added_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ PrinterFinder *finder)
+{
+ if (finder->found_printer)
+ return;
+
+ /* FIXME this skips "Print to PDF" - is this intentional ? */
+ if (gtk_printer_is_virtual (printer))
+ return;
+
+ if (finder->printer_name != NULL &&
+ strcmp (gtk_printer_get_name (printer), finder->printer_name) == 0)
+ {
+ finder->printer = g_object_ref (printer);
+ finder->found_printer = TRUE;
+ }
+ else if (finder->default_printer == NULL &&
+ gtk_printer_is_default (printer))
+ {
+ finder->default_printer = g_object_ref (printer);
+ if (finder->printer_name == NULL)
+ finder->found_printer = TRUE;
+ }
+ else
+ {
+ if (finder->first_printer == NULL)
+ finder->first_printer = g_object_ref (printer);
+ }
+
+ if (finder->found_printer)
+ g_idle_add (find_printer_idle, finder);
+}
+
+static void
+printer_list_done_cb (GtkPrintBackend *backend,
+ PrinterFinder *finder)
+{
+ finder->backends = g_list_remove (finder->backends, backend);
+
+ g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
+ g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
+
+ gtk_print_backend_destroy (backend);
+ g_object_unref (backend);
+
+ if (finder->backends == NULL)
+ g_idle_add (find_printer_idle, finder);
+}
+
+static void
+find_printer_init (PrinterFinder *finder,
+ GtkPrintBackend *backend)
+{
+ GList *list;
+ GList *node;
+
+ list = gtk_print_backend_get_printer_list (backend);
+
+ node = list;
+ while (node != NULL)
+ {
+ printer_added_cb (backend, node->data, finder);
+ node = node->next;
+
+ if (finder->found_printer)
+ break;
+ }
+
+ g_list_free (list);
+
+ if (gtk_print_backend_printer_list_is_done (backend))
+ {
+ finder->backends = g_list_remove (finder->backends, backend);
+ gtk_print_backend_destroy (backend);
+ g_object_unref (backend);
+ }
+ else
+ {
+ g_signal_connect (backend, "printer-added",
+ (GCallback) printer_added_cb,
+ finder);
+ g_signal_connect (backend, "printer-list-done",
+ (GCallback) printer_list_done_cb,
+ finder);
+ }
+
+}
+
+static void
+printer_finder_free (PrinterFinder *finder)
+{
+ GList *l;
+
+ g_free (finder->printer_name);
+
+ if (finder->printer)
+ g_object_unref (finder->printer);
+
+ if (finder->default_printer)
+ g_object_unref (finder->default_printer);
+
+ if (finder->first_printer)
+ g_object_unref (finder->first_printer);
+
+ for (l = finder->backends; l != NULL; l = l->next)
+ {
+ GtkPrintBackend *backend = l->data;
+ g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
+ g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
+ gtk_print_backend_destroy (backend);
+ g_object_unref (backend);
+ }
+
+ g_list_free (finder->backends);
+
+ g_free (finder);
+}
+
+static void
+find_printer (const char *printer,
+ GFunc func,
+ gpointer data)
+{
+ GList *node, *next;
+ PrinterFinder *finder;
+
+ finder = g_new0 (PrinterFinder, 1);
+
+ finder->printer_name = g_strdup (printer);
+ finder->func = func;
+ finder->data = data;
+
+ finder->backends = NULL;
+ if (g_module_supported ())
+ finder->backends = gtk_print_backend_load_modules ();
+
+ for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
+ {
+ next = node->next;
+ find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
+ }
+
+ if (finder->backends == NULL)
+ g_idle_add (find_printer_idle, finder);
+}
+
+
+GtkPrintOperationResult
+_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ gboolean *do_print)
+{
+ if (gdk_should_use_portal ())
+ return gtk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print);
+ else
+ return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
+}
+void
+_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ GtkPrintOperationPrintFunc print_cb)
+{
+ if (gdk_should_use_portal ())
+ gtk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb);
+ else
+ gtk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb);
+}
+
+void
+_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ GtkWindow *parent,
+ const char *filename)
+{
+ if (gdk_should_use_portal ())
+ gtk_print_operation_portal_launch_preview (op, surface, parent, filename);
+ else
+ gtk_print_operation_unix_launch_preview (op, surface, parent, filename);
+}
+
+cairo_surface_t *
+_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ double *dpi_x,
+ double *dpi_y,
+ char **target)
+{
+ return gtk_print_operation_unix_create_preview_surface (op, page_setup, dpi_x, dpi_y, target);
+}
+
+void
+_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ cairo_surface_t *surface)
+{
+ gtk_print_operation_unix_resize_preview_surface (op, page_setup, surface);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr)
+{
+ gtk_print_operation_unix_preview_start_page (op, surface, cr);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr)
+{
+ gtk_print_operation_unix_preview_end_page (op, surface, cr);
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation-win32.c: Print Operation Details for Win32
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#ifndef _MSC_VER
+#ifndef _WIN32_WINNT
+/* Vista or newer */
+#define _WIN32_WINNT 0x0600
+#endif
+#ifndef WINVER
+#define WINVER _WIN32_WINNT
+#endif
+#endif
+
+#define COBJMACROS
+#include "config.h"
+#include <math.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <cairo-win32.h>
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include "gtkprintoperation-private.h"
+#include "gtkprint-win32.h"
+#include "gtkwindow.h"
+#include "gtkprivate.h"
+#include "gtkwidgetprivate.h"
+#include "gtknative.h"
+#include "win32/gdkprivate-win32.h"
+
+#define MAX_PAGE_RANGES 20
+#define STATUS_POLLING_TIME 2000
+
+#ifndef JOB_STATUS_RESTART
+#define JOB_STATUS_RESTART 0x800
+#endif
+
+#ifndef JOB_STATUS_COMPLETE
+#define JOB_STATUS_COMPLETE 0x1000
+#endif
+
+/* Forward declarations */
+GtkPrintOperationResult
+gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
+ gboolean *do_print);
+GtkPrintOperationResult
+gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
+ GtkWindow *parent,
+ gboolean *do_print);
+UINT_PTR CALLBACK
+run_mainloop_hook (HWND hdlg,
+ UINT uiMsg,
+ WPARAM wParam,
+ LPARAM lParam);
+void
+win32_start_page (GtkPrintOperation *op,
+ GtkPrintContext *print_context,
+ GtkPageSetup *page_setup);
+
+typedef struct {
+ HDC hdc;
+ HGLOBAL devmode;
+ HGLOBAL devnames;
+ HANDLE printerHandle;
+ int job_id;
+ guint timeout_id;
+
+ cairo_surface_t *surface;
+ GtkWidget *embed_widget;
+} GtkPrintOperationWin32;
+
+static void win32_poll_status (GtkPrintOperation *op);
+
+static const GUID myIID_IPrintDialogCallback = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
+
+#if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK)
+#undef INTERFACE
+#define INTERFACE IPrintDialogCallback
+DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
+{
+ STDMETHOD (QueryInterface)(THIS_ REFIID,LPVOID*) PURE;
+ STDMETHOD_ (ULONG, AddRef)(THIS) PURE;
+ STDMETHOD_ (ULONG, Release)(THIS) PURE;
+ STDMETHOD (InitDone)(THIS) PURE;
+ STDMETHOD (SelectionChange)(THIS) PURE;
+ STDMETHOD (HandleMessage)(THIS_ HWND,UINT,WPARAM,LPARAM,LRESULT*) PURE;
+};
+#endif
+
+static UINT got_gdk_events_message;
+
+UINT_PTR CALLBACK
+run_mainloop_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uiMsg == WM_INITDIALOG)
+ {
+ gdk_win32_set_modal_dialog_libgtk_only (hdlg);
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration (NULL, TRUE);
+ }
+ else if (uiMsg == got_gdk_events_message)
+ {
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration (NULL, TRUE);
+ return 1;
+ }
+ return 0;
+}
+
+static GtkPageOrientation
+orientation_from_win32 (short orientation)
+{
+ if (orientation == DMORIENT_LANDSCAPE)
+ return GTK_PAGE_ORIENTATION_LANDSCAPE;
+ return GTK_PAGE_ORIENTATION_PORTRAIT;
+}
+
+static short
+orientation_to_win32 (GtkPageOrientation orientation)
+{
+ if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
+ orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
+ return DMORIENT_LANDSCAPE;
+ return DMORIENT_PORTRAIT;
+}
+
+static GtkPaperSize *
+paper_size_from_win32 (short size)
+{
+ const char *name;
+
+ switch (size)
+ {
+ case DMPAPER_LETTER_TRANSVERSE:
+ case DMPAPER_LETTER:
+ case DMPAPER_LETTERSMALL:
+ name = "na_letter";
+ break;
+ case DMPAPER_TABLOID:
+ case DMPAPER_LEDGER:
+ name = "na_ledger";
+ break;
+ case DMPAPER_LEGAL:
+ name = "na_legal";
+ break;
+ case DMPAPER_STATEMENT:
+ name = "na_invoice";
+ break;
+ case DMPAPER_EXECUTIVE:
+ name = "na_executive";
+ break;
+ case DMPAPER_A3:
+ case DMPAPER_A3_TRANSVERSE:
+ name = "iso_a3";
+ break;
+ case DMPAPER_A4:
+ case DMPAPER_A4SMALL:
+ case DMPAPER_A4_TRANSVERSE:
+ name = "iso_a4";
+ break;
+ case DMPAPER_A5:
+ case DMPAPER_A5_TRANSVERSE:
+ name = "iso_a5";
+ break;
+ case DMPAPER_B4:
+ name = "jis_b4";
+ break;
+ case DMPAPER_B5:
+ case DMPAPER_B5_TRANSVERSE:
+ name = "jis_b5";
+ break;
+ case DMPAPER_QUARTO:
+ name = "na_quarto";
+ break;
+ case DMPAPER_10X14:
+ name = "na_10x14";
+ break;
+ case DMPAPER_11X17:
+ name = "na_ledger";
+ break;
+ case DMPAPER_NOTE:
+ name = "na_letter";
+ break;
+ case DMPAPER_ENV_9:
+ name = "na_number-9";
+ break;
+ case DMPAPER_ENV_10:
+ name = "na_number-10";
+ break;
+ case DMPAPER_ENV_11:
+ name = "na_number-11";
+ break;
+ case DMPAPER_ENV_12:
+ name = "na_number-12";
+ break;
+ case DMPAPER_ENV_14:
+ name = "na_number-14";
+ break;
+ case DMPAPER_CSHEET:
+ name = "na_c";
+ break;
+ case DMPAPER_DSHEET:
+ name = "na_d";
+ break;
+ case DMPAPER_ESHEET:
+ name = "na_e";
+ break;
+ case DMPAPER_ENV_DL:
+ name = "iso_dl";
+ break;
+ case DMPAPER_ENV_C5:
+ name = "iso_c5";
+ break;
+ case DMPAPER_ENV_C3:
+ name = "iso_c3";
+ break;
+ case DMPAPER_ENV_C4:
+ name = "iso_c4";
+ break;
+ case DMPAPER_ENV_C6:
+ name = "iso_c6";
+ break;
+ case DMPAPER_ENV_C65:
+ name = "iso_c6c5";
+ break;
+ case DMPAPER_ENV_B4:
+ name = "iso_b4";
+ break;
+ case DMPAPER_ENV_B5:
+ name = "iso_b5";
+ break;
+ case DMPAPER_ENV_B6:
+ name = "iso_b6";
+ break;
+ case DMPAPER_ENV_ITALY:
+ name = "om_italian";
+ break;
+ case DMPAPER_ENV_MONARCH:
+ name = "na_monarch";
+ break;
+ case DMPAPER_ENV_PERSONAL:
+ name = "na_personal";
+ break;
+ case DMPAPER_FANFOLD_US:
+ name = "na_fanfold-us";
+ break;
+ case DMPAPER_FANFOLD_STD_GERMAN:
+ name = "na_fanfold-eur";
+ break;
+ case DMPAPER_FANFOLD_LGL_GERMAN:
+ name = "na_foolscap";
+ break;
+ case DMPAPER_ISO_B4:
+ name = "iso_b4";
+ break;
+ case DMPAPER_JAPANESE_POSTCARD:
+ name = "jpn_hagaki";
+ break;
+ case DMPAPER_9X11:
+ name = "na_9x11";
+ break;
+ case DMPAPER_10X11:
+ name = "na_10x11";
+ break;
+ case DMPAPER_ENV_INVITE:
+ name = "om_invite";
+ break;
+ case DMPAPER_LETTER_EXTRA:
+ case DMPAPER_LETTER_EXTRA_TRANSVERSE:
+ name = "na_letter-extra";
+ break;
+ case DMPAPER_LEGAL_EXTRA:
+ name = "na_legal-extra";
+ break;
+ case DMPAPER_TABLOID_EXTRA:
+ name = "na_arch";
+ break;
+ case DMPAPER_A4_EXTRA:
+ name = "iso_a4-extra";
+ break;
+ case DMPAPER_B_PLUS:
+ name = "na_b-plus";
+ break;
+ case DMPAPER_LETTER_PLUS:
+ name = "na_letter-plus";
+ break;
+ case DMPAPER_A3_EXTRA:
+ case DMPAPER_A3_EXTRA_TRANSVERSE:
+ name = "iso_a3-extra";
+ break;
+ case DMPAPER_A5_EXTRA:
+ name = "iso_a5-extra";
+ break;
+ case DMPAPER_B5_EXTRA:
+ name = "iso_b5-extra";
+ break;
+ case DMPAPER_A2:
+ name = "iso_a2";
+ break;
+
+ default:
+ name = NULL;
+ break;
+ }
+
+ if (name)
+ return gtk_paper_size_new (name);
+ else
+ return NULL;
+}
+
+static short
+paper_size_to_win32 (GtkPaperSize *paper_size)
+{
+ const char *format;
+
+ if (gtk_paper_size_is_custom (paper_size))
+ return 0;
+
+ format = gtk_paper_size_get_name (paper_size);
+
+ if (strcmp (format, "na_letter") == 0)
+ return DMPAPER_LETTER;
+ if (strcmp (format, "na_ledger") == 0)
+ return DMPAPER_LEDGER;
+ if (strcmp (format, "na_legal") == 0)
+ return DMPAPER_LEGAL;
+ if (strcmp (format, "na_invoice") == 0)
+ return DMPAPER_STATEMENT;
+ if (strcmp (format, "na_executive") == 0)
+ return DMPAPER_EXECUTIVE;
+ if (strcmp (format, "iso_a2") == 0)
+ return DMPAPER_A2;
+ if (strcmp (format, "iso_a3") == 0)
+ return DMPAPER_A3;
+ if (strcmp (format, "iso_a4") == 0)
+ return DMPAPER_A4;
+ if (strcmp (format, "iso_a5") == 0)
+ return DMPAPER_A5;
+ if (strcmp (format, "iso_b4") == 0)
+ return DMPAPER_B4;
+ if (strcmp (format, "iso_b5") == 0)
+ return DMPAPER_B5;
+ if (strcmp (format, "na_quarto") == 0)
+ return DMPAPER_QUARTO;
+ if (strcmp (format, "na_10x14") == 0)
+ return DMPAPER_10X14;
+ if (strcmp (format, "na_number-9") == 0)
+ return DMPAPER_ENV_9;
+ if (strcmp (format, "na_number-10") == 0)
+ return DMPAPER_ENV_10;
+ if (strcmp (format, "na_number-11") == 0)
+ return DMPAPER_ENV_11;
+ if (strcmp (format, "na_number-12") == 0)
+ return DMPAPER_ENV_12;
+ if (strcmp (format, "na_number-14") == 0)
+ return DMPAPER_ENV_14;
+ if (strcmp (format, "na_c") == 0)
+ return DMPAPER_CSHEET;
+ if (strcmp (format, "na_d") == 0)
+ return DMPAPER_DSHEET;
+ if (strcmp (format, "na_e") == 0)
+ return DMPAPER_ESHEET;
+ if (strcmp (format, "iso_dl") == 0)
+ return DMPAPER_ENV_DL;
+ if (strcmp (format, "iso_c3") == 0)
+ return DMPAPER_ENV_C3;
+ if (strcmp (format, "iso_c4") == 0)
+ return DMPAPER_ENV_C4;
+ if (strcmp (format, "iso_c5") == 0)
+ return DMPAPER_ENV_C5;
+ if (strcmp (format, "iso_c6") == 0)
+ return DMPAPER_ENV_C6;
+ if (strcmp (format, "iso_c5c6") == 0)
+ return DMPAPER_ENV_C65;
+ if (strcmp (format, "iso_b6") == 0)
+ return DMPAPER_ENV_B6;
+ if (strcmp (format, "om_italian") == 0)
+ return DMPAPER_ENV_ITALY;
+ if (strcmp (format, "na_monarch") == 0)
+ return DMPAPER_ENV_MONARCH;
+ if (strcmp (format, "na_personal") == 0)
+ return DMPAPER_ENV_PERSONAL;
+ if (strcmp (format, "na_fanfold-us") == 0)
+ return DMPAPER_FANFOLD_US;
+ if (strcmp (format, "na_fanfold-eur") == 0)
+ return DMPAPER_FANFOLD_STD_GERMAN;
+ if (strcmp (format, "na_foolscap") == 0)
+ return DMPAPER_FANFOLD_LGL_GERMAN;
+ if (strcmp (format, "jpn_hagaki") == 0)
+ return DMPAPER_JAPANESE_POSTCARD;
+ if (strcmp (format, "na_9x11") == 0)
+ return DMPAPER_9X11;
+ if (strcmp (format, "na_10x11") == 0)
+ return DMPAPER_10X11;
+ if (strcmp (format, "om_invite") == 0)
+ return DMPAPER_ENV_INVITE;
+ if (strcmp (format, "na_letter-extra") == 0)
+ return DMPAPER_LETTER_EXTRA;
+ if (strcmp (format, "na_legal-extra") == 0)
+ return DMPAPER_LEGAL_EXTRA;
+ if (strcmp (format, "na_arch") == 0)
+ return DMPAPER_TABLOID_EXTRA;
+ if (strcmp (format, "iso_a3-extra") == 0)
+ return DMPAPER_A3_EXTRA;
+ if (strcmp (format, "iso_a4-extra") == 0)
+ return DMPAPER_A4_EXTRA;
+ if (strcmp (format, "iso_a5-extra") == 0)
+ return DMPAPER_A5_EXTRA;
+ if (strcmp (format, "iso_b5-extra") == 0)
+ return DMPAPER_B5_EXTRA;
+ if (strcmp (format, "na_b-plus") == 0)
+ return DMPAPER_B_PLUS;
+ if (strcmp (format, "na_letter-plus") == 0)
+ return DMPAPER_LETTER_PLUS;
+
+ return 0;
+}
+
+static char *
+get_default_printer (void)
+{
+ wchar_t *win32_printer_name = NULL;
+ char *printer_name = NULL;
+ DWORD needed;
+
+ GetDefaultPrinterW (NULL, &needed);
+ win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
+ if (!GetDefaultPrinterW (win32_printer_name, &needed))
+ {
+ g_free (win32_printer_name);
+ return NULL;
+ }
+ printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
+ g_free (win32_printer_name);
+
+ return printer_name;
+}
+
+static void
+set_hard_margins (GtkPrintOperation *op)
+{
+ double top, bottom, left, right;
+ GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+
+ top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
+ bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT)
+ - GetDeviceCaps (op_win32->hdc, VERTRES) - top;
+ left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
+ right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH)
+ - GetDeviceCaps (op_win32->hdc, HORZRES) - left;
+
+ _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right);
+}
+
+void
+win32_start_page (GtkPrintOperation *op,
+ GtkPrintContext *print_context,
+ GtkPageSetup *page_setup)
+{
+ GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+ LPDEVMODEW devmode;
+ GtkPaperSize *paper_size;
+ double x_off, y_off;
+
+ devmode = GlobalLock (op_win32->devmode);
+
+ devmode->dmFields |= DM_ORIENTATION;
+ devmode->dmOrientation =
+ orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+ devmode->dmFields |= DM_PAPERSIZE;
+ devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
+ devmode->dmPaperSize = paper_size_to_win32 (paper_size);
+ if (devmode->dmPaperSize == 0)
+ {
+ devmode->dmPaperSize = DMPAPER_USER;
+ devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
+
+ /* Lengths in DEVMODE are in tenths of a millimeter */
+ devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
+ devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
+ }
+
+ ResetDCW (op_win32->hdc, devmode);
+
+ GlobalUnlock (op_win32->devmode);
+
+ set_hard_margins (op);
+ x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
+ y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
+ cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
+
+ StartPage (op_win32->hdc);
+}
+
+static void
+win32_end_page (GtkPrintOperation *op,
+ GtkPrintContext *print_context)
+{
+ GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+
+ cairo_surface_show_page (op_win32->surface);
+
+ EndPage (op_win32->hdc);
+}
+
+static gboolean
+win32_poll_status_timeout (GtkPrintOperation *op)
+{
+ GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+
+ op_win32->timeout_id = 0;
+ /* We need to ref this, as setting the status to finished
+ might unref the object */
+ g_object_ref (op);
+ win32_poll_status (op);
+
+ if (!gtk_print_operation_is_finished (op)) {
+ op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
+ (GSourceFunc)win32_poll_status_timeout,
+ op);
+ gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
+ }
+ g_object_unref (op);
+ return FALSE;
+}
+
+
+static void
+win32_end_run (GtkPrintOperation *op,
+ gboolean wait,
+ gboolean cancelled)
+{
+ GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+ LPDEVNAMES devnames;
+ HANDLE printerHandle = 0;
+
+ cairo_surface_finish (op_win32->surface);
+
+ EndDoc (op_win32->hdc);
+
+ if (op->priv->track_print_status)
+ {
+ devnames = GlobalLock (op_win32->devnames);
+ if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
+ &printerHandle, NULL))
+ printerHandle = 0;
+ GlobalUnlock (op_win32->devnames);
+ }
+
+ GlobalFree (op_win32->devmode);
+ GlobalFree (op_win32->devnames);
+
+ cairo_surface_destroy (op_win32->surface);
+ op_win32->surface = NULL;
+
+ DeleteDC (op_win32->hdc);
+
+ if (printerHandle != 0)
+ {
+ op_win32->printerHandle = printerHandle;
+ win32_poll_status (op);
+ op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
+ (GSourceFunc)win32_poll_status_timeout,
+ op);
+ gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
+ }
+ else
+ /* Dunno what happened, pretend its finished */
+ _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
+}
+
+static void
+win32_poll_status (GtkPrintOperation *op)
+{
+ GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+ guchar *data;
+ DWORD needed;
+ JOB_INFO_1W *job_info;
+ GtkPrintStatus status;
+ char *status_str;
+ BOOL ret;
+
+ GetJobW (op_win32->printerHandle, op_win32->job_id,
+ 1,(LPBYTE)NULL, 0, &needed);
+ data = g_malloc (needed);
+ ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
+ 1, (LPBYTE)data, needed, &needed);
+
+ status_str = NULL;
+ if (ret)
+ {
+ DWORD win32_status;
+ job_info = (JOB_INFO_1W *)data;
+ win32_status = job_info->Status;
+
+ if (job_info->pStatus)
+ status_str = g_utf16_to_utf8 (job_info->pStatus,
+ -1, NULL, NULL, NULL);
+
+ if (win32_status &
+ (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
+ status = GTK_PRINT_STATUS_FINISHED;
+ else if (win32_status &
+ (JOB_STATUS_OFFLINE |
+ JOB_STATUS_PAPEROUT |
+ JOB_STATUS_PAUSED |
+ JOB_STATUS_USER_INTERVENTION))
+ {
+ status = GTK_PRINT_STATUS_PENDING_ISSUE;
+ if (status_str == NULL)
+ {
+ if (win32_status & JOB_STATUS_OFFLINE)
+ status_str = g_strdup (_("Printer offline"));
+ else if (win32_status & JOB_STATUS_PAPEROUT)
+ status_str = g_strdup (_("Out of paper"));
+ else if (win32_status & JOB_STATUS_PAUSED)
+ status_str = g_strdup (_("Paused"));
+ else if (win32_status & JOB_STATUS_USER_INTERVENTION)
+ status_str = g_strdup (_("Need user intervention"));
+ }
+ }
+ else if (win32_status &
+ (JOB_STATUS_BLOCKED_DEVQ |
+ JOB_STATUS_DELETED |
+ JOB_STATUS_ERROR))
+ status = GTK_PRINT_STATUS_FINISHED_ABORTED;
+ else if (win32_status &
+ (JOB_STATUS_SPOOLING |
+ JOB_STATUS_DELETING))
+ status = GTK_PRINT_STATUS_PENDING;
+ else if (win32_status & JOB_STATUS_PRINTING)
+ status = GTK_PRINT_STATUS_PRINTING;
+ else
+ status = GTK_PRINT_STATUS_FINISHED;
+ }
+ else
+ status = GTK_PRINT_STATUS_FINISHED;
+
+ g_free (data);
+
+ _gtk_print_operation_set_status (op, status, status_str);
+
+ g_free (status_str);
+}
+
+static void
+op_win32_free (GtkPrintOperationWin32 *op_win32)
+{
+ if (op_win32->printerHandle)
+ ClosePrinter (op_win32->printerHandle);
+ if (op_win32->timeout_id != 0)
+ g_source_remove (op_win32->timeout_id);
+ g_free (op_win32);
+}
+
+static HWND
+get_parent_hwnd (GtkWidget *widget)
+{
+ GtkNative *native;
+
+ native = gtk_widget_get_native (widget);
+ gtk_widget_realize (GTK_WIDGET (native));
+ return gdk_win32_surface_get_handle (gtk_native_get_surface (native));
+}
+
+static void
+devnames_to_settings (GtkPrintSettings *settings,
+ HANDLE hDevNames)
+{
+ GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
+ gtk_print_settings_set_printer (settings, devnames->device);
+ gtk_print_win32_devnames_free (devnames);
+}
+
+static void
+devmode_to_settings (GtkPrintSettings *settings,
+ HANDLE hDevMode)
+{
+ LPDEVMODEW devmode;
+
+ devmode = GlobalLock (hDevMode);
+
+ gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
+ devmode->dmDriverVersion);
+ if (devmode->dmDriverExtra != 0)
+ {
+ char *extra = g_base64_encode (((const guchar *)devmode) + sizeof (DEVMODEW),
+ devmode->dmDriverExtra);
+ gtk_print_settings_set (settings,
+ GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
+ extra);
+ g_free (extra);
+ }
+
+ char *devmode_name = g_utf16_to_utf8 (devmode->dmDeviceName, -1, NULL, NULL, NULL);
+ gtk_print_settings_set (settings, "win32-devmode-name", devmode_name);
+ g_free (devmode_name);
+
+ if (devmode->dmFields & DM_ORIENTATION)
+ gtk_print_settings_set_orientation (settings,
+ orientation_from_win32 (devmode->dmOrientation));
+
+
+ if (devmode->dmFields & DM_PAPERSIZE &&
+ devmode->dmPaperSize != 0)
+ {
+ GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
+ if (paper_size)
+ {
+ gtk_print_settings_set_paper_size (settings, paper_size);
+ gtk_paper_size_free (paper_size);
+ }
+ gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
+ }
+ else if ((devmode->dmFields & DM_PAPERSIZE &&
+ devmode->dmPaperSize == 0) ||
+ ((devmode->dmFields & DM_PAPERWIDTH) &&
+ (devmode->dmFields & DM_PAPERLENGTH)))
+ {
+ GtkPaperSize *paper_size;
+ char *form_name = NULL;
+ if (devmode->dmFields & DM_FORMNAME)
+ form_name = g_utf16_to_utf8 (devmode->dmFormName,
+ -1, NULL, NULL, NULL);
+ if (form_name == NULL || form_name[0] == 0)
+ form_name = g_strdup (_("Custom size"));
+
+ /* Lengths in DEVMODE are in tenths of a millimeter */
+ paper_size = gtk_paper_size_new_custom (form_name,
+ form_name,
+ devmode->dmPaperWidth / 10.0,
+ devmode->dmPaperLength / 10.0,
+ GTK_UNIT_MM);
+ gtk_print_settings_set_paper_size (settings, paper_size);
+ gtk_paper_size_free (paper_size);
+ }
+
+ if (devmode->dmFields & DM_SCALE)
+ gtk_print_settings_set_scale (settings, devmode->dmScale);
+
+ if (devmode->dmFields & DM_COPIES)
+ gtk_print_settings_set_n_copies (settings,
+ devmode->dmCopies);
+
+ if (devmode->dmFields & DM_DEFAULTSOURCE)
+ {
+ const char *source;
+ switch (devmode->dmDefaultSource)
+ {
+ default:
+ case DMBIN_AUTO:
+ source = "auto";
+ break;
+ case DMBIN_CASSETTE:
+ source = "cassette";
+ break;
+ case DMBIN_ENVELOPE:
+ source = "envelope";
+ break;
+ case DMBIN_ENVMANUAL:
+ source = "envelope-manual";
+ break;
+ case DMBIN_LOWER:
+ source = "lower";
+ break;
+ case DMBIN_MANUAL:
+ source = "manual";
+ break;
+ case DMBIN_MIDDLE:
+ source = "middle";
+ break;
+ case DMBIN_ONLYONE:
+ source = "only-one";
+ break;
+ case DMBIN_FORMSOURCE:
+ source = "form-source";
+ break;
+ case DMBIN_LARGECAPACITY:
+ source = "large-capacity";
+ break;
+ case DMBIN_LARGEFMT:
+ source = "large-format";
+ break;
+ case DMBIN_TRACTOR:
+ source = "tractor";
+ break;
+ case DMBIN_SMALLFMT:
+ source = "small-format";
+ break;
+ }
+ gtk_print_settings_set_default_source (settings, source);
+ gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
+ }
+
+ if (devmode->dmFields & DM_PRINTQUALITY)
+ {
+ GtkPrintQuality quality;
+ switch (devmode->dmPrintQuality)
+ {
+ case DMRES_LOW:
+ quality = GTK_PRINT_QUALITY_LOW;
+ break;
+ case DMRES_MEDIUM:
+ quality = GTK_PRINT_QUALITY_NORMAL;
+ break;
+ default:
+ case DMRES_HIGH:
+ quality = GTK_PRINT_QUALITY_HIGH;
+ break;
+ case DMRES_DRAFT:
+ quality = GTK_PRINT_QUALITY_DRAFT;
+ break;
+ }
+ gtk_print_settings_set_quality (settings, quality);
+ gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
+ }
+
+ if (devmode->dmFields & DM_COLOR)
+ gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
+
+ if (devmode->dmFields & DM_DUPLEX)
+ {
+ GtkPrintDuplex duplex;
+ switch (devmode->dmDuplex)
+ {
+ default:
+ case DMDUP_SIMPLEX:
+ duplex = GTK_PRINT_DUPLEX_SIMPLEX;
+ break;
+ case DMDUP_HORIZONTAL:
+ duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
+ break;
+ case DMDUP_VERTICAL:
+ duplex = GTK_PRINT_DUPLEX_VERTICAL;
+ break;
+ }
+
+ gtk_print_settings_set_duplex (settings, duplex);
+ }
+
+ if (devmode->dmFields & DM_COLLATE)
+ gtk_print_settings_set_collate (settings,
+ devmode->dmCollate == DMCOLLATE_TRUE);
+
+ if (devmode->dmFields & DM_MEDIATYPE)
+ {
+ const char *media_type;
+ switch (devmode->dmMediaType)
+ {
+ default:
+ case DMMEDIA_STANDARD:
+ media_type = "stationery";
+ break;
+ case DMMEDIA_TRANSPARENCY:
+ media_type = "transparency";
+ break;
+ case DMMEDIA_GLOSSY:
+ media_type = "photographic-glossy";
+ break;
+ }
+ gtk_print_settings_set_media_type (settings, media_type);
+ gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
+ }
+
+ if (devmode->dmFields & DM_DITHERTYPE)
+ {
+ const char *dither;
+ switch (devmode->dmDitherType)
+ {
+ default:
+ case DMDITHER_FINE:
+ dither = "fine";
+ break;
+ case DMDITHER_NONE:
+ dither = "none";
+ break;
+ case DMDITHER_COARSE:
+ dither = "coarse";
+ break;
+ case DMDITHER_LINEART:
+ dither = "lineart";
+ break;
+ case DMDITHER_GRAYSCALE:
+ dither = "grayscale";
+ break;
+ case DMDITHER_ERRORDIFFUSION:
+ dither = "error-diffusion";
+ break;
+ }
+ gtk_print_settings_set_dither (settings, dither);
+ gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
+ }
+
+ GlobalUnlock (hDevMode);
+}
+
+static void
+dialog_to_print_settings (GtkPrintOperation *op,
+ LPPRINTDLGEXW printdlgex)
+{
+ guint i;
+ GtkPrintSettings *settings;
+
+ settings = gtk_print_settings_new ();
+
+ gtk_print_settings_set_print_pages (settings,
+ GTK_PRINT_PAGES_ALL);
+ if (printdlgex->Flags & PD_CURRENTPAGE)
+ gtk_print_settings_set_print_pages (settings,
+ GTK_PRINT_PAGES_CURRENT);
+ else if (printdlgex->Flags & PD_PAGENUMS)
+ gtk_print_settings_set_print_pages (settings,
+ GTK_PRINT_PAGES_RANGES);
+
+ if (printdlgex->nPageRanges > 0)
+ {
+ GtkPageRange *ranges;
+ ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
+
+ for (i = 0; i < printdlgex->nPageRanges; i++)
+ {
+ ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
+ ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
+ }
+
+ gtk_print_settings_set_page_ranges (settings, ranges,
+ printdlgex->nPageRanges);
+ g_free (ranges);
+ }
+
+ if (printdlgex->hDevNames != NULL)
+ devnames_to_settings (settings, printdlgex->hDevNames);
+
+ if (printdlgex->hDevMode != NULL)
+ devmode_to_settings (settings, printdlgex->hDevMode);
+
+ gtk_print_operation_set_print_settings (op, settings);
+}
+
+static HANDLE
+devmode_from_settings (GtkPrintSettings *settings,
+ GtkPageSetup *page_setup,
+ HANDLE hDevModeParam)
+{
+ HANDLE hDevMode = hDevModeParam;
+ LPDEVMODEW devmode;
+ guchar *extras;
+ GtkPaperSize *paper_size;
+ const char *extras_base64;
+ gsize extras_len;
+ const char *val;
+
+ /* If we already provided a valid hDevMode, don't initialize a new one; just lock the one we have */
+ if (hDevMode)
+ {
+ devmode = GlobalLock (hDevMode);
+ }
+ else
+ {
+ extras = NULL;
+ extras_len = 0;
+ extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
+ if (extras_base64)
+ extras = g_base64_decode (extras_base64, &extras_len);
+
+ hDevMode = GlobalAlloc (GMEM_MOVEABLE,
+ sizeof (DEVMODEW) + extras_len);
+
+ devmode = GlobalLock (hDevMode);
+
+ memset (devmode, 0, sizeof (DEVMODEW));
+
+ devmode->dmSpecVersion = DM_SPECVERSION;
+ devmode->dmSize = sizeof (DEVMODEW);
+
+ gunichar2 *device_name = g_utf8_to_utf16 (gtk_print_settings_get (settings, "win32-devmode-name"), -1, NULL, NULL, NULL);
+ memcpy (devmode->dmDeviceName, device_name, CCHDEVICENAME);
+ g_free (device_name);
+
+
+ devmode->dmDriverExtra = 0;
+ if (extras && extras_len > 0)
+ {
+ devmode->dmDriverExtra = extras_len;
+ memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
+ }
+ g_free (extras);
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
+ {
+ devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
+ }
+ }
+
+ if (page_setup ||
+ gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
+ {
+ GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
+ if (page_setup)
+ orientation = gtk_page_setup_get_orientation (page_setup);
+ devmode->dmFields |= DM_ORIENTATION;
+ devmode->dmOrientation = orientation_to_win32 (orientation);
+ }
+
+ if (page_setup)
+ paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
+ else
+ {
+ int size;
+ if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
+ (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
+ {
+ devmode->dmFields |= DM_PAPERSIZE;
+ devmode->dmPaperSize = size;
+ paper_size = NULL;
+ }
+ else
+ paper_size = gtk_print_settings_get_paper_size (settings);
+ }
+ if (paper_size)
+ {
+ devmode->dmFields |= DM_PAPERSIZE;
+ devmode->dmPaperSize = paper_size_to_win32 (paper_size);
+ if (devmode->dmPaperSize == 0)
+ {
+ devmode->dmPaperSize = DMPAPER_USER;
+ devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
+
+ /* Lengths in DEVMODE are in tenths of a millimeter */
+ devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
+ devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
+ }
+ gtk_paper_size_free (paper_size);
+ }
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
+ {
+ devmode->dmFields |= DM_SCALE;
+ devmode->dmScale = gtk_print_settings_get_scale (settings);
+ }
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
+ {
+ devmode->dmFields |= DM_COPIES;
+ devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
+ }
+
+ if (gtk_print_settings_has_key (settings, "win32-default-source"))
+ {
+ devmode->dmFields |= DM_DEFAULTSOURCE;
+ devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
+ }
+ else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
+ {
+ devmode->dmFields |= DM_DEFAULTSOURCE;
+ devmode->dmDefaultSource = DMBIN_AUTO;
+
+ val = gtk_print_settings_get_default_source (settings);
+ if (strcmp (val, "auto") == 0)
+ devmode->dmDefaultSource = DMBIN_AUTO;
+ if (strcmp (val, "cassette") == 0)
+ devmode->dmDefaultSource = DMBIN_CASSETTE;
+ if (strcmp (val, "envelope") == 0)
+ devmode->dmDefaultSource = DMBIN_ENVELOPE;
+ if (strcmp (val, "envelope-manual") == 0)
+ devmode->dmDefaultSource = DMBIN_ENVMANUAL;
+ if (strcmp (val, "lower") == 0)
+ devmode->dmDefaultSource = DMBIN_LOWER;
+ if (strcmp (val, "manual") == 0)
+ devmode->dmDefaultSource = DMBIN_MANUAL;
+ if (strcmp (val, "middle") == 0)
+ devmode->dmDefaultSource = DMBIN_MIDDLE;
+ if (strcmp (val, "only-one") == 0)
+ devmode->dmDefaultSource = DMBIN_ONLYONE;
+ if (strcmp (val, "form-source") == 0)
+ devmode->dmDefaultSource = DMBIN_FORMSOURCE;
+ if (strcmp (val, "large-capacity") == 0)
+ devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
+ if (strcmp (val, "large-format") == 0)
+ devmode->dmDefaultSource = DMBIN_LARGEFMT;
+ if (strcmp (val, "tractor") == 0)
+ devmode->dmDefaultSource = DMBIN_TRACTOR;
+ if (strcmp (val, "small-format") == 0)
+ devmode->dmDefaultSource = DMBIN_SMALLFMT;
+ }
+
+ if (gtk_print_settings_has_key (settings, "win32-print-quality"))
+ {
+ devmode->dmFields |= DM_PRINTQUALITY;
+ devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
+ }
+ else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
+ {
+ devmode->dmFields |= DM_PRINTQUALITY;
+ devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
+ }
+ else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
+ {
+ devmode->dmFields |= DM_PRINTQUALITY;
+ switch (gtk_print_settings_get_quality (settings))
+ {
+ case GTK_PRINT_QUALITY_LOW:
+ devmode->dmPrintQuality = DMRES_LOW;
+ break;
+ case GTK_PRINT_QUALITY_DRAFT:
+ devmode->dmPrintQuality = DMRES_DRAFT;
+ break;
+ default:
+ case GTK_PRINT_QUALITY_NORMAL:
+ devmode->dmPrintQuality = DMRES_MEDIUM;
+ break;
+ case GTK_PRINT_QUALITY_HIGH:
+ devmode->dmPrintQuality = DMRES_HIGH;
+ break;
+ }
+ }
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
+ {
+ devmode->dmFields |= DM_COLOR;
+ if (gtk_print_settings_get_use_color (settings))
+ devmode->dmColor = DMCOLOR_COLOR;
+ else
+ devmode->dmColor = DMCOLOR_MONOCHROME;
+ }
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
+ {
+ devmode->dmFields |= DM_DUPLEX;
+ switch (gtk_print_settings_get_duplex (settings))
+ {
+ default:
+ case GTK_PRINT_DUPLEX_SIMPLEX:
+ devmode->dmDuplex = DMDUP_SIMPLEX;
+ break;
+ case GTK_PRINT_DUPLEX_HORIZONTAL:
+ devmode->dmDuplex = DMDUP_HORIZONTAL;
+ break;
+ case GTK_PRINT_DUPLEX_VERTICAL:
+ devmode->dmDuplex = DMDUP_VERTICAL;
+ break;
+ }
+ }
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
+ {
+ devmode->dmFields |= DM_COLLATE;
+ if (gtk_print_settings_get_collate (settings))
+ devmode->dmCollate = DMCOLLATE_TRUE;
+ else
+ devmode->dmCollate = DMCOLLATE_FALSE;
+ }
+
+ if (gtk_print_settings_has_key (settings, "win32-media-type"))
+ {
+ devmode->dmFields |= DM_MEDIATYPE;
+ devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
+ }
+ else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
+ {
+ devmode->dmFields |= DM_MEDIATYPE;
+ devmode->dmMediaType = DMMEDIA_STANDARD;
+
+ val = gtk_print_settings_get_media_type (settings);
+ if (strcmp (val, "transparency") == 0)
+ devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
+ if (strcmp (val, "photographic-glossy") == 0)
+ devmode->dmMediaType = DMMEDIA_GLOSSY;
+ }
+
+ if (gtk_print_settings_has_key (settings, "win32-dither-type"))
+ {
+ devmode->dmFields |= DM_DITHERTYPE;
+ devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
+ }
+ else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
+ {
+ devmode->dmFields |= DM_DITHERTYPE;
+ devmode->dmDitherType = DMDITHER_FINE;
+
+ val = gtk_print_settings_get_dither (settings);
+ if (strcmp (val, "none") == 0)
+ devmode->dmDitherType = DMDITHER_NONE;
+ if (strcmp (val, "coarse") == 0)
+ devmode->dmDitherType = DMDITHER_COARSE;
+ if (strcmp (val, "fine") == 0)
+ devmode->dmDitherType = DMDITHER_FINE;
+ if (strcmp (val, "lineart") == 0)
+ devmode->dmDitherType = DMDITHER_LINEART;
+ if (strcmp (val, "grayscale") == 0)
+ devmode->dmDitherType = DMDITHER_GRAYSCALE;
+ if (strcmp (val, "error-diffusion") == 0)
+ devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
+ }
+
+ GlobalUnlock (hDevMode);
+
+ return hDevMode;
+}
+
+static void
+dialog_from_print_settings (GtkPrintOperation *op,
+ LPPRINTDLGEXW printdlgex)
+{
+ GtkPrintSettings *settings = op->priv->print_settings;
+ const char *printer;
+
+ if (settings == NULL)
+ return;
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
+ {
+ GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
+
+ switch (print_pages)
+ {
+ default:
+ case GTK_PRINT_PAGES_SELECTION:
+ case GTK_PRINT_PAGES_ALL:
+ printdlgex->Flags |= PD_ALLPAGES;
+ break;
+ case GTK_PRINT_PAGES_CURRENT:
+ printdlgex->Flags |= PD_CURRENTPAGE;
+ break;
+ case GTK_PRINT_PAGES_RANGES:
+ printdlgex->Flags |= PD_PAGENUMS;
+ break;
+ }
+ }
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
+ {
+ GtkPageRange *ranges;
+ int num_ranges, i;
+
+ ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
+
+ if (num_ranges > MAX_PAGE_RANGES)
+ num_ranges = MAX_PAGE_RANGES;
+
+ printdlgex->nPageRanges = num_ranges;
+ for (i = 0; i < num_ranges; i++)
+ {
+ printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
+ printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
+ }
+ }
+
+ /* If we have a printer saved, restore our settings */
+ printer = gtk_print_settings_get_printer (settings);
+ if (printer)
+ {
+ printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
+
+ printdlgex->hDevMode = devmode_from_settings (settings,
+ op->priv->default_page_setup, NULL);
+ }
+ else
+ {
+ /* Otherwise, use the default settings */
+ DWORD FlagsCopy = printdlgex->Flags;
+ printdlgex->Flags |= PD_RETURNDEFAULT;
+ PrintDlgExW (printdlgex);
+ printdlgex->Flags = FlagsCopy;
+
+ devmode_from_settings (settings, op->priv->default_page_setup, printdlgex->hDevMode);
+ }
+}
+
+typedef struct {
+ IPrintDialogCallback iPrintDialogCallback;
+ gboolean set_hwnd;
+ int ref_count;
+} PrintDialogCallback;
+
+
+static ULONG STDMETHODCALLTYPE
+iprintdialogcallback_addref (IPrintDialogCallback *This)
+{
+ PrintDialogCallback *callback = (PrintDialogCallback *)This;
+ return ++callback->ref_count;
+}
+
+static ULONG STDMETHODCALLTYPE
+iprintdialogcallback_release (IPrintDialogCallback *This)
+{
+ PrintDialogCallback *callback = (PrintDialogCallback *)This;
+ int ref_count = --callback->ref_count;
+
+ if (ref_count == 0)
+ g_free (This);
+
+ return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
+ REFIID riid,
+ LPVOID *ppvObject)
+{
+ if (IsEqualIID (riid, &IID_IUnknown) ||
+ IsEqualIID (riid, &myIID_IPrintDialogCallback))
+ {
+ *ppvObject = This;
+ IUnknown_AddRef ((IUnknown *)This);
+ return NOERROR;
+ }
+ else
+ {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_initdone (IPrintDialogCallback *This)
+{
+ return S_FALSE;
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
+{
+ return S_FALSE;
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
+ HWND hDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam,
+ LRESULT *pResult)
+{
+ PrintDialogCallback *callback = (PrintDialogCallback *)This;
+
+ if (!callback->set_hwnd)
+ {
+ gdk_win32_set_modal_dialog_libgtk_only (hDlg);
+ callback->set_hwnd = TRUE;
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration (NULL, TRUE);
+ }
+ else if (uMsg == got_gdk_events_message)
+ {
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration (NULL, TRUE);
+ *pResult = TRUE;
+ return S_OK;
+ }
+
+ *pResult = 0;
+ return S_FALSE;
+}
+
+static IPrintDialogCallbackVtbl ipdc_vtbl = {
+ iprintdialogcallback_queryinterface,
+ iprintdialogcallback_addref,
+ iprintdialogcallback_release,
+ iprintdialogcallback_initdone,
+ iprintdialogcallback_selectionchange,
+ iprintdialogcallback_handlemessage
+};
+
+static IPrintDialogCallback *
+print_callback_new (void)
+{
+ PrintDialogCallback *callback;
+
+ callback = g_new0 (PrintDialogCallback, 1);
+ callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
+ callback->ref_count = 1;
+ callback->set_hwnd = FALSE;
+
+ return &callback->iPrintDialogCallback;
+}
+
+static INT_PTR CALLBACK
+pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ GtkPrintOperation *op;
+ GtkPrintOperationWin32 *op_win32;
+
+ if (message == WM_INITDIALOG)
+ {
+ PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
+ GtkWidget *plug;
+
+ op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
+ op_win32 = op->priv->platform_data;
+ plug = g_object_new(GTK_TYPE_WIDGET, NULL);
+
+ SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
+
+ gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
+ op_win32->embed_widget = plug;
+ gtk_box_append (GTK_BOX (plug), op->priv->custom_widget);
+ gtk_widget_set_visible (op->priv->custom_widget, TRUE);
+ gtk_widget_set_visible (plug, TRUE);
+
+ /* This dialog is modal, so we grab the embed widget */
+ gtk_grab_add (plug);
+ return FALSE;
+ }
+ else if (message == WM_DESTROY)
+ {
+ op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
+ op_win32 = op->priv->platform_data;
+
+ g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
+ g_object_unref (g_object_ref_sink (op_win32->embed_widget));
+ op_win32->embed_widget = NULL;
+ op->priv->custom_widget = NULL;
+ }
+ else
+ {
+ op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
+ op_win32 = op->priv->platform_data;
+
+ /* TODO: We don't have GtkWin32EmbedWidgets anymore, but it is not currently clear
+ * at this point what will be the proper replacement for this. For now,
+ * do the message handling that was in _gtk_win32_embed_widget_dialog_procedure ()
+ * here and fill in the rest when things become clearer.
+ */
+ if (message == WM_SIZE)
+ {
+ gtk_widget_queue_resize (op_win32->embed_widget);
+ }
+
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+static HPROPSHEETPAGE
+create_application_page (GtkPrintOperation *op)
+{
+ HPROPSHEETPAGE hpage;
+ PROPSHEETPAGEW page;
+ DLGTEMPLATE *template;
+ HGLOBAL htemplate;
+ LONG base_units;
+ WORD baseunitX, baseunitY;
+ WORD *array;
+ GtkRequisition requisition;
+ const char *tab_label;
+
+ /* Make the template the size of the custom widget size request */
+ gtk_widget_get_preferred_size (op->priv->custom_widget,
+ &requisition, NULL);
+
+ base_units = GetDialogBaseUnits ();
+ baseunitX = LOWORD (base_units);
+ baseunitY = HIWORD (base_units);
+
+ htemplate = GlobalAlloc (GMEM_MOVEABLE,
+ sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
+ template = GlobalLock (htemplate);
+ template->style = WS_CHILDWINDOW | DS_CONTROL;
+ template->dwExtendedStyle = WS_EX_CONTROLPARENT;
+ template->cdit = 0;
+ template->x = MulDiv (0, 4, baseunitX);
+ template->y = MulDiv (0, 8, baseunitY);
+ template->cx = MulDiv (requisition.width, 4, baseunitX);
+ template->cy = MulDiv (requisition.height, 8, baseunitY);
+
+ array = (WORD *) (template+1);
+ *array++ = 0; /* menu */
+ *array++ = 0; /* class */
+ *array++ = 0; /* title */
+
+ memset (&page, 0, sizeof (page));
+ page.dwSize = sizeof (page);
+ page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
+ page.hInstance = NULL;
+ page.pResource = template;
+
+ tab_label = op->priv->custom_tab_label;
+ if (tab_label == NULL)
+ tab_label = g_get_application_name ();
+ if (tab_label == NULL)
+ tab_label = _("Application");
+ page.pszTitle = g_utf8_to_utf16 (tab_label,
+ -1, NULL, NULL, NULL);
+ page.pfnDlgProc = pageDlgProc;
+ page.pfnCallback = NULL;
+ page.lParam = (LPARAM) op;
+ hpage = CreatePropertySheetPageW (&page);
+
+ GlobalUnlock (htemplate);
+
+ /* TODO: We're leaking htemplate here... */
+
+ return hpage;
+}
+
+static GtkPageSetup *
+create_page_setup (GtkPrintOperation *op)
+{
+ GtkPrintOperationPrivate *priv = op->priv;
+ GtkPageSetup *page_setup;
+ GtkPrintSettings *settings;
+
+ if (priv->default_page_setup)
+ page_setup = gtk_page_setup_copy (priv->default_page_setup);
+ else
+ page_setup = gtk_page_setup_new ();
+
+ settings = priv->print_settings;
+ if (settings)
+ {
+ GtkPaperSize *paper_size;
+
+ if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
+ gtk_page_setup_set_orientation (page_setup,
+ gtk_print_settings_get_orientation (settings));
+
+
+ paper_size = gtk_print_settings_get_paper_size (settings);
+ if (paper_size)
+ {
+ gtk_page_setup_set_paper_size (page_setup, paper_size);
+ gtk_paper_size_free (paper_size);
+ }
+
+ /* TODO: Margins? */
+ }
+
+ return page_setup;
+}
+
+GtkPrintOperationResult
+gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
+ gboolean *do_print)
+{
+ GtkPrintOperationResult result;
+ GtkPrintOperationWin32 *op_win32;
+ GtkPrintOperationPrivate *priv;
+ GtkPrintSettings *settings;
+ GtkPageSetup *page_setup;
+ DOCINFOW docinfo;
+ HGLOBAL hDevMode = NULL;
+ HGLOBAL hDevNames = NULL;
+ HDC hDC = NULL;
+ const char *printer = NULL;
+ double dpi_x, dpi_y;
+ int job_id;
+ cairo_t *cr;
+ DEVNAMES *pdn;
+ DEVMODEW *pdm;
+
+ *do_print = FALSE;
+
+ priv = op->priv;
+ settings = priv->print_settings;
+
+ op_win32 = g_new0 (GtkPrintOperationWin32, 1);
+ priv->platform_data = op_win32;
+ priv->free_platform_data = (GDestroyNotify) op_win32_free;
+ printer = gtk_print_settings_get_printer (settings);
+
+ if (!printer)
+ {
+ /* No printer selected. Get the system default printer and store
+ * it in settings.
+ */
+ char *tmp_printer = get_default_printer ();
+ if (!tmp_printer)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_INTERNAL_ERROR,
+ _("No printer found"));
+ goto out;
+ }
+ gtk_print_settings_set_printer (settings, tmp_printer);
+ printer = gtk_print_settings_get_printer (settings);
+ g_free (tmp_printer);
+ }
+
+ hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
+ hDevMode = devmode_from_settings (settings, op->priv->default_page_setup, NULL);
+
+ /* Create a printer DC for the print settings and page setup provided. */
+ pdn = GlobalLock (hDevNames);
+ pdm = GlobalLock (hDevMode);
+ hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
+ (wchar_t*)pdn + pdn->wDeviceOffset,
+ (wchar_t*)pdn + pdn->wOutputOffset,
+ pdm );
+ GlobalUnlock (hDevNames);
+ GlobalUnlock (hDevMode);
+
+ if (!hDC)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_INTERNAL_ERROR,
+ _("Invalid argument to CreateDC"));
+ goto out;
+ }
+
+ priv->print_context = _gtk_print_context_new (op);
+ page_setup = create_page_setup (op);
+ _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+ g_object_unref (page_setup);
+
+ *do_print = TRUE;
+
+ op_win32->surface = cairo_win32_printing_surface_create (hDC);
+ dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
+ dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
+
+ cr = cairo_create (op_win32->surface);
+ gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
+ cairo_destroy (cr);
+
+ set_hard_margins (op);
+
+ memset (&docinfo, 0, sizeof (DOCINFOW));
+ docinfo.cbSize = sizeof (DOCINFOW);
+ docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
+ docinfo.lpszOutput = NULL;
+ docinfo.lpszDatatype = NULL;
+ docinfo.fwType = 0;
+
+ job_id = StartDocW (hDC, &docinfo);
+ g_free ((void *)docinfo.lpszDocName);
+ if (job_id <= 0)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_GENERAL,
+ _("Error from StartDoc"));
+ *do_print = FALSE;
+ cairo_surface_destroy (op_win32->surface);
+ op_win32->surface = NULL;
+ goto out;
+ }
+
+ result = GTK_PRINT_OPERATION_RESULT_APPLY;
+ op_win32->hdc = hDC;
+ op_win32->devmode = hDevMode;
+ op_win32->devnames = hDevNames;
+ op_win32->job_id = job_id;
+ op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
+ op->priv->num_page_ranges = 0;
+ if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
+ op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
+ &op->priv->num_page_ranges);
+ op->priv->manual_num_copies = 1;
+ op->priv->manual_collation = FALSE;
+ op->priv->manual_reverse = FALSE;
+ op->priv->manual_orientation = FALSE;
+ op->priv->manual_scale = 1.0;
+ op->priv->manual_page_set = GTK_PAGE_SET_ALL;
+ op->priv->manual_number_up = 1;
+ op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+
+ op->priv->start_page = win32_start_page;
+ op->priv->end_page = win32_end_page;
+ op->priv->end_run = win32_end_run;
+
+ out:
+ if (!*do_print && hDC != NULL)
+ DeleteDC (hDC);
+
+ if (!*do_print && hDevMode != NULL)
+ GlobalFree (hDevMode);
+
+ if (!*do_print && hDevNames != NULL)
+ GlobalFree (hDevNames);
+
+ return result;
+}
+
+GtkPrintOperationResult
+gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
+ GtkWindow *parent,
+ gboolean *do_print)
+{
+ HRESULT hResult;
+ LPPRINTDLGEXW printdlgex = NULL;
+ LPPRINTPAGERANGE page_ranges = NULL;
+ HWND parentHWnd;
+ GtkWidget *invisible = NULL;
+ GtkPrintOperationResult result;
+ GtkPrintOperationWin32 *op_win32;
+ GtkPrintOperationPrivate *priv;
+ IPrintDialogCallback *callback;
+ HPROPSHEETPAGE prop_page;
+ static gsize common_controls_initialized = 0;
+
+ if (g_once_init_enter (&common_controls_initialized))
+ {
+ BOOL initialized;
+ INITCOMMONCONTROLSEX icc;
+
+ memset (&icc, 0, sizeof (icc));
+ icc.dwSize = sizeof (icc);
+ icc.dwICC = ICC_WIN95_CLASSES;
+
+ initialized = InitCommonControlsEx (&icc);
+ if (!initialized)
+ g_warning ("Failed to InitCommonControlsEx: %lu", GetLastError ());
+
+ _gtk_load_dll_with_libgtk3_manifest ("comdlg32.dll");
+
+ g_once_init_leave (&common_controls_initialized, initialized ? 1 : 0);
+ }
+
+ *do_print = FALSE;
+
+ priv = op->priv;
+
+ op_win32 = g_new0 (GtkPrintOperationWin32, 1);
+ priv->platform_data = op_win32;
+ priv->free_platform_data = (GDestroyNotify) op_win32_free;
+
+ if (parent == NULL)
+ {
+ invisible = gtk_window_new ();
+ parentHWnd = get_parent_hwnd (invisible);
+ }
+ else
+ parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
+
+ printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
+ if (!printdlgex)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_NOMEM,
+ _("Not enough free memory"));
+ goto out;
+ }
+
+ printdlgex->lStructSize = sizeof (PRINTDLGEXW);
+ printdlgex->hwndOwner = parentHWnd;
+ printdlgex->hDevMode = NULL;
+ printdlgex->hDevNames = NULL;
+ printdlgex->hDC = NULL;
+ printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
+ if (op->priv->current_page == -1)
+ printdlgex->Flags |= PD_NOCURRENTPAGE;
+ printdlgex->Flags2 = 0;
+ printdlgex->ExclusionFlags = 0;
+
+ page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR,
+ MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
+ if (!page_ranges)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_NOMEM,
+ _("Not enough free memory"));
+ goto out;
+ }
+
+ printdlgex->nPageRanges = 0;
+ printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
+ printdlgex->lpPageRanges = page_ranges;
+ printdlgex->nMinPage = 1;
+ if (op->priv->nr_of_pages != -1)
+ printdlgex->nMaxPage = op->priv->nr_of_pages;
+ else
+ printdlgex->nMaxPage = 10000;
+ printdlgex->nCopies = 1;
+ printdlgex->hInstance = 0;
+ printdlgex->lpPrintTemplateName = NULL;
+ printdlgex->lpCallback = NULL;
+
+ g_signal_emit_by_name (op, "create-custom-widget",
+ &op->priv->custom_widget);
+ if (op->priv->custom_widget) {
+ prop_page = create_application_page (op);
+ printdlgex->nPropertyPages = 1;
+ printdlgex->lphPropertyPages = &prop_page;
+ } else {
+ printdlgex->nPropertyPages = 0;
+ printdlgex->lphPropertyPages = NULL;
+ }
+
+ printdlgex->nStartPage = START_PAGE_GENERAL;
+ printdlgex->dwResultAction = 0;
+
+ dialog_from_print_settings (op, printdlgex);
+
+ callback = print_callback_new ();
+ printdlgex->lpCallback = (IUnknown *)callback;
+ got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
+
+ hResult = PrintDlgExW (printdlgex);
+ IUnknown_Release ((IUnknown *)callback);
+ gdk_win32_set_modal_dialog_libgtk_only (NULL);
+
+ if (hResult != S_OK)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ if (hResult == E_OUTOFMEMORY)
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_NOMEM,
+ _("Not enough free memory"));
+ else if (hResult == E_INVALIDARG)
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_INTERNAL_ERROR,
+ _("Invalid argument to PrintDlgEx"));
+ else if (hResult == E_POINTER)
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_INTERNAL_ERROR,
+ _("Invalid pointer to PrintDlgEx"));
+ else if (hResult == E_HANDLE)
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_INTERNAL_ERROR,
+ _("Invalid handle to PrintDlgEx"));
+ else /* E_FAIL */
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_GENERAL,
+ _("Unspecified error"));
+ goto out;
+ }
+
+ if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
+ printdlgex->dwResultAction == PD_RESULT_APPLY)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_APPLY;
+ dialog_to_print_settings (op, printdlgex);
+ }
+ else
+ result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+
+ if (printdlgex->dwResultAction == PD_RESULT_PRINT)
+ {
+ DOCINFOW docinfo;
+ int job_id;
+ double dpi_x, dpi_y;
+ cairo_t *cr;
+ GtkPageSetup *page_setup;
+
+ priv->print_context = _gtk_print_context_new (op);
+ page_setup = create_page_setup (op);
+ _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+ g_object_unref (page_setup);
+
+ *do_print = TRUE;
+
+ op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
+
+ dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
+ dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
+
+ cr = cairo_create (op_win32->surface);
+ gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
+ cairo_destroy (cr);
+
+ set_hard_margins (op);
+
+ memset ( &docinfo, 0, sizeof (DOCINFOW));
+ docinfo.cbSize = sizeof (DOCINFOW);
+ docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
+ docinfo.lpszOutput = (LPCWSTR) NULL;
+ docinfo.lpszDatatype = (LPCWSTR) NULL;
+ docinfo.fwType = 0;
+
+ job_id = StartDocW (printdlgex->hDC, &docinfo);
+ g_free ((void *)docinfo.lpszDocName);
+ if (job_id <= 0)
+ {
+ result = GTK_PRINT_OPERATION_RESULT_ERROR;
+ g_set_error_literal (&priv->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_GENERAL,
+ _("Error from StartDoc"));
+ *do_print = FALSE;
+ cairo_surface_destroy (op_win32->surface);
+ op_win32->surface = NULL;
+ goto out;
+ }
+
+ op_win32->hdc = printdlgex->hDC;
+ op_win32->devmode = printdlgex->hDevMode;
+ op_win32->devnames = printdlgex->hDevNames;
+ op_win32->job_id = job_id;
+
+ op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
+ op->priv->num_page_ranges = 0;
+ if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
+ op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
+ &op->priv->num_page_ranges);
+ op->priv->manual_num_copies = printdlgex->nCopies;
+ op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
+ op->priv->manual_reverse = FALSE;
+ op->priv->manual_orientation = FALSE;
+ op->priv->manual_scale = 1.0;
+ op->priv->manual_page_set = GTK_PAGE_SET_ALL;
+ op->priv->manual_number_up = 1;
+ op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+ }
+
+ op->priv->start_page = win32_start_page;
+ op->priv->end_page = win32_end_page;
+ op->priv->end_run = win32_end_run;
+
+ out:
+ if (!*do_print && printdlgex && printdlgex->hDC != NULL)
+ DeleteDC (printdlgex->hDC);
+
+ if (!*do_print && printdlgex && printdlgex->hDevMode != NULL)
+ GlobalFree (printdlgex->hDevMode);
+
+ if (!*do_print && printdlgex && printdlgex->hDevNames != NULL)
+ GlobalFree (printdlgex->hDevNames);
+
+ if (page_ranges)
+ GlobalFree (page_ranges);
+
+ if (printdlgex)
+ GlobalFree (printdlgex);
+
+ if (invisible)
+ gtk_window_destroy (GTK_WINDOW (invisible));
+
+ return result;
+}
+
+GtkPrintOperationResult
+_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
+ gboolean show_dialog,
+ GtkWindow *parent,
+ gboolean *do_print)
+{
+ if (show_dialog)
+ return gtk_print_operation_run_with_dialog (op, parent, do_print);
+ else
+ return gtk_print_operation_run_without_dialog (op, do_print);
+}
+
+void
+_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ GtkWindow *parent,
+ const char *filename)
+{
+ HDC dc;
+ HENHMETAFILE metafile;
+
+ dc = cairo_win32_surface_get_dc (surface);
+ cairo_surface_destroy (surface);
+ metafile = CloseEnhMetaFile (dc);
+ DeleteEnhMetaFile (metafile);
+
+ ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr)
+{
+ HDC dc = cairo_win32_surface_get_dc (surface);
+ StartPage (dc);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
+ cairo_surface_t *surface,
+ cairo_t *cr)
+{
+ HDC dc;
+
+ cairo_surface_show_page (surface);
+
+ /* TODO: Enhanced metafiles don't support multiple pages.
+ */
+ dc = cairo_win32_surface_get_dc (surface);
+ EndPage (dc);
+}
+
+cairo_surface_t *
+_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ double *dpi_x,
+ double *dpi_y,
+ char **target)
+{
+ GtkPaperSize *paper_size;
+ HDC metafile_dc;
+ RECT rect;
+ char *template;
+ char *filename;
+ gunichar2 *filename_utf16;
+ int fd;
+
+ template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
+ fd = g_mkstemp (template);
+ close (fd);
+
+ filename = g_strconcat (template, ".emf", NULL);
+ g_free (template);
+
+ filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+ g_free (filename);
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+
+ /* The rectangle dimensions are given in hundredths of a millimeter */
+ rect.left = 0;
+ rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
+ rect.top = 0;
+ rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
+
+ metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
+ &rect, L"Gtk+\0Print Preview\0\0");
+ if (metafile_dc == NULL)
+ {
+ g_warning ("Can't create metafile");
+ return NULL;
+ }
+
+ *target = (char *)filename_utf16;
+
+ *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
+ *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
+
+ return cairo_win32_printing_surface_create (metafile_dc);
+}
+
+void
+_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
+ GtkPageSetup *page_setup,
+ cairo_surface_t *surface)
+{
+ /* TODO: Implement */
+}
+
+/**
+ * gtk_print_run_page_setup_dialog:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ *
+ * Runs a page setup dialog, letting the user modify the values from
+ * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
+ * is identical to the passed in @page_setup, otherwise it contains the
+ * modifications done in the dialog.
+ *
+ * Note that this function may use a recursive mainloop to show the page
+ * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
+ * a problem.
+ *
+ * Returns: (transfer full): a new `GtkPageSetup`
+ */
+GtkPageSetup *
+gtk_print_run_page_setup_dialog (GtkWindow *parent,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings)
+{
+ LPPAGESETUPDLGW pagesetupdlg = NULL;
+ BOOL res;
+ gboolean free_settings;
+ const char *printer;
+ GtkPaperSize *paper_size;
+ DWORD measure_system;
+ GtkUnit unit;
+ double scale;
+
+ pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
+ if (!pagesetupdlg)
+ return NULL;
+
+ free_settings = FALSE;
+ if (settings == NULL)
+ {
+ settings = gtk_print_settings_new ();
+ free_settings = TRUE;
+ }
+
+ memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
+
+ pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
+
+ if (parent != NULL)
+ pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
+ else
+ pagesetupdlg->hwndOwner = NULL;
+
+ pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
+ pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup, NULL);
+ pagesetupdlg->hDevNames = NULL;
+ printer = gtk_print_settings_get_printer (settings);
+ if (printer)
+ pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
+
+ GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
+ (LPWSTR)&measure_system, sizeof (DWORD));
+
+ if (measure_system == 0)
+ {
+ pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
+ unit = GTK_UNIT_MM;
+ scale = 100;
+ }
+ else
+ {
+ pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
+ unit = GTK_UNIT_INCH;
+ scale = 1000;
+ }
+
+ /* This is the object we return, we allocate it here so that
+ * we can use the default page margins */
+ if (page_setup)
+ page_setup = gtk_page_setup_copy (page_setup);
+ else
+ page_setup = gtk_page_setup_new ();
+
+ pagesetupdlg->Flags |= PSD_MARGINS;
+ pagesetupdlg->rtMargin.left =
+ floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
+ pagesetupdlg->rtMargin.right =
+ floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
+ pagesetupdlg->rtMargin.top =
+ floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
+ pagesetupdlg->rtMargin.bottom =
+ floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
+
+ pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
+ pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
+ got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
+
+ res = PageSetupDlgW (pagesetupdlg);
+ gdk_win32_set_modal_dialog_libgtk_only (NULL);
+
+ if (res)
+ {
+ if (pagesetupdlg->hDevNames != NULL)
+ devnames_to_settings (settings, pagesetupdlg->hDevNames);
+
+ if (pagesetupdlg->hDevMode != NULL)
+ devmode_to_settings (settings, pagesetupdlg->hDevMode);
+ }
+
+ if (res)
+ {
+ gtk_page_setup_set_orientation (page_setup,
+ gtk_print_settings_get_orientation (settings));
+ paper_size = gtk_print_settings_get_paper_size (settings);
+ if (paper_size)
+ {
+ gtk_page_setup_set_paper_size (page_setup, paper_size);
+ gtk_paper_size_free (paper_size);
+ }
+
+ if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
+ {
+ unit = GTK_UNIT_MM;
+ scale = 100;
+ }
+ else
+ {
+ unit = GTK_UNIT_INCH;
+ scale = 1000;
+ }
+
+ gtk_page_setup_set_left_margin (page_setup,
+ pagesetupdlg->rtMargin.left / scale,
+ unit);
+ gtk_page_setup_set_right_margin (page_setup,
+ pagesetupdlg->rtMargin.right / scale,
+ unit);
+ gtk_page_setup_set_top_margin (page_setup,
+ pagesetupdlg->rtMargin.top / scale,
+ unit);
+ gtk_page_setup_set_bottom_margin (page_setup,
+ pagesetupdlg->rtMargin.bottom / scale,
+ unit);
+ }
+
+ if (free_settings)
+ g_object_unref (settings);
+
+ return page_setup;
+}
+
+/**
+ * gtk_print_run_page_setup_dialog_async:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ * @done_cb: (scope async): a function to call when the user saves
+ * the modified page setup
+ * @data: user data to pass to @done_cb
+ *
+ * Runs a page setup dialog, letting the user modify the values from @page_setup.
+ *
+ * In contrast to gtk_print_run_page_setup_dialog(), this function returns after
+ * showing the page setup dialog on platforms that support this, and calls @done_cb
+ * from a signal handler for the ::response signal of the dialog.
+ */
+void
+gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
+ GtkPageSetup *page_setup,
+ GtkPrintSettings *settings,
+ GtkPageSetupDoneFunc done_cb,
+ gpointer data)
+{
+ GtkPageSetup *new_page_setup;
+
+ new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
+ done_cb (new_page_setup, data);
+ g_object_unref (new_page_setup);
+}
--- /dev/null
+/* GtkPrintUnixDialog
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ * Copyright © 2006, 2007 Christian Persch
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "gtkprintunixdialog.h"
+
+#include "gtkcustompaperunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprinterprivate.h"
+#include "gtkprinteroptionwidgetprivate.h"
+#include "gtkprintutilsprivate.h"
+
+#include "gtkspinbutton.h"
+#include "gtkimage.h"
+#include "gtknotebook.h"
+#include "gtkscrolledwindow.h"
+#include "gtktogglebutton.h"
+#include "gtkdrawingarea.h"
+#include "gtkbox.h"
+#include "gtkgrid.h"
+#include "gtkframe.h"
+#include "gtklabel.h"
+#include "gtkbuildable.h"
+#include "deprecated/gtkmessagedialog.h"
+#include "gtkbutton.h"
+#include "gtksnapshot.h"
+#include "gtkrenderbackgroundprivate.h"
+#include "gtkrenderborderprivate.h"
+#include <glib/gi18n-lib.h>
+#include "gtkprivate.h"
+#include "gtktypebuiltins.h"
+#include "deprecated/gtkdialogprivate.h"
+#include "gtkwidgetprivate.h"
+#include "gtkcsscolorvalueprivate.h"
+
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+/**
+ * GtkPrintUnixDialog:
+ *
+ * `GtkPrintUnixDialog` implements a print dialog for platforms
+ * which don’t provide a native print dialog, like Unix.
+ *
+ * 
+ *
+ * It can be used very much like any other GTK dialog, at the cost of
+ * the portability offered by the high-level printing API with
+ * [class@Gtk.PrintOperation].
+ *
+ * In order to print something with `GtkPrintUnixDialog`, you need to
+ * use [method@Gtk.PrintUnixDialog.get_selected_printer] to obtain a
+ * [class@Gtk.Printer] object and use it to construct a [class@Gtk.PrintJob]
+ * using [ctor@Gtk.PrintJob.new].
+ *
+ * `GtkPrintUnixDialog` uses the following response values:
+ *
+ * - %GTK_RESPONSE_OK: for the “Print” button
+ * - %GTK_RESPONSE_APPLY: for the “Preview” button
+ * - %GTK_RESPONSE_CANCEL: for the “Cancel” button
+ *
+ * # GtkPrintUnixDialog as GtkBuildable
+ *
+ * The `GtkPrintUnixDialog` implementation of the `GtkBuildable` interface
+ * exposes its @notebook internal children with the name “notebook”.
+ *
+ * An example of a `GtkPrintUnixDialog` UI definition fragment:
+ *
+ * ```xml
+ * <object class="GtkPrintUnixDialog" id="dialog1">
+ * <child internal-child="notebook">
+ * <object class="GtkNotebook" id="notebook">
+ * <child>
+ * <object type="GtkNotebookPage">
+ * <property name="tab_expand">False</property>
+ * <property name="tab_fill">False</property>
+ * <property name="tab">
+ * <object class="GtkLabel" id="tablabel">
+ * <property name="label">Tab label</property>
+ * </object>
+ * </property>
+ * <property name="child">
+ * <object class="GtkLabel" id="tabcontent">
+ * <property name="label">Content on notebook tab</property>
+ * </object>
+ * </property>
+ * </object>
+ * </child>
+ * </object>
+ * </child>
+ * </object>
+ * ```
+ *
+ * # CSS nodes
+ *
+ * `GtkPrintUnixDialog` has a single CSS node with name window. The style classes
+ * dialog and print are added.
+ */
+
+
+#define EXAMPLE_PAGE_AREA_SIZE 110
+#define RULER_DISTANCE 7.5
+#define RULER_RADIUS 2
+
+
+static void gtk_print_unix_dialog_constructed (GObject *object);
+static void gtk_print_unix_dialog_dispose (GObject *object);
+static void gtk_print_unix_dialog_finalize (GObject *object);
+static void gtk_print_unix_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_print_unix_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog);
+static void selected_printer_changed (GtkPrintUnixDialog *dialog);
+static void clear_per_printer_ui (GtkPrintUnixDialog *dialog);
+static void printer_added_cb (GListModel *model,
+ guint position,
+ guint removed,
+ guint added,
+ GtkPrintUnixDialog *dialog);
+static void printer_status_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPrintUnixDialog *dialog);
+static void update_collate_icon (GtkToggleButton *toggle_button,
+ GtkPrintUnixDialog *dialog);
+static void error_dialogs (GtkPrintUnixDialog *print_dialog,
+ int print_dialog_response_id,
+ gpointer data);
+static gboolean page_range_entry_focus_changed (GtkWidget *entry,
+ GParamSpec *pspec,
+ GtkPrintUnixDialog *dialog);
+static void update_page_range_entry_sensitivity(GtkWidget *button,
+ GtkPrintUnixDialog *dialog);
+static void update_print_at_entry_sensitivity (GtkWidget *button,
+ GtkPrintUnixDialog *dialog);
+static void update_print_at_option (GtkPrintUnixDialog *dialog);
+static void update_dialog_from_capabilities (GtkPrintUnixDialog *dialog);
+static void draw_collate (GtkDrawingArea *da,
+ cairo_t *cr,
+ int width,
+ int height,
+ gpointer data);
+static gboolean is_printer_active (gpointer item,
+ gpointer data);
+static int default_printer_list_sort_func (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data);
+static void update_number_up_layout (GtkPrintUnixDialog *dialog);
+static void draw_page (GtkDrawingArea *da,
+ cairo_t *cr,
+ int width,
+ int height,
+ gpointer data);
+
+
+static gboolean dialog_get_collate (GtkPrintUnixDialog *dialog);
+static gboolean dialog_get_reverse (GtkPrintUnixDialog *dialog);
+static int dialog_get_n_copies (GtkPrintUnixDialog *dialog);
+
+static gboolean set_active_printer (GtkPrintUnixDialog *dialog,
+ const char *printer_name);
+static void redraw_page_layout_preview (GtkPrintUnixDialog *dialog);
+static GListModel *load_print_backends (GtkPrintUnixDialog *dialog);
+
+/* GtkBuildable */
+static void gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface);
+static GObject *gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ const char *childname);
+
+static const char common_paper_sizes[][16] = {
+ "na_letter",
+ "na_legal",
+ "iso_a4",
+ "iso_a5",
+ "roc_16k",
+ "iso_b5",
+ "jis_b5",
+ "na_number-10",
+ "iso_dl",
+ "jpn_chou3",
+ "na_ledger",
+ "iso_a3",
+};
+
+/* Keep in line with liststore defined in gtkprintunixdialog.ui */
+enum {
+ PAGE_SETUP_LIST_COL_PAGE_SETUP,
+ PAGE_SETUP_LIST_COL_IS_SEPARATOR,
+ PAGE_SETUP_LIST_N_COLS
+};
+
+/* Keep in line with liststore defined in gtkprintunixdialog.ui */
+enum {
+ PRINTER_LIST_COL_ICON,
+ PRINTER_LIST_COL_NAME,
+ PRINTER_LIST_COL_STATE,
+ PRINTER_LIST_COL_JOBS,
+ PRINTER_LIST_COL_LOCATION,
+ PRINTER_LIST_COL_PRINTER_OBJ,
+ PRINTER_LIST_N_COLS
+};
+
+enum {
+ PROP_0,
+ PROP_PAGE_SETUP,
+ PROP_CURRENT_PAGE,
+ PROP_PRINT_SETTINGS,
+ PROP_SELECTED_PRINTER,
+ PROP_MANUAL_CAPABILITIES,
+ PROP_SUPPORT_SELECTION,
+ PROP_HAS_SELECTION,
+ PROP_EMBED_PAGE_SETUP
+};
+
+typedef struct _GtkPrintUnixDialogClass GtkPrintUnixDialogClass;
+
+struct _GtkPrintUnixDialog
+{
+ GtkDialog parent_instance;
+
+ GtkWidget *notebook;
+
+ GtkWidget *printer_list;
+
+ GtkPrintCapabilities manual_capabilities;
+ GtkPrintCapabilities printer_capabilities;
+
+ GtkPageSetup *page_setup;
+ gboolean page_setup_set;
+ gboolean embed_page_setup;
+ GListStore *page_setup_list;
+ GListStore *custom_paper_list;
+ GListStore *manage_papers_list;
+
+ gboolean support_selection;
+ gboolean has_selection;
+
+ GtkWidget *all_pages_radio;
+ GtkWidget *current_page_radio;
+ GtkWidget *selection_radio;
+ GtkWidget *range_table;
+ GtkWidget *page_range_radio;
+ GtkWidget *page_range_entry;
+
+ GtkWidget *copies_spin;
+ GtkWidget *collate_check;
+ GtkWidget *reverse_check;
+ GtkWidget *collate_image;
+ GtkWidget *page_layout_preview;
+ GtkWidget *scale_spin;
+ GtkWidget *page_set_combo;
+ GtkWidget *print_now_radio;
+ GtkWidget *print_at_radio;
+ GtkWidget *print_at_entry;
+ GtkWidget *print_hold_radio;
+ GtkWidget *paper_size_combo;
+ GtkWidget *orientation_combo;
+ gboolean internal_page_setup_change;
+ gboolean updating_print_at;
+ GtkPrinterOptionWidget *pages_per_sheet;
+ GtkPrinterOptionWidget *duplex;
+ GtkPrinterOptionWidget *paper_type;
+ GtkPrinterOptionWidget *paper_source;
+ GtkPrinterOptionWidget *output_tray;
+ GtkPrinterOptionWidget *job_prio;
+ GtkPrinterOptionWidget *billing_info;
+ GtkPrinterOptionWidget *cover_before;
+ GtkPrinterOptionWidget *cover_after;
+ GtkPrinterOptionWidget *number_up_layout;
+
+ GtkWidget *conflicts_widget;
+
+ GtkWidget *job_page;
+ GtkWidget *finishing_table;
+ GtkWidget *finishing_page;
+ GtkWidget *image_quality_table;
+ GtkWidget *image_quality_page;
+ GtkWidget *color_table;
+ GtkWidget *color_page;
+
+ GtkWidget *advanced_vbox;
+ GtkWidget *advanced_page;
+
+ GtkWidget *extension_point;
+
+ /* These are set initially on selected printer (either default printer,
+ * printer taken from set settings, or user-selected), but when any
+ * setting is changed by the user it is cleared.
+ */
+ GtkPrintSettings *initial_settings;
+
+ GtkPrinterOption *number_up_layout_n_option;
+ GtkPrinterOption *number_up_layout_2_option;
+
+ /* This is the initial printer set by set_settings. We look for it in
+ * the added printers. We clear this whenever the user manually changes
+ * to another printer, when the user changes a setting or when we find
+ * this printer.
+ */
+ char *waiting_for_printer;
+ gboolean internal_printer_change;
+
+ GList *print_backends;
+
+ GtkPrinter *current_printer;
+ GtkPrinter *request_details_printer;
+ gulong request_details_tag;
+ GtkPrinterOptionSet *options;
+ gulong options_changed_handler;
+ gulong mark_conflicts_id;
+
+ char *format_for_printer;
+
+ int current_page;
+ GtkCssNode *collate_paper_node;
+ GtkCssNode *page_layout_paper_node;
+};
+
+struct _GtkPrintUnixDialogClass
+{
+ GtkDialogClass parent_class;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ gtk_print_unix_dialog_buildable_init))
+
+static GtkBuildableIface *parent_buildable_iface;
+
+static gboolean
+is_default_printer (GtkPrintUnixDialog *dialog,
+ GtkPrinter *printer)
+{
+ if (dialog->format_for_printer)
+ return strcmp (dialog->format_for_printer,
+ gtk_printer_get_name (printer)) == 0;
+ else
+ return gtk_printer_is_default (printer);
+}
+
+static void
+gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+
+ object_class->constructed = gtk_print_unix_dialog_constructed;
+ object_class->finalize = gtk_print_unix_dialog_finalize;
+ object_class->dispose = gtk_print_unix_dialog_dispose;
+ object_class->set_property = gtk_print_unix_dialog_set_property;
+ object_class->get_property = gtk_print_unix_dialog_get_property;
+
+ /**
+ * GtkPrintUnixDialog:page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_page_setup)
+ *
+ * The `GtkPageSetup` object to use.
+ */
+ g_object_class_install_property (object_class,
+ PROP_PAGE_SETUP,
+ g_param_spec_object ("page-setup", NULL, NULL,
+ GTK_TYPE_PAGE_SETUP,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkPrintUnixDialog:current-page: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_current_page org.gtk.Property.set=gtk_print_unix_dialog_set_current_page)
+ *
+ * The current page in the document.
+ */
+ g_object_class_install_property (object_class,
+ PROP_CURRENT_PAGE,
+ g_param_spec_int ("current-page", NULL, NULL,
+ -1,
+ G_MAXINT,
+ -1,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkPrintUnixDialog:print-settings: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_settings org.gtk.Property.set=gtk_print_unix_dialog_set_settings)
+ *
+ * The `GtkPrintSettings` object used for this dialog.
+ */
+ g_object_class_install_property (object_class,
+ PROP_PRINT_SETTINGS,
+ g_param_spec_object ("print-settings", NULL, NULL,
+ GTK_TYPE_PRINT_SETTINGS,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkPrintUnixDialog:selected-printer: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_selected_printer)
+ *
+ * The `GtkPrinter` which is selected.
+ */
+ g_object_class_install_property (object_class,
+ PROP_SELECTED_PRINTER,
+ g_param_spec_object ("selected-printer", NULL, NULL,
+ GTK_TYPE_PRINTER,
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkPrintUnixDialog:manual-capabilities: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_manual_capabilities org.gtk.Property.set=gtk_print_unix_dialog_set_manual_capabilities)
+ *
+ * Capabilities the application can handle.
+ */
+ g_object_class_install_property (object_class,
+ PROP_MANUAL_CAPABILITIES,
+ g_param_spec_flags ("manual-capabilities", NULL, NULL,
+ GTK_TYPE_PRINT_CAPABILITIES,
+ 0,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkPrintUnixDialog:support-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_support_selection org.gtk.Property.set=gtk_print_unix_dialog_set_support_selection)
+ *
+ * Whether the dialog supports selection.
+ */
+ g_object_class_install_property (object_class,
+ PROP_SUPPORT_SELECTION,
+ g_param_spec_boolean ("support-selection", NULL, NULL,
+ FALSE,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkPrintUnixDialog:has-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_has_selection org.gtk.Property.set=gtk_print_unix_dialog_set_has_selection)
+ *
+ * Whether the application has a selection.
+ */
+ g_object_class_install_property (object_class,
+ PROP_HAS_SELECTION,
+ g_param_spec_boolean ("has-selection", NULL, NULL,
+ FALSE,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkPrintUnixDialog:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_embed_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_embed_page_setup)
+ *
+ * %TRUE if the page setup controls are embedded.
+ */
+ g_object_class_install_property (object_class,
+ PROP_EMBED_PAGE_SETUP,
+ g_param_spec_boolean ("embed-page-setup", NULL, NULL,
+ FALSE,
+ GTK_PARAM_READWRITE));
+
+ /* Bind class to template
+ */
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gtk/libgtk/ui/gtkprintunixdialog.ui");
+
+ /* GtkTreeView / GtkTreeModel */
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, printer_list);
+
+ /* General Widgetry */
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, notebook);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, current_page_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, selection_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, range_table);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_entry);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, copies_spin);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_check);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, reverse_check);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_image);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_layout_preview);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, scale_spin);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_set_combo);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_now_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_entry);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_hold_radio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_size_combo);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, orientation_combo);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, conflicts_widget);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_page);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_table);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_page);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_table);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_page);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_table);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_page);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_vbox);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_page);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, extension_point);
+
+ /* GtkPrinterOptionWidgets... */
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, pages_per_sheet);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, duplex);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_type);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_source);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, output_tray);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_prio);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, billing_info);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_before);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_after);
+ gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, number_up_layout);
+
+ /* Callbacks handled in the UI */
+ gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
+ gtk_widget_class_bind_template_callback (widget_class, error_dialogs);
+ gtk_widget_class_bind_template_callback (widget_class, page_range_entry_focus_changed);
+ gtk_widget_class_bind_template_callback (widget_class, update_page_range_entry_sensitivity);
+ gtk_widget_class_bind_template_callback (widget_class, update_print_at_entry_sensitivity);
+ gtk_widget_class_bind_template_callback (widget_class, update_print_at_option);
+ gtk_widget_class_bind_template_callback (widget_class, update_dialog_from_capabilities);
+ gtk_widget_class_bind_template_callback (widget_class, update_collate_icon);
+ gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
+ gtk_widget_class_bind_template_callback (widget_class, update_number_up_layout);
+ gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
+}
+
+/* Returns a toplevel GtkWindow, or NULL if none */
+static GtkWindow *
+get_toplevel (GtkWidget *widget)
+{
+ GtkWidget *toplevel = NULL;
+
+ toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
+ if (GTK_IS_WINDOW (toplevel))
+ return GTK_WINDOW (toplevel);
+ else
+ return NULL;
+}
+
+static void
+set_busy_cursor (GtkPrintUnixDialog *dialog,
+ gboolean busy)
+{
+ GtkWidget *widget;
+ GtkWindow *toplevel;
+
+ toplevel = get_toplevel (GTK_WIDGET (dialog));
+ widget = GTK_WIDGET (toplevel);
+
+ if (!toplevel || !gtk_widget_get_realized (widget))
+ return;
+
+ if (busy)
+ gtk_widget_set_cursor_from_name (widget, "progress");
+ else
+ gtk_widget_set_cursor (widget, NULL);
+}
+
+typedef struct {
+ GMainLoop *loop;
+ int response;
+} ConfirmationData;
+
+static void
+on_confirmation_dialog_response (GtkWidget *dialog,
+ int response,
+ gpointer user_data)
+{
+ ConfirmationData *data = user_data;
+
+ data->response = response;
+
+ g_main_loop_quit (data->loop);
+
+ gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+/* This function handles error messages before printing.
+ */
+static void
+error_dialogs (GtkPrintUnixDialog *dialog,
+ int dialog_response_id,
+ gpointer data)
+{
+ if (dialog != NULL && dialog_response_id == GTK_RESPONSE_OK)
+ {
+ GtkPrinter *printer = gtk_print_unix_dialog_get_selected_printer (dialog);
+
+ if (printer != NULL)
+ {
+ if (dialog->request_details_tag || !gtk_printer_is_accepting_jobs (printer))
+ {
+ g_signal_stop_emission_by_name (dialog, "response");
+ return;
+ }
+
+ /* Shows overwrite confirmation dialog in the case of printing
+ * to file which already exists.
+ */
+ if (gtk_printer_is_virtual (printer))
+ {
+ GtkPrinterOption *option =
+ gtk_printer_option_set_lookup (dialog->options,
+ "gtk-main-page-custom-input");
+
+ if (option != NULL &&
+ option->type == GTK_PRINTER_OPTION_TYPE_FILESAVE)
+ {
+ GFile *file = g_file_new_for_uri (option->value);
+
+ if (g_file_query_exists (file, NULL))
+ {
+ GtkWidget *message_dialog;
+ GtkWindow *toplevel;
+ char *basename;
+ char *dirname;
+ GFile *parent;
+
+ toplevel = get_toplevel (GTK_WIDGET (dialog));
+
+ basename = g_file_get_basename (file);
+ parent = g_file_get_parent (file);
+ dirname = g_file_get_parse_name (parent);
+ g_object_unref (parent);
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ message_dialog = gtk_message_dialog_new (toplevel,
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("A file named “%s” already exists. Do you want to replace it?"),
+ basename);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
+ _("The file already exists in “%s”. Replacing it will "
+ "overwrite its contents."),
+ dirname);
+
+ gtk_dialog_add_button (GTK_DIALOG (message_dialog),
+ _("_Cancel"),
+ GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (message_dialog),
+ _("_Replace"),
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (message_dialog),
+ GTK_RESPONSE_ACCEPT);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ if (gtk_window_has_group (toplevel))
+ gtk_window_group_add_window (gtk_window_get_group (toplevel),
+ GTK_WINDOW (message_dialog));
+
+ gtk_window_present (GTK_WINDOW (message_dialog));
+
+ /* Block on the confirmation dialog until we have a response,
+ * so that we can stop the "response" signal emission on the
+ * print dialog
+ */
+ ConfirmationData cdata;
+
+ cdata.loop = g_main_loop_new (NULL, FALSE);
+ cdata.response = 0;
+
+ g_signal_connect (message_dialog, "response",
+ G_CALLBACK (on_confirmation_dialog_response),
+ &cdata);
+
+ g_main_loop_run (cdata.loop);
+ g_main_loop_unref (cdata.loop);
+
+ g_free (dirname);
+ g_free (basename);
+
+ if (cdata.response != GTK_RESPONSE_ACCEPT)
+ g_signal_stop_emission_by_name (dialog, "response");
+ }
+
+ g_object_unref (file);
+ }
+ }
+ }
+ }
+}
+
+static char *
+get_printer_key (GtkPrinter *printer)
+{
+ return g_strconcat ("", gtk_printer_get_name (printer), " ", gtk_printer_get_location (printer), NULL);
+}
+
+static void
+setup_paper_size_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new ("");
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_paper_size_list_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item,
+ GtkPrintUnixDialog *self)
+{
+ GtkPageSetup *page_setup;
+ GtkWidget *label;
+ guint pos;
+ GListModel *papers;
+ GListModel *model;
+ gpointer first;
+
+ page_setup = gtk_list_item_get_item (item);
+ label = gtk_list_item_get_child (item);
+
+ pos = gtk_list_item_get_position (item);
+ papers = gtk_drop_down_get_model (GTK_DROP_DOWN (self->paper_size_combo));
+ model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), pos);
+ if (model != G_LIST_MODEL (self->manage_papers_list))
+ {
+ GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
+ gtk_label_set_text (GTK_LABEL (label), gtk_paper_size_get_display_name (paper_size));
+ }
+ else
+ gtk_label_set_text (GTK_LABEL (label), _("Manage Custom Sizes…"));
+
+ first = g_list_model_get_item (model, 0);
+ g_object_unref (first);
+ if (pos != 0 &&
+ page_setup == GTK_PAGE_SETUP (first))
+ gtk_widget_add_css_class (gtk_widget_get_parent (label), "separator");
+ else
+ gtk_widget_remove_css_class (gtk_widget_get_parent (label), "separator");
+}
+
+static void
+bind_paper_size_item (GtkSignalListItemFactory *factory,
+ GtkListItem *item,
+ GtkPrintUnixDialog *self)
+{
+ GtkWidget *label;
+
+ bind_paper_size_list_item (factory, item, self);
+
+ label = gtk_list_item_get_child (item);
+ gtk_widget_remove_css_class (label, "separator-before");
+}
+
+static void
+gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog)
+{
+ GtkWidget *widget;
+ GListModel *model;
+ GListModel *sorted;
+ GListModel *filtered;
+ GListModel *selection;
+ GtkSorter *sorter;
+ GtkFilter *filter;
+ GtkStringFilter *filter1;
+ GtkCustomFilter *filter2;
+ GtkListItemFactory *factory;
+ GListStore *store;
+ GListModel *paper_size_list;
+ GtkPageSetup *page_setup;
+
+ dialog->print_backends = NULL;
+ dialog->current_page = -1;
+ dialog->number_up_layout_n_option = NULL;
+ dialog->number_up_layout_2_option = NULL;
+
+ dialog->page_setup = gtk_page_setup_new ();
+ dialog->page_setup_set = FALSE;
+ dialog->embed_page_setup = FALSE;
+ dialog->internal_page_setup_change = FALSE;
+ dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+ dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+ dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+ page_setup = gtk_page_setup_new ();
+ g_list_store_append (dialog->manage_papers_list, page_setup);
+ g_object_unref (page_setup);
+
+ dialog->support_selection = FALSE;
+ dialog->has_selection = FALSE;
+
+ g_type_ensure (GTK_TYPE_PRINTER);
+ g_type_ensure (GTK_TYPE_PRINTER_OPTION);
+ g_type_ensure (GTK_TYPE_PRINTER_OPTION_SET);
+ g_type_ensure (GTK_TYPE_PRINTER_OPTION_WIDGET);
+
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+ gtk_widget_add_css_class (GTK_WIDGET (dialog), "print");
+
+ gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("Pre_view"), GTK_RESPONSE_APPLY,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Print"), GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ widget = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ gtk_widget_set_visible (dialog->selection_radio, FALSE);
+ gtk_widget_set_visible (dialog->conflicts_widget, FALSE);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
+ gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+ g_object_unref (factory);
+
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
+ gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+ g_object_unref (factory);
+
+ store = g_list_store_new (G_TYPE_LIST_MODEL);
+ g_list_store_append (store, dialog->page_setup_list);
+ g_list_store_append (store, dialog->custom_paper_list);
+ g_list_store_append (store, dialog->manage_papers_list);
+ paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
+ gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
+ g_object_unref (paper_size_list);
+
+ /* Load backends */
+ model = load_print_backends (dialog);
+ sorter = GTK_SORTER (gtk_custom_sorter_new (default_printer_list_sort_func, NULL, NULL));
+ sorted = G_LIST_MODEL (gtk_sort_list_model_new (model, sorter));
+
+ filter = GTK_FILTER (gtk_every_filter_new ());
+
+ filter1 = gtk_string_filter_new (
+ gtk_cclosure_expression_new (G_TYPE_STRING,
+ NULL, 0, NULL,
+ G_CALLBACK (get_printer_key),
+ NULL, NULL));
+ gtk_string_filter_set_match_mode (filter1, GTK_STRING_FILTER_MATCH_MODE_SUBSTRING);
+ gtk_string_filter_set_ignore_case (filter1, TRUE);
+ gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter1));
+
+ filter2 = gtk_custom_filter_new (is_printer_active, dialog, NULL);
+ gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter2));
+
+ filtered = G_LIST_MODEL (gtk_filter_list_model_new (sorted, filter));
+
+ selection = G_LIST_MODEL (gtk_single_selection_new (filtered));
+ gtk_single_selection_set_autoselect (GTK_SINGLE_SELECTION (selection), FALSE);
+ gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (selection), GTK_INVALID_LIST_POSITION);
+ gtk_column_view_set_model (GTK_COLUMN_VIEW (dialog->printer_list), GTK_SELECTION_MODEL (selection));
+ g_signal_connect (selection, "items-changed", G_CALLBACK (printer_added_cb), dialog);
+ g_signal_connect_swapped (selection, "notify::selected", G_CALLBACK (selected_printer_changed), dialog);
+ g_object_unref (selection);
+
+ gtk_print_load_custom_papers (dialog->custom_paper_list);
+
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->collate_image),
+ draw_collate,
+ dialog, NULL);
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->page_layout_preview),
+ draw_page,
+ dialog, NULL);
+
+ gtk_css_node_set_name (gtk_widget_get_css_node (dialog->collate_image), g_quark_from_static_string ("drawing"));
+ gtk_css_node_set_name (gtk_widget_get_css_node (dialog->page_layout_preview), g_quark_from_static_string ("drawing"));
+
+ dialog->collate_paper_node = gtk_css_node_new();
+ gtk_css_node_set_name (dialog->collate_paper_node, g_quark_from_static_string ("paper"));
+ gtk_css_node_set_parent (dialog->collate_paper_node,
+ gtk_widget_get_css_node (dialog->collate_image));
+ g_object_unref (dialog->collate_paper_node);
+
+ dialog->page_layout_paper_node = gtk_css_node_new();
+ gtk_css_node_set_name (dialog->page_layout_paper_node, g_quark_from_static_string ("paper"));
+ gtk_css_node_set_parent (dialog->page_layout_paper_node,
+ gtk_widget_get_css_node (dialog->page_layout_preview));
+ g_object_unref (dialog->page_layout_paper_node);
+}
+
+static void
+gtk_print_unix_dialog_constructed (GObject *object)
+{
+ gboolean use_header;
+
+ G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->constructed (object);
+
+ g_object_get (object, "use-header-bar", &use_header, NULL);
+ if (use_header)
+ {
+ /* Reorder the preview button */
+ GtkWidget *button, *parent;
+ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (object), GTK_RESPONSE_APPLY);
+ g_object_ref (button);
+ parent = gtk_widget_get_ancestor (button, GTK_TYPE_HEADER_BAR);
+ gtk_box_remove (GTK_BOX (gtk_widget_get_parent (button)), button);
+ gtk_header_bar_pack_end (GTK_HEADER_BAR (parent), button);
+ g_object_unref (button);
+ }
+
+ update_dialog_from_capabilities (GTK_PRINT_UNIX_DIALOG (object));
+}
+
+static void
+gtk_print_unix_dialog_dispose (GObject *object)
+{
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+
+ /* Make sure we don't destroy custom widgets owned by the backends */
+ clear_per_printer_ui (dialog);
+
+ G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->dispose (object);
+}
+
+static void
+disconnect_printer_details_request (GtkPrintUnixDialog *dialog,
+ gboolean details_failed)
+{
+ if (dialog->request_details_tag)
+ {
+ g_signal_handler_disconnect (dialog->request_details_printer,
+ dialog->request_details_tag);
+ dialog->request_details_tag = 0;
+ set_busy_cursor (dialog, FALSE);
+ if (details_failed)
+ gtk_printer_set_state_message (dialog->request_details_printer, _("Getting printer information failed"));
+ g_clear_object (&dialog->request_details_printer);
+ }
+}
+
+static void
+gtk_print_unix_dialog_finalize (GObject *object)
+{
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+ GList *iter;
+
+ unschedule_idle_mark_conflicts (dialog);
+ disconnect_printer_details_request (dialog, FALSE);
+
+ g_clear_object (&dialog->current_printer);
+ g_clear_object (&dialog->options);
+
+ if (dialog->number_up_layout_2_option)
+ {
+ dialog->number_up_layout_2_option->choices[0] = NULL;
+ dialog->number_up_layout_2_option->choices[1] = NULL;
+ g_free (dialog->number_up_layout_2_option->choices_display[0]);
+ g_free (dialog->number_up_layout_2_option->choices_display[1]);
+ dialog->number_up_layout_2_option->choices_display[0] = NULL;
+ dialog->number_up_layout_2_option->choices_display[1] = NULL;
+ g_object_unref (dialog->number_up_layout_2_option);
+ dialog->number_up_layout_2_option = NULL;
+ }
+
+ g_clear_object (&dialog->number_up_layout_n_option);
+ g_clear_object (&dialog->page_setup);
+ g_clear_object (&dialog->initial_settings);
+ g_clear_pointer (&dialog->waiting_for_printer, (GDestroyNotify)g_free);
+ g_clear_pointer (&dialog->format_for_printer, (GDestroyNotify)g_free);
+
+ for (iter = dialog->print_backends; iter != NULL; iter = iter->next)
+ gtk_print_backend_destroy (GTK_PRINT_BACKEND (iter->data));
+ g_list_free_full (dialog->print_backends, g_object_unref);
+ dialog->print_backends = NULL;
+
+ g_clear_object (&dialog->page_setup_list);
+ g_clear_object (&dialog->custom_paper_list);
+ g_clear_object (&dialog->manage_papers_list);
+
+ G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
+}
+
+static void
+gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+ iface->get_internal_child = gtk_print_unix_dialog_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ const char *childname)
+{
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (buildable);
+
+ if (strcmp (childname, "notebook") == 0)
+ return G_OBJECT (dialog->notebook);
+
+ return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
+static void
+printer_status_cb (GtkPrintBackend *backend,
+ GtkPrinter *printer,
+ GtkPrintUnixDialog *dialog)
+{
+ GListModel *model;
+
+ /* When the pause state change then we need to update sensitive property
+ * of GTK_RESPONSE_OK button inside of selected_printer_changed function.
+ */
+ selected_printer_changed (dialog);
+
+ model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
+
+ if (gtk_print_backend_printer_list_is_done (backend) &&
+ gtk_printer_is_default (printer) &&
+ gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
+ set_active_printer (dialog, gtk_printer_get_name (printer));
+}
+
+static void
+printer_added_cb (GListModel *model,
+ guint position,
+ guint removed,
+ guint added,
+ GtkPrintUnixDialog *dialog)
+{
+ guint i;
+
+ for (i = position; i < position + added; i++)
+ {
+ GtkPrinter *printer = g_list_model_get_item (model, i);
+
+ if (dialog->waiting_for_printer != NULL &&
+ strcmp (gtk_printer_get_name (printer), dialog->waiting_for_printer) == 0)
+ {
+ gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
+ g_free (dialog->waiting_for_printer);
+ dialog->waiting_for_printer = NULL;
+ g_object_unref (printer);
+ return;
+ }
+ else if (is_default_printer (dialog, printer) &&
+ gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
+ {
+ gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
+ g_object_unref (printer);
+ return;
+ }
+
+ g_object_unref (printer);
+ }
+}
+
+static GListModel *
+load_print_backends (GtkPrintUnixDialog *dialog)
+{
+ GList *node;
+ GListStore *lists;
+
+ lists = g_list_store_new (G_TYPE_LIST_MODEL);
+
+ if (g_module_supported ())
+ dialog->print_backends = gtk_print_backend_load_modules ();
+
+ for (node = dialog->print_backends; node != NULL; node = node->next)
+ {
+ GtkPrintBackend *backend = node->data;
+
+ g_signal_connect_object (backend, "printer-status-changed",
+ G_CALLBACK (printer_status_cb), G_OBJECT (dialog), 0);
+ g_list_store_append (lists, gtk_print_backend_get_printers (backend));
+ }
+
+ return G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (lists)));
+}
+
+static void
+gtk_print_unix_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_PAGE_SETUP:
+ gtk_print_unix_dialog_set_page_setup (dialog, g_value_get_object (value));
+ break;
+ case PROP_CURRENT_PAGE:
+ gtk_print_unix_dialog_set_current_page (dialog, g_value_get_int (value));
+ break;
+ case PROP_PRINT_SETTINGS:
+ gtk_print_unix_dialog_set_settings (dialog, g_value_get_object (value));
+ break;
+ case PROP_MANUAL_CAPABILITIES:
+ gtk_print_unix_dialog_set_manual_capabilities (dialog, g_value_get_flags (value));
+ break;
+ case PROP_SUPPORT_SELECTION:
+ gtk_print_unix_dialog_set_support_selection (dialog, g_value_get_boolean (value));
+ break;
+ case PROP_HAS_SELECTION:
+ gtk_print_unix_dialog_set_has_selection (dialog, g_value_get_boolean (value));
+ break;
+ case PROP_EMBED_PAGE_SETUP:
+ gtk_print_unix_dialog_set_embed_page_setup (dialog, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_print_unix_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_PAGE_SETUP:
+ g_value_set_object (value, dialog->page_setup);
+ break;
+ case PROP_CURRENT_PAGE:
+ g_value_set_int (value, dialog->current_page);
+ break;
+ case PROP_PRINT_SETTINGS:
+ g_value_take_object (value, gtk_print_unix_dialog_get_settings (dialog));
+ break;
+ case PROP_SELECTED_PRINTER:
+ g_value_set_object (value, dialog->current_printer);
+ break;
+ case PROP_MANUAL_CAPABILITIES:
+ g_value_set_flags (value, dialog->manual_capabilities);
+ break;
+ case PROP_SUPPORT_SELECTION:
+ g_value_set_boolean (value, dialog->support_selection);
+ break;
+ case PROP_HAS_SELECTION:
+ g_value_set_boolean (value, dialog->has_selection);
+ break;
+ case PROP_EMBED_PAGE_SETUP:
+ g_value_set_boolean (value, dialog->embed_page_setup);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+is_printer_active (gpointer item, gpointer data)
+{
+ GtkPrinter *printer = item;
+ GtkPrintUnixDialog *dialog = data;
+ gboolean result;
+
+ result = gtk_printer_is_active (printer);
+
+ if (result &&
+ dialog->manual_capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF |
+ GTK_PRINT_CAPABILITY_GENERATE_PS))
+ {
+ /* Check that the printer can handle at least one of the data
+ * formats that the application supports.
+ */
+ result = ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF) &&
+ gtk_printer_accepts_pdf (printer)) ||
+ ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS) &&
+ gtk_printer_accepts_ps (printer));
+ }
+
+ return result;
+}
+
+static int
+default_printer_list_sort_func (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ GtkPrinter *a_printer = (gpointer)a;
+ GtkPrinter *b_printer = (gpointer)b;
+ const char *a_name;
+ const char *b_name;
+
+ if (a_printer == NULL && b_printer == NULL)
+ return 0;
+ else if (a_printer == NULL)
+ return 1;
+ else if (b_printer == NULL)
+ return -1;
+
+ if (gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
+ return 0;
+ else if (gtk_printer_is_virtual (a_printer) && !gtk_printer_is_virtual (b_printer))
+ return -1;
+ else if (!gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
+ return 1;
+
+ a_name = gtk_printer_get_name (a_printer);
+ b_name = gtk_printer_get_name (b_printer);
+
+ if (a_name == NULL && b_name == NULL)
+ return 0;
+ else if (a_name == NULL && b_name != NULL)
+ return 1;
+ else if (a_name != NULL && b_name == NULL)
+ return -1;
+
+ return g_ascii_strcasecmp (a_name, b_name);
+}
+
+static GtkWidget *
+wrap_in_frame (const char *label,
+ GtkWidget *child)
+{
+ GtkWidget *box, *label_widget;
+ char *bold_text;
+
+ label_widget = gtk_label_new (NULL);
+ gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
+ gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
+
+ bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
+ gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
+ g_free (bold_text);
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_box_append (GTK_BOX (box), label_widget);
+
+ gtk_widget_set_margin_start (child, 12);
+ gtk_widget_set_halign (child, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (child, GTK_ALIGN_FILL);
+
+ gtk_box_append (GTK_BOX (box), child);
+
+ return box;
+}
+
+static gboolean
+setup_option (GtkPrintUnixDialog *dialog,
+ const char *option_name,
+ GtkPrinterOptionWidget *widget)
+{
+ GtkPrinterOption *option;
+
+ option = gtk_printer_option_set_lookup (dialog->options, option_name);
+ gtk_printer_option_widget_set_source (widget, option);
+
+ return option != NULL;
+}
+
+static void
+add_option_to_extension_point (GtkPrinterOption *option,
+ gpointer data)
+{
+ GtkWidget *extension_point = data;
+ GtkWidget *widget;
+
+ widget = gtk_printer_option_widget_new (option);
+
+ if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
+ {
+ GtkWidget *label, *hbox;
+
+ gtk_widget_set_valign (widget, GTK_ALIGN_BASELINE_FILL);
+
+ label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
+ gtk_widget_set_visible (label, TRUE);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_widget_set_valign (hbox, GTK_ALIGN_BASELINE_FILL);
+ gtk_box_append (GTK_BOX (hbox), label);
+ gtk_box_append (GTK_BOX (hbox), widget);
+
+ gtk_box_append (GTK_BOX (extension_point), hbox);
+ }
+ else
+ gtk_box_append (GTK_BOX (extension_point), widget);
+}
+
+static int
+grid_rows (GtkGrid *table)
+{
+ int t0, t1, l, t, w, h;
+ GtkWidget *c;
+ gboolean first;
+
+ t0 = t1 = 0;
+ for (c = gtk_widget_get_first_child (GTK_WIDGET (table)), first = TRUE;
+ c != NULL;
+ c = gtk_widget_get_next_sibling (GTK_WIDGET (c)), first = FALSE)
+ {
+ gtk_grid_query_child (table, c, &l, &t, &w, &h);
+ if (first)
+ {
+ t0 = t;
+ t1 = t + h;
+ }
+ else
+ {
+ if (t < t0)
+ t0 = t;
+ if (t + h > t1)
+ t1 = t + h;
+ }
+ }
+
+ return t1 - t0;
+}
+
+static void
+add_option_to_table (GtkPrinterOption *option,
+ gpointer user_data)
+{
+ GtkGrid *table;
+ GtkWidget *label, *widget;
+ guint row;
+
+ table = GTK_GRID (user_data);
+
+ if (g_str_has_prefix (option->name, "gtk-"))
+ return;
+
+ row = grid_rows (table);
+
+ widget = gtk_printer_option_widget_new (option);
+
+ if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
+ {
+ label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
+ gtk_widget_set_visible (label, TRUE);
+
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+
+ gtk_grid_attach (table, label, 0, row - 1, 1, 1);
+ gtk_grid_attach (table, widget, 1, row - 1, 1, 1);
+ }
+ else
+ gtk_grid_attach (table, widget, 0, row - 1, 2, 1);
+}
+
+static void
+setup_page_table (GtkPrinterOptionSet *options,
+ const char *group,
+ GtkWidget *table,
+ GtkWidget *page)
+{
+ int nrows;
+
+ gtk_printer_option_set_foreach_in_group (options, group,
+ add_option_to_table,
+ table);
+
+ nrows = grid_rows (GTK_GRID (table));
+ gtk_widget_set_visible (page, nrows > 0);
+}
+
+static void
+update_print_at_option (GtkPrintUnixDialog *dialog)
+{
+ GtkPrinterOption *option;
+
+ option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
+
+ if (option == NULL)
+ return;
+
+ if (dialog->updating_print_at)
+ return;
+
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_at_radio)))
+ gtk_printer_option_set (option, "at");
+ else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_hold_radio)))
+ gtk_printer_option_set (option, "on-hold");
+ else
+ gtk_printer_option_set (option, "now");
+
+ option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
+ if (option != NULL)
+ {
+ const char *text;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (dialog->print_at_entry));
+ gtk_printer_option_set (option, text);
+ }
+}
+
+
+static gboolean
+setup_print_at (GtkPrintUnixDialog *dialog)
+{
+ GtkPrinterOption *option;
+
+ option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
+
+ if (option == NULL)
+ {
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
+ gtk_widget_set_sensitive (dialog->print_at_radio, FALSE);
+ gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
+ gtk_widget_set_sensitive (dialog->print_hold_radio, FALSE);
+ gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), "");
+ return FALSE;
+ }
+
+ dialog->updating_print_at = TRUE;
+
+ gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
+ gtk_widget_set_sensitive (dialog->print_at_radio,
+ gtk_printer_option_has_choice (option, "at"));
+
+ gtk_widget_set_sensitive (dialog->print_hold_radio,
+ gtk_printer_option_has_choice (option, "on-hold"));
+
+ update_print_at_option (dialog);
+
+ if (strcmp (option->value, "at") == 0)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_at_radio), TRUE);
+ else if (strcmp (option->value, "on-hold") == 0)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_hold_radio), TRUE);
+ else
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
+
+ option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
+ if (option != NULL)
+ gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), option->value);
+
+ dialog->updating_print_at = FALSE;
+
+ return TRUE;
+}
+
+static void
+update_dialog_from_settings (GtkPrintUnixDialog *dialog)
+{
+ GList *groups, *l;
+ char *group;
+ GtkWidget *table, *frame;
+ gboolean has_advanced, has_job;
+ guint nrows;
+ GtkWidget *child;
+
+ if (dialog->current_printer == NULL)
+ {
+ clear_per_printer_ui (dialog);
+ gtk_widget_set_visible (dialog->job_page, FALSE);
+ gtk_widget_set_visible (dialog->advanced_page, FALSE);
+ gtk_widget_set_visible (dialog->image_quality_page, FALSE);
+ gtk_widget_set_visible (dialog->finishing_page, FALSE);
+ gtk_widget_set_visible (dialog->color_page, FALSE);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+
+ return;
+ }
+
+ setup_option (dialog, "gtk-n-up", dialog->pages_per_sheet);
+ setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
+ setup_option (dialog, "gtk-duplex", dialog->duplex);
+ setup_option (dialog, "gtk-paper-type", dialog->paper_type);
+ setup_option (dialog, "gtk-paper-source", dialog->paper_source);
+ setup_option (dialog, "gtk-output-tray", dialog->output_tray);
+
+ has_job = FALSE;
+ has_job |= setup_option (dialog, "gtk-job-prio", dialog->job_prio);
+ has_job |= setup_option (dialog, "gtk-billing-info", dialog->billing_info);
+ has_job |= setup_option (dialog, "gtk-cover-before", dialog->cover_before);
+ has_job |= setup_option (dialog, "gtk-cover-after", dialog->cover_after);
+ has_job |= setup_print_at (dialog);
+
+ gtk_widget_set_visible (dialog->job_page, has_job);
+
+ setup_page_table (dialog->options,
+ "ImageQualityPage",
+ dialog->image_quality_table,
+ dialog->image_quality_page);
+
+ setup_page_table (dialog->options,
+ "FinishingPage",
+ dialog->finishing_table,
+ dialog->finishing_page);
+
+ setup_page_table (dialog->options,
+ "ColorPage",
+ dialog->color_table,
+ dialog->color_page);
+
+ gtk_printer_option_set_foreach_in_group (dialog->options,
+ "GtkPrintDialogExtension",
+ add_option_to_extension_point,
+ dialog->extension_point);
+
+ /* A bit of a hack, keep the last option flush right.
+ * This keeps the file format radios from moving as the
+ * filename changes.
+ */
+ child = gtk_widget_get_last_child (dialog->extension_point);
+ if (child && child != gtk_widget_get_first_child (dialog->extension_point))
+ gtk_widget_set_halign (child, GTK_ALIGN_END);
+
+ /* Put the rest of the groups in the advanced page */
+ groups = gtk_printer_option_set_get_groups (dialog->options);
+
+ has_advanced = FALSE;
+ for (l = groups; l != NULL; l = l->next)
+ {
+ group = l->data;
+
+ if (group == NULL)
+ continue;
+
+ if (strcmp (group, "ImageQualityPage") == 0 ||
+ strcmp (group, "ColorPage") == 0 ||
+ strcmp (group, "FinishingPage") == 0 ||
+ strcmp (group, "GtkPrintDialogExtension") == 0)
+ continue;
+
+ table = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (table), 6);
+ gtk_grid_set_column_spacing (GTK_GRID (table), 12);
+
+ gtk_printer_option_set_foreach_in_group (dialog->options,
+ group,
+ add_option_to_table,
+ table);
+
+ nrows = grid_rows (GTK_GRID (table));
+ if (nrows == 0)
+ {
+ g_object_unref (g_object_ref_sink (table));
+ }
+ else
+ {
+ has_advanced = TRUE;
+ frame = wrap_in_frame (group, table);
+ gtk_box_append (GTK_BOX (dialog->advanced_vbox), frame);
+ }
+ }
+
+ gtk_widget_set_visible (dialog->advanced_page, has_advanced);
+
+ g_list_free_full (groups, g_free);
+}
+
+static void
+update_dialog_from_capabilities (GtkPrintUnixDialog *dialog)
+{
+ GtkPrintCapabilities caps;
+ gboolean can_collate;
+ const char *copies;
+ GtkWidget *button;
+
+ copies = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
+ can_collate = (*copies != '\0' && atoi (copies) > 1);
+
+ caps = dialog->manual_capabilities | dialog->printer_capabilities;
+
+ gtk_widget_set_sensitive (dialog->page_set_combo,
+ caps & GTK_PRINT_CAPABILITY_PAGE_SET);
+ gtk_widget_set_sensitive (dialog->copies_spin,
+ caps & GTK_PRINT_CAPABILITY_COPIES);
+ gtk_widget_set_sensitive (dialog->collate_check,
+ can_collate &&
+ (caps & GTK_PRINT_CAPABILITY_COLLATE));
+ gtk_widget_set_sensitive (dialog->reverse_check,
+ caps & GTK_PRINT_CAPABILITY_REVERSE);
+ gtk_widget_set_sensitive (dialog->scale_spin,
+ caps & GTK_PRINT_CAPABILITY_SCALE);
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->pages_per_sheet),
+ caps & GTK_PRINT_CAPABILITY_NUMBER_UP);
+
+ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
+ gtk_widget_set_visible (button, (caps & GTK_PRINT_CAPABILITY_PREVIEW) != 0);
+
+ update_collate_icon (NULL, dialog);
+}
+
+static gboolean
+page_setup_is_equal (GtkPageSetup *a,
+ GtkPageSetup *b)
+{
+ return
+ gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+ gtk_page_setup_get_paper_size (b)) &&
+ gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
+ gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
+ gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
+ gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
+}
+
+static gboolean
+page_setup_is_same_size (GtkPageSetup *a,
+ GtkPageSetup *b)
+{
+ return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+ gtk_page_setup_get_paper_size (b));
+}
+
+static gboolean
+set_paper_size (GtkPrintUnixDialog *dialog,
+ GtkPageSetup *page_setup,
+ gboolean size_only,
+ gboolean add_item)
+{
+ GListModel *model;
+ GtkPageSetup *list_page_setup;
+ guint i;
+
+ if (!dialog->internal_page_setup_change)
+ return TRUE;
+
+ if (page_setup == NULL)
+ return FALSE;
+
+ model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+ for (i = 0; i < g_list_model_get_n_items (model); i++)
+ {
+ list_page_setup = g_list_model_get_item (model, i);
+ if (list_page_setup == NULL)
+ continue;
+
+ if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
+ (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
+ {
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
+ gtk_page_setup_get_orientation (page_setup));
+ g_object_unref (list_page_setup);
+ return TRUE;
+ }
+
+ g_object_unref (list_page_setup);
+ }
+
+ if (add_item)
+ {
+ i = g_list_model_get_n_items (model);
+ g_list_store_append (dialog->page_setup_list, page_setup);
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
+ gtk_page_setup_get_orientation (page_setup));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+fill_custom_paper_sizes (GtkPrintUnixDialog *dialog)
+{
+ g_list_store_remove_all (dialog->custom_paper_list);
+ gtk_print_load_custom_papers (dialog->custom_paper_list);
+}
+
+static void
+fill_paper_sizes (GtkPrintUnixDialog *dialog,
+ GtkPrinter *printer)
+{
+ GList *list, *l;
+ GtkPageSetup *page_setup;
+ GtkPaperSize *paper_size;
+ int i;
+
+ g_list_store_remove_all (dialog->page_setup_list);
+
+ if (printer == NULL || (list = gtk_printer_list_papers (printer)) == NULL)
+ {
+ for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
+ {
+ page_setup = gtk_page_setup_new ();
+ paper_size = gtk_paper_size_new (common_paper_sizes[i]);
+ gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
+ gtk_paper_size_free (paper_size);
+ g_list_store_append (dialog->page_setup_list, page_setup);
+ g_object_unref (page_setup);
+ }
+ }
+ else
+ {
+ for (l = list; l != NULL; l = l->next)
+ {
+ page_setup = l->data;
+ g_list_store_append (dialog->page_setup_list, page_setup);
+ g_object_unref (page_setup);
+ }
+ g_list_free (list);
+ }
+}
+
+static void
+update_paper_sizes (GtkPrintUnixDialog *dialog)
+{
+ GtkPageSetup *current_page_setup = NULL;
+ GtkPrinter *printer;
+
+ printer = gtk_print_unix_dialog_get_selected_printer (dialog);
+
+ fill_paper_sizes (dialog, printer);
+ fill_custom_paper_sizes (dialog);
+
+ current_page_setup = gtk_page_setup_copy (gtk_print_unix_dialog_get_page_setup (dialog));
+
+ if (current_page_setup)
+ {
+ if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
+ set_paper_size (dialog, current_page_setup, TRUE, TRUE);
+
+ g_object_unref (current_page_setup);
+ }
+}
+
+static void
+mark_conflicts (GtkPrintUnixDialog *dialog)
+{
+ GtkPrinter *printer;
+ gboolean have_conflict;
+
+ have_conflict = FALSE;
+
+ printer = dialog->current_printer;
+
+ if (printer)
+ {
+ g_signal_handler_block (dialog->options, dialog->options_changed_handler);
+
+ gtk_printer_option_set_clear_conflicts (dialog->options);
+ have_conflict = _gtk_printer_mark_conflicts (printer, dialog->options);
+
+ g_signal_handler_unblock (dialog->options, dialog->options_changed_handler);
+ }
+
+ gtk_widget_set_visible (dialog->conflicts_widget, have_conflict);
+}
+
+static gboolean
+mark_conflicts_callback (gpointer data)
+{
+ GtkPrintUnixDialog *dialog = data;
+
+ dialog->mark_conflicts_id = 0;
+
+ mark_conflicts (dialog);
+
+ return FALSE;
+}
+
+static void
+unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
+{
+ if (dialog->mark_conflicts_id != 0)
+ {
+ g_source_remove (dialog->mark_conflicts_id);
+ dialog->mark_conflicts_id = 0;
+ }
+}
+
+static void
+schedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
+{
+ if (dialog->mark_conflicts_id != 0)
+ return;
+
+ dialog->mark_conflicts_id = g_idle_add (mark_conflicts_callback, dialog);
+ gdk_source_set_static_name_by_id (dialog->mark_conflicts_id, "[gtk] mark_conflicts_callback");
+}
+
+static void
+options_changed_cb (GtkPrintUnixDialog *dialog)
+{
+ schedule_idle_mark_conflicts (dialog);
+
+ g_free (dialog->waiting_for_printer);
+ dialog->waiting_for_printer = NULL;
+}
+
+static void
+clear_per_printer_ui (GtkPrintUnixDialog *dialog)
+{
+ GtkWidget *child;
+
+ if (dialog->finishing_table == NULL)
+ return;
+
+ while ((child = gtk_widget_get_first_child (dialog->finishing_table)))
+ gtk_grid_remove (GTK_GRID (dialog->finishing_table), child);
+ while ((child = gtk_widget_get_first_child (dialog->image_quality_table)))
+ gtk_grid_remove (GTK_GRID (dialog->image_quality_table), child);
+ while ((child = gtk_widget_get_first_child (dialog->color_table)))
+ gtk_grid_remove (GTK_GRID (dialog->color_table), child);
+ while ((child = gtk_widget_get_first_child (dialog->advanced_vbox)))
+ gtk_box_remove (GTK_BOX (dialog->advanced_vbox), child);
+ while ((child = gtk_widget_get_first_child (dialog->extension_point)))
+ gtk_box_remove (GTK_BOX (dialog->extension_point), child);
+}
+
+static void
+printer_details_acquired (GtkPrinter *printer,
+ gboolean success,
+ GtkPrintUnixDialog *dialog)
+{
+ disconnect_printer_details_request (dialog, !success);
+
+ if (success)
+ selected_printer_changed (dialog);
+}
+
+static void
+selected_printer_changed (GtkPrintUnixDialog *dialog)
+{
+ GListModel *model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
+ GtkPrinter *printer;
+
+ /* Whenever the user selects a printer we stop looking for
+ * the printer specified in the initial settings
+ */
+ if (dialog->waiting_for_printer &&
+ !dialog->internal_printer_change)
+ {
+ g_free (dialog->waiting_for_printer);
+ dialog->waiting_for_printer = NULL;
+ }
+
+ disconnect_printer_details_request (dialog, FALSE);
+
+ printer = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
+
+ /* sets GTK_RESPONSE_OK button sensitivity depending on whether the printer
+ * accepts/rejects jobs
+ */
+ if (printer != NULL)
+ {
+ if (!gtk_printer_is_accepting_jobs (printer))
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+ else if (dialog->current_printer == printer && gtk_printer_has_details (printer))
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
+ }
+
+ if (printer != NULL && !gtk_printer_has_details (printer))
+ {
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+ dialog->request_details_tag = g_signal_connect (printer, "details-acquired",
+ G_CALLBACK (printer_details_acquired), dialog);
+
+ dialog->request_details_printer = g_object_ref (printer);
+ set_busy_cursor (dialog, TRUE);
+ gtk_printer_set_state_message (printer, _("Getting printer information…"));
+ gtk_printer_request_details (printer);
+ return;
+ }
+
+ if (printer == dialog->current_printer)
+ return;
+
+ if (dialog->options)
+ {
+ g_clear_object (&dialog->options);
+ clear_per_printer_ui (dialog);
+ }
+
+ g_clear_object (&dialog->current_printer);
+ dialog->printer_capabilities = 0;
+
+ if (printer != NULL && gtk_printer_is_accepting_jobs (printer))
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
+ dialog->current_printer = g_object_ref (printer);
+
+ if (printer != NULL)
+ {
+ if (!dialog->page_setup_set)
+ {
+ /* if no explicit page setup has been set, use the printer default */
+ GtkPageSetup *page_setup;
+
+ page_setup = gtk_printer_get_default_page_size (printer);
+
+ if (!page_setup)
+ page_setup = gtk_page_setup_new ();
+
+ if (page_setup && dialog->page_setup)
+ gtk_page_setup_set_orientation (page_setup, gtk_page_setup_get_orientation (dialog->page_setup));
+
+ g_clear_object (&dialog->page_setup);
+ dialog->page_setup = page_setup; /* transfer ownership */
+ }
+
+ dialog->printer_capabilities = gtk_printer_get_capabilities (printer);
+ dialog->options = _gtk_printer_get_options (printer,
+ dialog->initial_settings,
+ dialog->page_setup,
+ dialog->manual_capabilities);
+
+ dialog->options_changed_handler =
+ g_signal_connect_swapped (dialog->options, "changed", G_CALLBACK (options_changed_cb), dialog);
+ schedule_idle_mark_conflicts (dialog);
+ }
+
+ update_dialog_from_settings (dialog);
+ update_dialog_from_capabilities (dialog);
+
+ dialog->internal_page_setup_change = TRUE;
+ update_paper_sizes (dialog);
+ dialog->internal_page_setup_change = FALSE;
+
+ g_object_notify (G_OBJECT (dialog), "selected-printer");
+}
+
+static void
+update_collate_icon (GtkToggleButton *toggle_button,
+ GtkPrintUnixDialog *dialog)
+{
+ gtk_widget_queue_draw (dialog->collate_image);
+}
+
+static void
+paint_page (GtkPrintUnixDialog *dialog,
+ GtkWidget *widget,
+ cairo_t *cr,
+ int x,
+ int y,
+ const char *text,
+ int text_x)
+{
+ GtkCssStyle *style;
+ int width, height;
+ int text_y;
+ GdkRGBA color;
+ GtkSnapshot *snapshot;
+ GskRenderNode *node;
+ GtkCssBoxes boxes;
+
+ width = 20;
+ height = 26;
+ text_y = 21;
+
+ style = gtk_css_node_get_style (dialog->collate_paper_node);
+
+ snapshot = gtk_snapshot_new ();
+ gtk_css_boxes_init_border_box (&boxes, style, x, y, width, height);
+ gtk_css_style_snapshot_background (&boxes, snapshot);
+ gtk_css_style_snapshot_border (&boxes, snapshot);
+
+ node = gtk_snapshot_free_to_node (snapshot);
+ if (node)
+ {
+ gsk_render_node_draw (node, cr);
+ gsk_render_node_unref (node);
+ }
+
+ color = *gtk_css_color_value_get_rgba (style->core->color);
+ gdk_cairo_set_source_rgba (cr, &color);
+
+ cairo_select_font_face (cr, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, 9);
+ cairo_move_to (cr, x + text_x, y + text_y);
+ cairo_show_text (cr, text);
+}
+
+static void
+draw_collate (GtkDrawingArea *da,
+ cairo_t *cr,
+ int width,
+ int height,
+ gpointer data)
+{
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
+ GtkWidget *widget = GTK_WIDGET (da);
+ gboolean collate, reverse, rtl;
+ int copies;
+ int text_x;
+ int x, y, x1, x2, p1, p2;
+
+ collate = dialog_get_collate (dialog);
+ reverse = dialog_get_reverse (dialog);
+ copies = dialog_get_n_copies (dialog);
+
+ rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
+
+ x = (width - 30) / 2;
+ y = (height - 36) / 2;
+ if (rtl)
+ {
+ x1 = x;
+ x2 = x - 36;
+ p1 = 0;
+ p2 = 10;
+ text_x = 4;
+ }
+ else
+ {
+ x1 = x;
+ x2 = x + 36;
+ p1 = 10;
+ p2 = 0;
+ text_x = 11;
+ }
+
+ if (copies == 1)
+ {
+ paint_page (dialog, widget, cr, x1 + p1, y, reverse ? "1" : "2", text_x);
+ paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
+ }
+ else
+ {
+ paint_page (dialog, widget, cr, x1 + p1, y, collate == reverse ? "1" : "2", text_x);
+ paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
+
+ paint_page (dialog, widget, cr, x2 + p1, y, reverse ? "1" : "2", text_x);
+ paint_page (dialog, widget, cr, x2 + p2, y + 10, collate == reverse ? "2" : "1", text_x);
+ }
+}
+
+static gboolean
+page_range_entry_focus_changed (GtkWidget *entry,
+ GParamSpec *pspec,
+ GtkPrintUnixDialog *dialog)
+{
+ if (gtk_widget_has_focus (entry))
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
+
+ return FALSE;
+}
+
+static void
+update_page_range_entry_sensitivity (GtkWidget *button,
+ GtkPrintUnixDialog *dialog)
+{
+ gboolean active;
+
+ active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
+
+ if (active)
+ gtk_widget_grab_focus (dialog->page_range_entry);
+}
+
+static void
+update_print_at_entry_sensitivity (GtkWidget *button,
+ GtkPrintUnixDialog *dialog)
+{
+ gboolean active;
+
+ active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
+
+ gtk_widget_set_sensitive (dialog->print_at_entry, active);
+
+ if (active)
+ gtk_widget_grab_focus (dialog->print_at_entry);
+}
+
+static gboolean
+is_range_separator (char c)
+{
+ return (c == ',' || c == ';' || c == ':');
+}
+
+static GtkPageRange *
+dialog_get_page_ranges (GtkPrintUnixDialog *dialog,
+ int *n_ranges_out)
+{
+ int i, n_ranges;
+ const char *text, *p;
+ char *next;
+ GtkPageRange *ranges;
+ int start, end;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (dialog->page_range_entry));
+
+ if (*text == 0)
+ {
+ *n_ranges_out = 0;
+ return NULL;
+ }
+
+ n_ranges = 1;
+ p = text;
+ while (*p)
+ {
+ if (is_range_separator (*p))
+ n_ranges++;
+ p++;
+ }
+
+ ranges = g_new0 (GtkPageRange, n_ranges);
+
+ i = 0;
+ p = text;
+ while (*p)
+ {
+ while (isspace (*p)) p++;
+
+ if (*p == '-')
+ {
+ /* a half-open range like -2 */
+ start = 1;
+ }
+ else
+ {
+ start = (int)strtol (p, &next, 10);
+ if (start < 1)
+ start = 1;
+ p = next;
+ }
+
+ end = start;
+
+ while (isspace (*p)) p++;
+
+ if (*p == '-')
+ {
+ p++;
+ end = (int)strtol (p, &next, 10);
+ if (next == p) /* a half-open range like 2- */
+ end = 0;
+ else if (end < start)
+ end = start;
+ }
+
+ ranges[i].start = start - 1;
+ ranges[i].end = end - 1;
+ i++;
+
+ /* Skip until end or separator */
+ while (*p && !is_range_separator (*p))
+ p++;
+
+ /* if not at end, skip separator */
+ if (*p)
+ p++;
+ }
+
+ *n_ranges_out = i;
+
+ return ranges;
+}
+
+static void
+dialog_set_page_ranges (GtkPrintUnixDialog *dialog,
+ GtkPageRange *ranges,
+ int n_ranges)
+{
+ int i;
+ GString *s = g_string_new (NULL);
+
+ for (i = 0; i < n_ranges; i++)
+ {
+ g_string_append_printf (s, "%d", ranges[i].start + 1);
+ if (ranges[i].end > ranges[i].start)
+ g_string_append_printf (s, "-%d", ranges[i].end + 1);
+ else if (ranges[i].end == -1)
+ g_string_append (s, "-");
+
+ if (i != n_ranges - 1)
+ g_string_append (s, ",");
+ }
+
+ gtk_editable_set_text (GTK_EDITABLE (dialog->page_range_entry), s->str);
+
+ g_string_free (s, TRUE);
+}
+
+static GtkPrintPages
+dialog_get_print_pages (GtkPrintUnixDialog *dialog)
+{
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->all_pages_radio)))
+ return GTK_PRINT_PAGES_ALL;
+ else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->current_page_radio)))
+ return GTK_PRINT_PAGES_CURRENT;
+ else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->selection_radio)))
+ return GTK_PRINT_PAGES_SELECTION;
+ else
+ return GTK_PRINT_PAGES_RANGES;
+}
+
+static void
+dialog_set_print_pages (GtkPrintUnixDialog *dialog,
+ GtkPrintPages pages)
+{
+ if (pages == GTK_PRINT_PAGES_RANGES)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
+ else if (pages == GTK_PRINT_PAGES_CURRENT)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->current_page_radio), TRUE);
+ else if (pages == GTK_PRINT_PAGES_SELECTION)
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->selection_radio), TRUE);
+ else
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->all_pages_radio), TRUE);
+}
+
+static double
+dialog_get_scale (GtkPrintUnixDialog *dialog)
+{
+ if (gtk_widget_is_sensitive (dialog->scale_spin))
+ return gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->scale_spin));
+ else
+ return 100.0;
+}
+
+static void
+dialog_set_scale (GtkPrintUnixDialog *dialog,
+ double val)
+{
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->scale_spin), val);
+}
+
+static GtkPageSet
+dialog_get_page_set (GtkPrintUnixDialog *dialog)
+{
+ if (gtk_widget_is_sensitive (dialog->page_set_combo))
+ return (GtkPageSet)gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->page_set_combo));
+ else
+ return GTK_PAGE_SET_ALL;
+}
+
+static void
+dialog_set_page_set (GtkPrintUnixDialog *dialog,
+ GtkPageSet val)
+{
+ gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->page_set_combo), (guint)val);
+}
+
+static int
+dialog_get_n_copies (GtkPrintUnixDialog *dialog)
+{
+ GtkAdjustment *adjustment;
+ const char *text;
+ char *endptr = NULL;
+ int n_copies;
+
+ adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (dialog->copies_spin));
+
+ text = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
+ n_copies = g_ascii_strtoull (text, &endptr, 0);
+
+ if (gtk_widget_is_sensitive (dialog->copies_spin))
+ {
+ if (n_copies != 0 && endptr != text && (endptr != NULL && endptr[0] == '\0') &&
+ n_copies >= gtk_adjustment_get_lower (adjustment) &&
+ n_copies <= gtk_adjustment_get_upper (adjustment))
+ {
+ return n_copies;
+ }
+
+ return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->copies_spin));
+ }
+
+ return 1;
+}
+
+static void
+dialog_set_n_copies (GtkPrintUnixDialog *dialog,
+ int n_copies)
+{
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->copies_spin), n_copies);
+}
+
+static gboolean
+dialog_get_collate (GtkPrintUnixDialog *dialog)
+{
+ if (gtk_widget_is_sensitive (dialog->collate_check))
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->collate_check));
+ return FALSE;
+}
+
+static void
+dialog_set_collate (GtkPrintUnixDialog *dialog,
+ gboolean collate)
+{
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->collate_check), collate);
+}
+
+static gboolean
+dialog_get_reverse (GtkPrintUnixDialog *dialog)
+{
+ if (gtk_widget_is_sensitive (dialog->reverse_check))
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_check));
+ return FALSE;
+}
+
+static void
+dialog_set_reverse (GtkPrintUnixDialog *dialog,
+ gboolean reverse)
+{
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_check), reverse);
+}
+
+static int
+dialog_get_pages_per_sheet (GtkPrintUnixDialog *dialog)
+{
+ const char *val;
+ int num;
+
+ val = gtk_printer_option_widget_get_value (dialog->pages_per_sheet);
+
+ num = 1;
+
+ if (val)
+ {
+ num = atoi(val);
+ if (num < 1)
+ num = 1;
+ }
+
+ return num;
+}
+
+static GtkNumberUpLayout
+dialog_get_number_up_layout (GtkPrintUnixDialog *dialog)
+{
+ GtkPrintCapabilities caps;
+ GtkNumberUpLayout layout;
+ const char *val;
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+
+ val = gtk_printer_option_widget_get_value (dialog->number_up_layout);
+
+ caps = dialog->manual_capabilities | dialog->printer_capabilities;
+
+ if ((caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) == 0)
+ return GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+
+ if (gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR)
+ layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+ else
+ layout = GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM;
+
+ if (val == NULL)
+ return layout;
+
+ if (val[0] == '\0' && dialog->options)
+ {
+ GtkPrinterOption *option = gtk_printer_option_set_lookup (dialog->options, "gtk-n-up-layout");
+ if (option)
+ val = option->value;
+ }
+
+ enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
+ enum_value = g_enum_get_value_by_nick (enum_class, val);
+ if (enum_value)
+ layout = enum_value->value;
+ g_type_class_unref (enum_class);
+
+ return layout;
+}
+
+static void
+draw_page (GtkDrawingArea *da,
+ cairo_t *cr,
+ int width,
+ int height,
+ gpointer data)
+{
+ GtkWidget *widget = GTK_WIDGET (da);
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
+ GtkCssStyle *style;
+ double ratio;
+ int w, h, tmp;
+ int pages_x, pages_y, i, x, y, layout_w, layout_h;
+ double page_width, page_height;
+ GtkPageOrientation orientation;
+ gboolean landscape;
+ PangoLayout *layout;
+ PangoFontDescription *font;
+ char *text;
+ GdkRGBA color;
+ GtkNumberUpLayout number_up_layout;
+ int start_x, end_x, start_y, end_y;
+ int dx, dy;
+ gboolean horizontal;
+ GtkPageSetup *page_setup;
+ double paper_width, paper_height;
+ double pos_x, pos_y;
+ int pages_per_sheet;
+ gboolean ltr = TRUE;
+ GtkSnapshot *snapshot;
+ GtkCssBoxes boxes;
+ GskRenderNode *node;
+
+ orientation = gtk_page_setup_get_orientation (dialog->page_setup);
+ landscape =
+ (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
+ (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
+
+ number_up_layout = dialog_get_number_up_layout (dialog);
+
+ cairo_save (cr);
+
+ page_setup = gtk_print_unix_dialog_get_page_setup (dialog);
+
+ if (page_setup != NULL)
+ {
+ if (!landscape)
+ {
+ paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
+ paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
+ }
+ else
+ {
+ paper_width = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
+ paper_height = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
+ }
+
+ if (paper_width < paper_height)
+ {
+ h = EXAMPLE_PAGE_AREA_SIZE - 3;
+ w = (paper_height != 0) ? h * paper_width / paper_height : 0;
+ }
+ else
+ {
+ w = EXAMPLE_PAGE_AREA_SIZE - 3;
+ h = (paper_width != 0) ? w * paper_height / paper_width : 0;
+ }
+
+ if (paper_width == 0)
+ w = 0;
+
+ if (paper_height == 0)
+ h = 0;
+ }
+ else
+ {
+ ratio = G_SQRT2;
+ w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
+ h = EXAMPLE_PAGE_AREA_SIZE - 3;
+ }
+
+ pages_per_sheet = dialog_get_pages_per_sheet (dialog);
+ switch (pages_per_sheet)
+ {
+ default:
+ case 1:
+ pages_x = 1; pages_y = 1;
+ break;
+ case 2:
+ landscape = !landscape;
+ pages_x = 1; pages_y = 2;
+ break;
+ case 4:
+ pages_x = 2; pages_y = 2;
+ break;
+ case 6:
+ landscape = !landscape;
+ pages_x = 2; pages_y = 3;
+ break;
+ case 9:
+ pages_x = 3; pages_y = 3;
+ break;
+ case 16:
+ pages_x = 4; pages_y = 4;
+ break;
+ }
+
+ if (landscape)
+ {
+ tmp = w;
+ w = h;
+ h = tmp;
+
+ tmp = pages_x;
+ pages_x = pages_y;
+ pages_y = tmp;
+ }
+
+ style = gtk_css_node_get_style (dialog->page_layout_paper_node);
+ color = *gtk_css_color_value_get_rgba (style->core->color);
+
+ pos_x = (width - w) / 2;
+ pos_y = (height - h) / 2 - 10;
+ cairo_translate (cr, pos_x, pos_y);
+
+ snapshot = gtk_snapshot_new ();
+ gtk_css_boxes_init_border_box (&boxes, style, 1, 1, w, h);
+ gtk_css_style_snapshot_background (&boxes, snapshot);
+ gtk_css_style_snapshot_border (&boxes, snapshot);
+
+ node = gtk_snapshot_free_to_node (snapshot);
+ if (node)
+ {
+ gsk_render_node_draw (node, cr);
+ gsk_render_node_unref (node);
+ }
+
+ cairo_set_line_width (cr, 1.0);
+
+ i = 1;
+
+ page_width = (double)w / pages_x;
+ page_height = (double)h / pages_y;
+
+ layout = pango_cairo_create_layout (cr);
+
+ font = pango_font_description_new ();
+ pango_font_description_set_family (font, "sans");
+
+ if (page_height > 0)
+ pango_font_description_set_absolute_size (font, page_height * 0.4 * PANGO_SCALE);
+ else
+ pango_font_description_set_absolute_size (font, 1);
+
+ pango_layout_set_font_description (layout, font);
+ pango_font_description_free (font);
+
+ pango_layout_set_width (layout, page_width * PANGO_SCALE);
+ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+
+ switch (number_up_layout)
+ {
+ default:
+ case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
+ start_x = 0;
+ end_x = pages_x - 1;
+ start_y = 0;
+ end_y = pages_y - 1;
+ dx = 1;
+ dy = 1;
+ horizontal = TRUE;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
+ start_x = 0;
+ end_x = pages_x - 1;
+ start_y = pages_y - 1;
+ end_y = 0;
+ dx = 1;
+ dy = - 1;
+ horizontal = TRUE;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
+ start_x = pages_x - 1;
+ end_x = 0;
+ start_y = 0;
+ end_y = pages_y - 1;
+ dx = - 1;
+ dy = 1;
+ horizontal = TRUE;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
+ start_x = pages_x - 1;
+ end_x = 0;
+ start_y = pages_y - 1;
+ end_y = 0;
+ dx = - 1;
+ dy = - 1;
+ horizontal = TRUE;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
+ start_x = 0;
+ end_x = pages_x - 1;
+ start_y = 0;
+ end_y = pages_y - 1;
+ dx = 1;
+ dy = 1;
+ horizontal = FALSE;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
+ start_x = pages_x - 1;
+ end_x = 0;
+ start_y = 0;
+ end_y = pages_y - 1;
+ dx = - 1;
+ dy = 1;
+ horizontal = FALSE;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
+ start_x = 0;
+ end_x = pages_x - 1;
+ start_y = pages_y - 1;
+ end_y = 0;
+ dx = 1;
+ dy = - 1;
+ horizontal = FALSE;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
+ start_x = pages_x - 1;
+ end_x = 0;
+ start_y = pages_y - 1;
+ end_y = 0;
+ dx = - 1;
+ dy = - 1;
+ horizontal = FALSE;
+ break;
+ }
+
+ gdk_cairo_set_source_rgba (cr, &color);
+ if (horizontal)
+ for (y = start_y; y != end_y + dy; y += dy)
+ {
+ for (x = start_x; x != end_x + dx; x += dx)
+ {
+ text = g_strdup_printf ("%d", i++);
+ pango_layout_set_text (layout, text, -1);
+ g_free (text);
+ pango_layout_get_size (layout, &layout_w, &layout_h);
+ cairo_save (cr);
+ cairo_translate (cr,
+ x * page_width,
+ y * page_height + (page_height - layout_h / 1024.0) / 2);
+
+ pango_cairo_show_layout (cr, layout);
+ cairo_restore (cr);
+ }
+ }
+ else
+ for (x = start_x; x != end_x + dx; x += dx)
+ {
+ for (y = start_y; y != end_y + dy; y += dy)
+ {
+ text = g_strdup_printf ("%d", i++);
+ pango_layout_set_text (layout, text, -1);
+ g_free (text);
+ pango_layout_get_size (layout, &layout_w, &layout_h);
+ cairo_save (cr);
+ cairo_translate (cr,
+ x * page_width,
+ y * page_height + (page_height - layout_h / 1024.0) / 2);
+
+ pango_cairo_show_layout (cr, layout);
+ cairo_restore (cr);
+ }
+ }
+
+ g_object_unref (layout);
+
+ style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
+ color = *gtk_css_color_value_get_rgba (style->core->color);
+
+ if (page_setup != NULL)
+ {
+ PangoContext *pango_c = NULL;
+ PangoFontDescription *pango_f = NULL;
+ int font_size = 12 * PANGO_SCALE;
+
+ pos_x += 1;
+ pos_y += 1;
+
+ if (pages_per_sheet == 2 || pages_per_sheet == 6)
+ {
+ paper_width = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
+ paper_height = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
+ }
+ else
+ {
+ paper_width = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
+ paper_height = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
+ }
+
+ cairo_restore (cr);
+ cairo_save (cr);
+
+ layout = pango_cairo_create_layout (cr);
+
+ font = pango_font_description_new ();
+ pango_font_description_set_family (font, "sans");
+
+ pango_c = gtk_widget_get_pango_context (widget);
+ if (pango_c != NULL)
+ {
+ pango_f = pango_context_get_font_description (pango_c);
+ if (pango_f != NULL)
+ font_size = pango_font_description_get_size (pango_f);
+ }
+
+ pango_font_description_set_size (font, font_size);
+ pango_layout_set_font_description (layout, font);
+ pango_font_description_free (font);
+
+ pango_layout_set_width (layout, -1);
+ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+
+ if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
+ text = g_strdup_printf ("%.1f mm", paper_height);
+ else
+ text = g_strdup_printf ("%.2f inch", paper_height);
+
+ pango_layout_set_text (layout, text, -1);
+ g_free (text);
+ pango_layout_get_size (layout, &layout_w, &layout_h);
+
+ ltr = gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR;
+
+ if (ltr)
+ cairo_translate (cr, pos_x - layout_w / PANGO_SCALE - 2 * RULER_DISTANCE,
+ (height - layout_h / PANGO_SCALE) / 2);
+ else
+ cairo_translate (cr, pos_x + w + 2 * RULER_DISTANCE,
+ (height - layout_h / PANGO_SCALE) / 2);
+
+ gdk_cairo_set_source_rgba (cr, &color);
+ pango_cairo_show_layout (cr, layout);
+
+ cairo_restore (cr);
+ cairo_save (cr);
+
+ if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
+ text = g_strdup_printf ("%.1f mm", paper_width);
+ else
+ text = g_strdup_printf ("%.2f inch", paper_width);
+
+ pango_layout_set_text (layout, text, -1);
+ g_free (text);
+ pango_layout_get_size (layout, &layout_w, &layout_h);
+
+ cairo_translate (cr, (width - layout_w / PANGO_SCALE) / 2,
+ pos_y + h + 2 * RULER_DISTANCE);
+
+ gdk_cairo_set_source_rgba (cr, &color);
+ pango_cairo_show_layout (cr, layout);
+
+ g_object_unref (layout);
+
+ cairo_restore (cr);
+
+ cairo_set_line_width (cr, 1);
+
+ gdk_cairo_set_source_rgba (cr, &color);
+
+ if (ltr)
+ {
+ cairo_move_to (cr, pos_x - RULER_DISTANCE, pos_y);
+ cairo_line_to (cr, pos_x - RULER_DISTANCE, pos_y + h);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
+ cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
+ cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
+ cairo_stroke (cr);
+ }
+ else
+ {
+ cairo_move_to (cr, pos_x + w + RULER_DISTANCE, pos_y);
+ cairo_line_to (cr, pos_x + w + RULER_DISTANCE, pos_y + h);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
+ cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
+ cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
+ cairo_stroke (cr);
+ }
+
+ cairo_move_to (cr, pos_x, pos_y + h + RULER_DISTANCE);
+ cairo_line_to (cr, pos_x + w, pos_y + h + RULER_DISTANCE);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
+ cairo_line_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
+ cairo_line_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
+ cairo_stroke (cr);
+ }
+}
+
+static void
+redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
+{
+ if (dialog->page_layout_preview)
+ gtk_widget_queue_draw (dialog->page_layout_preview);
+}
+
+static void
+update_number_up_layout (GtkPrintUnixDialog *dialog)
+{
+ GtkPrintCapabilities caps;
+ GtkPrinterOptionSet *set;
+ GtkNumberUpLayout layout;
+ GtkPrinterOption *option;
+ GtkPrinterOption *old_option;
+ GtkPageOrientation page_orientation;
+
+ set = dialog->options;
+
+ caps = dialog->manual_capabilities | dialog->printer_capabilities;
+
+ if (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT)
+ {
+ if (dialog->number_up_layout_n_option == NULL)
+ {
+ dialog->number_up_layout_n_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
+ if (dialog->number_up_layout_n_option == NULL)
+ {
+ const char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" };
+ /* Translators: These strings name the possible arrangements of
+ * multiple pages on a sheet when printing (same as in gtkprintbackendcups.c)
+ */
+ const char *n_up_layout_display[] = { N_("Left to right, top to bottom"), N_("Left to right, bottom to top"),
+ N_("Right to left, top to bottom"), N_("Right to left, bottom to top"),
+ N_("Top to bottom, left to right"), N_("Top to bottom, right to left"),
+ N_("Bottom to top, left to right"), N_("Bottom to top, right to left") };
+ int i;
+
+ dialog->number_up_layout_n_option = gtk_printer_option_new ("gtk-n-up-layout",
+ _("Page Ordering"),
+ GTK_PRINTER_OPTION_TYPE_PICKONE);
+ gtk_printer_option_allocate_choices (dialog->number_up_layout_n_option, 8);
+
+ for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++)
+ {
+ dialog->number_up_layout_n_option->choices[i] = g_strdup (n_up_layout[i]);
+ dialog->number_up_layout_n_option->choices_display[i] = g_strdup (_(n_up_layout_display[i]));
+ }
+ }
+ g_object_ref (dialog->number_up_layout_n_option);
+
+ dialog->number_up_layout_2_option = gtk_printer_option_new ("gtk-n-up-layout",
+ _("Page Ordering"),
+ GTK_PRINTER_OPTION_TYPE_PICKONE);
+ gtk_printer_option_allocate_choices (dialog->number_up_layout_2_option, 2);
+ }
+
+ page_orientation = gtk_page_setup_get_orientation (dialog->page_setup);
+ if (page_orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+ page_orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+ {
+ if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
+ dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[2]))
+ {
+ g_free (dialog->number_up_layout_2_option->choices_display[0]);
+ g_free (dialog->number_up_layout_2_option->choices_display[1]);
+ dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
+ dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[2];
+ dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Left to right"));
+ dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Right to left"));
+ }
+ }
+ else
+ {
+ if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
+ dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[1]))
+ {
+ g_free (dialog->number_up_layout_2_option->choices_display[0]);
+ g_free (dialog->number_up_layout_2_option->choices_display[1]);
+ dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
+ dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[1];
+ dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Top to bottom"));
+ dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Bottom to top"));
+ }
+ }
+
+ layout = dialog_get_number_up_layout (dialog);
+
+ old_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
+ if (old_option != NULL)
+ gtk_printer_option_set_remove (set, old_option);
+
+ if (dialog_get_pages_per_sheet (dialog) != 1)
+ {
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+ enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
+
+ if (dialog_get_pages_per_sheet (dialog) == 2)
+ {
+ option = dialog->number_up_layout_2_option;
+
+ switch (layout)
+ {
+ case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
+ case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
+ enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
+ break;
+
+ case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
+ case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
+ enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP);
+ break;
+
+ case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
+ case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
+ enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM);
+ break;
+
+ case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
+ case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
+ enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP);
+ break;
+
+ default:
+ g_assert_not_reached();
+ enum_value = NULL;
+ }
+ }
+ else
+ {
+ option = dialog->number_up_layout_n_option;
+
+ enum_value = g_enum_get_value (enum_class, layout);
+ }
+
+ g_assert (enum_value != NULL);
+ gtk_printer_option_set (option, enum_value->value_nick);
+ g_type_class_unref (enum_class);
+
+ gtk_printer_option_set_add (set, option);
+ }
+ }
+
+ setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
+
+ if (dialog->number_up_layout != NULL)
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->number_up_layout),
+ (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) &&
+ (dialog_get_pages_per_sheet (dialog) > 1));
+}
+
+static void
+custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
+ int response_id,
+ gpointer user_data)
+{
+ GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (user_data);
+
+ dialog->internal_page_setup_change = TRUE;
+ gtk_print_load_custom_papers (dialog->custom_paper_list);
+ update_paper_sizes (dialog);
+ dialog->internal_page_setup_change = FALSE;
+
+ if (dialog->page_setup_set)
+ {
+ GListModel *model;
+ guint n, i;
+
+ model = G_LIST_MODEL (dialog->custom_paper_list);
+ n = g_list_model_get_n_items (model);
+ for (i = 0; i < n; i++)
+ {
+ GtkPageSetup *page_setup = g_list_model_get_item (model, i);
+
+ if (g_strcmp0 (gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (page_setup)),
+ gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (dialog->page_setup))) == 0)
+ gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
+
+ g_clear_object (&page_setup);
+ }
+ }
+
+ gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
+}
+
+static void
+orientation_changed (GObject *object,
+ GParamSpec *pspec,
+ GtkPrintUnixDialog *dialog)
+{
+ GtkPageOrientation orientation;
+ GtkPageSetup *page_setup;
+
+ if (dialog->internal_page_setup_change)
+ return;
+
+ orientation = (GtkPageOrientation) gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->orientation_combo));
+
+ if (dialog->page_setup)
+ {
+ page_setup = gtk_page_setup_copy (dialog->page_setup);
+ if (page_setup)
+ gtk_page_setup_set_orientation (page_setup, orientation);
+
+ gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
+ }
+
+ redraw_page_layout_preview (dialog);
+}
+
+static void
+paper_size_changed (GtkDropDown *combo_box,
+ GParamSpec *pspec,
+ GtkPrintUnixDialog *dialog)
+{
+ GtkPageSetup *page_setup, *last_page_setup;
+ GtkPageOrientation orientation;
+ guint selected;
+
+ if (dialog->internal_page_setup_change)
+ return;
+
+ selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
+ if (selected != GTK_INVALID_LIST_POSITION)
+ {
+ GListModel *papers, *model;
+
+ papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+ page_setup = g_list_model_get_item (papers, selected);
+ model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
+
+ if (model == G_LIST_MODEL (dialog->manage_papers_list))
+ {
+ GtkWidget *custom_paper_dialog;
+
+ /* Change from "manage" menu item to last value */
+ if (dialog->page_setup)
+ last_page_setup = g_object_ref (dialog->page_setup);
+ else
+ last_page_setup = gtk_page_setup_new (); /* "good" default */
+
+ if (!set_paper_size (dialog, last_page_setup, FALSE, FALSE))
+ set_paper_size (dialog, last_page_setup, TRUE, TRUE);
+ g_object_unref (last_page_setup);
+
+ /* And show the custom paper dialog */
+ custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), _("Manage Custom Sizes"));
+ g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
+ gtk_window_present (GTK_WINDOW (custom_paper_dialog));
+
+ g_object_unref (page_setup);
+
+ return;
+ }
+
+ if (dialog->page_setup)
+ orientation = gtk_page_setup_get_orientation (dialog->page_setup);
+ else
+ orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
+
+ gtk_page_setup_set_orientation (page_setup, orientation);
+ gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
+
+ g_object_unref (page_setup);
+ }
+
+ redraw_page_layout_preview (dialog);
+}
+
+/**
+ * gtk_print_unix_dialog_new:
+ * @title: (nullable): Title of the dialog
+ * @parent: (nullable): Transient parent of the dialog
+ *
+ * Creates a new `GtkPrintUnixDialog`.
+ *
+ * Returns: a new `GtkPrintUnixDialog`
+ */
+GtkWidget *
+gtk_print_unix_dialog_new (const char *title,
+ GtkWindow *parent)
+{
+ GtkWidget *result;
+
+ result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
+ "transient-for", parent,
+ "title", title ? title : _("Print"),
+ NULL);
+
+ return result;
+}
+
+/**
+ * gtk_print_unix_dialog_get_selected_printer: (attributes org.gtk.Method.get_property=selected-printer)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the currently selected printer.
+ *
+ * Returns: (transfer none) (nullable): the currently selected printer
+ */
+GtkPrinter *
+gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
+
+ return dialog->current_printer;
+}
+
+/**
+ * gtk_print_unix_dialog_set_page_setup: (attributes org.gtk.Method.set_property=page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @page_setup: a `GtkPageSetup`
+ *
+ * Sets the page setup of the `GtkPrintUnixDialog`.
+ */
+void
+gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
+ GtkPageSetup *page_setup)
+{
+ g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+ g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
+
+ if (dialog->page_setup != page_setup)
+ {
+ g_clear_object (&dialog->page_setup);
+ dialog->page_setup = g_object_ref (page_setup);
+
+ dialog->page_setup_set = TRUE;
+
+ g_object_notify (G_OBJECT (dialog), "page-setup");
+ }
+}
+
+/**
+ * gtk_print_unix_dialog_get_page_setup: (attributes org.gtk.Method.get_property=page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the page setup that is used by the `GtkPrintUnixDialog`.
+ *
+ * Returns: (transfer none): the page setup of @dialog.
+ */
+GtkPageSetup *
+gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
+
+ return dialog->page_setup;
+}
+
+/**
+ * gtk_print_unix_dialog_get_page_setup_set:
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether a page setup was set by the user.
+ *
+ * Returns: whether a page setup was set by user.
+ */
+gboolean
+gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+ return dialog->page_setup_set;
+}
+
+/**
+ * gtk_print_unix_dialog_set_current_page: (attributes org.gtk.Method.set_property=current-page)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @current_page: the current page number.
+ *
+ * Sets the current page number.
+ *
+ * If @current_page is not -1, this enables the current page choice
+ * for the range of pages to print.
+ */
+void
+gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
+ int current_page)
+{
+ g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+ if (dialog->current_page != current_page)
+ {
+ dialog->current_page = current_page;
+
+ if (dialog->current_page_radio)
+ gtk_widget_set_sensitive (dialog->current_page_radio, current_page != -1);
+
+ g_object_notify (G_OBJECT (dialog), "current-page");
+ }
+}
+
+/**
+ * gtk_print_unix_dialog_get_current_page: (attributes org.gtk.Method.get_property=current-page)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the current page of the `GtkPrintUnixDialog`.
+ *
+ * Returns: the current page of @dialog
+ */
+int
+gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
+
+ return dialog->current_page;
+}
+
+static gboolean
+set_active_printer (GtkPrintUnixDialog *dialog,
+ const char *printer_name)
+{
+ GListModel *model;
+ GtkPrinter *printer;
+ guint i;
+
+ model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
+
+ for (i = 0; i < g_list_model_get_n_items (model); i++)
+ {
+ printer = g_list_model_get_item (model, i);
+
+ if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
+ {
+ gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
+
+ g_free (dialog->waiting_for_printer);
+ dialog->waiting_for_printer = NULL;
+
+ g_object_unref (printer);
+ return TRUE;
+ }
+
+ g_object_unref (printer);
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_print_unix_dialog_set_settings: (attributes org.gtk.Method.set_property=print-settings)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @settings: (nullable): a `GtkPrintSettings`
+ *
+ * Sets the `GtkPrintSettings` for the `GtkPrintUnixDialog`.
+ *
+ * Typically, this is used to restore saved print settings
+ * from a previous print operation before the print dialog
+ * is shown.
+ */
+void
+gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
+ GtkPrintSettings *settings)
+{
+ const char *printer;
+ GtkPageRange *ranges;
+ int num_ranges;
+
+ g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+ g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
+
+ if (settings != NULL)
+ {
+ dialog_set_collate (dialog, gtk_print_settings_get_collate (settings));
+ dialog_set_reverse (dialog, gtk_print_settings_get_reverse (settings));
+ dialog_set_n_copies (dialog, gtk_print_settings_get_n_copies (settings));
+ dialog_set_scale (dialog, gtk_print_settings_get_scale (settings));
+ dialog_set_page_set (dialog, gtk_print_settings_get_page_set (settings));
+ dialog_set_print_pages (dialog, gtk_print_settings_get_print_pages (settings));
+ ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
+ if (ranges)
+ {
+ dialog_set_page_ranges (dialog, ranges, num_ranges);
+ g_free (ranges);
+ }
+
+ dialog->format_for_printer =
+ g_strdup (gtk_print_settings_get (settings, "format-for-printer"));
+ }
+
+ if (dialog->initial_settings)
+ g_object_unref (dialog->initial_settings);
+
+ dialog->initial_settings = settings;
+
+ g_free (dialog->waiting_for_printer);
+ dialog->waiting_for_printer = NULL;
+
+ if (settings)
+ {
+ g_object_ref (settings);
+
+ printer = gtk_print_settings_get_printer (settings);
+
+ if (printer && !set_active_printer (dialog, printer))
+ dialog->waiting_for_printer = g_strdup (printer);
+ }
+
+ g_object_notify (G_OBJECT (dialog), "print-settings");
+}
+
+/**
+ * gtk_print_unix_dialog_get_settings: (attributes org.gtk.Method.set_property=print-settings)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets a new `GtkPrintSettings` object that represents the
+ * current values in the print dialog.
+ *
+ * Note that this creates a new object, and you need to unref
+ * it if don’t want to keep it.
+ *
+ * Returns: (transfer full): a new `GtkPrintSettings` object with the values from @dialog
+ */
+GtkPrintSettings *
+gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
+{
+ GtkPrintSettings *settings;
+ GtkPrintPages print_pages;
+ GtkPageRange *ranges;
+ int n_ranges;
+
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
+
+ settings = gtk_print_settings_new ();
+
+ if (dialog->current_printer)
+ gtk_print_settings_set_printer (settings,
+ gtk_printer_get_name (dialog->current_printer));
+ else
+ gtk_print_settings_set_printer (settings, "default");
+
+ gtk_print_settings_set (settings, "format-for-printer",
+ dialog->format_for_printer);
+
+ gtk_print_settings_set_collate (settings,
+ dialog_get_collate (dialog));
+
+ gtk_print_settings_set_reverse (settings,
+ dialog_get_reverse (dialog));
+
+ gtk_print_settings_set_n_copies (settings,
+ dialog_get_n_copies (dialog));
+
+ gtk_print_settings_set_scale (settings,
+ dialog_get_scale (dialog));
+
+ gtk_print_settings_set_page_set (settings,
+ dialog_get_page_set (dialog));
+
+ print_pages = dialog_get_print_pages (dialog);
+ gtk_print_settings_set_print_pages (settings, print_pages);
+
+ ranges = dialog_get_page_ranges (dialog, &n_ranges);
+ if (ranges)
+ {
+ gtk_print_settings_set_page_ranges (settings, ranges, n_ranges);
+ g_free (ranges);
+ }
+
+ /* TODO: print when. How to handle? */
+
+ if (dialog->current_printer)
+ _gtk_printer_get_settings_from_options (dialog->current_printer,
+ dialog->options,
+ settings);
+
+ return settings;
+}
+
+/**
+ * gtk_print_unix_dialog_add_custom_tab:
+ * @dialog: a `GtkPrintUnixDialog`
+ * @child: the widget to put in the custom tab
+ * @tab_label: the widget to use as tab label
+ *
+ * Adds a custom tab to the print dialog.
+ */
+void
+gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
+ GtkWidget *child,
+ GtkWidget *tab_label)
+{
+ gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->notebook),
+ child, tab_label, 2);
+ gtk_widget_set_visible (child, TRUE);
+ gtk_widget_set_visible (tab_label, TRUE);
+}
+
+/**
+ * gtk_print_unix_dialog_set_manual_capabilities: (attributes org.gtk.Method.set_property=manual-capabilities)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @capabilities: the printing capabilities of your application
+ *
+ * This lets you specify the printing capabilities your application
+ * supports.
+ *
+ * For instance, if you can handle scaling the output then you pass
+ * %GTK_PRINT_CAPABILITY_SCALE. If you don’t pass that, then the dialog
+ * will only let you select the scale if the printing system automatically
+ * handles scaling.
+ */
+void
+gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog,
+ GtkPrintCapabilities capabilities)
+{
+ if (dialog->manual_capabilities != capabilities)
+ {
+ dialog->manual_capabilities = capabilities;
+ update_dialog_from_capabilities (dialog);
+
+ if (dialog->current_printer)
+ {
+ g_clear_object (&dialog->current_printer);
+ selected_printer_changed (dialog);
+ }
+
+ g_object_notify (G_OBJECT (dialog), "manual-capabilities");
+ }
+}
+
+/**
+ * gtk_print_unix_dialog_get_manual_capabilities: (attributes org.gtk.Method.get_property=manual-capabilities)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the capabilities that have been set on this `GtkPrintUnixDialog`.
+ *
+ * Returns: the printing capabilities
+ */
+GtkPrintCapabilities
+gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+ return dialog->manual_capabilities;
+}
+
+/**
+ * gtk_print_unix_dialog_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @support_selection: %TRUE to allow print selection
+ *
+ * Sets whether the print dialog allows user to print a selection.
+ */
+void
+gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
+ gboolean support_selection)
+{
+ g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+ support_selection = support_selection != FALSE;
+ if (dialog->support_selection != support_selection)
+ {
+ dialog->support_selection = support_selection;
+
+ if (dialog->selection_radio)
+ {
+ gtk_widget_set_visible (dialog->selection_radio, support_selection);
+ gtk_widget_set_sensitive (dialog->selection_radio, support_selection && dialog->has_selection);
+ }
+
+ g_object_notify (G_OBJECT (dialog), "support-selection");
+ }
+}
+
+/**
+ * gtk_print_unix_dialog_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether the print dialog allows user to print a selection.
+ *
+ * Returns: whether the application supports print of selection
+ */
+gboolean
+gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+ return dialog->support_selection;
+}
+
+/**
+ * gtk_print_unix_dialog_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @has_selection: %TRUE indicates that a selection exists
+ *
+ * Sets whether a selection exists.
+ */
+void
+gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
+ gboolean has_selection)
+{
+ g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+ has_selection = has_selection != FALSE;
+ if (dialog->has_selection != has_selection)
+ {
+ dialog->has_selection = has_selection;
+
+ if (dialog->selection_radio)
+ {
+ if (dialog->support_selection)
+ gtk_widget_set_sensitive (dialog->selection_radio, has_selection);
+ else
+ gtk_widget_set_sensitive (dialog->selection_radio, FALSE);
+ }
+
+ g_object_notify (G_OBJECT (dialog), "has-selection");
+ }
+}
+
+/**
+ * gtk_print_unix_dialog_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether there is a selection.
+ *
+ * Returns: whether there is a selection
+ */
+gboolean
+gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+ return dialog->has_selection;
+}
+
+/**
+ * gtk_print_unix_dialog_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @embed: embed page setup selection
+ *
+ * Embed page size combo box and orientation combo box into page setup page.
+ */
+void
+gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
+ gboolean embed)
+{
+ g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+ embed = embed != FALSE;
+ if (dialog->embed_page_setup != embed)
+ {
+ dialog->embed_page_setup = embed;
+
+ gtk_widget_set_sensitive (dialog->paper_size_combo, dialog->embed_page_setup);
+ gtk_widget_set_sensitive (dialog->orientation_combo, dialog->embed_page_setup);
+
+ if (dialog->embed_page_setup)
+ {
+ if (dialog->paper_size_combo != NULL)
+ g_signal_connect (dialog->paper_size_combo, "notify::selected", G_CALLBACK (paper_size_changed), dialog);
+
+ if (dialog->orientation_combo)
+ g_signal_connect (dialog->orientation_combo, "notify::selected", G_CALLBACK (orientation_changed), dialog);
+ }
+ else
+ {
+ if (dialog->paper_size_combo != NULL)
+ g_signal_handlers_disconnect_by_func (dialog->paper_size_combo, G_CALLBACK (paper_size_changed), dialog);
+
+ if (dialog->orientation_combo)
+ g_signal_handlers_disconnect_by_func (dialog->orientation_combo, G_CALLBACK (orientation_changed), dialog);
+ }
+
+ dialog->internal_page_setup_change = TRUE;
+ update_paper_sizes (dialog);
+ dialog->internal_page_setup_change = FALSE;
+ }
+}
+
+/**
+ * gtk_print_unix_dialog_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether to embed the page setup.
+ *
+ * Returns: whether to embed the page setup
+ */
+gboolean
+gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog)
+{
+ g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+ return dialog->embed_page_setup;
+}
--- /dev/null
+/* GtkPrintUnixDialog
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.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/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+#include <gtk/print/gtkprinter.h>
+#include <gtk/print/gtkprintjob.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINT_UNIX_DIALOG (gtk_print_unix_dialog_get_type ())
+#define GTK_PRINT_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_UNIX_DIALOG, GtkPrintUnixDialog))
+#define GTK_IS_PRINT_UNIX_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_UNIX_DIALOG))
+
+
+typedef struct _GtkPrintUnixDialog GtkPrintUnixDialog;
+
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_print_unix_dialog_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkWidget * gtk_print_unix_dialog_new (const char *title,
+ GtkWindow *parent);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
+ GtkPageSetup *page_setup);
+GDK_AVAILABLE_IN_ALL
+GtkPageSetup * gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
+ int current_page);
+GDK_AVAILABLE_IN_ALL
+int gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
+ GtkPrintSettings *settings);
+GDK_AVAILABLE_IN_ALL
+GtkPrintSettings * gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+GtkPrinter * gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
+ GtkWidget *child,
+ GtkWidget *tab_label);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog,
+ GtkPrintCapabilities capabilities);
+GDK_AVAILABLE_IN_ALL
+GtkPrintCapabilities gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
+ gboolean support_selection);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
+ gboolean has_selection);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
+ gboolean embed);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintUnixDialog, g_object_unref)
+
+G_END_DECLS
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <gdk/gdk.h>
+#include "gtkenums.h"
+
+
+G_BEGIN_DECLS
+
+#define MM_PER_INCH 25.4
+#define POINTS_PER_INCH 72
+
+double _gtk_print_convert_to_mm (double len, GtkUnit unit);
+double _gtk_print_convert_from_mm (double len, GtkUnit unit);
+
+G_END_DECLS
+
--- /dev/null
+/* GtkUnixPrint
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#define __GTK_UNIX_PRINT_H_INSIDE__
+
+#include <gtk/print/gtkpagesetupunixdialog.h>
+#include <gtk/print/gtkprinter.h>
+#include <gtk/print/gtkprintjob.h>
+#include <gtk/print/gtkprintunixdialog.h>
+
+#undef __GTK_UNIX_PRINT_H_INSIDE__
+
'gtkprintsettings.c',
'gtkprintutils.c',
])
+
+gtk_unix_print_headers = []
+gtk_unix_print_sources = []
+
+if os_unix
+ gtk_unix_print_headers += files([
+ 'gtkpagesetupunixdialog.h',
+ 'gtkprintunixdialog.h',
+ 'gtkprinter.h',
+ 'gtkprintjob.h',
+ 'gtkunixprint.h',
+ ])
+
+ gtk_unix_print_sources += files([
+ 'gtkcustompaperunixdialog.c',
+ 'gtkpagesetupunixdialog.c',
+ 'gtkprintbackend.c',
+ 'gtkprinter.c',
+ 'gtkprinteroption.c',
+ 'gtkprinteroptionset.c',
+ 'gtkprinteroptionwidget.c',
+ 'gtkprintjob.c',
+ 'gtkprintoperation-unix.c',
+ 'gtkprintoperation-portal.c',
+ 'gtkprintunixdialog.c',
+ ])
+endif
+
+gtk_win32_print_headers = []
+gtk_win32_print_sources = []
+
+if os_win32
+ gtk_win32_print_sources += files([
+ 'gtkprint-win32.c',
+ 'gtkprintoperation-win32.c',
+ ])
+
+ if cc.has_header_symbol('windows.h', 'IPrintDialogCallback')
+ cdata.set('HAVE_IPRINTDIALOGCALLBACK', 1)
+ endif
+endif
--- /dev/null
+#define N_(s) s
+
+/* The paper size names are from:
+ * PWG 5101.1-2002 PWG: Standard for Media Standardized Names
+ * PWG 5101.1-2013 PWG: PWG Media Standardized Names 2.0 (MSN2)
+ *
+ * The PPD names come from the PPD specification and from
+ * CUPS' cups/pwg-media.c.
+ */
+
+typedef struct {
+ const char *name;
+ const char *size;
+ const char *display_name;
+ const char *ppd_name;
+} PaperInfo;
+
+static const PaperInfo standard_names[] = {
+ /* sorted by name, remember to sort when changing */
+ {"asme_f", "28x40in", N_("asme_f")}, /* f 5 e1 */
+ {"iso_2a0", "1189x1682mm", N_("A0×2")},
+ {"iso_a0", "841x1189mm", N_("A0"), "A0"},
+ {"iso_a0x3", "1189x2523mm", N_("A0×3")},
+ {"iso_a1", "594x841mm", N_("A1"), "A1"},
+ {"iso_a10", "26x37mm", N_("A10"), "A10"},
+ {"iso_a1x3", "841x1783mm", N_("A1×3")},
+ {"iso_a1x4", "841x2378mm", N_("A1×4")},
+ {"iso_a2", "420x594mm", N_("A2"), "A2"},
+ {"iso_a2x3", "594x1261mm", N_("A2×3")},
+ {"iso_a2x4", "594x1682mm", N_("A2×4")},
+ {"iso_a2x5", "594x2102mm", N_("A2×5")},
+ {"iso_a3", "297x420mm", N_("A3"), "A3"},
+ {"iso_a3-extra", "322x445mm", N_("A3 Extra"), "A3Extra"},
+ {"iso_a3x3", "420x891mm", N_("A3×3")},
+ {"iso_a3x4", "420x1189mm", N_("A3×4")},
+ {"iso_a3x5", "420x1486mm", N_("A3×5")},
+ {"iso_a3x6", "420x1783mm", N_("A3×6")},
+ {"iso_a3x7", "420x2080mm", N_("A3×7")},
+ {"iso_a4", "210x297mm", N_("A4"), "A4"},
+ {"iso_a4-extra", "235.5x322.3mm", N_("A4 Extra"), "A4Extra"},
+ {"iso_a4-tab", "225x297mm", N_("A4 Tab"), "A4Tab"},
+ {"iso_a4x3", "297x630mm", N_("A4×3")},
+ {"iso_a4x4", "297x841mm", N_("A4×4")},
+ {"iso_a4x5", "297x1051mm", N_("A4×5")},
+ {"iso_a4x6", "297x1261mm", N_("A4×6")},
+ {"iso_a4x7", "297x1471mm", N_("A4×7")},
+ {"iso_a4x8", "297x1682mm", N_("A4×8")},
+ {"iso_a4x9", "297x1892mm", N_("A4×9")},
+ {"iso_a5", "148x210mm", N_("A5"), "A5"},
+ {"iso_a5-extra", "174x235mm", N_("A5 Extra"), "A5Extra"},
+ {"iso_a6", "105x148mm", N_("A6"), "A6"},
+ {"iso_a7", "74x105mm", N_("A7"), "A7"},
+ {"iso_a8", "52x74mm", N_("A8"), "A8"},
+ {"iso_a9", "37x52mm", N_("A9"), "A9"},
+ {"iso_b0", "1000x1414mm", N_("B0"), "ISOB0"},
+ {"iso_b1", "707x1000mm", N_("B1"), "ISOB1"},
+ {"iso_b10", "31x44mm", N_("B10"), "ISOB10"},
+ {"iso_b2", "500x707mm", N_("B2"), "ISOB2"},
+ {"iso_b3", "353x500mm", N_("B3"), "ISOB3"},
+ {"iso_b4", "250x353mm", N_("B4"), "ISOB4"},
+ {"iso_b5", "176x250mm", N_("B5"), "ISOB5"},
+ {"iso_b5-extra", "201x276mm", N_("B5 Extra"), "ISOB5Extra"},
+ {"iso_b6", "125x176mm", N_("B6"), "ISOB6"},
+ {"iso_b6c4", "125x324mm", N_("B6/C4")}, /* b6/c4 Envelope */
+ {"iso_b7", "88x125mm", N_("B7"), "ISOB7"},
+ {"iso_b8", "62x88mm", N_("B8"), "ISOB8"},
+ {"iso_b9", "44x62mm", N_("B9"), "ISOB9"},
+ {"iso_c0", "917x1297mm", N_("C0"), "EnvC0"},
+ {"iso_c1", "648x917mm", N_("C1"), "EnvC1"},
+ {"iso_c10", "28x40mm", N_("C10"), "EnvC10"},
+ {"iso_c2", "458x648mm", N_("C2"), "EnvC2"},
+ {"iso_c3", "324x458mm", N_("C3"), "EnvC3"},
+ {"iso_c4", "229x324mm", N_("C4"), "EnvC4"},
+ {"iso_c5", "162x229mm", N_("C5"), "EnvC5"},
+ {"iso_c6", "114x162mm", N_("C6"), "EnvC6"},
+ {"iso_c6c5", "114x229mm", N_("C6/C5"), "EnvC65"},
+ {"iso_c7", "81x114mm", N_("C7"), "EnvC7"},
+ {"iso_c7c6", "81x162mm", N_("C7/C6")}, /* c7/c6 Envelope */
+ {"iso_c8", "57x81mm", N_("C8"), "EnvC8"},
+ {"iso_c9", "40x57mm", N_("C9"), "EnvC9"},
+ {"iso_dl", "110x220mm", N_("DL Envelope"), "EnvDL"}, /* iso-designated 1, 2 designated-long, dl Envelope */
+ {"iso_ra0", "860x1220mm", N_("RA0")},
+ {"iso_ra1", "610x860mm", N_("RA1")},
+ {"iso_ra2", "430x610mm", N_("RA2")},
+ {"iso_ra3", "305x430mm", N_("RA3")},
+ {"iso_ra4", "215x305mm", N_("RA4")},
+ {"iso_sra0", "900x1280mm", N_("SRA0")},
+ {"iso_sra1", "640x900mm", N_("SRA1")},
+ {"iso_sra2", "450x640mm", N_("SRA2")},
+ {"iso_sra3", "320x450mm", N_("SRA3")},
+ {"iso_sra4", "225x320mm", N_("SRA4")},
+ {"jis_b0", "1030x1456mm", N_("JB0"), "B0"},
+ {"jis_b1", "728x1030mm", N_("JB1"), "B1"},
+ {"jis_b10", "32x45mm", N_("JB10"), "B10"},
+ {"jis_b2", "515x728mm", N_("JB2"), "B2"},
+ {"jis_b3", "364x515mm", N_("JB3"), "B3"},
+ {"jis_b4", "257x364mm", N_("JB4"), "B4"},
+ {"jis_b5", "182x257mm", N_("JB5"), "B5"},
+ {"jis_b6", "128x182mm", N_("JB6"), "B6"},
+ {"jis_b7", "91x128mm", N_("JB7"), "B7"},
+ {"jis_b8", "64x91mm", N_("JB8"), "B8"},
+ {"jis_b9", "45x64mm", N_("JB9"), "B9"},
+ {"jis_exec", "216x330mm", N_("jis exec")},
+ {"jpn_chou2", "111.1x146mm", N_("Choukei 2 Envelope")},
+ {"jpn_chou3", "120x235mm", N_("Choukei 3 Envelope"), "EnvChou3"},
+ {"jpn_chou4", "90x205mm", N_("Choukei 4 Envelope"), "EnvChou4"},
+ {"jpn_chou40", "90x225mm", N_("Choukei 40 Envelope"), "EnvChou40"},
+ {"jpn_hagaki", "100x148mm", N_("hagaki (postcard)"), "Postcard"},
+ {"jpn_kahu", "240x322.1mm", N_("kahu Envelope")},
+ {"jpn_kaku2", "240x332mm", N_("kaku2 Envelope"), "EnvKaku2"},
+ {"jpn_kaku3", "216x277mm", N_("kaku3 Envelope"), "EnvKaku3"},
+ {"jpn_kaku4", "197x267mm", N_("kaku4 Envelope"), "EnvKaku4"},
+ {"jpn_kaku5", "190x240mm", N_("kaku5 Envelope"), "EnvKaku5"},
+ {"jpn_kaku7", "142x205mm", N_("kaku7 Envelope"), "EnvKaku7"},
+ {"jpn_kaku8", "119x197mm", N_("kaku8 Envelope"), "EnvKaku8"},
+ {"jpn_oufuku", "148x200mm", N_("oufuku (reply postcard)"), "DoublePostcard"},
+ {"jpn_you4", "105x235mm", N_("you4 Envelope"), "EnvYou4"},
+ {"jpn_you6", "98x190mm", N_("you6 Envelope"), "EnvYou6"},
+ {"na_10x11", "10x11in", N_("10×11"), "10x11"},
+ {"na_10x13", "10x13in", N_("10×13"), "10x13"},
+ {"na_10x14", "10x14in", N_("10×14"), "10x14"},
+ {"na_10x15", "10x15in", N_("10×15"), "10x15"},
+ {"na_11x12", "11x12in", N_("11×12"), "12x11"},
+ {"na_11x15", "11x15in", N_("11×15"), "15x11"},
+ {"na_12x19", "12x19in", N_("12×19"), "12x19"},
+ {"na_5x7", "5x7in", N_("5×7"), "5x7"},
+ {"na_6x9", "6x9in", N_("6×9 Envelope"), "6x9"},
+ {"na_7x9", "7x9in", N_("7×9 Envelope"), "7x9"},
+ {"na_8x10", "8x10in", N_("8×10 Envelope"), "8x10"},
+ {"na_9x11", "9x11in", N_("9×11 Envelope"), "9x11"},
+ {"na_9x12", "9x12in", N_("9×12 Envelope"), "9x12"},
+ {"na_a2", "4.375x5.75in", N_("a2 Envelope"), "EnvA2"},
+ {"na_arch-a", "9x12in", N_("Arch A"), "ARCHA"},
+ {"na_arch-b", "12x18in", N_("Arch B"), "ARCHB"},
+ {"na_arch-c", "18x24in", N_("Arch C"), "ARCHC"},
+ {"na_arch-d", "24x36in", N_("Arch D"), "ARCHD"},
+ {"na_arch-e", "36x48in", N_("Arch E"), "ARCHE"},
+ {"na_b-plus", "12x19.17in", N_("b-plus"), "SuperB"},
+ {"na_c", "17x22in", N_("c"), "AnsiC"},
+ {"na_c5", "6.5x9.5in", N_("c5 Envelope"), "6.5x9.5"},
+ {"na_d", "22x34in", N_("d"), "AnsiD"},
+ {"na_e", "34x44in", N_("e"), "AnsiE"},
+ {"na_edp", "11x14in", N_("edp"), "11x14"},
+ {"na_eur-edp", "12x14in", N_("European edp")},
+ {"na_executive", "7.25x10.5in", N_("Executive"), "Executive"},
+ {"na_f", "44x68in", N_("f"), "AnsiF"},
+ {"na_fanfold-eur", "8.5x12in", N_("Fan-Fold European"), "FanFoldGerman"},
+ {"na_fanfold-us", "11x14.875in", N_("Fan-Fold US"), "FanFoldUS"},
+ {"na_foolscap", "8.5x13in", N_("Fan-Fold German Legal"), "FanFoldGermanLegal"}, /* foolscap, german-legal-fanfold */
+ {"na_govt-legal", "8x13in", N_("Government Legal"), "8x13"},
+ {"na_govt-letter", "8x10in", N_("Government Letter"), "8x10"},
+ {"na_index-3x5", "3x5in", N_("Index 3×5"), "3x5"},
+ {"na_index-4x6", "4x6in", N_("Index 4×6 (postcard)"), "4x6"},
+ {"na_index-4x6-ext", "6x8in", N_("Index 4×6 ext")},
+ {"na_index-5x8", "5x8in", N_("Index 5×8"), "5x8"},
+ {"na_invoice", "5.5x8.5in", N_("Invoice"), "Statement"}, /* invoice, statement, mini, half-letter */
+ {"na_ledger", "11x17in", N_("Tabloid"), "Ledger"}, /* tabloid, engineering-b */
+ {"na_legal", "8.5x14in", N_("US Legal"), "Legal"},
+ {"na_legal-extra", "9.5x15in", N_("US Legal Extra"), "LegalExtra"},
+ {"na_letter", "8.5x11in", N_("US Letter"), "Letter"},
+ {"na_letter-extra", "9.5x12in", N_("US Letter Extra"), "LetterExtra"},
+ {"na_letter-plus", "8.5x12.69in", N_("US Letter Plus"), "LetterPlus"},
+ {"na_monarch", "3.875x7.5in", N_("Monarch Envelope"), "EnvMonarch"},
+ {"na_number-10", "4.125x9.5in", N_("#10 Envelope"), "Env10"}, /* na-number-10-envelope 1, 2 comm-10 Envelope */
+ {"na_number-11", "4.5x10.375in", N_("#11 Envelope"), "Env11"}, /* number-11 Envelope */
+ {"na_number-12", "4.75x11in", N_("#12 Envelope"), "Env12"}, /* number-12 Envelope */
+ {"na_number-14", "5x11.5in", N_("#14 Envelope"), "Env14"}, /* number-14 Envelope */
+ {"na_number-9", "3.875x8.875in", N_("#9 Envelope"), "Env9"},
+ {"na_oficio", "8.5x13.4in", N_("Oficio"), "Oficio"},
+ {"na_personal", "3.625x6.5in", N_("Personal Envelope"), "EnvPersonal"},
+ {"na_quarto", "8.5x10.83in", N_("Quarto"), "Quarto"},
+ {"na_super-a", "8.94x14in", N_("Super A"), "SuperA"},
+ {"na_super-b", "13x19in", N_("Super B"), "SuperB"},
+ {"na_wide-format", "30x42in", N_("Wide Format")},
+ {"oe_photo-l", "3.5x5in", N_("Photo L"), "3.5x5"},
+ {"om_dai-pa-kai", "275x395mm", N_("Dai-pa-kai")},
+ {"om_folio", "210x330mm", N_("Folio"), "Folio"},
+ {"om_folio-sp", "215x315mm", N_("Folio sp"), "FolioSP"},
+ {"om_invite", "220x220mm", N_("Invite Envelope"), "EnvInvite"},
+ {"om_italian", "110x230mm", N_("Italian Envelope"), "EnvItalian"},
+ {"om_juuro-ku-kai", "198x275mm", N_("juuro-ku-kai")},
+ {"om_large-photo", "200x300mm", N_("Large Photo"), "om_large-photo"},
+ {"om_medium-photo", "130x180mm", N_("Medium Photo")},
+ {"om_pa-kai", "267x389mm", N_("pa-kai")},
+ {"om_postfix", "114x229mm", N_("Postfix Envelope")},
+ {"om_small-photo", "100x150mm", N_("Small Photo"), "om_small-photo"},
+ {"om_wide-photo", "100x200mm", N_("Wide Photo"), "om_wide-photo"},
+ {"prc_1", "102x165mm", N_("prc1 Envelope"), "EnvPRC1"},
+ {"prc_10", "324x458mm", N_("prc10 Envelope"), "EnvPRC10"},
+ {"prc_16k", "146x215mm", N_("prc 16k"), "PRC16K"},
+ {"prc_2", "102x176mm", N_("prc2 Envelope"), "EnvPRC2"},
+ {"prc_3", "125x176mm", N_("prc3 Envelope"), "EnvPRC3"},
+ {"prc_32k", "97x151mm", N_("prc 32k"), "PRC32K"},
+ {"prc_4", "110x208mm", N_("prc4 Envelope"), "EnvPRC4"},
+ {"prc_5", "110x220mm", N_("prc5 Envelope"), "EnvPRC5"},
+ {"prc_6", "120x230mm", N_("prc6 Envelope"), "EnvPRC6"},
+ {"prc_7", "160x230mm", N_("prc7 Envelope"), "EnvPRC7"},
+ {"prc_8", "120x309mm", N_("prc8 Envelope"), "EnvPRC8"},
+ {"prc_9", "229x324mm", N_("prc9 Envelope"), "EnvPRC9"},
+ {"roc_16k", "7.75x10.75in", N_("ROC 16k"), "roc16k"},
+ {"roc_8k", "10.75x15.5in", N_("ROC 8k"), "roc8k"},
+};
+
+/* Some page sizes have multiple PPD names in use.
+ * The array above only contains the preferred one,
+ * and this array fills out with the duplicates.
+ */
+const struct {
+ const char *ppd_name;
+ const char *standard_name;
+} extra_ppd_names[] = {
+ /* sorted by ppd_name, remember to sort when changing */
+ { "C4", "iso_c4"},
+ { "C5", "iso_c5"},
+ { "C6", "iso_c6"},
+ { "Comm10", "na_number-10"},
+ { "DL", "iso_dl"},
+ { "Monarch", "na_monarch"},
+};
--- /dev/null
+/* Generated by gen-paper-names */
+
+#if 0
+NC_("paper size", "asme_f")
+NC_("paper size", "A0×2")
+NC_("paper size", "A0")
+NC_("paper size", "A0×3")
+NC_("paper size", "A1")
+NC_("paper size", "A10")
+NC_("paper size", "A1×3")
+NC_("paper size", "A1×4")
+NC_("paper size", "A2")
+NC_("paper size", "A2×3")
+NC_("paper size", "A2×4")
+NC_("paper size", "A2×5")
+NC_("paper size", "A3")
+NC_("paper size", "A3 Extra")
+NC_("paper size", "A3×3")
+NC_("paper size", "A3×4")
+NC_("paper size", "A3×5")
+NC_("paper size", "A3×6")
+NC_("paper size", "A3×7")
+NC_("paper size", "A4")
+NC_("paper size", "A4 Extra")
+NC_("paper size", "A4 Tab")
+NC_("paper size", "A4×3")
+NC_("paper size", "A4×4")
+NC_("paper size", "A4×5")
+NC_("paper size", "A4×6")
+NC_("paper size", "A4×7")
+NC_("paper size", "A4×8")
+NC_("paper size", "A4×9")
+NC_("paper size", "A5")
+NC_("paper size", "A5 Extra")
+NC_("paper size", "A6")
+NC_("paper size", "A7")
+NC_("paper size", "A8")
+NC_("paper size", "A9")
+NC_("paper size", "B0")
+NC_("paper size", "B1")
+NC_("paper size", "B10")
+NC_("paper size", "B2")
+NC_("paper size", "B3")
+NC_("paper size", "B4")
+NC_("paper size", "B5")
+NC_("paper size", "B5 Extra")
+NC_("paper size", "B6")
+NC_("paper size", "B6/C4")
+NC_("paper size", "B7")
+NC_("paper size", "B8")
+NC_("paper size", "B9")
+NC_("paper size", "C0")
+NC_("paper size", "C1")
+NC_("paper size", "C10")
+NC_("paper size", "C2")
+NC_("paper size", "C3")
+NC_("paper size", "C4")
+NC_("paper size", "C5")
+NC_("paper size", "C6")
+NC_("paper size", "C6/C5")
+NC_("paper size", "C7")
+NC_("paper size", "C7/C6")
+NC_("paper size", "C8")
+NC_("paper size", "C9")
+NC_("paper size", "DL Envelope")
+NC_("paper size", "RA0")
+NC_("paper size", "RA1")
+NC_("paper size", "RA2")
+NC_("paper size", "RA3")
+NC_("paper size", "RA4")
+NC_("paper size", "SRA0")
+NC_("paper size", "SRA1")
+NC_("paper size", "SRA2")
+NC_("paper size", "SRA3")
+NC_("paper size", "SRA4")
+NC_("paper size", "JB0")
+NC_("paper size", "JB1")
+NC_("paper size", "JB10")
+NC_("paper size", "JB2")
+NC_("paper size", "JB3")
+NC_("paper size", "JB4")
+NC_("paper size", "JB5")
+NC_("paper size", "JB6")
+NC_("paper size", "JB7")
+NC_("paper size", "JB8")
+NC_("paper size", "JB9")
+NC_("paper size", "jis exec")
+NC_("paper size", "Choukei 2 Envelope")
+NC_("paper size", "Choukei 3 Envelope")
+NC_("paper size", "Choukei 4 Envelope")
+NC_("paper size", "Choukei 40 Envelope")
+NC_("paper size", "hagaki (postcard)")
+NC_("paper size", "kahu Envelope")
+NC_("paper size", "kaku2 Envelope")
+NC_("paper size", "kaku3 Envelope")
+NC_("paper size", "kaku4 Envelope")
+NC_("paper size", "kaku5 Envelope")
+NC_("paper size", "kaku7 Envelope")
+NC_("paper size", "kaku8 Envelope")
+NC_("paper size", "oufuku (reply postcard)")
+NC_("paper size", "you4 Envelope")
+NC_("paper size", "you6 Envelope")
+NC_("paper size", "10×11")
+NC_("paper size", "10×13")
+NC_("paper size", "10×14")
+NC_("paper size", "10×15")
+NC_("paper size", "11×12")
+NC_("paper size", "11×15")
+NC_("paper size", "12×19")
+NC_("paper size", "5×7")
+NC_("paper size", "6×9 Envelope")
+NC_("paper size", "7×9 Envelope")
+NC_("paper size", "8×10 Envelope")
+NC_("paper size", "9×11 Envelope")
+NC_("paper size", "9×12 Envelope")
+NC_("paper size", "a2 Envelope")
+NC_("paper size", "Arch A")
+NC_("paper size", "Arch B")
+NC_("paper size", "Arch C")
+NC_("paper size", "Arch D")
+NC_("paper size", "Arch E")
+NC_("paper size", "b-plus")
+NC_("paper size", "c")
+NC_("paper size", "c5 Envelope")
+NC_("paper size", "d")
+NC_("paper size", "e")
+NC_("paper size", "edp")
+NC_("paper size", "European edp")
+NC_("paper size", "Executive")
+NC_("paper size", "f")
+NC_("paper size", "Fan-Fold European")
+NC_("paper size", "Fan-Fold US")
+NC_("paper size", "Fan-Fold German Legal")
+NC_("paper size", "Government Legal")
+NC_("paper size", "Government Letter")
+NC_("paper size", "Index 3×5")
+NC_("paper size", "Index 4×6 (postcard)")
+NC_("paper size", "Index 4×6 ext")
+NC_("paper size", "Index 5×8")
+NC_("paper size", "Invoice")
+NC_("paper size", "Tabloid")
+NC_("paper size", "US Legal")
+NC_("paper size", "US Legal Extra")
+NC_("paper size", "US Letter")
+NC_("paper size", "US Letter Extra")
+NC_("paper size", "US Letter Plus")
+NC_("paper size", "Monarch Envelope")
+NC_("paper size", "#10 Envelope")
+NC_("paper size", "#11 Envelope")
+NC_("paper size", "#12 Envelope")
+NC_("paper size", "#14 Envelope")
+NC_("paper size", "#9 Envelope")
+NC_("paper size", "Oficio")
+NC_("paper size", "Personal Envelope")
+NC_("paper size", "Quarto")
+NC_("paper size", "Super A")
+NC_("paper size", "Super B")
+NC_("paper size", "Wide Format")
+NC_("paper size", "Photo L")
+NC_("paper size", "Dai-pa-kai")
+NC_("paper size", "Folio")
+NC_("paper size", "Folio sp")
+NC_("paper size", "Invite Envelope")
+NC_("paper size", "Italian Envelope")
+NC_("paper size", "juuro-ku-kai")
+NC_("paper size", "Large Photo")
+NC_("paper size", "Medium Photo")
+NC_("paper size", "pa-kai")
+NC_("paper size", "Postfix Envelope")
+NC_("paper size", "Small Photo")
+NC_("paper size", "Wide Photo")
+NC_("paper size", "prc1 Envelope")
+NC_("paper size", "prc10 Envelope")
+NC_("paper size", "prc 16k")
+NC_("paper size", "prc2 Envelope")
+NC_("paper size", "prc3 Envelope")
+NC_("paper size", "prc 32k")
+NC_("paper size", "prc4 Envelope")
+NC_("paper size", "prc5 Envelope")
+NC_("paper size", "prc6 Envelope")
+NC_("paper size", "prc7 Envelope")
+NC_("paper size", "prc8 Envelope")
+NC_("paper size", "prc9 Envelope")
+NC_("paper size", "ROC 16k")
+NC_("paper size", "ROC 8k")
+#endif
+
+static const char paper_names[] =
+ "asme_f\0"
+ "iso_2a0\0"
+ "A0×2\0"
+ "iso_a0\0"
+ "iso_a0x3\0"
+ "A0×3\0"
+ "iso_a1\0"
+ "iso_a10\0"
+ "A10\0"
+ "iso_a1x3\0"
+ "A1×3\0"
+ "iso_a1x4\0"
+ "A1×4\0"
+ "iso_a2\0"
+ "iso_a2x3\0"
+ "A2×3\0"
+ "iso_a2x4\0"
+ "A2×4\0"
+ "iso_a2x5\0"
+ "A2×5\0"
+ "iso_a3\0"
+ "iso_a3-extra\0"
+ "A3 Extra\0"
+ "A3Extra\0"
+ "iso_a3x3\0"
+ "A3×3\0"
+ "iso_a3x4\0"
+ "A3×4\0"
+ "iso_a3x5\0"
+ "A3×5\0"
+ "iso_a3x6\0"
+ "A3×6\0"
+ "iso_a3x7\0"
+ "A3×7\0"
+ "iso_a4\0"
+ "iso_a4-extra\0"
+ "A4 Extra\0"
+ "A4Extra\0"
+ "iso_a4-tab\0"
+ "A4 Tab\0"
+ "A4Tab\0"
+ "iso_a4x3\0"
+ "A4×3\0"
+ "iso_a4x4\0"
+ "A4×4\0"
+ "iso_a4x5\0"
+ "A4×5\0"
+ "iso_a4x6\0"
+ "A4×6\0"
+ "iso_a4x7\0"
+ "A4×7\0"
+ "iso_a4x8\0"
+ "A4×8\0"
+ "iso_a4x9\0"
+ "A4×9\0"
+ "iso_a5\0"
+ "A5\0"
+ "iso_a5-extra\0"
+ "A5 Extra\0"
+ "A5Extra\0"
+ "iso_a6\0"
+ "A6\0"
+ "iso_a7\0"
+ "A7\0"
+ "iso_a8\0"
+ "A8\0"
+ "iso_a9\0"
+ "A9\0"
+ "iso_b0\0"
+ "ISOB0\0"
+ "iso_b1\0"
+ "ISOB1\0"
+ "iso_b10\0"
+ "ISOB10\0"
+ "iso_b2\0"
+ "ISOB2\0"
+ "iso_b3\0"
+ "ISOB3\0"
+ "iso_b4\0"
+ "ISOB4\0"
+ "iso_b5\0"
+ "ISOB5\0"
+ "iso_b5-extra\0"
+ "B5 Extra\0"
+ "ISOB5Extra\0"
+ "iso_b6\0"
+ "ISOB6\0"
+ "iso_b6c4\0"
+ "B6/C4\0"
+ "iso_b7\0"
+ "ISOB7\0"
+ "iso_b8\0"
+ "ISOB8\0"
+ "iso_b9\0"
+ "ISOB9\0"
+ "iso_c0\0"
+ "EnvC0\0"
+ "iso_c1\0"
+ "EnvC1\0"
+ "iso_c10\0"
+ "EnvC10\0"
+ "iso_c2\0"
+ "EnvC2\0"
+ "iso_c3\0"
+ "EnvC3\0"
+ "iso_c4\0"
+ "EnvC4\0"
+ "iso_c5\0"
+ "EnvC5\0"
+ "iso_c6\0"
+ "EnvC6\0"
+ "iso_c6c5\0"
+ "C6/C5\0"
+ "EnvC65\0"
+ "iso_c7\0"
+ "EnvC7\0"
+ "iso_c7c6\0"
+ "C7/C6\0"
+ "iso_c8\0"
+ "EnvC8\0"
+ "iso_c9\0"
+ "EnvC9\0"
+ "iso_dl\0"
+ "DL Envelope\0"
+ "EnvDL\0"
+ "iso_ra0\0"
+ "iso_ra1\0"
+ "iso_ra2\0"
+ "iso_ra3\0"
+ "iso_ra4\0"
+ "iso_sra0\0"
+ "SRA0\0"
+ "iso_sra1\0"
+ "SRA1\0"
+ "iso_sra2\0"
+ "SRA2\0"
+ "iso_sra3\0"
+ "SRA3\0"
+ "iso_sra4\0"
+ "SRA4\0"
+ "jis_b0\0"
+ "JB0\0"
+ "jis_b1\0"
+ "JB1\0"
+ "jis_b10\0"
+ "JB10\0"
+ "jis_b2\0"
+ "JB2\0"
+ "jis_b3\0"
+ "JB3\0"
+ "jis_b4\0"
+ "JB4\0"
+ "jis_b5\0"
+ "JB5\0"
+ "jis_b6\0"
+ "JB6\0"
+ "jis_b7\0"
+ "JB7\0"
+ "jis_b8\0"
+ "JB8\0"
+ "jis_b9\0"
+ "JB9\0"
+ "jis_exec\0"
+ "jis exec\0"
+ "jpn_chou2\0"
+ "Choukei 2 Envelope\0"
+ "jpn_chou3\0"
+ "Choukei 3 Envelope\0"
+ "EnvChou3\0"
+ "jpn_chou4\0"
+ "Choukei 4 Envelope\0"
+ "EnvChou4\0"
+ "jpn_chou40\0"
+ "Choukei 40 Envelope\0"
+ "EnvChou40\0"
+ "jpn_hagaki\0"
+ "hagaki (postcard)\0"
+ "jpn_kahu\0"
+ "kahu Envelope\0"
+ "jpn_kaku2\0"
+ "kaku2 Envelope\0"
+ "EnvKaku2\0"
+ "jpn_kaku3\0"
+ "kaku3 Envelope\0"
+ "EnvKaku3\0"
+ "jpn_kaku4\0"
+ "kaku4 Envelope\0"
+ "EnvKaku4\0"
+ "jpn_kaku5\0"
+ "kaku5 Envelope\0"
+ "EnvKaku5\0"
+ "jpn_kaku7\0"
+ "kaku7 Envelope\0"
+ "EnvKaku7\0"
+ "jpn_kaku8\0"
+ "kaku8 Envelope\0"
+ "EnvKaku8\0"
+ "jpn_oufuku\0"
+ "oufuku (reply postcard)\0"
+ "DoublePostcard\0"
+ "jpn_you4\0"
+ "you4 Envelope\0"
+ "EnvYou4\0"
+ "jpn_you6\0"
+ "you6 Envelope\0"
+ "EnvYou6\0"
+ "na_10x11\0"
+ "10×11\0"
+ "na_10x13\0"
+ "10×13\0"
+ "na_10x14\0"
+ "10×14\0"
+ "na_10x15\0"
+ "10×15\0"
+ "na_11x12\0"
+ "11×12\0"
+ "12x11\0"
+ "na_11x15\0"
+ "11×15\0"
+ "15x11\0"
+ "na_12x19\0"
+ "12×19\0"
+ "na_5x7\0"
+ "5×7\0"
+ "na_6x9\0"
+ "6×9 Envelope\0"
+ "na_7x9\0"
+ "7×9 Envelope\0"
+ "na_8x10\0"
+ "8×10 Envelope\0"
+ "na_9x11\0"
+ "9×11 Envelope\0"
+ "na_9x12\0"
+ "9×12 Envelope\0"
+ "na_a2\0"
+ "a2 Envelope\0"
+ "EnvA2\0"
+ "na_arch-a\0"
+ "Arch A\0"
+ "ARCHA\0"
+ "na_arch-b\0"
+ "Arch B\0"
+ "ARCHB\0"
+ "na_arch-c\0"
+ "Arch C\0"
+ "ARCHC\0"
+ "na_arch-d\0"
+ "Arch D\0"
+ "ARCHD\0"
+ "na_arch-e\0"
+ "Arch E\0"
+ "ARCHE\0"
+ "na_b-plus\0"
+ "SuperB\0"
+ "na_c\0"
+ "AnsiC\0"
+ "na_c5\0"
+ "6.5x9.5\0"
+ "na_d\0"
+ "AnsiD\0"
+ "na_e\0"
+ "AnsiE\0"
+ "na_edp\0"
+ "11x14\0"
+ "na_eur-edp\0"
+ "European edp\0"
+ "na_executive\0"
+ "Executive\0"
+ "na_f\0"
+ "AnsiF\0"
+ "na_fanfold-eur\0"
+ "Fan-Fold European\0"
+ "FanFoldGerman\0"
+ "na_fanfold-us\0"
+ "Fan-Fold US\0"
+ "FanFoldUS\0"
+ "na_foolscap\0"
+ "Fan-Fold German Legal\0"
+ "FanFoldGermanLegal\0"
+ "na_govt-legal\0"
+ "Government Legal\0"
+ "8x13\0"
+ "na_govt-letter\0"
+ "Government Letter\0"
+ "na_index-3x5\0"
+ "Index 3×5\0"
+ "na_index-4x6\0"
+ "Index 4×6 (postcard)\0"
+ "na_index-4x6-ext\0"
+ "Index 4×6 ext\0"
+ "na_index-5x8\0"
+ "Index 5×8\0"
+ "na_invoice\0"
+ "Invoice\0"
+ "Statement\0"
+ "na_ledger\0"
+ "Tabloid\0"
+ "Ledger\0"
+ "na_legal\0"
+ "US Legal\0"
+ "na_legal-extra\0"
+ "US Legal Extra\0"
+ "LegalExtra\0"
+ "na_letter\0"
+ "US Letter\0"
+ "na_letter-extra\0"
+ "US Letter Extra\0"
+ "LetterExtra\0"
+ "na_letter-plus\0"
+ "US Letter Plus\0"
+ "LetterPlus\0"
+ "na_monarch\0"
+ "Monarch Envelope\0"
+ "EnvMonarch\0"
+ "na_number-10\0"
+ "#10 Envelope\0"
+ "Env10\0"
+ "na_number-11\0"
+ "#11 Envelope\0"
+ "Env11\0"
+ "na_number-12\0"
+ "#12 Envelope\0"
+ "Env12\0"
+ "na_number-14\0"
+ "#14 Envelope\0"
+ "Env14\0"
+ "na_number-9\0"
+ "#9 Envelope\0"
+ "Env9\0"
+ "na_oficio\0"
+ "Oficio\0"
+ "na_personal\0"
+ "Personal Envelope\0"
+ "EnvPersonal\0"
+ "na_quarto\0"
+ "Quarto\0"
+ "na_super-a\0"
+ "Super A\0"
+ "SuperA\0"
+ "na_super-b\0"
+ "Super B\0"
+ "na_wide-format\0"
+ "Wide Format\0"
+ "oe_photo-l\0"
+ "Photo L\0"
+ "3.5x5\0"
+ "om_dai-pa-kai\0"
+ "Dai-pa-kai\0"
+ "om_folio\0"
+ "Folio\0"
+ "om_folio-sp\0"
+ "Folio sp\0"
+ "FolioSP\0"
+ "om_invite\0"
+ "Invite Envelope\0"
+ "EnvInvite\0"
+ "om_italian\0"
+ "Italian Envelope\0"
+ "EnvItalian\0"
+ "om_juuro-ku-kai\0"
+ "om_large-photo\0"
+ "Large Photo\0"
+ "om_medium-photo\0"
+ "Medium Photo\0"
+ "om_pa-kai\0"
+ "om_postfix\0"
+ "Postfix Envelope\0"
+ "om_small-photo\0"
+ "Small Photo\0"
+ "om_wide-photo\0"
+ "Wide Photo\0"
+ "prc_1\0"
+ "prc1 Envelope\0"
+ "EnvPRC1\0"
+ "prc_10\0"
+ "prc10 Envelope\0"
+ "EnvPRC10\0"
+ "prc_16k\0"
+ "prc 16k\0"
+ "PRC16K\0"
+ "prc_2\0"
+ "prc2 Envelope\0"
+ "EnvPRC2\0"
+ "prc_3\0"
+ "prc3 Envelope\0"
+ "EnvPRC3\0"
+ "prc_32k\0"
+ "prc 32k\0"
+ "PRC32K\0"
+ "prc_4\0"
+ "prc4 Envelope\0"
+ "EnvPRC4\0"
+ "prc_5\0"
+ "prc5 Envelope\0"
+ "EnvPRC5\0"
+ "prc_6\0"
+ "prc6 Envelope\0"
+ "EnvPRC6\0"
+ "prc_7\0"
+ "prc7 Envelope\0"
+ "EnvPRC7\0"
+ "prc_8\0"
+ "prc8 Envelope\0"
+ "EnvPRC8\0"
+ "prc_9\0"
+ "prc9 Envelope\0"
+ "EnvPRC9\0"
+ "roc_16k\0"
+ "ROC 16k\0"
+ "roc16k\0"
+ "roc_8k\0"
+ "ROC 8k\0"
+ "roc8k\0"
+ "Comm10\0";
+
+typedef struct {
+ int name;
+ float width;
+ float height;
+ int display_name;
+ int ppd_name;
+} PaperInfo;
+
+static const PaperInfo standard_names_offsets[] = {
+ { 0, 711.2, 1016, 0, -1 },
+ { 7, 1189, 1682, 15, -1 },
+ { 21, 841, 1189, 953, 953 },
+ { 28, 1189, 2523, 37, -1 },
+ { 43, 594, 841, 967, 967 },
+ { 50, 26, 37, 58, 58 },
+ { 62, 841, 1783, 71, -1 },
+ { 77, 841, 2378, 86, -1 },
+ { 92, 420, 594, 981, 981 },
+ { 99, 594, 1261, 108, -1 },
+ { 114, 594, 1682, 123, -1 },
+ { 129, 594, 2102, 138, -1 },
+ { 144, 297, 420, 995, 995 },
+ { 151, 322, 445, 164, 173 },
+ { 181, 420, 891, 190, -1 },
+ { 196, 420, 1189, 205, -1 },
+ { 211, 420, 1486, 220, -1 },
+ { 226, 420, 1783, 235, -1 },
+ { 241, 420, 2080, 250, -1 },
+ { 256, 210, 297, 1009, 1009 },
+ { 263, 235.5, 322.3, 276, 285 },
+ { 293, 225, 297, 304, 311 },
+ { 317, 297, 630, 326, -1 },
+ { 332, 297, 841, 341, -1 },
+ { 347, 297, 1051, 356, -1 },
+ { 362, 297, 1261, 371, -1 },
+ { 377, 297, 1471, 386, -1 },
+ { 392, 297, 1682, 401, -1 },
+ { 407, 297, 1892, 416, -1 },
+ { 422, 148, 210, 429, 429 },
+ { 432, 174, 235, 445, 454 },
+ { 462, 105, 148, 469, 469 },
+ { 472, 74, 105, 479, 479 },
+ { 482, 52, 74, 489, 489 },
+ { 492, 37, 52, 499, 499 },
+ { 502, 1000, 1414, 512, 509 },
+ { 515, 707, 1000, 525, 522 },
+ { 528, 31, 44, 539, 536 },
+ { 543, 500, 707, 553, 550 },
+ { 556, 353, 500, 566, 563 },
+ { 569, 250, 353, 579, 576 },
+ { 582, 176, 250, 592, 589 },
+ { 595, 201, 276, 608, 617 },
+ { 628, 125, 176, 638, 635 },
+ { 641, 125, 324, 650, -1 },
+ { 656, 88, 125, 666, 663 },
+ { 669, 62, 88, 679, 676 },
+ { 682, 44, 62, 692, 689 },
+ { 695, 917, 1297, 705, 702 },
+ { 708, 648, 917, 718, 715 },
+ { 721, 28, 40, 732, 729 },
+ { 736, 458, 648, 746, 743 },
+ { 749, 324, 458, 759, 756 },
+ { 762, 229, 324, 653, 769 },
+ { 775, 162, 229, 785, 782 },
+ { 788, 114, 162, 798, 795 },
+ { 801, 114, 229, 810, 816 },
+ { 823, 81, 114, 833, 830 },
+ { 836, 81, 162, 845, -1 },
+ { 851, 57, 81, 861, 858 },
+ { 864, 40, 57, 874, 871 },
+ { 877, 110, 220, 884, 896 },
+ { 902, 860, 1220, 952, -1 },
+ { 910, 610, 860, 966, -1 },
+ { 918, 430, 610, 980, -1 },
+ { 926, 305, 430, 994, -1 },
+ { 934, 215, 305, 1008, -1 },
+ { 942, 900, 1280, 951, -1 },
+ { 956, 640, 900, 965, -1 },
+ { 970, 450, 640, 979, -1 },
+ { 984, 320, 450, 993, -1 },
+ { 998, 225, 320, 1007, -1 },
+ { 1012, 1030, 1456, 1019, 512 },
+ { 1023, 728, 1030, 1030, 525 },
+ { 1034, 32, 45, 1042, 539 },
+ { 1047, 515, 728, 1054, 553 },
+ { 1058, 364, 515, 1065, 566 },
+ { 1069, 257, 364, 1076, 579 },
+ { 1080, 182, 257, 1087, 592 },
+ { 1091, 128, 182, 1098, 638 },
+ { 1102, 91, 128, 1109, 666 },
+ { 1113, 64, 91, 1120, 679 },
+ { 1124, 45, 64, 1131, 692 },
+ { 1135, 216, 330, 1144, -1 },
+ { 1153, 111.1, 146, 1163, -1 },
+ { 1182, 120, 235, 1192, 1211 },
+ { 1220, 90, 205, 1230, 1249 },
+ { 1258, 90, 225, 1269, 1289 },
+ { 1299, 100, 148, 1310, 1596 },
+ { 1328, 240, 322.1, 1337, -1 },
+ { 1351, 240, 332, 1361, 1376 },
+ { 1385, 216, 277, 1395, 1410 },
+ { 1419, 197, 267, 1429, 1444 },
+ { 1453, 190, 240, 1463, 1478 },
+ { 1487, 142, 205, 1497, 1512 },
+ { 1521, 119, 197, 1531, 1546 },
+ { 1555, 148, 200, 1566, 1590 },
+ { 1605, 105, 235, 1614, 1628 },
+ { 1636, 98, 190, 1645, 1659 },
+ { 1667, 254, 279.4, 1676, 1670 },
+ { 1683, 254, 330.2, 1692, 1686 },
+ { 1699, 254, 355.6, 1708, 1702 },
+ { 1715, 254, 381, 1724, 1718 },
+ { 1731, 279.4, 304.8, 1740, 1747 },
+ { 1753, 279.4, 381, 1762, 1769 },
+ { 1775, 304.8, 482.6, 1784, 1778 },
+ { 1791, 127, 177.8, 1798, 1794 },
+ { 1803, 152.4, 228.6, 1810, 1806 },
+ { 1824, 177.8, 228.6, 1831, 1827 },
+ { 1845, 203.2, 254, 1853, 1848 },
+ { 1868, 228.6, 279.4, 1876, 1871 },
+ { 1891, 228.6, 304.8, 1899, 1894 },
+ { 1914, 111.125, 146.05, 1920, 1932 },
+ { 1938, 228.6, 304.8, 1948, 1955 },
+ { 1961, 304.8, 457.2, 1971, 1978 },
+ { 1984, 457.2, 609.6, 1994, 2001 },
+ { 2007, 609.6, 914.4, 2017, 2024 },
+ { 2030, 914.4, 1219.2, 2040, 2047 },
+ { 2053, 304.8, 486.918, 2056, 2063 },
+ { 2070, 431.8, 558.8, 1142, 2075 },
+ { 2081, 165.1, 241.3, 3598, 2087 },
+ { 2095, 558.8, 863.6, 1603, 2100 },
+ { 2106, 863.6, 1117.6, 894, 2111 },
+ { 2117, 279.4, 355.6, 2120, 2124 },
+ { 2130, 304.8, 355.6, 2141, -1 },
+ { 2154, 184.15, 266.7, 2167, 2167 },
+ { 2177, 1117.6, 1727.2, 5, 2182 },
+ { 2188, 215.9, 304.8, 2203, 2221 },
+ { 2235, 279.4, 377.825, 2249, 2261 },
+ { 2271, 215.9, 330.2, 2283, 2305 },
+ { 2324, 203.2, 330.2, 2338, 2355 },
+ { 2360, 203.2, 254, 2375, 1848 },
+ { 2393, 76.2, 127, 2406, 216 },
+ { 2417, 101.6, 152.4, 2430, 367 },
+ { 2452, 152.4, 203.2, 2469, -1 },
+ { 2484, 127, 203.2, 2497, 2493 },
+ { 2508, 139.7, 215.9, 2519, 2527 },
+ { 2537, 279.4, 431.8, 2547, 2555 },
+ { 2562, 215.9, 355.6, 2571, 2299 },
+ { 2580, 241.3, 381, 2595, 2610 },
+ { 2621, 215.9, 279.4, 2631, 2386 },
+ { 2641, 241.3, 304.8, 2657, 2673 },
+ { 2685, 215.9, 322.326, 2700, 2715 },
+ { 2726, 98.425, 190.5, 2737, 2754 },
+ { 2765, 104.775, 241.3, 2778, 2791 },
+ { 2797, 114.3, 263.525, 2810, 2823 },
+ { 2829, 120.65, 279.4, 2842, 2855 },
+ { 2861, 127, 292.1, 2874, 2887 },
+ { 2893, 98.425, 225.425, 2905, 2917 },
+ { 2922, 215.9, 340.36, 2932, 2932 },
+ { 2939, 92.075, 165.1, 2951, 2969 },
+ { 2981, 215.9, 275.082, 2991, 2991 },
+ { 2998, 227.076, 355.6, 3009, 3017 },
+ { 3024, 330.2, 482.6, 3035, 2063 },
+ { 3043, 762, 1066.8, 3058, -1 },
+ { 3070, 88.9, 127, 3081, 3089 },
+ { 3095, 275, 395, 3109, -1 },
+ { 3120, 210, 330, 3129, 3129 },
+ { 3135, 215, 315, 3147, 3156 },
+ { 3164, 220, 220, 3174, 3190 },
+ { 3200, 110, 230, 3211, 3228 },
+ { 3239, 198, 275, 3242, -1 },
+ { 3255, 200, 300, 3270, 3255 },
+ { 3282, 130, 180, 3298, -1 },
+ { 3311, 267, 389, 3102, -1 },
+ { 3321, 114, 229, 3332, -1 },
+ { 3349, 100, 150, 3364, 3349 },
+ { 3376, 100, 200, 3390, 3376 },
+ { 3401, 102, 165, 3407, 3421 },
+ { 3429, 324, 458, 3436, 3451 },
+ { 3460, 146, 215, 3468, 3476 },
+ { 3483, 102, 176, 3489, 3503 },
+ { 3511, 125, 176, 3517, 3531 },
+ { 3539, 97, 151, 3547, 3555 },
+ { 3562, 110, 208, 3568, 3582 },
+ { 3590, 110, 220, 3596, 3610 },
+ { 3618, 120, 230, 3624, 3638 },
+ { 3646, 160, 230, 3652, 3666 },
+ { 3674, 120, 309, 3680, 3694 },
+ { 3702, 229, 324, 3708, 3722 },
+ { 3730, 196.85, 273.05, 3738, 3746 },
+ { 3753, 273.05, 393.7, 3760, 3767 },
+};
+
+static const struct {
+ int ppd_name;
+ int standard_name;
+} extra_ppd_names_offsets[] = {
+ { 653, 762 },
+ { 785, 775 },
+ { 798, 788 },
+ { 3773, 2765 },
+ { 899, 877 },
+ { 2757, 2726 },
+};
+
#include <gmodule.h>
#include <gtk/gtk.h>
-#include <gtk/gtkprintbackendprivate.h>
-#include <gtk/gtkunixprint.h>
-#include <gtk/gtkprinterprivate.h>
+#include <gtk/print/gtkprintbackendprivate.h>
+#include <gtk/print/gtkunixprint.h>
+#include <gtk/print/gtkprinterprivate.h>
#include <gtk/gtkprivate.h>
#include "gtkprintbackendcups.h"
#include "gtkcupssecretsutils.h"
#include "gtkprintbackendutils.h"
-#include <gtkprintutilsprivate.h>
+#include <gtk/print/gtkprintutilsprivate.h>
#include "gtkprivate.h"
#ifdef HAVE_COLORD
#define __GTK_PRINT_BACKEND_CUPS_H__
#include <glib-object.h>
-#include "gtkprintbackendprivate.h"
+#include "gtk/print/gtkprintbackendprivate.h"
G_BEGIN_DECLS
#include <glib/gi18n-lib.h>
#include "gtk/gtk.h"
-#include "gtk/gtkprinterprivate.h"
+#include "gtk/print/gtkprinterprivate.h"
#include "gtk/gtkprivate.h"
#include "gtkprintbackendfile.h"
#define __GTK_PRINT_BACKEND_FILE_H__
#include <glib-object.h>
-#include "gtkprintbackendprivate.h"
+#include "gtk/print/gtkprintbackendprivate.h"
G_BEGIN_DECLS
#include <cups/ppd.h>
#include "gtkcupsutils.h"
-#include <gtk/gtkunixprint.h>
-#include <gtk/gtkprinterprivate.h>
+#include <gtk/print/gtkunixprint.h>
+#include <gtk/print/gtkprinterprivate.h>
#ifdef HAVE_COLORD
#include <colord.h>