From: Matthias Clasen Date: Wed, 7 Jun 2023 03:14:39 +0000 (-0400) Subject: print: Move all the remaining sources X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~171^2~9 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=d1aae4bffafac19eb2effcf162b2a61d8f4f1bb0;p=gtk4.git print: Move all the remaining sources Move the unix- and Windows-specific print sources to the gtk/print subdirectory. --- diff --git a/gtk/gtkcustompaperunixdialog.c b/gtk/gtkcustompaperunixdialog.c deleted file mode 100644 index 375927e517..0000000000 --- a/gtk/gtkcustompaperunixdialog.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* GtkCustomPaperUnixDialog - * Copyright (C) 2006 Alexander Larsson - * 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 . - */ - - -#include "config.h" -#include -#include - -#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT -#include -#endif - -#include -#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 ("%s", 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); -} diff --git a/gtk/gtkcustompaperunixdialog.h b/gtk/gtkcustompaperunixdialog.h deleted file mode 100644 index 630737acf2..0000000000 --- a/gtk/gtkcustompaperunixdialog.h +++ /dev/null @@ -1,40 +0,0 @@ -/* GtkCustomPaperUnixDialog - * Copyright (C) 2006 Alexander Larsson - * - * 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 . - */ - -#pragma once - -#include - -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 - diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 9c07e3d652..573f250d8b 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -63,7 +63,7 @@ #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" diff --git a/gtk/gtkpagesetupunixdialog.c b/gtk/gtkpagesetupunixdialog.c deleted file mode 100644 index c0de95de55..0000000000 --- a/gtk/gtkpagesetupunixdialog.c +++ /dev/null @@ -1,950 +0,0 @@ -/* GtkPageSetupUnixDialog - * Copyright (C) 2006 Alexander Larsson - * 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 . - */ - - -#include "config.h" -#include -#include - -#include -#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. - * - * ![An example GtkPageSetupUnixDialog](pagesetupdialog.png) - * - * 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 ("%s\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; -} diff --git a/gtk/gtkpagesetupunixdialog.h b/gtk/gtkpagesetupunixdialog.h deleted file mode 100644 index 84a42cb94b..0000000000 --- a/gtk/gtkpagesetupunixdialog.h +++ /dev/null @@ -1,53 +0,0 @@ -/* GtkPageSetupUnixDialog - * Copyright (C) 2006 Alexander Larsson - * - * 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 . - */ - -#pragma once - -#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) -#error "Only can be included directly." -#endif - -#include - -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 - diff --git a/gtk/gtkprint-win32.c b/gtk/gtkprint-win32.c deleted file mode 100644 index 76b1d699cd..0000000000 --- a/gtk/gtkprint-win32.c +++ /dev/null @@ -1,159 +0,0 @@ -/* 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 . - */ - -#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; -} diff --git a/gtk/gtkprint-win32.h b/gtk/gtkprint-win32.h deleted file mode 100644 index 626e15de05..0000000000 --- a/gtk/gtkprint-win32.h +++ /dev/null @@ -1,62 +0,0 @@ -/* 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 . - */ - -#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 - diff --git a/gtk/gtkprintbackend.c b/gtk/gtkprintbackend.c deleted file mode 100644 index 1fd4c3572b..0000000000 --- a/gtk/gtkprintbackend.c +++ /dev/null @@ -1,749 +0,0 @@ -/* 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 . - */ - -#include "config.h" -#include - -#include - -#include -#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 ("%s", 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)); -} diff --git a/gtk/gtkprintbackendprivate.h b/gtk/gtkprintbackendprivate.h deleted file mode 100644 index be14331673..0000000000 --- a/gtk/gtkprintbackendprivate.h +++ /dev/null @@ -1,233 +0,0 @@ -/* 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 . - */ - -#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 -#include -#include - -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 - diff --git a/gtk/gtkprinter.c b/gtk/gtkprinter.c deleted file mode 100644 index 9b16d02463..0000000000 --- a/gtk/gtkprinter.c +++ /dev/null @@ -1,1368 +0,0 @@ -/* GtkPrinter - * Copyright (C) 2006 John (J5) Palmieri - * - * 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 . - */ - -#include "config.h" -#include -#include -#include - -#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; -} diff --git a/gtk/gtkprinter.h b/gtk/gtkprinter.h deleted file mode 100644 index 55e0fe4c8f..0000000000 --- a/gtk/gtkprinter.h +++ /dev/null @@ -1,166 +0,0 @@ -/* GtkPrinter - * Copyright (C) 2006 John (J5) Palmieri - * - * 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 . - */ - -#pragma once - -#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) -#error "Only can be included directly." -#endif - -#include -#include - -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 - diff --git a/gtk/gtkprinteroption.c b/gtk/gtkprinteroption.c deleted file mode 100644 index 91e4bdecb9..0000000000 --- a/gtk/gtkprinteroption.c +++ /dev/null @@ -1,291 +0,0 @@ -/* 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 . - */ - -#include "config.h" -#include -#include - -#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; -} diff --git a/gtk/gtkprinteroptionprivate.h b/gtk/gtkprinteroptionprivate.h deleted file mode 100644 index 0578e30ebb..0000000000 --- a/gtk/gtkprinteroptionprivate.h +++ /dev/null @@ -1,129 +0,0 @@ -/* 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 . - */ - -#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 - -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 - - - diff --git a/gtk/gtkprinteroptionset.c b/gtk/gtkprinteroptionset.c deleted file mode 100644 index 288fda6f37..0000000000 --- a/gtk/gtkprinteroptionset.c +++ /dev/null @@ -1,195 +0,0 @@ -/* 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 . - */ - -#include "config.h" -#include -#include -#include - -#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); -} diff --git a/gtk/gtkprinteroptionsetprivate.h b/gtk/gtkprinteroptionsetprivate.h deleted file mode 100644 index 416a82a604..0000000000 --- a/gtk/gtkprinteroptionsetprivate.h +++ /dev/null @@ -1,98 +0,0 @@ -/* 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 . - */ - -#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 -#include -#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 - diff --git a/gtk/gtkprinteroptionwidget.c b/gtk/gtkprinteroptionwidget.c deleted file mode 100644 index c14a675761..0000000000 --- a/gtk/gtkprinteroptionwidget.c +++ /dev/null @@ -1,1192 +0,0 @@ -/* GtkPrinterOptionWidget - * Copyright (C) 2006 Alexander Larsson - * - * 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 . - */ - -#include "config.h" -#include -#include -#include -#include - -#include -#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 ""; -} diff --git a/gtk/gtkprinteroptionwidgetprivate.h b/gtk/gtkprinteroptionwidgetprivate.h deleted file mode 100644 index b470cfd398..0000000000 --- a/gtk/gtkprinteroptionwidgetprivate.h +++ /dev/null @@ -1,72 +0,0 @@ -/* GtkPrinterOptionWidget - * Copyright (C) 2006 John (J5) Palmieri - * - * 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 . - */ -#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 - diff --git a/gtk/gtkprinterprivate.h b/gtk/gtkprinterprivate.h deleted file mode 100644 index 409e66ffb3..0000000000 --- a/gtk/gtkprinterprivate.h +++ /dev/null @@ -1,72 +0,0 @@ -/* 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 . - */ - -#pragma once - -#include -#include -#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 diff --git a/gtk/gtkprintjob.c b/gtk/gtkprintjob.c deleted file mode 100644 index b295d8d69f..0000000000 --- a/gtk/gtkprintjob.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* GtkPrintJob - * Copyright (C) 2006 John (J5) Palmieri - * - * 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 . - */ - -/** - * 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 -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include - -#include -#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; -} diff --git a/gtk/gtkprintjob.h b/gtk/gtkprintjob.h deleted file mode 100644 index b1e4563298..0000000000 --- a/gtk/gtkprintjob.h +++ /dev/null @@ -1,146 +0,0 @@ -/* 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 . - */ - -#pragma once - -#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) -#error "Only can be included directly." -#endif - -#include - -#include -#include - -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 - diff --git a/gtk/gtkprintoperation-portal.c b/gtk/gtkprintoperation-portal.c deleted file mode 100644 index 4f4c4ccaae..0000000000 --- a/gtk/gtkprintoperation-portal.c +++ /dev/null @@ -1,692 +0,0 @@ -/* 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 . - */ - -#include "config.h" - -#include - -#include -#include -#include - -#include -#include - -#include - -#include "gtkprintoperation-private.h" -#include "gtkprintoperation-portal.h" -#include "print/gtkprintsettings.h" -#include "print/gtkpagesetup.h" -#include "gtkprintbackendprivate.h" -#include "gtkfilelauncher.h" -#include -#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); -} diff --git a/gtk/gtkprintoperation-portal.h b/gtk/gtkprintoperation-portal.h deleted file mode 100644 index 6aa1219213..0000000000 --- a/gtk/gtkprintoperation-portal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* 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 . - */ - -#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 - diff --git a/gtk/gtkprintoperation-private.h b/gtk/gtkprintoperation-private.h deleted file mode 100644 index f5daa45291..0000000000 --- a/gtk/gtkprintoperation-private.h +++ /dev/null @@ -1,148 +0,0 @@ -/* 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 . - */ - -#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 - diff --git a/gtk/gtkprintoperation-unix.c b/gtk/gtkprintoperation-unix.c deleted file mode 100644 index 1108927bb2..0000000000 --- a/gtk/gtkprintoperation-unix.c +++ /dev/null @@ -1,1307 +0,0 @@ -/* 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 . - */ - -#include "config.h" -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#include -#include - -#include -#include "gtkprintoperation-private.h" -#include "gtkprintoperation-portal.h" - -#include -#include -#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 - - -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); -} diff --git a/gtk/gtkprintoperation-win32.c b/gtk/gtkprintoperation-win32.c deleted file mode 100644 index 15d68abff4..0000000000 --- a/gtk/gtkprintoperation-win32.c +++ /dev/null @@ -1,2244 +0,0 @@ -/* 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 . - */ - -#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 -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#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); -} diff --git a/gtk/gtkprintunixdialog.c b/gtk/gtkprintunixdialog.c deleted file mode 100644 index 1835002b9a..0000000000 --- a/gtk/gtkprintunixdialog.c +++ /dev/null @@ -1,3564 +0,0 @@ -/* GtkPrintUnixDialog - * Copyright (C) 2006 John (J5) Palmieri - * Copyright (C) 2006 Alexander Larsson - * 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 . - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#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 -#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. - * - * ![An example GtkPrintUnixDialog](printdialog.png) - * - * 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 - * - * - * - * - * - * False - * False - * - * - * Tab label - * - * - * - * - * Content on notebook tab - * - * - * - * - * - * - * - * ``` - * - * # 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 ("%s", 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; -} diff --git a/gtk/gtkprintunixdialog.h b/gtk/gtkprintunixdialog.h deleted file mode 100644 index 3c12c7abfa..0000000000 --- a/gtk/gtkprintunixdialog.h +++ /dev/null @@ -1,91 +0,0 @@ -/* GtkPrintUnixDialog - * Copyright (C) 2006 John (J5) Palmieri - * - * 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 . - */ - -#pragma once - -#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) -#error "Only can be included directly." -#endif - -#include -#include -#include - -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 - diff --git a/gtk/gtkprintutilsprivate.h b/gtk/gtkprintutilsprivate.h deleted file mode 100644 index 9e63e91f8f..0000000000 --- a/gtk/gtkprintutilsprivate.h +++ /dev/null @@ -1,33 +0,0 @@ -/* 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 . - */ - -#pragma once - -#include -#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 - diff --git a/gtk/gtkunixprint.h b/gtk/gtkunixprint.h deleted file mode 100644 index c285b4ed00..0000000000 --- a/gtk/gtkunixprint.h +++ /dev/null @@ -1,27 +0,0 @@ -/* 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 . - */ - -#pragma once - -#define __GTK_UNIX_PRINT_H_INSIDE__ - -#include -#include -#include -#include - -#undef __GTK_UNIX_PRINT_H_INSIDE__ - diff --git a/gtk/meson.build b/gtk/meson.build index 479a7b6269..7b8926451b 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -676,50 +676,18 @@ if os_unix and tracker3_dep.found() 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 diff --git a/gtk/paper_names.c b/gtk/paper_names.c deleted file mode 100644 index e5c9d0b839..0000000000 --- a/gtk/paper_names.c +++ /dev/null @@ -1,219 +0,0 @@ -#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"}, -}; diff --git a/gtk/paper_names_offsets.c b/gtk/paper_names_offsets.c deleted file mode 100644 index d4f79e299f..0000000000 --- a/gtk/paper_names_offsets.c +++ /dev/null @@ -1,808 +0,0 @@ -/* 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 }, -}; - diff --git a/gtk/print/gtkcustompaperunixdialog.c b/gtk/print/gtkcustompaperunixdialog.c new file mode 100644 index 0000000000..375927e517 --- /dev/null +++ b/gtk/print/gtkcustompaperunixdialog.c @@ -0,0 +1,1008 @@ +/* GtkCustomPaperUnixDialog + * Copyright (C) 2006 Alexander Larsson + * 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 . + */ + + +#include "config.h" +#include +#include + +#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT +#include +#endif + +#include +#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 ("%s", 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); +} diff --git a/gtk/print/gtkcustompaperunixdialog.h b/gtk/print/gtkcustompaperunixdialog.h new file mode 100644 index 0000000000..630737acf2 --- /dev/null +++ b/gtk/print/gtkcustompaperunixdialog.h @@ -0,0 +1,40 @@ +/* GtkCustomPaperUnixDialog + * Copyright (C) 2006 Alexander Larsson + * + * 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 . + */ + +#pragma once + +#include + +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 + diff --git a/gtk/print/gtkpagesetupunixdialog.c b/gtk/print/gtkpagesetupunixdialog.c new file mode 100644 index 0000000000..e9f5cfd6ab --- /dev/null +++ b/gtk/print/gtkpagesetupunixdialog.c @@ -0,0 +1,950 @@ +/* GtkPageSetupUnixDialog + * Copyright (C) 2006 Alexander Larsson + * 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 . + */ + + +#include "config.h" +#include +#include + +#include +#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. + * + * ![An example GtkPageSetupUnixDialog](pagesetupdialog.png) + * + * 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 ("%s\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; +} diff --git a/gtk/print/gtkpagesetupunixdialog.h b/gtk/print/gtkpagesetupunixdialog.h new file mode 100644 index 0000000000..84a42cb94b --- /dev/null +++ b/gtk/print/gtkpagesetupunixdialog.h @@ -0,0 +1,53 @@ +/* GtkPageSetupUnixDialog + * Copyright (C) 2006 Alexander Larsson + * + * 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 . + */ + +#pragma once + +#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +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 + diff --git a/gtk/print/gtkprint-win32.c b/gtk/print/gtkprint-win32.c new file mode 100644 index 0000000000..76b1d699cd --- /dev/null +++ b/gtk/print/gtkprint-win32.c @@ -0,0 +1,159 @@ +/* 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 . + */ + +#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; +} diff --git a/gtk/print/gtkprint-win32.h b/gtk/print/gtkprint-win32.h new file mode 100644 index 0000000000..626e15de05 --- /dev/null +++ b/gtk/print/gtkprint-win32.h @@ -0,0 +1,62 @@ +/* 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 . + */ + +#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 + diff --git a/gtk/print/gtkprintbackend.c b/gtk/print/gtkprintbackend.c new file mode 100644 index 0000000000..1fd4c3572b --- /dev/null +++ b/gtk/print/gtkprintbackend.c @@ -0,0 +1,749 @@ +/* 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 . + */ + +#include "config.h" +#include + +#include + +#include +#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 ("%s", 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)); +} diff --git a/gtk/print/gtkprintbackendprivate.h b/gtk/print/gtkprintbackendprivate.h new file mode 100644 index 0000000000..0e72f47cff --- /dev/null +++ b/gtk/print/gtkprintbackendprivate.h @@ -0,0 +1,233 @@ +/* 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 . + */ + +#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 +#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 + diff --git a/gtk/print/gtkprinter.c b/gtk/print/gtkprinter.c new file mode 100644 index 0000000000..9b16d02463 --- /dev/null +++ b/gtk/print/gtkprinter.c @@ -0,0 +1,1368 @@ +/* GtkPrinter + * Copyright (C) 2006 John (J5) Palmieri + * + * 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 . + */ + +#include "config.h" +#include +#include +#include + +#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; +} diff --git a/gtk/print/gtkprinter.h b/gtk/print/gtkprinter.h new file mode 100644 index 0000000000..55e0fe4c8f --- /dev/null +++ b/gtk/print/gtkprinter.h @@ -0,0 +1,166 @@ +/* GtkPrinter + * Copyright (C) 2006 John (J5) Palmieri + * + * 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 . + */ + +#pragma once + +#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +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 + diff --git a/gtk/print/gtkprinteroption.c b/gtk/print/gtkprinteroption.c new file mode 100644 index 0000000000..91e4bdecb9 --- /dev/null +++ b/gtk/print/gtkprinteroption.c @@ -0,0 +1,291 @@ +/* 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 . + */ + +#include "config.h" +#include +#include + +#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; +} diff --git a/gtk/print/gtkprinteroptionprivate.h b/gtk/print/gtkprinteroptionprivate.h new file mode 100644 index 0000000000..0578e30ebb --- /dev/null +++ b/gtk/print/gtkprinteroptionprivate.h @@ -0,0 +1,129 @@ +/* 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 . + */ + +#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 + +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 + + + diff --git a/gtk/print/gtkprinteroptionset.c b/gtk/print/gtkprinteroptionset.c new file mode 100644 index 0000000000..288fda6f37 --- /dev/null +++ b/gtk/print/gtkprinteroptionset.c @@ -0,0 +1,195 @@ +/* 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 . + */ + +#include "config.h" +#include +#include +#include + +#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); +} diff --git a/gtk/print/gtkprinteroptionsetprivate.h b/gtk/print/gtkprinteroptionsetprivate.h new file mode 100644 index 0000000000..416a82a604 --- /dev/null +++ b/gtk/print/gtkprinteroptionsetprivate.h @@ -0,0 +1,98 @@ +/* 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 . + */ + +#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 +#include +#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 + diff --git a/gtk/print/gtkprinteroptionwidget.c b/gtk/print/gtkprinteroptionwidget.c new file mode 100644 index 0000000000..c14a675761 --- /dev/null +++ b/gtk/print/gtkprinteroptionwidget.c @@ -0,0 +1,1192 @@ +/* GtkPrinterOptionWidget + * Copyright (C) 2006 Alexander Larsson + * + * 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 . + */ + +#include "config.h" +#include +#include +#include +#include + +#include +#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 ""; +} diff --git a/gtk/print/gtkprinteroptionwidgetprivate.h b/gtk/print/gtkprinteroptionwidgetprivate.h new file mode 100644 index 0000000000..dac14bc7a7 --- /dev/null +++ b/gtk/print/gtkprinteroptionwidgetprivate.h @@ -0,0 +1,72 @@ +/* GtkPrinterOptionWidget + * Copyright (C) 2006 John (J5) Palmieri + * + * 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 . + */ +#pragma once + +#include +#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 + diff --git a/gtk/print/gtkprinterprivate.h b/gtk/print/gtkprinterprivate.h new file mode 100644 index 0000000000..451588ed6f --- /dev/null +++ b/gtk/print/gtkprinterprivate.h @@ -0,0 +1,72 @@ +/* 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 . + */ + +#pragma once + +#include +#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 diff --git a/gtk/print/gtkprintjob.c b/gtk/print/gtkprintjob.c new file mode 100644 index 0000000000..b295d8d69f --- /dev/null +++ b/gtk/print/gtkprintjob.c @@ -0,0 +1,1001 @@ +/* GtkPrintJob + * Copyright (C) 2006 John (J5) Palmieri + * + * 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 . + */ + +/** + * 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 +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include +#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; +} diff --git a/gtk/print/gtkprintjob.h b/gtk/print/gtkprintjob.h new file mode 100644 index 0000000000..f15342497a --- /dev/null +++ b/gtk/print/gtkprintjob.h @@ -0,0 +1,146 @@ +/* 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 . + */ + +#pragma once + +#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +#include +#include + +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 + diff --git a/gtk/print/gtkprintoperation-portal.c b/gtk/print/gtkprintoperation-portal.c new file mode 100644 index 0000000000..d39ad1645c --- /dev/null +++ b/gtk/print/gtkprintoperation-portal.c @@ -0,0 +1,692 @@ +/* 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 . + */ + +#include "config.h" + +#include + +#include +#include +#include + +#include +#include + +#include + +#include "gtkprintoperation-private.h" +#include "gtkprintoperation-portal.h" +#include "gtkprintsettings.h" +#include "gtkpagesetup.h" +#include "gtkprintbackendprivate.h" +#include "gtkfilelauncher.h" +#include +#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); +} diff --git a/gtk/print/gtkprintoperation-portal.h b/gtk/print/gtkprintoperation-portal.h new file mode 100644 index 0000000000..ee84b28f69 --- /dev/null +++ b/gtk/print/gtkprintoperation-portal.h @@ -0,0 +1,38 @@ +/* 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 . + */ + +#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 + diff --git a/gtk/print/gtkprintoperation-private.h b/gtk/print/gtkprintoperation-private.h new file mode 100644 index 0000000000..46833a63c5 --- /dev/null +++ b/gtk/print/gtkprintoperation-private.h @@ -0,0 +1,148 @@ +/* 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 . + */ + +#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 + diff --git a/gtk/print/gtkprintoperation-unix.c b/gtk/print/gtkprintoperation-unix.c new file mode 100644 index 0000000000..1108927bb2 --- /dev/null +++ b/gtk/print/gtkprintoperation-unix.c @@ -0,0 +1,1307 @@ +/* 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 . + */ + +#include "config.h" +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include "gtkprintoperation-private.h" +#include "gtkprintoperation-portal.h" + +#include +#include +#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 + + +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); +} diff --git a/gtk/print/gtkprintoperation-win32.c b/gtk/print/gtkprintoperation-win32.c new file mode 100644 index 0000000000..15d68abff4 --- /dev/null +++ b/gtk/print/gtkprintoperation-win32.c @@ -0,0 +1,2244 @@ +/* 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 . + */ + +#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 +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/gtk/print/gtkprintunixdialog.c b/gtk/print/gtkprintunixdialog.c new file mode 100644 index 0000000000..1835002b9a --- /dev/null +++ b/gtk/print/gtkprintunixdialog.c @@ -0,0 +1,3564 @@ +/* GtkPrintUnixDialog + * Copyright (C) 2006 John (J5) Palmieri + * Copyright (C) 2006 Alexander Larsson + * 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 . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#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 +#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. + * + * ![An example GtkPrintUnixDialog](printdialog.png) + * + * 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 + * + * + * + * + * + * False + * False + * + * + * Tab label + * + * + * + * + * Content on notebook tab + * + * + * + * + * + * + * + * ``` + * + * # 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 ("%s", 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; +} diff --git a/gtk/print/gtkprintunixdialog.h b/gtk/print/gtkprintunixdialog.h new file mode 100644 index 0000000000..48a5ec7b85 --- /dev/null +++ b/gtk/print/gtkprintunixdialog.h @@ -0,0 +1,91 @@ +/* GtkPrintUnixDialog + * Copyright (C) 2006 John (J5) Palmieri + * + * 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 . + */ + +#pragma once + +#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +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 + diff --git a/gtk/print/gtkprintutilsprivate.h b/gtk/print/gtkprintutilsprivate.h new file mode 100644 index 0000000000..9e63e91f8f --- /dev/null +++ b/gtk/print/gtkprintutilsprivate.h @@ -0,0 +1,33 @@ +/* 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 . + */ + +#pragma once + +#include +#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 + diff --git a/gtk/print/gtkunixprint.h b/gtk/print/gtkunixprint.h new file mode 100644 index 0000000000..79158f1ef3 --- /dev/null +++ b/gtk/print/gtkunixprint.h @@ -0,0 +1,27 @@ +/* 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 . + */ + +#pragma once + +#define __GTK_UNIX_PRINT_H_INSIDE__ + +#include +#include +#include +#include + +#undef __GTK_UNIX_PRINT_H_INSIDE__ + diff --git a/gtk/print/meson.build b/gtk/print/meson.build index 78312aabd6..79f4d085de 100644 --- a/gtk/print/meson.build +++ b/gtk/print/meson.build @@ -16,3 +16,44 @@ gtk_print_sources = files([ '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 diff --git a/gtk/print/paper_names.c b/gtk/print/paper_names.c new file mode 100644 index 0000000000..e5c9d0b839 --- /dev/null +++ b/gtk/print/paper_names.c @@ -0,0 +1,219 @@ +#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"}, +}; diff --git a/gtk/print/paper_names_offsets.c b/gtk/print/paper_names_offsets.c new file mode 100644 index 0000000000..d4f79e299f --- /dev/null +++ b/gtk/print/paper_names_offsets.c @@ -0,0 +1,808 @@ +/* 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 }, +}; + diff --git a/modules/printbackends/gtkprintbackendcups.c b/modules/printbackends/gtkprintbackendcups.c index ed40db68aa..aa9b515878 100644 --- a/modules/printbackends/gtkprintbackendcups.c +++ b/modules/printbackends/gtkprintbackendcups.c @@ -45,9 +45,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include "gtkprintbackendcups.h" @@ -57,7 +57,7 @@ #include "gtkcupssecretsutils.h" #include "gtkprintbackendutils.h" -#include +#include #include "gtkprivate.h" #ifdef HAVE_COLORD diff --git a/modules/printbackends/gtkprintbackendcups.h b/modules/printbackends/gtkprintbackendcups.h index a37a571a35..b5ac6d3980 100644 --- a/modules/printbackends/gtkprintbackendcups.h +++ b/modules/printbackends/gtkprintbackendcups.h @@ -20,7 +20,7 @@ #define __GTK_PRINT_BACKEND_CUPS_H__ #include -#include "gtkprintbackendprivate.h" +#include "gtk/print/gtkprintbackendprivate.h" G_BEGIN_DECLS diff --git a/modules/printbackends/gtkprintbackendfile.c b/modules/printbackends/gtkprintbackendfile.c index 739313064b..eb0b00ce3b 100644 --- a/modules/printbackends/gtkprintbackendfile.c +++ b/modules/printbackends/gtkprintbackendfile.c @@ -35,7 +35,7 @@ #include #include "gtk/gtk.h" -#include "gtk/gtkprinterprivate.h" +#include "gtk/print/gtkprinterprivate.h" #include "gtk/gtkprivate.h" #include "gtkprintbackendfile.h" diff --git a/modules/printbackends/gtkprintbackendfile.h b/modules/printbackends/gtkprintbackendfile.h index 0ca051b5ff..280b901d00 100644 --- a/modules/printbackends/gtkprintbackendfile.h +++ b/modules/printbackends/gtkprintbackendfile.h @@ -21,7 +21,7 @@ #define __GTK_PRINT_BACKEND_FILE_H__ #include -#include "gtkprintbackendprivate.h" +#include "gtk/print/gtkprintbackendprivate.h" G_BEGIN_DECLS diff --git a/modules/printbackends/gtkprintercups.h b/modules/printbackends/gtkprintercups.h index 81b6cfb9c8..fb67f6ac83 100644 --- a/modules/printbackends/gtkprintercups.h +++ b/modules/printbackends/gtkprintercups.h @@ -23,8 +23,8 @@ #include #include "gtkcupsutils.h" -#include -#include +#include +#include #ifdef HAVE_COLORD #include